mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 06:30:59 +01:00
- Uploading a new file to a definition fully clears mapping - should fix some of the mapping confusion
- Add new / edit definition links in import dialog now open in new window, at the correct step - Reworked import file checking
This commit is contained in:
parent
c50a83a9a4
commit
b38775db65
@ -425,11 +425,37 @@ class importexport_definitions_ui
|
||||
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'])
|
||||
{
|
||||
//close window
|
||||
$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']))
|
||||
{
|
||||
@ -442,6 +468,14 @@ class importexport_definitions_ui
|
||||
$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);
|
||||
}
|
||||
|
||||
@ -572,7 +606,7 @@ class importexport_definitions_ui
|
||||
if ($content['closewindow'])
|
||||
{
|
||||
$this->response->addScript("window.close();");
|
||||
$this->response->addScript("opener.location = '" . egw::link('/index.php', array('menuaction' => 'importexport.importexport_definitions_ui.index')) . "';");
|
||||
//$this->response->addScript("opener.location = '" . egw::link('/index.php', array('menuaction' => 'importexport.importexport_definitions_ui.index')) . "';");
|
||||
// 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');
|
||||
|
@ -230,13 +230,6 @@ class importexport_import_csv implements importexport_iface_import_record { //,
|
||||
protected function do_fieldmapping( ) {
|
||||
$record = $this->record;
|
||||
$this->record = array();
|
||||
if(count($this->mapping) !== count($record))
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang("Column mismatch. Expected %1 columns, your file has %2.",
|
||||
count($this->mapping),
|
||||
count($record)
|
||||
));
|
||||
}
|
||||
foreach ($this->mapping as $cvs_idx => $new_idx)
|
||||
{
|
||||
if( $new_idx == '' ) continue;
|
||||
|
@ -78,26 +78,34 @@
|
||||
$GLOBALS['egw_info']['flags']['currentapp'] = $appname;
|
||||
|
||||
// Destination if we need to hold the file
|
||||
$cachefile = new egw_cache_files(array());
|
||||
$dst_file = $cachefile->filename(egw_cache::keys(egw_cache::INSTANCE, 'importexport',
|
||||
'import_'.md5($content['file']['name'].$GLOBALS['egw_info']['user']['account_id']), true),true);
|
||||
if($content['dry-run'])
|
||||
if($file)
|
||||
{
|
||||
echo $this->preview($file, $definition_obj);
|
||||
$cachefile = new egw_cache_files(array());
|
||||
$dst_file = $cachefile->filename(egw_cache::keys(egw_cache::INSTANCE, 'importexport',
|
||||
'import_'.md5($content['file']['name'].$GLOBALS['egw_info']['user']['account_id']), true),true);
|
||||
// Keep file
|
||||
if($dst_file)
|
||||
{
|
||||
if(copy($content['file']['tmp_name'],$dst_file)) {
|
||||
if($content['file']['name'] && copy($content['file']['tmp_name'],$dst_file)) {
|
||||
$preserve['file']['tmp_name'] = $dst_file;
|
||||
}
|
||||
}
|
||||
} elseif ($dst_file && $content['file']['tmp_name'] == $dst_file) {
|
||||
// Remove file
|
||||
$cachefile->delete(egw_cache::keys(egw_cache::INSTANCE, 'importexport',
|
||||
'import_'.md5($content['file']['name'].$GLOBALS['egw_info']['user']['account_id'])));
|
||||
|
||||
// Check on matching columns
|
||||
$check_message = array();
|
||||
if(!self::check_file($file, $definition_obj, $check_message, $dst_file))
|
||||
{
|
||||
// Set this so plugin doesn't do any data changes
|
||||
$content['dry-run'] = true;
|
||||
$definition_obj->plugin_options = (array)$definition_obj->plugin_options + array('dry_run' => true);
|
||||
}
|
||||
$this->message .= implode($check_message, "<br />\n") . "<br />\n";
|
||||
if($content['dry-run'])
|
||||
{
|
||||
echo $this->preview($file, $definition_obj);
|
||||
}
|
||||
$count = $plugin->import($file, $definition_obj);
|
||||
}
|
||||
|
||||
$count = $plugin->import($file, $definition_obj);
|
||||
|
||||
$this->message .= lang('%1 records processed', $count);
|
||||
|
||||
@ -121,31 +129,15 @@
|
||||
}
|
||||
if($count != $total_processed) $this->message .= "<br />\n".lang('Some records may not have been imported');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->message = $e->getMessage();
|
||||
|
||||
// Add links for new / edit definition
|
||||
$config = config::read('importexport');
|
||||
if($GLOBALS['egw_info']['user']['apps']['admin'] || $config['users_create_definitions'])
|
||||
{
|
||||
// New definition
|
||||
$add_link = egw::link('/index.php',array(
|
||||
'menuaction' => 'importexport.importexport_definitions_ui.edit'
|
||||
));
|
||||
$this->message .= "<br />\n" . lang('Create a <a href="%1">new definition</a> for this file.', $add_link);
|
||||
|
||||
// Edit selected definition, if allowed
|
||||
if($definition_obj->owner == $GLOBALS['egw_info']['user']['account_id'] ||
|
||||
!$definition_obj->owner && $GLOBALS['egw_info']['user']['apps']['admin'])
|
||||
{
|
||||
$edit_link = egw::link('/index.php',array(
|
||||
'menuaction' => 'importexport.importexport_definitions_ui.edit',
|
||||
'definition' => $definition
|
||||
));
|
||||
$this->message .= "<br />\n" . lang('<a href="%1">Edit definition %2</a>',
|
||||
$edit_link, $definition_obj->name );
|
||||
}
|
||||
if ($dst_file && $content['file']['tmp_name'] == $dst_file) {
|
||||
// Remove file
|
||||
$cachefile->delete(egw_cache::keys(egw_cache::INSTANCE, 'importexport',
|
||||
'import_'.md5($content['file']['name'].$GLOBALS['egw_info']['user']['account_id'])));
|
||||
unset($dst_file);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$this->message .= $e->getMessage();
|
||||
}
|
||||
}
|
||||
elseif($content['cancel'])
|
||||
@ -161,6 +153,11 @@
|
||||
);
|
||||
}
|
||||
|
||||
if(!array_key_exists('dry-run',$content))
|
||||
{
|
||||
$data['dry-run'] = true;
|
||||
}
|
||||
|
||||
$data['appname'] = $preserve['appname'] = $appname ? $appname : ($definition_obj ? $definition_obj->application : '');
|
||||
$data['definition'] = $definition;
|
||||
$data['delimiter'] = $definition_obj->plugin_options['delimiter'];
|
||||
@ -264,7 +261,91 @@
|
||||
|
||||
// Rewind
|
||||
rewind($_stream);
|
||||
return html::table($rows);
|
||||
return '<h2>' . lang('Preview') . '</h2>' . html::table($rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple check to see if the file at least matches the definition
|
||||
*
|
||||
* Checks that column headers match
|
||||
*/
|
||||
public static function check_file(&$file, &$definition, &$message = array(), $dst_file = false)
|
||||
{
|
||||
$options =& $definition->plugin_options;
|
||||
$data = fgetcsv($file, 8000, $options['fieldsep']);
|
||||
rewind($file);
|
||||
$data = translation::convert($data,$options['charset']);
|
||||
|
||||
$ok = true;
|
||||
if(max(array_keys($data)) != max(array_keys($options['csv_fields'])))
|
||||
{
|
||||
$message[] = lang("Column mismatch. Expected %1 columns, your file has %2.",
|
||||
max(array_keys($options['csv_fields'])),
|
||||
max(array_keys($data))
|
||||
);
|
||||
$ok = false;
|
||||
}
|
||||
foreach($data as $index => $header)
|
||||
{
|
||||
if($index < count($options['csv_fields']) && !$options['field_mapping'][$index])
|
||||
{
|
||||
// Skipped column in definition
|
||||
continue;
|
||||
}
|
||||
elseif($index < count($options['csv_fields']) && $options['csv_fields'][$index] != $header)
|
||||
{
|
||||
// Problem
|
||||
$message[] = lang("Column mismatch: %1 should be %2, not %3",
|
||||
$index,$options['csv_fields'][$index], $header);
|
||||
// But can still continue
|
||||
// $ok = false;
|
||||
}
|
||||
}
|
||||
if(!$ok)
|
||||
{
|
||||
// Add links for new / edit definition
|
||||
$config = config::read('importexport');
|
||||
if($GLOBALS['egw_info']['user']['apps']['admin'] || $config['users_create_definitions'])
|
||||
{
|
||||
$actions = '';
|
||||
// New definition
|
||||
$add_link = egw::link('/index.php',array(
|
||||
'menuaction' => 'importexport.importexport_definitions_ui.edit',
|
||||
'application' => $definition->application,
|
||||
'plugin' => $definition->plugin,
|
||||
// Jump to name step
|
||||
'step' => 'wizard_step21'
|
||||
));
|
||||
$add_link = "javascript:egw_openWindowCentered2('$add_link','_blank',500,500,'yes')";
|
||||
$actions[] = lang('Create a <a href="%1">new definition</a> for this file', $add_link);
|
||||
|
||||
// Edit selected definition, if allowed
|
||||
if($definition->owner == $GLOBALS['egw_info']['user']['account_id'] ||
|
||||
!$definition->owner && $GLOBALS['egw_info']['user']['apps']['admin'])
|
||||
{
|
||||
$edit_link = array(
|
||||
'menuaction' => 'importexport.importexport_definitions_ui.edit',
|
||||
'definition' => $definition->name,
|
||||
// Jump to file step
|
||||
'step' => 'wizard_step21'
|
||||
);
|
||||
if($dst_file)
|
||||
{
|
||||
// Still have uploaded file, jump there
|
||||
$GLOBALS['egw']->session->appsession('csvfile','',$dst_file);
|
||||
$edit_link['step'] = 'wizard_step30';
|
||||
}
|
||||
$edit_link = egw::link('/index.php',$edit_link);
|
||||
$edit_link = "javascript:egw_openWindowCentered2('$edit_link','_blank',500,500,'yes')";
|
||||
$actions[] = lang('Edit definition <a href="%1">%2</a> to match your file',
|
||||
$edit_link, $definition->name );
|
||||
}
|
||||
$actions[] = lang('Edit your file to match the definition: ')
|
||||
. implode(array_intersect_key($options['csv_fields'],$options['field_mapping']),', ');
|
||||
$message[] = "\n<li>".implode($actions,"\n<li>");
|
||||
}
|
||||
}
|
||||
return $ok;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -1,12 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare - A basic implementation of a wizard to go with the basic CSV plugin.
|
||||
*
|
||||
*
|
||||
* To add or remove steps, change $this->steps appropriately. The key is the function, the value is the title.
|
||||
* Don't go past 80, as that's where the wizard picks it back up again to finish it off.
|
||||
*
|
||||
*
|
||||
* For the mapping to work properly, you will have to fill $mapping_fields with the target fields for your application.
|
||||
*
|
||||
*
|
||||
* NB: Your wizard class must be in <appname>/inc/class.appname_wizard_<plugin_name>.inc.php
|
||||
*
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
@ -15,7 +15,7 @@
|
||||
* @author Nathan Gray
|
||||
*/
|
||||
|
||||
class importexport_wizard_basic_import_csv
|
||||
class importexport_wizard_basic_import_csv
|
||||
{
|
||||
|
||||
const TEMPLATE_MARKER = '-eTemplate-';
|
||||
@ -81,7 +81,7 @@ class importexport_wizard_basic_import_csv
|
||||
if($content['file']['tmp_name']) {
|
||||
$csvfile = tempnam($GLOBALS['egw_info']['server']['temp_dir'],$content['plugin']."_");
|
||||
move_uploaded_file($content['file']['tmp_name'], $csvfile);
|
||||
$GLOBALS['egw']->session->appsession('csvfile','',$csvfile);
|
||||
$GLOBALS['egw']->session->appsession('csvfile',$content['application'],$csvfile);
|
||||
}
|
||||
unset($content['file']);
|
||||
return $GLOBALS['egw']->importexport_definitions_ui->get_step($content['step'],1);
|
||||
@ -124,20 +124,22 @@ class importexport_wizard_basic_import_csv
|
||||
{
|
||||
case 'next':
|
||||
// Process sample file for fields
|
||||
if (($handle = fopen($GLOBALS['egw']->session->appsession('csvfile'), "rb")) !== FALSE) {
|
||||
if (($handle = fopen($GLOBALS['egw']->session->appsession('csvfile',$content['application']), "rb")) !== FALSE) {
|
||||
$data = fgetcsv($handle, 8000, $content['fieldsep']);
|
||||
fclose($handle);
|
||||
unlink($GLOBALS['egw']->session->appsession('csvfile'));
|
||||
|
||||
// Remove & forget file
|
||||
unlink($GLOBALS['egw']->session->appsession('csvfile',$content['application']));
|
||||
egw_cache::setSession($content['application'], 'csvfile', '');
|
||||
$content['csv_fields'] = translation::convert($data,$content['charset']);
|
||||
|
||||
// Reset field mapping for new file
|
||||
$content['field_mapping'] = array();
|
||||
|
||||
// Try to match automatically
|
||||
$english = array();
|
||||
foreach($content['csv_fields'] as $index => $field) {
|
||||
if($content['field_mapping'][$index]) continue;
|
||||
if(is_array($content['plugin_options']['field_mapping']) && $content['plugin_options']['field_mapping'][$index]) {
|
||||
# Copy already set, but allow new file to update
|
||||
$content['field_mapping'][$index] = $content['plugin_options']['field_mapping'][$index];
|
||||
}
|
||||
$best_match = '';
|
||||
$best_match_value = 0;
|
||||
foreach($this->mapping_fields as $key => $field_name) {
|
||||
@ -162,7 +164,7 @@ class importexport_wizard_basic_import_csv
|
||||
|
||||
// Check for similar but slightly different
|
||||
$match = 0;
|
||||
if(similar_text(strtolower($field), strtolower($field_name), $match) &&
|
||||
if(similar_text(strtolower($field), strtolower($field_name), $match) &&
|
||||
$match > 85 &&
|
||||
$match > $best_match_value
|
||||
) {
|
||||
@ -208,12 +210,22 @@ class importexport_wizard_basic_import_csv
|
||||
if(!$content['num_header_lines'] && $content['plugin_options']['num_header_lines']) {
|
||||
$content['num_header_lines'] = $content['plugin_options']['num_header_lines'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to 1 line
|
||||
$content['num_header_lines'] = 1;
|
||||
}
|
||||
if(!$content['update_cats'] && $content['plugin_options']['update_cats']) {
|
||||
$content['update_cats'] = $content['plugin_options']['update_cats'];
|
||||
}
|
||||
if(!array_key_exists('convert', $content) && array_key_exists('convert', $content['plugin_options'])) {
|
||||
$content['convert'] = $content['plugin_options']['convert'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to human
|
||||
$content['convert'] = 1;
|
||||
}
|
||||
|
||||
$sel_options['charset'] = $GLOBALS['egw']->translation->get_installed_charsets()+
|
||||
array(
|
||||
@ -247,10 +259,10 @@ class importexport_wizard_basic_import_csv
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the sample file, get the fields out of it, then allow them to be mapped onto
|
||||
* Process the sample file, get the fields out of it, then allow them to be mapped onto
|
||||
* the fields the destination understands. Also, set any translations to be done to the field.
|
||||
*
|
||||
* You can use the eTemplate
|
||||
*
|
||||
* You can use the eTemplate
|
||||
*/
|
||||
function wizard_step50(&$content, &$sel_options, &$readonlys, &$preserv)
|
||||
{
|
||||
@ -328,7 +340,7 @@ class importexport_wizard_basic_import_csv
|
||||
$content[++$i]['index'] = $i - 1;
|
||||
if(strstr($field,'no_csv_')) $j++;
|
||||
}
|
||||
while ($j <= 3)
|
||||
while ($j <= 3)
|
||||
{
|
||||
$content['csv_fields'][] = 'no_csv_'.$j;
|
||||
$content['field_mapping'][] = $content['field_conversion'][] = '';
|
||||
@ -395,7 +407,7 @@ class importexport_wizard_basic_import_csv
|
||||
|
||||
// Make at least 1 (empty) conditions
|
||||
$j = count($content['conditions']);
|
||||
while ($j < 1)
|
||||
while ($j < 1)
|
||||
{
|
||||
$content['conditions'][] = array(
|
||||
'string' => '',
|
||||
|
Loading…
Reference in New Issue
Block a user