massive improvements for the imports

This commit is contained in:
Cornelius Weiß 2007-06-07 22:08:38 +00:00
parent 92553ea37e
commit b4b6d5abef
12 changed files with 394 additions and 239 deletions

View File

@ -1,25 +1,47 @@
=importexport= = importexport =
Importexport is a framework for egroupware to handle imports and exports. Importexport is a framework for egroupware to handle imports and exports.
The idea behind importexport is to have a common userinterface in all apps regarding The idea behind importexport is to have a common userinterface in all apps
import and export stuff AND to have common backends whitch handle the stuff. regarding import and export stuff AND to have common backends whitch
Importexport can nothing without the plugins of the applications. handle the stuff. Importexport can nothing without the plugins of the
applications and its specific definitions.
== plugins ==
Attending importeport framework with you application is pretty easy. Attending importeport framework with you application is pretty easy.
You just need to have your plugins in files which start with You just need to have your plugins in files which start with
class.import_<type> or class.import_<name> or
class.export_<type> class.export_<name>
in in
EGW_INCLUDE_ROOT/YourApp/inc/ EGW_INCLUDE_ROOT/YourApp/importexport/
These pulugins only need to implement the corresponding interface
EGW_INCLUDE_ROOT/importexport/inc/class.iface_import_plugin.inc.php or
EGW_INCLUDE_ROOT/importexport/inc/class.iface_export_plugin.inc.php
Thats all, pretty easy, isn't it?
== definitions == == definitions ==
The bases of all imports and exports is the '''definition'''. The bases of all imports and exports is the '''definition'''.
A definition defines all nessesary parameters to perform the desired action. A definition defines all nessesary parameters to perform the desired action.
Moreover definitions can be stored and thus the same import / export can be redone Moreover definitions can be stored and thus the same import / export can be redone
by loading the definition. Definitions are also reachable by the importexport by loading the definition. Definitions are also reachable by the importexport
'''command line interface'''. '''command line interface'''.
An important point is, that the ACLs for import/export actions are given by the definitions.
That means, that your plugin can not work w.o. a definition. However, your plugin don't
need to parse that definition. This is up to you.
Definitions can be created in admin->importexport->define{im|ex}ports. They are stored
in the databasae but could be {im|ex}ported itselve.
Definitions (as xml files) residing in the folder <yourapp/importexport/definitions>
will be imported at apps installation time automatically.
== import ==
== export == == export ==
Starting an export is as easy as just putting a button in your app with: Starting an export is as easy as just putting a button in your app with:
onClick="importexport.uiexport.export_dialog&appname=<appname>&have_selection=<{true|false}>" onClick="importexport.uiexport.export_dialog&appname=<appname>&have_selection=<{true|false}>"

View File

@ -15,12 +15,12 @@
$usage = "usage: $usage = "usage:
--definition <name of definition> --definition <name of definition>
--file <name of file> --file <name of file>
--charset <charset>
--user <eGW username> --user <eGW username>
--password <password for user> --password <password for user>
--domain <domain name> \n"; --domain <domain name> \n";
if (php_sapi_name() != 'cli') if (php_sapi_name() != 'cli') {
{
die('This script only runs form command line'); die('This script only runs form command line');
} }
@ -48,6 +48,7 @@
$long_opts = array( $long_opts = array(
'definition=', 'definition=',
'file=', 'file=',
'charset=',
'user=', 'user=',
'password=', 'password=',
'domain=' 'domain='
@ -67,13 +68,14 @@
} }
$domain = 'default'; $domain = 'default';
foreach ($options[0] as $option) foreach ($options[0] as $option) {
{ switch ($option[0]) {
switch ($option[0])
{
case '--file' : case '--file' :
$file = $option[1]; $file = $option[1];
break; break;
case '--charset' :
$charset = $option[1];
break;
case '--definition' : case '--definition' :
$definition = $option[1]; $definition = $option[1];
break; break;
@ -92,11 +94,14 @@
} }
} }
// check file // check file
if (!$user || !$password) if ( !$user || !$password ) {
{
fwrite(STDERR,'importexport_cli: You have to supply a username / password'."\n".$usage); fwrite(STDERR,'importexport_cli: You have to supply a username / password'."\n".$usage);
exit(INVALID_OPTION); exit(INVALID_OPTION);
} }
if ( !$charset ) {
fwrite(STDERR,'importexport_cli: You have to supply a valid charset'."\n".$usage);
exit(INVALID_OPTION);
}
$GLOBALS['egw_info']['flags'] = array( $GLOBALS['egw_info']['flags'] = array(
'disable_Template_class' => True, 'disable_Template_class' => True,
@ -134,7 +139,7 @@
exit(INVALID_OPTION); exit(INVALID_OPTION);
} }
require_once('./inc/class.definition.inc.php'); require_once('inc/class.definition.inc.php');
try { try {
$definition = new definition($definition); $definition = new definition($definition);
} }
@ -143,10 +148,12 @@
exit(INVALID_OPTION); exit(INVALID_OPTION);
} }
require_once("$path_to_egroupware/$definition->application/inc/class.$definition->plugin.inc.php"); require_once("$path_to_egroupware/$definition->application/importexport/class.$definition->plugin.inc.php");
$po = new $definition->plugin; $po = new $definition->plugin;
$type = $definition->type; $type = $definition->type;
$po->$type($definition,array('file' => $file));
$resource = fopen( $file, 'r' );
$po->$type( $resource, $charset, $definition );
$GLOBALS['egw']->common->phpgw_exit(); $GLOBALS['egw']->common->phpgw_exit();

