egroupware/importexport/inc/class.importexport_definitions_ui.inc.php
Nathan Gray 0a91bc5aa9 Add support for filtering records to be exported.
Filterable fields are attempted to be autodetected by using the exportable fields.
Records can be filtered by fields with type select,select-cat,select-account,date,date-time (according to egw_record class) 
only at this time.  Filters are saved in the definition and used with scheduled exports.  They are also available to the
user for modification in the export dialog.
2012-12-31 20:36:28 +00:00

1029 lines
33 KiB
PHP

<?php
/**
* eGroupWare - importexport
*
* @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$
*/
/**
* Userinterface to define {im|ex}ports
*
* @package importexport
*/
class importexport_definitions_ui
{
const _debug = false;
const _appname = 'importexport';
public $public_functions = array(
'edit' => true,
'index' => true,
'wizard' => true,
'import_definition' => true,
'site_config' => true,
);
/**
* holds all available plugins
*
* @var array
*/
var $plugins;
/**
* holds user chosen plugin after step20
*
* @var object
*/
var $plugin;
/**
* xajax response object
*
* @var object
*/
var $response = true;
function __construct()
{
// 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(self::_appname);
$GLOBALS['egw_info']['flags']['currentapp'] = self::_appname;
$GLOBALS['egw_info']['flags']['include_xajax'] = true;
$this->etpl = new etemplate();
$this->clock = html::image(self::_appname,'clock');
$this->steps = array(
'wizard_step10' => lang('Choose an application'),
'wizard_step20' => lang('Choose a plugin'),
'wizard_step21' => lang('Choose a name for this definition'),
'wizard_step90' => lang('Which users are allowed to use this definition'),
'wizard_finish' => '',
);
//register plugins
$this->plugins = importexport_helper_functions::get_plugins();
}
/**
* List defined {im|ex}ports
*
* @param array $content=null
*/
function index($content = null,$msg='')
{
$filter = array('name' => '*');
if($GLOBALS['egw_info']['user']['apps']['admin']) {
// Any public definition
$filter[] = '(owner=0 OR owner IS NULL OR allowed_users IS NOT NULL OR owner = ' . $GLOBALS['egw_info']['user']['account_id'] . ')';
} else {
// Filter private definitions
$filter['owner'] = $GLOBALS['egw_info']['user']['account_id'];
$config = config::read('phpgwapi');
if($config['export_limit'] == 'no' && !bo_merge::is_export_limit_excepted()) {
$filter['type'] = 'import';
}
}
if (is_array($content))
{
// Handle legacy actions
if (isset($content['nm']['rows']['delete']))
{
$content['nm']['action'] = 'delete';
$content['nm']['selected'] = array_keys($content['nm']['rows']['delete'],'pressed');
}
elseif(($button = array_search('pressed',$content['nm']['rows'])) !== false)
{
$selected = $content['nm']['rows']['selected'];
if(count($selected) < 1 || !is_array($selected)) common::egw_exit();
switch ($button)
{
case 'delete_selected' :
$content['nm']['selected'] = $selected;
$content['nm']['action'] = 'delete';
break;
case 'export_selected':
$content['nm']['selected'] = $selected;
$content['nm']['action'] = 'export';
break;
}
}
if ($content['nm']['action'])
{
if (!count($content['nm']['selected']) && !$content['nm']['select_all'])
{
$msg = lang('You need to select some entries first!');
}
else
{
// Action has an additional parameter
if(in_array($content['nm']['action'], array('owner', 'allowed')))
{
$action = $content['nm']['action'];
if($content['nm']['action'] == 'allowed')
{
$content['allowed'] = $content['allowed_private'] ? null : ($content['all_users'] ? 'all' : implode(',',$content['allowed']));
}
if(is_array($content[$content['nm']['action']]))
{
$content[$content['nm']['action']] = implode(',',$content[$content['nm']['action']]);
}
$content['nm']['action'] .= '_' . $content[$content['nm']['action']];
unset($content[$action]);
unset($content['all_users']);
unset($content['allowed_private']);
}
if ($this->action($content['nm']['action'],$content['nm']['selected'],$content['nm']['select_all'],
$success,$failed,$action_msg,'index',$msg))
{
$msg .= lang('%1 definition(s) %2',$success,$action_msg);
}
elseif(empty($msg))
{
$msg .= lang('%1 definition(s) %2, %3 failed because of insufficent rights !!!',$success,$action_msg,$failed);
}
}
}
}
if(!is_array($content['nm'])) {
$content['nm'] = array(
'get_rows' => 'importexport.importexport_definitions_ui.get_rows',
'no_cat' => true,
'no_filter' => true,
'no_filter2' => true,
'header_right' => 'importexport.definition_index.add',
'csv_fields' => false, // Disable CSV export, uses own export
'default_cols' => '!actions', // switch legacy actions column and row off by default
'row_id' => 'definition_id',
);
if($_GET['application']) $content['nm']['col_filter']['application'] = $_GET['application'];
}
if(egw_session::appsession('index', 'importexport')) {
$content['nm'] = array_merge($content['nm'], egw_session::appsession('index', 'importexport'));
}
$content['nm']['actions'] = $this->get_actions();
$sel_options = array(
'type' => array(
'import' => lang('import'),
'export' => lang('export'),
),
'allowed_users' => array(null => lang('Private'), 'all' => lang('all'))
);
foreach ($this->plugins as $appname => $options)
{
if($GLOBALS['egw_info']['user']['apps'][$appname] || $GLOBALS['egw_info']['user']['apps']['admin']) {
$sel_options['application'][$appname] = lang($appname);
}
}
if($msg) $content['msg'] = $msg;
$etpl = new etemplate(self::_appname.'.definition_index');
return $etpl->exec( self::_appname.'.importexport_definitions_ui.index', $content, $sel_options, $readonlys, $preserv );
}
private function get_actions() {
$group = 0;
$actions = array(
'edit' => array(
'caption' => 'Open',
'default' => true,
'allowOnMultiple' => false,
'url' => 'menuaction=importexport.importexport_definitions_ui.edit&definition=$id',
'popup' => '500x500',
'group' => $group,
),
'add' => array(
'caption' => 'Add',
'url' => 'menuaction=importexport.importexport_definitions_ui.edit',
'popup' => '500x500',
'group' => $group,
),
'execute' => array(
'caption' => 'Execute',
'icon' => 'importexport/navbar',
'allowOnMultiple' => false,
'group' => $group,
),
'schedule' => array(
'caption' => 'Schedule',
'icon' => 'timesheet/navbar',
'allowOnMultiple' => false,
'url' => 'menuaction=importexport.importexport_schedule_ui.edit&definition=$id',
'popup' => '500x500',
'group' => $group,
),
'change' => array(
'caption' => 'Change',
'icon' => 'edit',
'children' => array(
'owner' => array(
'caption' => 'Owner',
'group' => 1,
'icon' => 'addressbook/accounts',
'nm_action' => 'open_popup',
),
'allowed' => array(
'caption' => 'Allowed users',
'group' => 1,
'icon' => 'addressbook/group',
'nm_action' => 'open_popup',
)
),
'disableClass' => 'rowNoEdit',
),
'select_all' => array(
'caption' => 'Whole query',
'checkbox' => true,
'hint' => 'Apply the action on the whole query, NOT only the shown definitions!!!',
'group' => ++$group,
),
'copy' => array(
'caption' => 'Copy',
'group' => ++$group,
),
'createexport' => array(
'caption' => 'Create export',
'hint' => 'Create a matching export definition based on this import definition',
'icon' => 'export',
'group' => $group,
'allowOnMultiple' => false,
'disableClass' => 'export'
),
'export' => array(
'caption' => 'Export',
'group' => $group,
'icon' => 'filesave'
),
'delete' => array(
'caption' => 'Delete',
'confirm' => 'Delete this entry',
'confirm_multiple' => 'Delete these entries',
'group' => ++$group,
'disableClass' => 'rowNoDelete',
),
);
// Unset admin actions
if(!$GLOBALS['egw_info']['user']['apps']['admin'])
{
unset($actions['schedule']);
}
return $actions;
}
/**
* apply an action to multiple entries
*
* @param string/int $action 'delete', 'export', etc.
* @param array $selected id's to use if !$use_all
* @param boolean $use_all if true use all entries of the current selection (in the session)
* @param int &$success number of succeded actions
* @param int &$failed number of failed actions (not enought permissions)
* @param string &$action_msg translated verb for the actions, to be used in a message like %1 entries 'deleted'
* @param string/array $session_name 'index' or 'email', or array with session-data depending if we are in the main list or the popup
* @return boolean true if all actions succeded, false otherwise
*/
function action($action,$selected,$use_all,&$success,&$failed,&$action_msg,$session_name,&$msg)
{
//echo __METHOD__."('$action', ".array2string($selected).', '.array2string($use_all).",,, '$session_name')";
if ($use_all)
{
// get the whole selection
$old_query = $query = is_array($session_name) ? $session_name : egw_session::appsession($session_name,'importexport');
@set_time_limit(0); // switch off the execution time limit, as it's for big selections to small
$query['num_rows'] = -1; // all
$query['csv_export'] = true; // so get_rows method _can_ produce different content or not store state in the session
$this->get_rows($query,$rows,$readonlys);
$selected = array();
foreach($rows as $row) {
$selected[] = $row['definition_id'];
}
if(!is_array($session_name))
{
// Restore old query
egw_session::appsession($session_name, 'importexport',$old_query);
}
}
// Dialogs to get options
list($action, $settings) = explode('_', $action, 2);
$bodefinitions = new importexport_definitions_bo(false, true);
switch($action) {
case 'execute':
// There's probably a way to do this in just JS, all the info should be there...
foreach($selected as $id) {
$definition = $bodefinitions->read((int)$id);
$link = egw::link('/index.php', array(
'menuaction' => 'importexport.importexport_'.$definition['type'].'_ui.'.$definition['type'].'_dialog',
'appname' => $definition['application'],
'definition' => $definition['name']
));
egw_framework::set_onload("egw_openWindowCentered2('$link','_blank',850,440,'yes');");
}
break;
case 'allowed':
$action = 'allowed_users';// Field is allowed_users, popup doesn't like _
case 'owner':
$action_msg = lang('changed'. ' ' . $action);
foreach($selected as $id) {
$definition = $bodefinitions->read((int)$id);
if($definition['definition_id']) {
// Prevent private with no owner
if(!$definition['owner'] && !$settings) $definition['owner'] = $GLOBALS['egw_info']['user']['account_id'];
$definition[$action] = $settings;
$bodefinitions->save($definition);
$success++;
}
}
break;
case 'delete':
$bodefinitions->delete($selected);
$action_msg = lang('deleted');
break;
case 'export' :
$action_msg = lang('exported');
$mime_type = ($GLOBALS['egw']->html->user_agent == 'msie' || $GLOBALS['egw']->html->user_agent == 'opera') ?
'application/octetstream' : 'application/octet-stream';
$name = 'importexport_definition.xml';
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
echo $bodefinitions->export($selected);
common::egw_exit();
break;
case 'copy':
$action_msg = lang('copied');
// Should only be one selected
foreach($selected as $id) {
$definition = $bodefinitions->read((int)$id);
if($definition['definition_id']) {
unset($definition['definition_id']);
$definition['name'] = $settings ? $settings : $definition['name'] . ' copy';
try {
$bodefinitions->save($definition);
} catch (Exception $e) {
try {
$definition['name'] .= ' ' . $GLOBALS['egw_info']['user']['account_lid'];
$bodefinitions->save($definition);
} catch (Exception $ex) {
$failed++;
$msg .= lang('Duplicate name, please choose another.');
continue;
}
}
$success++;
}
}
break;
case 'createexport':
$action_msg = lang('created');
// Should only be one selected
foreach($selected as $id) {
$definition = new importexport_definition($id);
try {
$export = $bodefinitions->export_from_import($definition);
$export->save();
} catch (Exception $e) {
if($export)
{
try {
$export->name = $export->name.' ' . $GLOBALS['egw_info']['user']['account_lid'];
$export->save();
} catch (Exception $ex) {
$failed++;
$msg .= lang('Duplicate name, please choose another.');
continue;
}
}
else
{
$failed++;
}
}
$success++;
}
break;
}
return !$failed;
}
public function get_rows(&$query, &$rows, &$readonlys) {
$rows = array();
egw_session::appsession('index','importexport',$query);
$bodefinitions = new importexport_definitions_bo($query['col_filter'], true);
return $bodefinitions->get_rows($query, $rows, $readonlys);
}
/**
* Edit a definition
*
* To jump to a certain step, pass the previous step in the URL step=wizard_stepXX
* The wizard will validate that step, then display the _next_ step..
*/
function edit()
{
if(!$_definition = $_GET['definition'])
{
$content = array(
'edit' => true,
'application' => $_GET['application'],
'plugin' => $_GET['plugin']
);
// Jump to a step
if($_GET['step'])
{
$content['edit'] = false;
// Wizard will process previous step, then advance
$content['step'] = $this->get_step($_GET['step'],-1);
$content['button']['next'] = 'pressed';
$this->wizard($content);
}
else
{
// Initial form
$this->wizard($content);
}
return;
}
if(is_numeric($_GET['definition']))
{
$definition = (int)$_GET['definition'];
}
else
{
$definition = array('name' => $_definition);
}
$bodefinitions = new importexport_definitions_bo();
$definition = $bodefinitions->read($definition);
$definition['edit'] = true;
// Jump to a step
if($_GET['step'])
{
$definition['edit'] = false;
// Wizard will process previous step, then advance
$definition['step'] = $_GET['step'];;
$definition['button'] = array('next' => 'pressed');
}
$this->wizard($definition);
}
function wizard($content = null, $msg='')
{
$GLOBALS['egw_info']['flags']['java_script'] .=
"<script type='text/javascript'>
function xajax_eT_wrapper_init() {
//window.resizeTo(document.documentElement.scrollWidth+20,document.documentElement.offsetHeight+40);
window.moveTo(screen.availWidth/2 - window.outerWidth/2,
screen.availHeight/2 - window.outerHeight/2);
}
</script>";
$this->etpl->read('importexport.wizardbox');
$this->wizard_content_template =& $this->etpl->children[0]['data'][1]['A'][2][1]['name'];
if(is_array($content) &&! $content['edit'])
{
if(self::_debug) error_log('importexport.wizard->$content '. print_r($content,true));
// fetch plugin object
if($content['plugin'] && $content['application'])
{
$wizard_name = $content['application'] . '_wizard_' . str_replace($content['application'] . '_', '', $content['plugin']);
// we need to deal with the wizard object if exists
if (file_exists(EGW_SERVER_ROOT . '/'. $content['application'].'/importexport/class.wizard_'. $content['plugin'].'.inc.php'))
{
error_log('Deprecated location for importexport wizard. Please move it to app/inc/ and rename it to follow new conventions');
}
elseif (file_exists(EGW_SERVER_ROOT . '/'. $content['application']."/inc/class.$wizard_name.inc.php"))
{
$wizard_plugin = $wizard_name;
}
else
{
$wizard_plugin = $content['plugin'];
}
// App translations
if($content['application']) translation::add_app($content['application']);
$this->plugin = is_object($GLOBALS['egw']->$wizard_plugin) ? $GLOBALS['egw']->$wizard_plugin : new $wizard_plugin;
// Global object needs to be the same, or references to plugin don't work
if(!is_object($GLOBALS['egw']->importexport_definitions_ui) || $GLOBALS['egw']->importexport_definitions_ui !== $this)
$GLOBALS['egw']->importexport_definitions_ui =& $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)
{
$button = array_keys($content['button']);
$content['button'] = array($button[0] => 'pressed');
}
// post process submitted step
if($content['step']) {
if(!$this->can_edit($content))
{
// Each step changes definition, reload it
$bodefinitions = new importexport_definitions_bo();
$definition = $bodefinitions->read($content);
$content = $definition + array('step' => $content['step'], 'button' => $content['button']);
}
if(!key_exists($content['step'],$this->steps))
{
$next_step = $this->plugin->$content['step']($content);
}
else
{
$next_step = $this->$content['step']($content);
}
} else {
die('Cannot find next step');
}
// pre precess next step
$sel_options = $readonlys = $preserv = array();
// Override next button on step 30, to do a regular submit for the file upload
if($next_step == 'wizard_step30')
{
$this->etpl->set_cell_attribute('button[next]', 'onclick', '');
}
// Disable finish button if required fields are missing
if(!$content['name'] || !$content['type'] || !$content['plugin']) {
$GLOBALS['egw']->js->set_onload("disable_button('exec[button][finish]');");
}
if(!key_exists($next_step,$this->steps))
{
$this->wizard_content_template = $this->plugin->$next_step($content,$sel_options,$readonlys,$preserv);
}
else
{
$this->wizard_content_template = $this->$next_step($content,$sel_options,$readonlys,$preserv);
}
if(!$this->can_edit($content))
{
$readonlys[$this->wizard_content_template] = true;
$preserve = $content;
$GLOBALS['egw']->js->set_onload("disable_button('exec[button][finish]');");
}
$html = $this->etpl->exec(self::_appname.'.importexport_definitions_ui.wizard',$content,$sel_options,$readonlys,$preserv,1);
}
else
{
// initial content
$GLOBALS['egw']->js->set_onload("xajax_eT_wrapper_init();");
$GLOBALS['egw']->js->set_onload("disable_button('exec[button][previous]');");
$sel_options = $readonlys = $preserv = array();
if($content['edit'])
unset ($content['edit']);
$this->wizard_content_template = $this->wizard_step10($content, $sel_options, $readonlys, $preserv);
if(!$this->can_edit($content))
{
$readonlys[$this->wizard_content_template] = true;
$preserve = $content;
$GLOBALS['egw']->js->set_onload("disable_button('exec[button][finish]');");
}
$html = $this->etpl->exec(self::_appname.'.importexport_definitions_ui.wizard',$content,$sel_options,$readonlys,$preserv,1);
}
if(class_exists('xajaxResponse'))
{
$this->response = new xajaxResponse();
egw_framework::include_css_js_response();
if ($content['closewindow'])
{
$this->response->addScript("opener.location.reload();");
$this->response->addScript("window.close();");
// If Browser can't close window we display a "close" buuton and
// need to disable normal buttons
$this->response->addAssign('exec[button][previous]','style.display', 'none');
$this->response->addAssign('exec[button][next]','style.display', 'none');
$this->response->addAssign('exec[button][finish]','style.display', 'none');
$this->response->addAssign('exec[button][cancel]','style.display', 'none');
}
$this->response->addAssign('contentbox', 'innerHTML', $html);
if (($onload = $GLOBALS['egw']->js->set_onload('')))
{
$this->response->addScript($onload);
}
$this->response->addAssign('picturebox', 'style.display', 'none');
$this->response->addScript("set_style_by_class('div','popupManual','display','inline');
popup_resize();
");
return $this->response->getXML();
}
else
{
$GLOBALS['egw']->js->set_onload("document.getElementById('picturebox').style.display = 'none';");
egw_framework::validate_file('.', 'etemplate', 'etemplate');
egw_framework::validate_file('.', 'etemplate', 'etemplate');
common::egw_header();
echo '<div id="divMain">'."\n";
echo '<div><h3>{Im|Ex}port Wizard</h3></div>';
// adding a manual icon to every popup
if ($GLOBALS['egw_info']['user']['apps']['manual'])
{
$manual = new etemplate('etemplate.popup.manual');
echo $manual->exec(self::_appname.'.importexport_definitions_ui.wizard',$content,$sel_options,$readonlys,$preserv,1);
unset($manual);
}
echo '<div id="contentbox">';
echo $html;
echo '</div></div>'."\n";
echo '<style type="text/css">#picturebox { position: absolute; right: 27px; top: 24px; }</style>'."\n";
echo '<div id="picturebox">'. $this->clock. '</div>';
return;
}
}
/**
* gets name of next step
*
* @param string $curr_step
* @param int $step_width
* @return string containing function name of next step
*/
function get_step ($curr_step, $step_width)
{
/*if($content['plugin'] && $content['application']&& !is_object($this->plugin))
{
$plugin_definition = $this->plugins[$content['application']][$content['plugin']]['definition'];
if($plugin_definition) $this->plugin = new $plugin_definition;
}*/
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);
}
else
{
$steps = $this->steps;
}
$step_keys = array_keys($steps);
$nn = array_search($curr_step,$step_keys)+(int)$step_width;
return (key_exists($nn,$step_keys)) ? $step_keys[$nn] : 'wizard_finish';
}
function wizard_step10(&$content, &$sel_options, &$readonlys, &$preserv)
{
if(self::_debug) error_log('importexport.importexport_definitions_ui::wizard_step10->$content '.print_r($content,true));
// return from step10
if ($content['step'] == 'wizard_step10')
{
switch (array_search('pressed', $content['button']))
{
case 'next':
return $this->get_step($content['step'],1);
case 'finish':
return 'wizard_finish';
default :
return $this->wizard_step10($content,$sel_options,$readonlys,$preserv);
}
}
// init step10
else
{
$content['msg'] = $this->steps['wizard_step10'];
foreach ($this->plugins as $appname => $options)
{
if($GLOBALS['egw_info']['user']['apps'][$appname] || $GLOBALS['egw_info']['user']['apps']['admin']) {
$sel_options['application'][$appname] = lang($appname);
}
}
$GLOBALS['egw']->js->set_onload("disable_button('exec[button][previous]');");
$content['step'] = 'wizard_step10';
$preserv = $content;
unset ($preserv['button']);
return 'importexport.wizard_chooseapp';
}
}
// get plugin
function wizard_step20(&$content, &$sel_options, &$readonlys, &$preserv)
{
if(self::_debug) error_log('importexport.' . get_class($this) . '::wizard_step20->$content '.print_r($content,true));
// return from step20
if ($content['step'] == 'wizard_step20')
{
switch (array_search('pressed', $content['button']))
{
case 'next':
// There's no real reason the plugin has to come from any of these, as long as it has a $steps variable
if($this->plugin instanceof importexport_iface_import_plugin || $this->plugin instanceof importexport_wizard_basic_import_csv || strpos(get_class($this->plugin), 'import') !== false) {
$content['type'] = 'import';
} elseif($this->plugin instanceof importexport_iface_export_plugin || $this->plugin instanceof importexport_wizard_basic_export_csv || strpos(get_class($this->plugin),'export') !== false) {
$content['type'] = 'export';
} else {
throw new egw_exception('Invalid plugin');
}
return $this->get_step($content['step'],1);
case 'previous' :
unset ($content['plugin']);
if(is_object($this->response)) {
$this->response->addScript("disable_button('exec[button][previous]');");
}
return $this->get_step($content['step'],-1);
case 'finish':
return 'wizard_finish';
default :
return $this->wizard_step20($content,$sel_options,$readonlys,$preserv);
}
}
// init step20
else
{
$content['msg'] = $this->steps['wizard_step20'];
$config = config::read('phpgwapi');
foreach ($this->plugins[$content['application']] as $type => $plugins) {
if($config['export_limit'] == 'no' && !$GLOBALS['egw_info']['user']['apps']['admin'] && $type == 'export') continue;
foreach($plugins as $plugin => $name) {
$sel_options['plugin'][$plugin] = $name;
}
}
$content['step'] = 'wizard_step20';
$preserv = $content;
unset ($preserv['button']);
return 'importexport.wizard_chooseplugin';
}
}
// name
function wizard_step21(&$content, &$sel_options, &$readonlys, &$preserv)
{
if(self::_debug) error_log('importexport.importexport_definitions_ui::wizard_step21->$content '.print_r($content,true));
// Check for duplicate name
$duplicate = isset($content['duplicate_error']);
if($content['name'] && !$duplicate)
{
try {
$check_definition = new importexport_definition($content['name']);
if($check_definition && $check_definition->definition_id && $check_definition->definition_id != $content['definition_id'])
{
throw new Exception('Already exists');
}
} catch (Exception $e) {
// throw new Exception('Already exists');
$content['duplicate_error'] = lang('Duplicate name, please choose another.');
// Try some suggestions
$suggestions = array(
$content['name'] .'-'. $GLOBALS['egw_info']['user']['account_lid'],
$content['name'] .'-'. $GLOBALS['egw_info']['user']['account_id'],
$content['name'] .'-'. egw_time::to('now', true),
//$content['name'] .'-'. rand(0,100),
);
foreach($suggestions as $key => $suggestion) {
$sug_definition = new importexport_definition($suggestion);
if($sug_definition->definition_id) {
unset($suggestions[$key]);
}
}
if($suggestions) {
$content['duplicate_error'] .= ' '. lang('Try')." \n" . implode("\n", $suggestions);
}
return $this->get_step($content['step'],0);
}
}
// return from step21
if ($content['step'] == 'wizard_step21' && !$duplicate)
{
switch (array_search('pressed', $content['button']))
{
case 'next':
return $this->get_step($content['step'],1);
case 'previous' :
return $this->get_step($content['step'],-1);
case 'finish':
return 'wizard_finish';
default :
return $this->wizard_step21($content,$sel_options,$readonlys,$preserv);
}
}
// init step21
else
{
$content['msg'] = $this->steps['wizard_step21'] . ($duplicate ? "\n".$content['duplicate_error'] : '');
$content['step'] = 'wizard_step21';
unset($content['duplicate_error']);
$preserv = $content;
unset ($preserv['button']);
return 'importexport.wizard_choosename';
}
}
// allowed users
function wizard_step90(&$content, &$sel_options, &$readonlys, &$preserv)
{
if(self::_debug) error_log('importexport.importexport_definitions_ui::wizard_step90->$content '.print_r($content,true));
// return from step90
if ($content['step'] == 'wizard_step90')
{
if($this->can_edit($content))
{
$content['owner'] = $content['just_me'] || !$GLOBALS['egw']->acl->check('share_definitions', EGW_ACL_READ,'importexport') ?
($content['owner'] ? $content['owner'] : $GLOBALS['egw_info']['user']['account_id']) :
null;
$content['allowed_users'] = $content['just_me'] ? '' : ($content['all_users'] ? 'all' : implode(',',$content['allowed_users']));
unset($content['just_me']);
}
// workaround for some ugly bug related to readonlys;
switch (array_search('pressed', $content['button']))
{
case 'previous' :
return $this->get_step($content['step'],-1);
case 'next':
case 'finish':
return 'wizard_finish';
default :
return $this->wizard_step90($content,$sel_options,$readonlys,$preserv);
}
}
// init step90
else
{
$content['msg'] = $this->steps['wizard_step90'];
$content['step'] = 'wizard_step90';
$preserv = $content;
// Set owner for non-admins
$content['just_me'] = ((!$content['allowed_users'] || !$content['allowed_users'][0] && count($content['allowed_users']) ==1) && $content['owner']);
//if(!$GLOBALS['egw_info']['user']['apps']['admin'] && !$GLOBALS['egw']->acl->check('share_definition', EGW_ACL_READ, 'importexport')) {
if(!$GLOBALS['egw']->acl->check('share_definition', EGW_ACL_READ, 'importexport') && !$GLOBALS['egw_info']['user']['apps']['admin']) {
$content['allowed_users'] = array();
$readonlys['allowed_users'] = true;
$readonlys['just_me'] = true;
$readonlys['all_users'] = true;
$content['just_me'] = true;
}
// Hide 'just me' checkbox, users get confused by read-only
if($readonlys['just_me'] || !$this->can_edit($content))
{
$content['no_just_me'] = true;
}
if($readonlys['all_users'] || !$this->can_edit($content))
{
$content['no_all_users'] = true;
}
unset ($preserv['button']);
$GLOBALS['egw']->js->set_onload("disable_button('exec[button][next]');");
if(is_object($this->response)) {
$this->response->addAssign('exec[button][next]','style.display', 'none');
}
return 'importexport.wizard_chooseallowedusers';
}
}
function wizard_finish(&$content)
{
if(self::_debug) error_log('importexport.importexport_definitions_ui::wizard_finish->$content '.print_r($content,true));
// Take out some UI leavings
unset($content['msg']);
unset($content['step']);
unset($content['button']);
$bodefinitions = new importexport_definitions_bo();
$bodefinitions->save($content);
// This message is displayed if browser cant close window
$content['msg'] = lang('ImportExport wizard finished successfully!');
$content['closewindow'] = true;
return 'importexport.wizard_close';
}
function import_definition($content='')
{
$bodefinitions = new importexport_definitions_bo();
if (is_array($content))
{
if($content['import_file']['tmp_name'])
{
$result = $bodefinitions->import($content['import_file']['tmp_name']);
$msg = lang('%1 definitions %2', count($result), lang('imported')) ."\n". implode("\n", array_keys($result));
return $this->index(null, $msg);
}
if($content['update'])
{
$applist = importexport_helper_functions::get_apps('all', true);
foreach($applist as $appname) {
importexport_helper_functions::load_defaults($appname);
}
return $this->index();
}
}
else
{
$etpl = new etemplate(self::_appname.'.import_definition');
return $etpl->exec(self::_appname.'.importexport_definitions_ui.import_definition',$content,array(),$readonlys,$preserv);
}
}
/**
* Determine if the user is allowed to edit the definition
*
*/
protected function can_edit(Array $definition)
{
if($definition['owner'] && $definition['owner'] == $GLOBALS['egw_info']['user']['account_id'])
{
// Definition belongs to user
return true;
}
elseif($definition['definition_id'] && !$definition['owner'] && $GLOBALS['egw_info']['user']['apps']['admin'])
{
// Definition is unowned, and user is an admin
return true;
}
elseif(!$definition['definition_id'])
{
// Definition is in-progress, not saved yet
return true;
}
return false;
}
/**
* Site configuration
*/
public function site_config($content = array())
{
if(!$GLOBALS['egw_info']['user']['apps']['admin'])
{
egw::redirect_link('/home');
}
if($content['save'])
{
unset($content['save']);
// ACL
$GLOBALS['egw']->acl->delete_repository(self::_appname, 'definition',false);
$GLOBALS['egw']->acl->delete_repository(self::_appname, 'share_definition',false);
foreach($content['share_definition'] as $group)
{
$GLOBALS['egw']->acl->add_repository(self::_appname, 'share_definition', $group,EGW_ACL_READ);
}
unset($content['share_definition']);
// Other config
foreach($content as $key=>$value)
{
config::save_value($key, $value, 'importexport');
}
} elseif (isset($content['cancel'])) {
$GLOBALS['egw']->redirect_link('/admin/index.php');
}
$data = config::read(self::_appname);
$data['share_definition'] = $GLOBALS['egw']->acl->get_ids_for_location('share_definition', EGW_ACL_READ, self::_appname);
$sel_options['import_charsets'] = array_combine(mb_list_encodings(),mb_list_encodings());
// Remove 'standard' encodings to prevent doubles
foreach($GLOBALS['egw']->translation->get_installed_charsets() as $charset => $label)
{
unset($sel_options['import_charsets'][strtoupper($charset)]);
}
if(!$data['update']) $data['update'] = 'request';
$GLOBALS['egw_info']['flags']['app_header'] = lang('Site configuration') . ' - ' . lang(self::_appname);
$etpl = new etemplate(self::_appname.'.config');
$etpl->exec(self::_appname.'.importexport_definitions_ui.site_config',$data,$sel_options,$readonlys,$preserv);
}
}