mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-25 01:13:25 +01:00
massive improvements for the imports
This commit is contained in:
parent
92553ea37e
commit
b4b6d5abef
@ -1,25 +1,47 @@
|
||||
=importexport=
|
||||
= importexport =
|
||||
|
||||
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
|
||||
import and export stuff AND to have common backends whitch handle the stuff.
|
||||
Importexport can nothing without the plugins of the applications.
|
||||
The idea behind importexport is to have a common userinterface in all apps
|
||||
regarding import and export stuff AND to have common backends whitch
|
||||
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.
|
||||
|
||||
You just need to have your plugins in files which start with
|
||||
class.import_<type> or
|
||||
class.export_<type>
|
||||
class.import_<name> or
|
||||
class.export_<name>
|
||||
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 ==
|
||||
The bases of all imports and exports is the '''definition'''.
|
||||
|
||||
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
|
||||
by loading the definition. Definitions are also reachable by the importexport
|
||||
'''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 ==
|
||||
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}>"
|
@ -15,12 +15,12 @@
|
||||
$usage = "usage:
|
||||
--definition <name of definition>
|
||||
--file <name of file>
|
||||
--charset <charset>
|
||||
--user <eGW username>
|
||||
--password <password for user>
|
||||
--domain <domain name> \n";
|
||||
|
||||
if (php_sapi_name() != 'cli')
|
||||
{
|
||||
if (php_sapi_name() != 'cli') {
|
||||
die('This script only runs form command line');
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
$long_opts = array(
|
||||
'definition=',
|
||||
'file=',
|
||||
'charset=',
|
||||
'user=',
|
||||
'password=',
|
||||
'domain='
|
||||
@ -67,13 +68,14 @@
|
||||
}
|
||||
|
||||
$domain = 'default';
|
||||
foreach ($options[0] as $option)
|
||||
{
|
||||
switch ($option[0])
|
||||
{
|
||||
foreach ($options[0] as $option) {
|
||||
switch ($option[0]) {
|
||||
case '--file' :
|
||||
$file = $option[1];
|
||||
break;
|
||||
case '--charset' :
|
||||
$charset = $option[1];
|
||||
break;
|
||||
case '--definition' :
|
||||
$definition = $option[1];
|
||||
break;
|
||||
@ -92,11 +94,14 @@
|
||||
}
|
||||
}
|
||||
// check file
|
||||
if (!$user || !$password)
|
||||
{
|
||||
if ( !$user || !$password ) {
|
||||
fwrite(STDERR,'importexport_cli: You have to supply a username / password'."\n".$usage);
|
||||
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(
|
||||
'disable_Template_class' => True,
|
||||
@ -134,7 +139,7 @@
|
||||
exit(INVALID_OPTION);
|
||||
}
|
||||
|
||||
require_once('./inc/class.definition.inc.php');
|
||||
require_once('inc/class.definition.inc.php');
|
||||
try {
|
||||
$definition = new definition($definition);
|
||||
}
|
||||
@ -143,10 +148,12 @@
|
||||
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;
|
||||
$type = $definition->type;
|
||||
$po->$type($definition,array('file' => $file));
|
||||
|
||||
$resource = fopen( $file, 'r' );
|
||||
$po->$type( $resource, $charset, $definition );
|
||||
|
||||
$GLOBALS['egw']->common->phpgw_exit();
|
||||
|
||||
|
113
importexport/inc/class.arrayxml.inc.php
Normal file
113
importexport/inc/class.arrayxml.inc.php
Normal 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;
|
||||
}
|
||||
}
|
||||
?>
|
@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
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');
|
||||
|
||||
/** 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() {
|
||||
return $this->definitions;
|
||||
}
|
||||
@ -48,11 +57,11 @@ class bodefinitions {
|
||||
/**
|
||||
* reads a definition from database
|
||||
*
|
||||
* @deprecated see class.definition.inc.php
|
||||
* @param mixed &$definition
|
||||
* @return bool success or not
|
||||
*/
|
||||
public function read(&$definition)
|
||||
{
|
||||
public function read(&$definition) {
|
||||
if(is_int($definition)) $definition = array('definition_id' => $definition);
|
||||
elseif(is_string($definition)) $definition = array('name' => $definition);
|
||||
if(!$definition = $this->so_sql->read($definition)) return false;
|
||||
@ -61,45 +70,14 @@ class bodefinitions {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function save($content)
|
||||
{
|
||||
$plugin = $content['plugin'];
|
||||
if (!$plugin) return false;
|
||||
|
||||
$definition = array_intersect_key($content,array_flip($this->so_sql->db_cols));
|
||||
|
||||
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)
|
||||
{
|
||||
/**
|
||||
* deletes a defintion
|
||||
*
|
||||
* @param array $keys
|
||||
*/
|
||||
public function delete($keys) {
|
||||
$this->so_sql->delete(array('definition_id' => $keys));
|
||||
// clear private cach
|
||||
// clear private cache
|
||||
foreach ($keys as $key) {
|
||||
unset($this->definitions[array_search($key,$this->definitions)]);
|
||||
}
|
||||
@ -126,36 +104,6 @@ class bodefinitions {
|
||||
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
|
||||
*
|
||||
@ -169,41 +117,53 @@ class bodefinitions {
|
||||
'entries' => count($keys),
|
||||
));
|
||||
|
||||
foreach ($keys as $definition_id)
|
||||
{
|
||||
$definition = array('definition_id' => $definition_id);
|
||||
$this->read($definition);
|
||||
unset($definition['definition_id']);
|
||||
$export_data[$definition['name']] = $definition;
|
||||
$export_data['definitions'] = array();
|
||||
foreach ($keys as $definition_id) {
|
||||
$definition = new definition( $definition_id );
|
||||
$export_data['definitions'][$definition->name] = $definition->get_record_array();
|
||||
unset($export_data['definitions'][$definition->name]['definition_id']);
|
||||
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)
|
||||
{
|
||||
// read given file and check if its a valid definition
|
||||
if (!is_file($import_file['tmp_name'])) return false;
|
||||
$f = fopen($import_file['tmp_name'],'r');
|
||||
$data = fread($f,100000);
|
||||
fclose($f);
|
||||
if (($data = unserialize($data)) === false) return false;
|
||||
$metainfo = $data['metainfo'];
|
||||
unset($data['metainfo']);
|
||||
$data = arrayxml::xml2array( file_get_contents( $_import_file ) );
|
||||
|
||||
$metainfo = $data['importExportDefinitions']['metainfo'];
|
||||
$definitions = $data['importExportDefinitions']['definitions'];
|
||||
unset ( $data );
|
||||
|
||||
// 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
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ class definition implements iface_egw_record {
|
||||
'plugin' => 'string',
|
||||
'type' => 'string',
|
||||
'allowed_users' => 'array',
|
||||
'options' => 'array',
|
||||
'plugin_options' => 'array',
|
||||
'owner' => 'int',
|
||||
'description' => 'string',
|
||||
);
|
||||
@ -80,15 +80,13 @@ class definition implements iface_egw_record {
|
||||
if (is_string($_identifier) && strlen($_identifier) > 3) $_identifier = $this->name2identifier($_identifier);
|
||||
|
||||
if ((int)$_identifier != 0) {
|
||||
$this->so_sql->read(array('definition_id' => $_identifier));
|
||||
if (empty($this->so_sql->data)) {
|
||||
$this->definition = $this->so_sql->read(array('definition_id' => $_identifier));
|
||||
if ( empty( $this->definition ) ) {
|
||||
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.'"!');
|
||||
$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
|
||||
* @return int
|
||||
*/
|
||||
private function name2identifier($_name) {
|
||||
private function name2identifier( $_name ) {
|
||||
$identifiers = $this->so_sql->search(array('name' => $_name),true);
|
||||
if (isset($identifiers[1])) {
|
||||
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) {
|
||||
case 'allowed_users' :
|
||||
return $this->get_allowed_users();
|
||||
case 'options' :
|
||||
case 'plugin_options' :
|
||||
return $this->get_options();
|
||||
default :
|
||||
return $this->definition[$_attribute_name];
|
||||
@ -127,7 +125,7 @@ class definition implements iface_egw_record {
|
||||
switch ($_attribute_name) {
|
||||
case 'allowed_users' :
|
||||
return $this->set_allowed_users($_data);
|
||||
case 'options' :
|
||||
case 'plugin_options' :
|
||||
return $this->set_options($_data);
|
||||
default :
|
||||
$this->definition[$_attribute_name] = $_data;
|
||||
@ -149,7 +147,7 @@ class definition implements iface_egw_record {
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -159,12 +157,7 @@ class definition implements iface_egw_record {
|
||||
* @return array
|
||||
*/
|
||||
private function get_options() {
|
||||
// oh compat funct to be removed!
|
||||
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']);
|
||||
return unserialize($this->definition['plugin_options']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,8 +165,8 @@ class definition implements iface_egw_record {
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
private function set_options(array $_options) {
|
||||
$this->definition['options'] = serialize($_options);
|
||||
private function set_options(array $_plugin_options) {
|
||||
$this->definition['plugin_options'] = serialize( $_plugin_options );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,7 +180,7 @@ class definition implements iface_egw_record {
|
||||
public function get_record_array() {
|
||||
$definition = $this->definition;
|
||||
$definition['allowed_users'] = $this->get_allowed_users();
|
||||
$definition['options'] = $this->get_options();
|
||||
$definition['plugin_options'] = $this->get_options();
|
||||
return $definition;
|
||||
}
|
||||
|
||||
@ -205,8 +198,20 @@ class definition implements iface_egw_record {
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_record(array $_record) {
|
||||
$this->definition = $_record;
|
||||
public function set_record( array $_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
|
||||
*/
|
||||
public function save ( $_dst_identifier ) {
|
||||
if ($owner = $this->get_owner() && $owner != $this->user && !$this->is_admin) {
|
||||
throw ('Error: User '. $this->user. ' is not allowed to save this definition!');
|
||||
if ( strlen($this->definition['name']) < 3 ) {
|
||||
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'];
|
||||
}
|
||||
|
@ -10,14 +10,12 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
//require_once(EGW_INCLUDE_ROOT. '/importexport/inc/class.iface_egw_record.inc.php');
|
||||
|
||||
/**
|
||||
* class iface_export_plugin
|
||||
* This a the abstract interface for an export plugin of importexport
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* NOTE: This is an easy interface, cause plugins live in theire own
|
||||
|
79
importexport/inc/class.iface_import_plugin.inc.php
Normal file
79
importexport/inc/class.iface_import_plugin.inc.php
Normal 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
|
||||
?>
|
@ -24,16 +24,10 @@ class import_csv implements iface_import_record { //, Iterator {
|
||||
|
||||
const csv_max_linelength = 8000;
|
||||
|
||||
/** Aggregations: */
|
||||
|
||||
/** Compositions: */
|
||||
|
||||
/**
|
||||
* @static import_export_helper_functions
|
||||
*/
|
||||
|
||||
/*** Attributes: ***/
|
||||
|
||||
/**
|
||||
* array with field mapping in form column number => new_field_name
|
||||
* @access public
|
||||
@ -235,7 +229,7 @@ class import_csv implements iface_import_record { //, Iterator {
|
||||
foreach ($this->mapping as $cvs_idx => $new_idx) {
|
||||
$this->record[$new_idx] = $record[$cvs_idx];
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} // end of member function do_fieldmapping
|
||||
|
||||
/**
|
||||
|
@ -16,14 +16,7 @@
|
||||
* class import_export_helper_functions (only static methods)
|
||||
* use import_export_helper_functions::method
|
||||
*/
|
||||
class import_export_helper_functions
|
||||
{
|
||||
|
||||
/** Aggregations: */
|
||||
|
||||
/** Compositions: */
|
||||
|
||||
/*** Attributes: ***/
|
||||
class import_export_helper_functions {
|
||||
|
||||
/**
|
||||
* nothing to construct here, only static functions!
|
||||
@ -236,13 +229,13 @@ class import_export_helper_functions
|
||||
* @param string $_appname {<appname> | all}
|
||||
* @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;
|
||||
$types = $_types == 'all' ? array('import','export') : (array)$_type;
|
||||
$types = $_type == 'all' ? array('import','export') : (array)$_type;
|
||||
$plugins = array();
|
||||
|
||||
foreach ($appnames as $appname) {
|
||||
$appdir = EGW_INCLUDE_ROOT. "/$appname/inc";
|
||||
$appdir = EGW_INCLUDE_ROOT. "/$appname/importexport";
|
||||
if(!is_dir($appdir)) continue;
|
||||
$d = dir($appdir);
|
||||
|
||||
@ -252,7 +245,7 @@ class import_export_helper_functions
|
||||
$file = $appdir. '/'. $entry;
|
||||
|
||||
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);
|
||||
|
||||
try {
|
||||
@ -269,6 +262,7 @@ class import_export_helper_functions
|
||||
}
|
||||
$d->close();
|
||||
}
|
||||
//error_log(__CLASS__.__FUNCTION__.print_r($plugins,true));
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
@ -282,5 +276,8 @@ class import_export_helper_functions
|
||||
return array_keys(self::get_plugins('all',$_type));
|
||||
}
|
||||
|
||||
public static function guess_filetype( $_file ) {
|
||||
|
||||
}
|
||||
} // end of import_export_helper_functions
|
||||
?>
|
||||
|
@ -13,11 +13,6 @@
|
||||
require_once(EGW_INCLUDE_ROOT.'/etemplate/inc/class.uietemplate.inc.php');
|
||||
require_once('class.bodefinitions.inc.php');
|
||||
|
||||
if (!defined('IMPORTEXPORT_APP'))
|
||||
{
|
||||
define('IMPORTEXPORT_APP','importexport');
|
||||
}
|
||||
|
||||
/**
|
||||
* Userinterface to define {im|ex}ports
|
||||
*
|
||||
@ -27,6 +22,8 @@ class uidefinitions
|
||||
{
|
||||
const _debug = true;
|
||||
|
||||
const _appname = 'importexport';
|
||||
|
||||
public $public_functions = array(
|
||||
'edit' => true,
|
||||
'index' => true,
|
||||
@ -59,8 +56,8 @@ class uidefinitions
|
||||
{
|
||||
// we cant deal with notice and warnings, as we are on ajax!
|
||||
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
||||
$GLOBALS['egw']->translation->add_app(IMPORTEXPORT_APP);
|
||||
$GLOBALS['egw_info']['flags']['currentapp'] = IMPORTEXPORT_APP;
|
||||
$GLOBALS['egw']->translation->add_app(self::_appname);
|
||||
$GLOBALS['egw_info']['flags']['currentapp'] = self::_appname;
|
||||
|
||||
$GLOBALS['egw_info']['flags']['include_xajax'] = true;
|
||||
if(!@is_object($GLOBALS['egw']->js))
|
||||
@ -68,7 +65,7 @@ class uidefinitions
|
||||
$GLOBALS['egw']->js =& CreateObject('phpgwapi.javascript');
|
||||
}
|
||||
$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(
|
||||
'wizzard_step10' => lang('Choose an application'),
|
||||
'wizzard_step20' => lang('Choose a plugin'),
|
||||
@ -77,7 +74,7 @@ class uidefinitions
|
||||
'wizzard_finish' => '',
|
||||
);
|
||||
//register plugins (depricated)
|
||||
$this->plugins = bodefinitions::plugins();
|
||||
//$this->plugins = bodefinitions::plugins();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,7 +104,7 @@ class uidefinitions
|
||||
case 'export_selected' :
|
||||
$mime_type = ($GLOBALS['egw']->html->user_agent == 'msie' || $GLOBALS['egw']->html->user_agent == 'opera') ?
|
||||
'application/octetstream' : 'application/octet-stream';
|
||||
$name = 'importexport.definition';
|
||||
$name = 'importexport_definition.xml';
|
||||
header('Content-Type: ' . $mime_type);
|
||||
header('Content-Disposition: attachment; filename="'.$name.'"');
|
||||
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 ...
|
||||
$definitions = array('row0');
|
||||
@ -131,7 +128,7 @@ class uidefinitions
|
||||
unset($definition);
|
||||
}
|
||||
$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()
|
||||
@ -203,7 +200,7 @@ class uidefinitions
|
||||
$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
|
||||
{
|
||||
@ -216,7 +213,7 @@ class uidefinitions
|
||||
unset ($content['edit']);
|
||||
|
||||
$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'))
|
||||
@ -254,7 +251,7 @@ class uidefinitions
|
||||
if ($GLOBALS['egw_info']['user']['apps']['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);
|
||||
}
|
||||
|
||||
@ -448,14 +445,14 @@ class uidefinitions
|
||||
$bodefinitions = new bodefinitions();
|
||||
if (is_array($content))
|
||||
{
|
||||
$bodefinitions->import($content['import_file']);
|
||||
$bodefinitions->import($content['import_file']['tmp_name']);
|
||||
// TODO make redirect here!
|
||||
return $this->index();
|
||||
}
|
||||
else
|
||||
{
|
||||
$etpl =& new etemplate(IMPORTEXPORT_APP.'.import_definition');
|
||||
return $etpl->exec(IMPORTEXPORT_APP.'.uidefinitions.import_definition',$content,array(),$readonlys,$preserv);
|
||||
$etpl =& new etemplate(self::_appname.'.import_definition');
|
||||
return $etpl->exec(self::_appname.'.uidefinitions.import_definition',$content,array(),$readonlys,$preserv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,10 +57,11 @@ class uiexport {
|
||||
if(empty($_content)) {
|
||||
$et = new etemplate(self::_appname. '.export_dialog');
|
||||
$_appname = $_GET['appname'];
|
||||
$_definition =$_GET['definition'];
|
||||
$_definition =$_GET['definition'] = 'expert';
|
||||
$_plugin = $_GET['plugin']; // NOTE: definition _must_ be 'expert' if for plugin to be used!
|
||||
$_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 (!empty($_appname) && $GLOBALS['egw']->acl->check('run',1,$_appname)) {
|
||||
$content['appname'] = $_appname;
|
||||
@ -84,7 +85,7 @@ class uiexport {
|
||||
unset($definitions);
|
||||
$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;
|
||||
}
|
||||
else {
|
||||
@ -101,6 +102,7 @@ class uiexport {
|
||||
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);
|
||||
@ -181,19 +183,19 @@ class uiexport {
|
||||
$definition = new definition($_content['definition']);
|
||||
}
|
||||
|
||||
if (isset($definition->options['selection'])) {
|
||||
//$definition->options = parse(...)
|
||||
if (isset($definition->plugin_options['selection'])) {
|
||||
//$definition->plugin_options = parse(...)
|
||||
}
|
||||
else {
|
||||
$definition->options = array_merge(
|
||||
$definition->options,
|
||||
$definition->plugin_options = array_merge(
|
||||
$definition->plugin_options,
|
||||
array('selection' => $_content['selection'])
|
||||
);
|
||||
}
|
||||
|
||||
$tmpfname = tempnam('/tmp','export');
|
||||
$file = fopen($tmpfname, "w+");
|
||||
if (! $charset = $definition->options['charset']) {
|
||||
if (! $charset = $definition->plugin_options['charset']) {
|
||||
$charset = $GLOBALS['egw']->translation->charset();
|
||||
}
|
||||
$plugin_object = new $definition->plugin;
|
||||
@ -234,6 +236,7 @@ class uiexport {
|
||||
//nothing else expected!
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
/**
|
||||
* eGroupWare - importexport
|
||||
*
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
@ -9,45 +9,23 @@
|
||||
* @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...
|
||||
$plugin_options = serialize(array(
|
||||
'fieldsep' => ',',
|
||||
'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,
|
||||
),
|
||||
// apps, whose definitions should be installed automatically
|
||||
$appnames = array (
|
||||
'addressbook',
|
||||
);
|
||||
|
||||
)),
|
||||
));
|
||||
$oProc->query("INSERT INTO {$definition_table } (name,application,plugin,type,allowed_users,plugin_options) VALUES ( 'oelheld','addressbook','addressbook_csv_import','import','5','$plugin_options')");
|
||||
foreach ($appnames as $appname) {
|
||||
$defdir = EGW_INCLUDE_ROOT. "/$appname/importexport/definitions";
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user