View File

@ -0,0 +1,113 @@
<?php
/**
* eGroupWare
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package importexport
* @link http://www.egroupware.org
* @author Cornelius Weiss <nelius@cwtech.de>
* @copyright Cornelius Weiss <nelius@cwtech.de>
* @version $Id: $
*/
/**
* class arrayxml
* easy to use array2xml and xml2array functions. Presumably this is the n+1
* class of this kind out there, but i wasn't able to find a wokring one...
*
* @abstract PHP allowes array keys to be numeric while XML prohibits this.
* Therefore the XML structur of this class is a bit uncommon but nessesary!
* @todo deal with other types like objects
* @static only namespace here
*/
class arrayxml {
/**
* converts a php array to an xml string
*
* @static
* @param mixed $_data
* @param string $_name
* @param DOMElement $_node
* @return string XML string
*/
public static function array2xml ( $_data, $_name = 'root', $_node=null ) {
$returnXML = false;
if ( $_node === null ) {
$_node = new DOMDocument( '1.0', 'utf-8' );
$_node->formatOutput = true;
$returnXML = true;
}
$datatype = gettype( $_data );
switch ( $datatype ) {
case 'array' :
$subnode = new DOMElement( 'entry' );
$_node->appendChild( $subnode );
$subnode->setAttribute( 'type', $datatype );
$subnode->setAttribute( 'name' , $_name );
foreach ( $_data as $ikey => $ivalue ) {
self::array2xml( $ivalue, $ikey, $subnode );
}
break;
default :
switch ( $datatype ) {
case 'boolean' :
$data = $_data !== false ? 'TRUE' : 'FALSE';
break;
default:
$data = &$_data;
}
$subnode = new DOMElement( 'entry' , $data );
$_node->appendChild( $subnode );
$subnode->setAttribute( 'type', $datatype );
$subnode->setAttribute( 'name' , $_name );
break;
}
return $returnXML ? $_node->saveXML() : '';
}
/**
* converts XML string into php array
*
* @static
* @param string $_xml
* @return array
*/
public static function xml2array( $_xml ) {
if ( $_xml instanceof DOMElement ) {
$n = &$_xml;
} else {
$n = new DOMDocument;
$n->loadXML($_xml);
}
$xml_array = array();
foreach($n->childNodes as $nc) {
if ( $nc->nodeType != XML_ELEMENT_NODE ) continue;
$name = $nc->attributes->getNamedItem('name')->nodeValue;
$type = $nc->attributes->getNamedItem('type')->nodeValue;
//echo $nc->nodeType. "(length ): ". $nc->nodeName. " => ". $nc->nodeValue. "; Attriubtes: name=$name, type=$type \n ";
if( $nc->childNodes->length >= 2) {
$xml_array[$name] = self::xml2array($nc);
} else {
switch ( $type ) {
case 'boolean' :
$value = utf8_decode($nc->nodeValue) == 'FALSE' ? false : true;
break;
default :
$value = utf8_decode($nc->nodeValue);
}
$xml_array[$name] = $value;
}
}
return $xml_array;
}
}
?>

View File

