From 731abfd2a3836561ae8e6c4c03d32a359ae9cc5b Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Thu, 25 Feb 2010 23:13:18 +0000 Subject: [PATCH] Some more work toward completion: - Wizard now works to define input definitions; you can define the mapping, translations and conditions using the UI. - Added ability to schedule imports / export using async services Still a lot of work to be done... --- importexport/inc/class.bodefinitions.inc.php | 11 ++ .../inc/class.iface_import_plugin.inc.php | 11 ++ ...ass.import_export_helper_functions.inc.php | 5 +- ...rtexport_admin_prefs_sidebox_hooks.inc.php | 5 +- importexport/inc/class.uidefinitions.inc.php | 33 +++-- importexport/inc/class.uiexport.inc.php | 123 ++++++++++++++---- importexport/js/export_dialog.js | 11 +- importexport/setup/etemplates.inc.php | 28 ++-- 8 files changed, 171 insertions(+), 56 deletions(-) diff --git a/importexport/inc/class.bodefinitions.inc.php b/importexport/inc/class.bodefinitions.inc.php index 77221d0200..d37dbbf04a 100644 --- a/importexport/inc/class.bodefinitions.inc.php +++ b/importexport/inc/class.bodefinitions.inc.php @@ -70,6 +70,17 @@ class bodefinitions { } } + /** + * Save a definition + * + * @param definition $definition + */ + public function save(Array $data) { + $definition = new definition(); + $definition->set_record($data); + $definition->save($data['definition_id']); + } + /** * checkes if user if permitted to access given definition * diff --git a/importexport/inc/class.iface_import_plugin.inc.php b/importexport/inc/class.iface_import_plugin.inc.php index a0744129cc..a168af8bea 100644 --- a/importexport/inc/class.iface_import_plugin.inc.php +++ b/importexport/inc/class.iface_import_plugin.inc.php @@ -31,6 +31,7 @@ interface iface_import_plugin { * * @param stram $_stram * @param definition $_definition + * @return int number of successful imports */ public function import( $_stream, definition $_definition ); @@ -76,5 +77,15 @@ interface iface_import_plugin { */ public function get_selectors_etpl(); + /** + * Returns errors that were encountered during importing + * Maximum of one error message per record, but you can concatenate them if you need to + * + * @return Array ( + * record_# => error message + * ) + */ + public function get_errors(); + } // end of iface_export_plugin ?> diff --git a/importexport/inc/class.import_export_helper_functions.inc.php b/importexport/inc/class.import_export_helper_functions.inc.php index b2cfe66684..4de42606bf 100755 --- a/importexport/inc/class.import_export_helper_functions.inc.php +++ b/importexport/inc/class.import_export_helper_functions.inc.php @@ -184,7 +184,7 @@ class import_export_helper_functions { $CntlPre = '|TC{'; // Filter all cntl-chars \x01-\x1f and trim $CntlnCLPre = '|TCnCL{'; // Like |C{ but allowes CR and LF $INE = '|INE{'; // Only insert if stuff in ^^ is not empty - + foreach ( $_conversion as $idx => $conversion_string ) { if ( empty( $conversion_string ) ) continue; @@ -221,7 +221,7 @@ class import_export_helper_functions { } // clean each field $val = preg_replace_callback("/(\|T\{|\|TC\{|\|TCnCL\{|\|INE\{)(.*)\}/", array( self, 'strclean'), $val ); - + $_record[$idx] = $val; } return $_record; @@ -249,7 +249,6 @@ class import_export_helper_functions { } private static function strclean( $_matches ) { - //print_r($_matches); switch( $_matches[1] ) { case '|T{' : return trim( $_matches[2] ); case '|TC{' : return trim( preg_replace( '/[\x01-\x1F]+/', '', $_matches[2] ) ); diff --git a/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php b/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php index ea5f1b35d9..7e5961a235 100644 --- a/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php +++ b/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php @@ -62,6 +62,9 @@ class importexport_admin_prefs_sidebox_hooks 'Define {im|ex}ports' => $GLOBALS['egw']->link('/index.php',array( 'menuaction' => 'importexport.uidefinitions.index', )), + 'Schedule' => $GLOBALS['egw']->link('/index.php', array( + 'menuaction' => 'importexport.importexport_schedule_ui.index' + )), ); if ($location == 'admin') { @@ -114,4 +117,4 @@ class importexport_admin_prefs_sidebox_hooks $GLOBALS['egw']->preferences->save_repository(False,'default'); } } -} \ No newline at end of file +} diff --git a/importexport/inc/class.uidefinitions.inc.php b/importexport/inc/class.uidefinitions.inc.php index a6c648a875..14eacbc923 100644 --- a/importexport/inc/class.uidefinitions.inc.php +++ b/importexport/inc/class.uidefinitions.inc.php @@ -19,7 +19,7 @@ require_once('class.bodefinitions.inc.php'); */ class uidefinitions { - const _debug = true; + const _debug = false; const _appname = 'importexport'; @@ -64,12 +64,12 @@ class uidefinitions $this->steps = array( 'wizzard_step10' => lang('Choose an application'), 'wizzard_step20' => lang('Choose a plugin'), - 'wizzard_step80' => lang('Which useres are allowed for this definition'), + 'wizzard_step80' => lang('Which users are allowed to use this definition'), 'wizzard_step90' => lang('Choose a name for this definition'), 'wizzard_finish' => '', ); - //register plugins (depricated) - //$this->plugins = bodefinitions::plugins(); + //register plugins + $this->plugins = import_export_helper_functions::get_plugins(); } /** @@ -134,7 +134,7 @@ class uidefinitions } $definition = array('name' => $_definition); $bodefinitions = new bodefinitions(); - $bodefinitions->read($definition); + $definition = $bodefinitions->read($definition); $definition['edit'] = true; $this->wizzard($definition); } @@ -160,8 +160,9 @@ class uidefinitions if($content['plugin'] && $content['application']) { // we need to deal with the wizzard object if exists - if (file_exists(EGW_SERVER_ROOT . '/'. $content['application'].'/inc/class.wizzard_'. $content['plugin'].'.inc.php')) + if (file_exists(EGW_SERVER_ROOT . '/'. $content['application'].'/importexport/class.wizzard_'. $content['plugin'].'.inc.php')) { + require_once(EGW_SERVER_ROOT . '/'. $content['application'].'/importexport/class.wizzard_'. $content['plugin'].'.inc.php'); $wizzard_plugin = 'wizzard_'.$content['plugin']; } else @@ -169,7 +170,10 @@ class uidefinitions $wizzard_plugin = $content['plugin']; } $this->plugin = is_object($GLOBALS['egw']->$wizzard_plugin) ? $GLOBALS['egw']->$wizzard_plugin : new $wizzard_plugin; - if(!is_object($GLOBALS['egw']->uidefinitions)) $GLOBALS['egw']->uidefinitions =& $this; + + // Global object needs to be the same, or references to plugin don't work + if(!is_object($GLOBALS['egw']->uidefinitions) || $GLOBALS['egw']->uidefinitions !== $this) + $GLOBALS['egw']->uidefinitions =& $this; } // deal with buttons even if we are not on ajax if(isset($content['button']) && array_search('pressed',$content['button']) === false && count($content['button']) == 1) @@ -273,7 +277,7 @@ class uidefinitions $plugin_definition = $this->plugins[$content['application']][$content['plugin']]['definition']; if($plugin_definition) $this->plugin = new $plugin_definition; }*/ - if(is_object($this->plugin)) + if(is_object($this->plugin) && is_array($this->plugin->steps)) { $steps = array_merge($this->steps,$this->plugin->steps); $steps = array_flip($steps); asort($steps); $steps = array_flip($steps); @@ -331,7 +335,7 @@ class uidefinitions switch (array_search('pressed', $content['button'])) { case 'next': - $content['type'] = $this->plugin->plugin_info['type']; + $content['type'] = $this->plugin instanceof iface_import_plugin ? 'import' : 'export'; return $this->get_step($content['step'],1); case 'previous' : unset ($content['plugin']); @@ -347,7 +351,11 @@ class uidefinitions else { $content['msg'] = $this->steps['wizzard_step20']; - foreach ($this->plugins[$content['application']] as $plugin => $info) $sel_options['plugin'][$plugin] = $info['name']; + foreach ($this->plugins[$content['application']] as $type => $plugins) { + foreach($plugins as $plugin => $name) { + $sel_options['plugin'][$plugin] = $name; + } + } $content['step'] = 'wizzard_step20'; $preserv = $content; unset ($preserv['button']); @@ -427,6 +435,11 @@ class uidefinitions function wizzard_finish(&$content) { if(self::_debug) error_log('importexport.uidefinitions::wizzard_finish->$content '.print_r($content,true)); + // Take out some UI leavings + unset($content['msg']); + unset($content['step']); + unset($content['button']); + $bodefinitions = new bodefinitions(); $bodefinitions->save($content); // This message is displayed if browser cant close window diff --git a/importexport/inc/class.uiexport.inc.php b/importexport/inc/class.uiexport.inc.php index 211e6a46c1..87cbbd68c8 100644 --- a/importexport/inc/class.uiexport.inc.php +++ b/importexport/inc/class.uiexport.inc.php @@ -57,7 +57,8 @@ class uiexport { if(empty($_content)) { $et = new etemplate(self::_appname. '.export_dialog'); $_appname = $_GET['appname']; - $_definition =$_GET['definition'] = 'expert'; + //$_definition = $_GET['definition'] = 'expert'; + $_definition = $_GET['definition']; $_plugin = $_GET['plugin']; // NOTE: definition _must_ be 'expert' if for plugin to be used! $_selection = $_GET['selection']; @@ -67,6 +68,7 @@ class uiexport { $content['appname'] = $_appname; $preserv['appname'] = $_appname; $readonlys['appname'] = true; + $this->js->set_onload("export_dialog.appname = '$_appname';"); $this->js->set_onload("set_style_by_class('tr','select_appname','display','none');"); // fill definitions @@ -84,8 +86,9 @@ class uiexport { } unset($definitions); $sel_options['definition']['expert'] = lang('Expert options'); + - if(isset($_definition) && array_key_exists($_definition,$sel_options)) { + if(isset($_definition) && array_key_exists($_definition,$sel_options['definition'])) { $content['definition'] = $_definition; } else { @@ -98,16 +101,17 @@ class uiexport { $sel_options['plugin'] = $this->export_plugins[$_appname]['export']; // show definitions or plugins in ui? - if($content['defintion'] == 'expert') { + if($content['definition'] == 'expert') { if(isset($_plugin) && array_key_exists($_plugin,$sel_options['plugin'])) { $content['plugin'] = $_plugin; $selected_plugin = $_plugin; - error_log('hallo'); } else { - $plugins_classnames = array_keys($plugins); +/* + $plugins_classnames = array_keys($sel_options['plugin']); $selected_plugin = $plugins_classnames[0]; $sel_options['plugin'] = $plugins; +*/ } $this->js->set_onload("set_style_by_class('tr','select_definition','display','none');"); } @@ -120,15 +124,17 @@ class uiexport { } // handle selector - //$plugin_object = new $selected_plugin; - - //$content['description'] = $plugin_object->get_description(); - - // fill options tab - // TODO: do we need all options templates online? - // NO, we can manipulate the session array of template id on xajax request - // however, there might be other solutions... we solve this in 1.3 - //$content['plugin_options_html'] = $plugin_object->get_options_etpl(); + if($selected_plugin) { + $plugin_object = new $selected_plugin; + + $content['description'] = $plugin_object->get_description(); + + // fill options tab + // TODO: do we need all options templates online? + // NO, we can manipulate the session array of template id on xajax request + // however, there might be other solutions... we solve this in 1.3 + $content['plugin_options_html'] = $plugin_object->get_options_etpl(); + } // fill selection tab if ($_selection) { @@ -169,7 +175,7 @@ class uiexport { //error_log(__LINE__.__FILE__.'$_content: '.print_r($_content,true)); $response = new xajaxResponse(); - if ($_content['defintion'] == 'expert') { + if ($_content['definition'] == 'expert') { $definition = new definition(); $definition->definition_id = $_content['definition_id'] ? $_content['definition_id'] : ''; $definition->name = $_content['name'] ? $_content['name'] : ''; @@ -247,11 +253,52 @@ class uiexport { return $et->exec(self::_appname. '.uiexport.export_dialog',$content,$sel_options,$readonlys,$preserv,2); } - public function ajax_get_plugins($_appname) { - $response = new xajaxResponse(); + public function ajax_get_definitions($_appname, xajaxResponse &$response = null) { + if(is_null($response)) { + $response = new xajaxResponse(); + } else { + $no_return = true; + } + if (!$_appname) { + $response->addScript("set_style_by_class('tr','select_definition','display','none');"); + return $no_return ? '' : $response->getXML(); + } + + $definitions = new bodefinitions(array( + 'type' => 'export', + 'application' => $_appname + )); + foreach ((array)$definitions->get_definitions() as $identifier) { + $definition = new definition($identifier); + if ($title = $definition->get_title()) { + if (!$selected_plugin) $selected_plugin = $plugin; + $sel_options['definition'] .= ''; + } + unset($definition); + } + unset($definitions); + $sel_options['definition'] .= '