@ -11,6 +11,7 @@
*/ */
require_once(EGW_INCLUDE_ROOT. '/importexport/inc/class.definition.inc.php'); require_once(EGW_INCLUDE_ROOT. '/importexport/inc/class.definition.inc.php');
require_once(EGW_INCLUDE_ROOT. '/importexport/inc/class.arrayxml.inc.php');
require_once(EGW_INCLUDE_ROOT.'/etemplate/inc/class.so_sql.inc.php'); require_once(EGW_INCLUDE_ROOT.'/etemplate/inc/class.so_sql.inc.php');
/** bo to define {im|ex}ports /** bo to define {im|ex}ports
@ -41,6 +42,14 @@ class bodefinitions {
} }
} }
/**
* gets definitions as raw data.
* well, we need a god idea for egw_record pools...
* its not a god idea to make a definition object of each
* at the moment, as each defintion holds an so_sql instance.
*
* @return array
*/
public function get_definitions() { public function get_definitions() {
return $this->definitions; return $this->definitions;
} }
@ -48,11 +57,11 @@ class bodefinitions {
/** /**
* reads a definition from database * reads a definition from database
* *
* @deprecated see class.definition.inc.php
* @param mixed &$definition * @param mixed &$definition
* @return bool success or not * @return bool success or not
*/ */
public function read(&$definition) public function read(&$definition) {
{
if(is_int($definition)) $definition = array('definition_id' => $definition); if(is_int($definition)) $definition = array('definition_id' => $definition);
elseif(is_string($definition)) $definition = array('name' => $definition); elseif(is_string($definition)) $definition = array('name' => $definition);
if(!$definition = $this->so_sql->read($definition)) return false; if(!$definition = $this->so_sql->read($definition)) return false;
@ -61,45 +70,14 @@ class bodefinitions {
return true; return true;
} }
public function save($content) /**
{ * deletes a defintion
$plugin = $content['plugin']; *
if (!$plugin) return false; * @param array $keys
*/
$definition = array_intersect_key($content,array_flip($this->so_sql->db_cols)); public function delete($keys) {
if(is_object($this->plugin) && $this->plugin->plugin_info['plugin'] == $plugin)
{
$plugin_options = array_intersect_key($content,array_flip($this->plugin->plugin_options));
}
else
{
// we come eg. from definition import
$file = EGW_SERVER_ROOT . SEP . $definition['application'] . SEP . 'inc' . SEP . 'importexport'. SEP . 'class.'.$definition['plugin'].'.inc.php';
if (is_file($file))
{
@include_once($file);
$obj = new $plugin;
$plugin_options = array_intersect_key($content,array_flip($obj->plugin_options));
unset($obj);
}
else
{
foreach ($this->so_sql->db_cols as $col) unset($content[$col]);
$plugin_options = $content;
}
}
$definition['plugin_options'] = serialize($plugin_options);
$this->so_sql->data = $definition;
//print_r($definition);
return $this->so_sql->save();
}
public function delete($keys)
{
$this->so_sql->delete(array('definition_id' => $keys)); $this->so_sql->delete(array('definition_id' => $keys));
// clear private cach // clear private cache
foreach ($keys as $key) { foreach ($keys as $key) {
unset($this->definitions[array_search($key,$this->definitions)]); unset($this->definitions[array_search($key,$this->definitions)]);
} }
@ -126,36 +104,6 @@ class bodefinitions {
return in_array($this_user_id,$alluser) ? true : false; return in_array($this_user_id,$alluser) ? true : false;
} }
/**
* searches and registers plugins from all apps
*
* @deprecated see import_export_helperfunctions::get_plugins
* @return array $info info about existing plugins
*/
static public function plugins()
{
if (!key_exists('apps',$GLOBALS['egw_info'])) return false;
foreach (array_keys($GLOBALS['egw_info']['apps']) as $appname)
{
$dir = EGW_INCLUDE_ROOT . "/$appname/inc";
if(!$d = @opendir($dir)) continue;
while (false !== ($file = readdir($d)))
{
//echo $file."\n";
$pnparts = explode('.',$file);
if(!is_file($file = "$dir/$file") || substr($pnparts[1],0,7) != 'wizzard' || $pnparts[count($pnparts)-1] != 'php') continue;
$plugin_classname = $pnparts[1];
include_once($file);
if (!is_object($GLOBALS['egw']->$plugin_classname))
$GLOBALS['egw']->$plugin_classname = new $plugin_classname;
$info[$appname][$GLOBALS['egw']->$plugin_classname->plugin_info['plugin']] = $GLOBALS['egw']->$plugin_classname->plugin_info;
}
closedir($d);
}
return $info;
}
/** /**
* exports definitions * exports definitions
* *
@ -169,41 +117,53 @@ class bodefinitions {
'entries' => count($keys), 'entries' => count($keys),
)); ));
foreach ($keys as $definition_id) $export_data['definitions'] = array();
{ foreach ($keys as $definition_id) {
$definition = array('definition_id' => $definition_id); $definition = new definition( $definition_id );
$this->read($definition); $export_data['definitions'][$definition->name] = $definition->get_record_array();
unset($definition['definition_id']); unset($export_data['definitions'][$definition->name]['definition_id']);
$export_data[$definition['name']] = $definition; unset($definition);
} }
/* This is no fun as import -> export cycle in xmltools results in different datas :-(
$xml =& CreateObject('etemplate.xmltool','root');
$xml->import_var('importexport.definitions', $export_data);
$xml_data = $xml->export_xml();
we export serialised arrays in the meantime
$xml = new arrayxml();
return $xml->array2xml($export_data, 'importExportDefinitions');
}
/**
* imports definitions from file
*
* @param string $import_file
* @throws Exeption
* @return void
*/ */
return serialize($export_data); public static function import( $_import_file )
{
if ( !is_file( $_import_file ) ) {
throw new Exception("'$_import_file' is not a valid file" );
} }
public function import($import_file) $data = arrayxml::xml2array( file_get_contents( $_import_file ) );
{
// read given file and check if its a valid definition $metainfo = $data['importExportDefinitions']['metainfo'];
if (!is_file($import_file['tmp_name'])) return false; $definitions = $data['importExportDefinitions']['definitions'];
$f = fopen($import_file['tmp_name'],'r'); unset ( $data );
$data = fread($f,100000);
fclose($f);
if (($data = unserialize($data)) === false) return false;
$metainfo = $data['metainfo'];
unset($data['metainfo']);
// convert charset into internal used charset // convert charset into internal used charset
$data = $GLOBALS['egw']->translation->convert($data,$metainfo['charset'],$GLOBALS['egw']->translation->charset()); $definitions = $GLOBALS['egw']->translation->convert(
$definitions,
$metainfo['charset'],
$GLOBALS['egw']->translation->charset()
);
// save definition(s) into internal table // save definition(s) into internal table
foreach ($data as $name => $definition) foreach ( $definitions as $name => $definition_data )
{ {
$this->save($definition); $definition = new definition( $definition_data['name'] );
$definition_id = $definition->get_identifier() ? $definition->get_identifier() : NULL;
$definition->set_record( $definition_data );
$definition->save( $definition_id );
} }
} }

View File

@ -33,7 +33,7 @@ class definition implements iface_egw_record {
'plugin' => 'string', 'plugin' => 'string',
'type' => 'string', 'type' => 'string',
'allowed_users' => 'array', 'allowed_users' => 'array',
'options' => 'array', 'plugin_options' => 'array',
'owner' => 'int', 'owner' => 'int',
'description' => 'string', 'description' => 'string',
); );
@ -80,15 +80,13 @@ class definition implements iface_egw_record {
if (is_string($_identifier) && strlen($_identifier) > 3) $_identifier = $this->name2identifier($_identifier); if (is_string($_identifier) && strlen($_identifier) > 3) $_identifier = $this->name2identifier($_identifier);
if ((int)$_identifier != 0) { if ((int)$_identifier != 0) {
$this->so_sql->read(array('definition_id' => $_identifier)); $this->definition = $this->so_sql->read(array('definition_id' => $_identifier));
if (empty($this->so_sql->data)) { if ( empty( $this->definition ) ) {
throw new Exception('Error: No such definition with identifier :"'.$_identifier.'"!'); throw new Exception('Error: No such definition with identifier :"'.$_identifier.'"!');
} }
if (!(in_array($this->user,$this->get_allowed_users()) || $this->get_owner() == $this->user || $this->is_admin)) { if ( !( in_array( $this->user, $this->get_allowed_users() ) || $this->definition['owner'] == $this->user || $this->is_admin)) {
throw new Exception('Error: User "'.$this->user.'" is not permitted to get definition with identifier "'.$_identifier.'"!'); throw new Exception('Error: User "'.$this->user.'" is not permitted to get definition with identifier "'.$_identifier.'"!');
$this->definition = $this->so_sql->data;
} }
$this->definition = $this->so_sql->data;
} }
} }
@ -98,7 +96,7 @@ class definition implements iface_egw_record {
* @param string $_name * @param string $_name
* @return int * @return int
*/ */
private function name2identifier($_name) { private function name2identifier( $_name ) {
$identifiers = $this->so_sql->search(array('name' => $_name),true); $identifiers = $this->so_sql->search(array('name' => $_name),true);
if (isset($identifiers[1])) { if (isset($identifiers[1])) {
throw new Exception('Error: Definition: "'.$_name. '" is not unique! Can\'t convert to identifier'); throw new Exception('Error: Definition: "'.$_name. '" is not unique! Can\'t convert to identifier');
@ -113,7 +111,7 @@ class definition implements iface_egw_record {
switch ($_attribute_name) { switch ($_attribute_name) {
case 'allowed_users' : case 'allowed_users' :
return $this->get_allowed_users(); return $this->get_allowed_users();
case 'options' : case 'plugin_options' :
return $this->get_options(); return $this->get_options();
default : default :
return $this->definition[$_attribute_name]; return $this->definition[$_attribute_name];
@ -127,7 +125,7 @@ class definition implements iface_egw_record {
switch ($_attribute_name) { switch ($_attribute_name) {
case 'allowed_users' : case 'allowed_users' :
return $this->set_allowed_users($_data); return $this->set_allowed_users($_data);
case 'options' : case 'plugin_options' :
return $this->set_options($_data); return $this->set_options($_data);
default : default :
$this->definition[$_attribute_name] = $_data; $this->definition[$_attribute_name] = $_data;
@ -149,7 +147,7 @@ class definition implements iface_egw_record {
* *
* @param array $_allowed_users * @param array $_allowed_users
*/ */
private function set_allowed_users($_allowed_users) { private function set_allowed_users( $_allowed_users ) {
$this->definition['allowed_users'] = implode(',',(array)$_allowed_users); $this->definition['allowed_users'] = implode(',',(array)$_allowed_users);
} }
@ -159,12 +157,7 @@ class definition implements iface_egw_record {
* @return array * @return array
*/ */
private function get_options() { private function get_options() {
// oh compat funct to be removed! return unserialize($this->definition['plugin_options']);
if(array_key_exists('plugin_options',$this->definition)) {
$this->definition['options'] = $this->definition['plugin_options'];
unset($this->definition['plugin_options']);
}
return unserialize($this->definition['options']);
} }
/** /**
@ -172,8 +165,8 @@ class definition implements iface_egw_record {
* *
* @param array $options * @param array $options
*/ */
private function set_options(array $_options) { private function set_options(array $_plugin_options) {
$this->definition['options'] = serialize($_options); $this->definition['plugin_options'] = serialize( $_plugin_options );
} }
/** /**
@ -187,7 +180,7 @@ class definition implements iface_egw_record {
public function get_record_array() { public function get_record_array() {
$definition = $this->definition; $definition = $this->definition;
$definition['allowed_users'] = $this->get_allowed_users(); $definition['allowed_users'] = $this->get_allowed_users();
$definition['options'] = $this->get_options(); $definition['plugin_options'] = $this->get_options();
return $definition; return $definition;
} }
@ -205,8 +198,20 @@ class definition implements iface_egw_record {
* *
* @return void * @return void
*/ */
public function set_record(array $_record) { public function set_record( array $_record ) {
$this->definition = $_record; $this->definition = array_intersect_key( $_record, $this->attributes );
// anything which is not an attribute is perhaps a plugin_option.
// If not, it gets whiped out on save time.
foreach ( $_record as $attribute => $value) {
if ( !array_key_exists( $attribute, $this->attributes ) ) {
$this->definition['plugin_options'][$attribute] = $value;
}
}
// convert plugin_options into internal representation
$this->set_allowed_users($this->definition['allowed_users']);
$this->set_options($this->definition['plugin_options']);
} }
/** /**
@ -225,11 +230,13 @@ class definition implements iface_egw_record {
* @return string identifier * @return string identifier
*/ */
public function save ( $_dst_identifier ) { public function save ( $_dst_identifier ) {
if ($owner = $this->get_owner() && $owner != $this->user && !$this->is_admin) { if ( strlen($this->definition['name']) < 3 ) {
throw ('Error: User '. $this->user. ' is not allowed to save this definition!'); throw new Exception('Error: Can\'t save definition, no valid name given!');
} }
if ($this->so_sql->save($_dst_identifier)) {
throw('Error: so_sql was not able to save definition: '.$this->get_identifier()); $this->so_sql->data = $this->definition;
if ($this->so_sql->save( array( 'definition_id' => $_dst_identifier ))) {
throw new Exception('Error: so_sql was not able to save definition: '.$this->get_identifier());
} }
return $this->definition['definition_id']; return $this->definition['definition_id'];
} }

View File

@ -10,14 +10,12 @@
* @version $Id$ * @version $Id$
*/ */
//require_once(EGW_INCLUDE_ROOT. '/importexport/inc/class.iface_egw_record.inc.php');
/** /**
* class iface_export_plugin * class iface_export_plugin
* This a the abstract interface for an export plugin of importexport * This a the abstract interface for an export plugin of importexport
* *
* You need to implement this class in * You need to implement this class in
* EGW_INCLUDE_ROOT/appname/inc/class.export_<type>.inc.php * EGW_INCLUDE_ROOT/appname/inc/importexport/class.export_<type>.inc.php
* to attend the importexport framwork with your export. * to attend the importexport framwork with your export.
* *
* NOTE: This is an easy interface, cause plugins live in theire own * NOTE: This is an easy interface, cause plugins live in theire own

View File

@ -0,0 +1,79 @@
<?php
/**
* eGroupWare
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package importexport
* @link http://www.egroupware.org
* @author Cornelius Weiss <nelius@cwtech.de>
* @copyright Cornelius Weiss <nelius@cwtech.de>
* @version $Id:$
*/
/**
* class iface_import_plugin
* This a the abstract interface for an import plugin of importexport
*
* You need to implement this class in
* EGW_INCLUDE_ROOT/appname/inc/importexport/class.import_<type>.inc.php
* to attend the importexport framwork with your export.
*
* NOTE: This is an easy interface, cause plugins live in theire own
* space. Means that they are responsible for generating a defintion AND
* working on that definition.
* So this interface just garanties the interaction with userinterfaces. It
* has nothing to do with datatypes.
*/
interface iface_import_plugin {
/**
* imports entries according to given definition object.
*
* @param definition $_definition
*/
public function import($_stream, $_charset, definition $_definition);
/**
* returns translated name of plugin
*
* @return string name
*/
public static function get_name();
/**
* returns translated (user) description of plugin
*
* @return string descriprion
*/
public static function get_description();
/**
* retruns file suffix(s) plugin can handle (e.g. csv)
*
* @return string suffix (comma seperated)
*/
public static function get_filesuffix();
/**
* return etemplate components for options.
* @abstract We can't deal with etemplate objects here, as an uietemplate
* objects itself are scipt orientated and not "dialog objects"
*
* @return array (
* name => string,
* content => array,
* sel_options => array,
* preserv => array,
* )
*/
public function get_options_etpl();
/**
* returns etemplate name for slectors of this plugin
*
* @return string etemplate name
*/
public function get_selectors_etpl();
} // end of iface_export_plugin
?>

View File

@ -24,16 +24,10 @@ class import_csv implements iface_import_record { //, Iterator {
const csv_max_linelength = 8000; const csv_max_linelength = 8000;
/** Aggregations: */
/** Compositions: */
/** /**
* @static import_export_helper_functions * @static import_export_helper_functions
*/ */
/*** Attributes: ***/
/** /**
* array with field mapping in form column number => new_field_name * array with field mapping in form column number => new_field_name
* @access public * @access public
@ -235,7 +229,7 @@ class import_csv implements iface_import_record { //, Iterator {
foreach ($this->mapping as $cvs_idx => $new_idx) { foreach ($this->mapping as $cvs_idx => $new_idx) {
$this->record[$new_idx] = $record[$cvs_idx]; $this->record[$new_idx] = $record[$cvs_idx];
} }
return; return true;
} // end of member function do_fieldmapping } // end of member function do_fieldmapping
/** /**

View File

@ -16,14 +16,7 @@
* class import_export_helper_functions (only static methods) * class import_export_helper_functions (only static methods)
* use import_export_helper_functions::method * use import_export_helper_functions::method
*/ */
class import_export_helper_functions class import_export_helper_functions {
{
/** Aggregations: */
/** Compositions: */
/*** Attributes: ***/
/** /**
* nothing to construct here, only static functions! * nothing to construct here, only static functions!
@ -236,13 +229,13 @@ class import_export_helper_functions
* @param string $_appname {<appname> | all} * @param string $_appname {<appname> | all}
* @return array(<appname> => array( <type> => array(<plugin> => <title>))) * @return array(<appname> => array( <type> => array(<plugin> => <title>)))
*/ */
public static function get_plugins($_appname, $_type){ public static function get_plugins( $_appname = 'all', $_type = 'all' ) {
$appnames = $_appname == 'all' ? array_keys($GLOBALS['egw_info']['apps']) : (array)$_appname; $appnames = $_appname == 'all' ? array_keys($GLOBALS['egw_info']['apps']) : (array)$_appname;
$types = $_types == 'all' ? array('import','export') : (array)$_type; $types = $_type == 'all' ? array('import','export') : (array)$_type;
$plugins = array(); $plugins = array();
foreach ($appnames as $appname) { foreach ($appnames as $appname) {
$appdir = EGW_INCLUDE_ROOT. "/$appname/inc"; $appdir = EGW_INCLUDE_ROOT. "/$appname/importexport";
if(!is_dir($appdir)) continue; if(!is_dir($appdir)) continue;
$d = dir($appdir); $d = dir($appdir);
@ -252,7 +245,7 @@ class import_export_helper_functions
$file = $appdir. '/'. $entry; $file = $appdir. '/'. $entry;
foreach ($types as $type) { foreach ($types as $type) {
if(!is_file($file) || substr($classname,0,7) != $type.'_' || $extension != 'php') continue; if( !is_file($file) || substr($classname,0,7) != $type.'_' || $extension != 'php' ) continue;
require_once($file); require_once($file);
try { try {
@ -269,6 +262,7 @@ class import_export_helper_functions
} }
$d->close(); $d->close();
} }
//error_log(__CLASS__.__FUNCTION__.print_r($plugins,true));
return $plugins; return $plugins;
} }
@ -282,5 +276,8 @@ class import_export_helper_functions
return array_keys(self::get_plugins('all',$_type)); return array_keys(self::get_plugins('all',$_type));
} }
public static function guess_filetype( $_file ) {
}
} // end of import_export_helper_functions } // end of import_export_helper_functions
?> ?>

View File

@ -13,11 +13,6 @@
require_once(EGW_INCLUDE_ROOT.'/etemplate/inc/class.uietemplate.inc.php'); require_once(EGW_INCLUDE_ROOT.'/etemplate/inc/class.uietemplate.inc.php');
require_once('class.bodefinitions.inc.php'); require_once('class.bodefinitions.inc.php');
if (!defined('IMPORTEXPORT_APP'))
{
define('IMPORTEXPORT_APP','importexport');
}
/** /**
* Userinterface to define {im|ex}ports * Userinterface to define {im|ex}ports
* *
@ -27,6 +22,8 @@ class uidefinitions
{ {
const _debug = true; const _debug = true;
const _appname = 'importexport';
public $public_functions = array( public $public_functions = array(
'edit' => true, 'edit' => true,
'index' => true, 'index' => true,
@ -59,8 +56,8 @@ class uidefinitions
{ {
// we cant deal with notice and warnings, as we are on ajax! // we cant deal with notice and warnings, as we are on ajax!
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
$GLOBALS['egw']->translation->add_app(IMPORTEXPORT_APP); $GLOBALS['egw']->translation->add_app(self::_appname);
$GLOBALS['egw_info']['flags']['currentapp'] = IMPORTEXPORT_APP; $GLOBALS['egw_info']['flags']['currentapp'] = self::_appname;
$GLOBALS['egw_info']['flags']['include_xajax'] = true; $GLOBALS['egw_info']['flags']['include_xajax'] = true;
if(!@is_object($GLOBALS['egw']->js)) if(!@is_object($GLOBALS['egw']->js))
@ -68,7 +65,7 @@ class uidefinitions
$GLOBALS['egw']->js =& CreateObject('phpgwapi.javascript'); $GLOBALS['egw']->js =& CreateObject('phpgwapi.javascript');
} }
$this->etpl =& new etemplate(); $this->etpl =& new etemplate();
$this->clock = $GLOBALS['egw']->html->image(IMPORTEXPORT_APP,'clock'); $this->clock = $GLOBALS['egw']->html->image(self::_appname,'clock');
$this->steps = array( $this->steps = array(
'wizzard_step10' => lang('Choose an application'), 'wizzard_step10' => lang('Choose an application'),
'wizzard_step20' => lang('Choose a plugin'), 'wizzard_step20' => lang('Choose a plugin'),
@ -77,7 +74,7 @@ class uidefinitions
'wizzard_finish' => '', 'wizzard_finish' => '',
); );
//register plugins (depricated) //register plugins (depricated)
$this->plugins = bodefinitions::plugins(); //$this->plugins = bodefinitions::plugins();
} }
/** /**
@ -107,7 +104,7 @@ class uidefinitions
case 'export_selected' : case 'export_selected' :
$mime_type = ($GLOBALS['egw']->html->user_agent == 'msie' || $GLOBALS['egw']->html->user_agent == 'opera') ? $mime_type = ($GLOBALS['egw']->html->user_agent == 'msie' || $GLOBALS['egw']->html->user_agent == 'opera') ?
'application/octetstream' : 'application/octet-stream'; 'application/octetstream' : 'application/octet-stream';
$name = 'importexport.definition'; $name = 'importexport_definition.xml';
header('Content-Type: ' . $mime_type); header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"'); header('Content-Disposition: attachment; filename="'.$name.'"');
echo $bodefinitions->export($selected); echo $bodefinitions->export($selected);
@ -120,7 +117,7 @@ class uidefinitions
} }
} }
$etpl =& new etemplate(IMPORTEXPORT_APP.'.definition_index'); $etpl =& new etemplate(self::_appname.'.definition_index');
// we need an offset because of autocontinued rows in etemplate ... // we need an offset because of autocontinued rows in etemplate ...
$definitions = array('row0'); $definitions = array('row0');
@ -131,7 +128,7 @@ class uidefinitions
unset($definition); unset($definition);
} }
$content = $definitions; $content = $definitions;
return $etpl->exec(IMPORTEXPORT_APP.'.uidefinitions.index',$content,array(),$readonlys,$preserv); return $etpl->exec(self::_appname.'.uidefinitions.index',$content,array(),$readonlys,$preserv);
} }
function edit() function edit()
@ -203,7 +200,7 @@ class uidefinitions
$this->wizzard_content_template = $this->$next_step($content,$sel_options,$readonlys,$preserv); $this->wizzard_content_template = $this->$next_step($content,$sel_options,$readonlys,$preserv);
} }
$html = $this->etpl->exec(IMPORTEXPORT_APP.'.uidefinitions.wizzard',$content,$sel_options,$readonlys,$preserv,1); $html = $this->etpl->exec(self::_appname.'.uidefinitions.wizzard',$content,$sel_options,$readonlys,$preserv,1);
} }
else else
{ {
@ -216,7 +213,7 @@ class uidefinitions
unset ($content['edit']); unset ($content['edit']);
$this->wizzard_content_template = $this->wizzard_step10($content, $sel_options, $readonlys, $preserv); $this->wizzard_content_template = $this->wizzard_step10($content, $sel_options, $readonlys, $preserv);
$html = $this->etpl->exec(IMPORTEXPORT_APP.'.uidefinitions.wizzard',$content,$sel_options,$readonlys,$preserv,1); $html = $this->etpl->exec(self::_appname.'.uidefinitions.wizzard',$content,$sel_options,$readonlys,$preserv,1);
} }
if(class_exists('xajaxResponse')) if(class_exists('xajaxResponse'))
@ -254,7 +251,7 @@ class uidefinitions
if ($GLOBALS['egw_info']['user']['apps']['manual']) if ($GLOBALS['egw_info']['user']['apps']['manual'])
{ {
$manual =& new etemplate('etemplate.popup.manual'); $manual =& new etemplate('etemplate.popup.manual');
echo $manual->exec(IMPORTEXPORT_APP.'.uidefinitions.wizzard',$content,$sel_options,$readonlys,$preserv,1); echo $manual->exec(self::_appname.'.uidefinitions.wizzard',$content,$sel_options,$readonlys,$preserv,1);
unset($manual); unset($manual);
} }
@ -448,14 +445,14 @@ class uidefinitions
$bodefinitions = new bodefinitions(); $bodefinitions = new bodefinitions();
if (is_array($content)) if (is_array($content))
{ {
$bodefinitions->import($content['import_file']); $bodefinitions->import($content['import_file']['tmp_name']);
// TODO make redirect here! // TODO make redirect here!
return $this->index(); return $this->index();
} }
else else
{ {
$etpl =& new etemplate(IMPORTEXPORT_APP.'.import_definition'); $etpl =& new etemplate(self::_appname.'.import_definition');
return $etpl->exec(IMPORTEXPORT_APP.'.uidefinitions.import_definition',$content,array(),$readonlys,$preserv); return $etpl->exec(self::_appname.'.uidefinitions.import_definition',$content,array(),$readonlys,$preserv);
} }
} }
} }

View File

@ -57,10 +57,11 @@ class uiexport {
if(empty($_content)) { if(empty($_content)) {
$et = new etemplate(self::_appname. '.export_dialog'); $et = new etemplate(self::_appname. '.export_dialog');
$_appname = $_GET['appname']; $_appname = $_GET['appname'];
$_definition =$_GET['definition']; $_definition =$_GET['definition'] = 'expert';
$_plugin = $_GET['plugin']; // NOTE: definition _must_ be 'expert' if for plugin to be used! $_plugin = $_GET['plugin']; // NOTE: definition _must_ be 'expert' if for plugin to be used!
$_selection = $_GET['selection']; $_selection = $_GET['selection'];
error_log(__FILE__.__FUNCTION__. '::$_GET[\'appname\']='. $_appname. ',$_GET[\'definition\']='. $_definition. ',$_GET[\'plugin\']='.$_plugin. ',$_GET[\'selection\']='.$_selection);
// if appname is given and valid, list available definitions (if no definition is given) // if appname is given and valid, list available definitions (if no definition is given)
if (!empty($_appname) && $GLOBALS['egw']->acl->check('run',1,$_appname)) { if (!empty($_appname) && $GLOBALS['egw']->acl->check('run',1,$_appname)) {
$content['appname'] = $_appname; $content['appname'] = $_appname;
@ -84,7 +85,7 @@ class uiexport {
unset($definitions); unset($definitions);
$sel_options['definition']['expert'] = lang('Expert options'); $sel_options['definition']['expert'] = lang('Expert options');
if(isset($_definition) && array_key_exists($_definition,$sel_options[$_definition])) { if(isset($_definition) && array_key_exists($_definition,$sel_options)) {
$content['definition'] = $_definition; $content['definition'] = $_definition;
} }
else { else {
@ -101,6 +102,7 @@ class uiexport {
if(isset($_plugin) && array_key_exists($_plugin,$sel_options['plugin'])) { if(isset($_plugin) && array_key_exists($_plugin,$sel_options['plugin'])) {
$content['plugin'] = $_plugin; $content['plugin'] = $_plugin;
$selected_plugin = $_plugin; $selected_plugin = $_plugin;
error_log('hallo');
} }
else { else {
$plugins_classnames = array_keys($plugins); $plugins_classnames = array_keys($plugins);
@ -181,19 +183,19 @@ class uiexport {
$definition = new definition($_content['definition']); $definition = new definition($_content['definition']);
} }
if (isset($definition->options['selection'])) { if (isset($definition->plugin_options['selection'])) {
//$definition->options = parse(...) //$definition->plugin_options = parse(...)
} }
else { else {
$definition->options = array_merge( $definition->plugin_options = array_merge(
$definition->options, $definition->plugin_options,
array('selection' => $_content['selection']) array('selection' => $_content['selection'])
); );
} }
$tmpfname = tempnam('/tmp','export'); $tmpfname = tempnam('/tmp','export');
$file = fopen($tmpfname, "w+"); $file = fopen($tmpfname, "w+");
if (! $charset = $definition->options['charset']) { if (! $charset = $definition->plugin_options['charset']) {
$charset = $GLOBALS['egw']->translation->charset(); $charset = $GLOBALS['egw']->translation->charset();
} }
$plugin_object = new $definition->plugin; $plugin_object = new $definition->plugin;
@ -234,6 +236,7 @@ class uiexport {
//nothing else expected! //nothing else expected!
throw new Exception('Error: unexpected submit in export_dialog!'); throw new Exception('Error: unexpected submit in export_dialog!');
} }
//error_log(print_r($content,true));
return $et->exec(self::_appname. '.uiexport.export_dialog',$content,$sel_options,$readonlys,$preserv,2); return $et->exec(self::_appname. '.uiexport.export_dialog',$content,$sel_options,$readonlys,$preserv,2);
} }

View File

@ -1,5 +1,5 @@
<?php <?php
/** /**
* eGroupWare - importexport * eGroupWare - importexport
* *
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
@ -9,45 +9,23 @@
* @version $Id$ * @version $Id$
*/ */
$definition_table = 'egw_importexport_definitions'; require_once(EGW_INCLUDE_ROOT. '/importexport/inc/class.bodefinitions.inc.php');
// Add two rooms to give user an idea of what resources is... // apps, whose definitions should be installed automatically
$plugin_options = serialize(array( $appnames = array (
'fieldsep' => ',', 'addressbook',
'charset' => 'ISO-8859-1', );
'addressbook' => 'n',
'owner' => 5,
'field_mapping' => array(
0 => '#kundennummer',
1 => 'n_given',
2 => 'n_family',
3 => 'adr_one_street',
4 => 'adr_one_countryname',
5 => 'adr_one_postalcode',
6 => 'adr_one_locality',
7 => 'tel_work',
8 => '',
9 => '',
10 => '',
11 => '',
),
'field_tanslation' => array(),
'has_header_line' => false,
'max' => false,
'conditions' => array(
0 => array(
'type' => 0, // exists
'string' => '#kundennummer',
'true' => array(
'action' => 1, // update
'last' => true,
),
'false' => array(
'action' => 2, // insert
'last' => true,
),
)), foreach ($appnames as $appname) {
)); $defdir = EGW_INCLUDE_ROOT. "/$appname/importexport/definitions";
$oProc->query("INSERT INTO {$definition_table } (name,application,plugin,type,allowed_users,plugin_options) VALUES ( 'oelheld','addressbook','addressbook_csv_import','import','5','$plugin_options')"); if(!is_dir($defdir)) continue;
$d = dir($defdir);
// step through each file in appdir
while (false !== ($entry = $d->read())) {
$file = $appdir. '/'. $entry;
list( $filename, $extension) = explode('.',$entry);
if ( $extension != 'xml' ) continue;
bodefinitions::import( $file );
}
}