* InfoLog: make fields excluded from copying to a new sub-entry configurable and add scheduling an appointment to action

refactured copy and sub creation into one method, as they do essentialy the same thing with just setting the parent and excluding different configurable fields
This commit is contained in:
Ralf Becker 2012-02-24 09:29:27 +00:00
parent 2f2a252b51
commit ec694d4a4f
4 changed files with 184 additions and 119 deletions

View File

@ -60,11 +60,17 @@ class infolog_bo
*/ */
var $responsible_edit=array('info_status','info_percent','info_datecompleted'); var $responsible_edit=array('info_status','info_percent','info_datecompleted');
/** /**
* fields a user may exclude from copy, if an entry is copied, the ones below are excluded by default. * Fields to exclude from copy, if an entry is copied, the ones below are excluded by default.
* *
* @var array * @var array
*/ */
var $copy_excludefields = array('info_id', 'info_uid', 'info_etag', 'caldav_name', 'info_created', 'info_creator', 'info_datemodified', 'info_modifier'); var $copy_excludefields = array('info_id', 'info_uid', 'info_etag', 'caldav_name', 'info_created', 'info_creator', 'info_datemodified', 'info_modifier');
/**
* Fields to exclude from copy, if a sub-entry is created, the ones below are excluded by default.
*
* @var array
*/
var $sub_excludefields = array('info_des','info_id', 'info_uid', 'info_etag', 'caldav_name', 'info_created', 'info_creator', 'info_datemodified', 'info_modifier');
/** /**
* implicit ACL rights of the responsible user: read or edit * implicit ACL rights of the responsible user: read or edit
* *
@ -236,6 +242,11 @@ class infolog_bo
{ {
$this->copy_excludefields = array_merge($this->copy_excludefields,$config_data['copy_excludefields']); $this->copy_excludefields = array_merge($this->copy_excludefields,$config_data['copy_excludefields']);
} }
if (is_array($config_data['sub_excludefields']) && $config_data['sub_excludefields'])
{
if (($k = array_search('info_des',$this->sub_excludefields))) unset($this->sub_excludefields[$k]);
$this->sub_excludefields = array_merge($this->sub_excludefields,$config_data['sub_excludefields']);
}
if ($config_data['implicit_rights'] == 'edit') if ($config_data['implicit_rights'] == 'edit')
{ {
$this->implicit_rights = 'edit'; $this->implicit_rights = 'edit';
@ -802,7 +813,8 @@ class infolog_bo
} }
// Check required custom fields // Check required custom fields
if($throw_exception) { if($throw_exception)
{
$custom = config::get_customfields('infolog'); $custom = config::get_customfields('infolog');
foreach($custom as $c_name => $c_field) foreach($custom as $c_name => $c_field)
{ {

View File

@ -5,7 +5,7 @@
* @link http://www.egroupware.org * @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de> * @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package infolog * @package infolog
* @copyright (c) 2003-10 by Ralf Becker <RalfBecker-AT-outdoor-training.de> * @copyright (c) 2003-12 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @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
* @version $Id$ * @version $Id$
*/ */

View File

@ -1466,7 +1466,7 @@ class infolog_ui
function edit($content = null,$action = '',$action_id=0,$type='',$referer='') function edit($content = null,$action = '',$action_id=0,$type='',$referer='')
{ {
$tabs = 'description|links|delegation|project|customfields|history'; $tabs = 'description|links|delegation|project|customfields|history';
if (is_array($content)) if (($submit = is_array($content)))
{ {
//echo "infolog_ui::edit: content="; _debug_array($content); //echo "infolog_ui::edit: content="; _debug_array($content);
$info_id = $content['info_id']; $info_id = $content['info_id'];
@ -1483,9 +1483,12 @@ class infolog_ui
unset($content['button']); unset($content['button']);
if ($button) if ($button)
{ {
//Copy Infolog // Copy or schedule Infolog
if ($button == 'copy') $action = 'copy'; if (in_array($button,array('copy','schedule')))
{
$action = $button;
if (!$info_id) $button = 'apply'; // need to store infolog first
}
if ($button == 'print') if ($button == 'print')
{ {
$content['js'] = $this->custom_print($content,!$content['info_id'])."\n".$js; // first open the new window and then update the view $content['js'] = $this->custom_print($content,!$content['info_id'])."\n".$js; // first open the new window and then update the view
@ -1494,7 +1497,7 @@ class infolog_ui
if (($button == 'save' || $button == 'apply') && isset($content['info_subject']) && empty($content['info_subject'])) if (($button == 'save' || $button == 'apply') && isset($content['info_subject']) && empty($content['info_subject']))
{ {
$this->tmpl->set_validation_error('info_subject',lang('Field must not be empty !!!')); $this->tmpl->set_validation_error('info_subject',lang('Field must not be empty !!!'));
$button = ''; // stop save or apply $button = $action = ''; // stop save or apply
} }
if (($button == 'save' || $button == 'apply') && $info_id) if (($button == 'save' || $button == 'apply') && $info_id)
{ {
@ -1531,7 +1534,7 @@ class infolog_ui
'no_popup' => $no_popup, 'no_popup' => $no_popup,
'referer' => $referer, 'referer' => $referer,
))).'">','</a>'); ))).'">','</a>');
$button = ''; // not exiting edit $button = $action = ''; // not exiting edit
$info_id = $content['info_id']; $info_id = $content['info_id'];
} }
else else
@ -1626,7 +1629,7 @@ class infolog_ui
if ($content['info_status'] != 'done') $content['info_datecompleted'] = ''; if ($content['info_status'] != 'done') $content['info_datecompleted'] = '';
} }
} }
else else // new call via GET
{ {
//echo "<p>infolog_ui::edit: info_id=$info_id, action='$action', action_id='$action_id', type='$type', referer='$referer'</p>\n"; //echo "<p>infolog_ui::edit: info_id=$info_id, action='$action', action_id='$action_id', type='$type', referer='$referer'</p>\n";
$action = $action ? $action : get_var('action', array('POST','GET')); $action = $action ? $action : get_var('action', array('POST','GET'));
@ -1695,36 +1698,6 @@ class infolog_ui
{ {
return $referer ? $this->tmpl->location($referer) : $this->index(0,$action,$action_id); return $referer ? $this->tmpl->location($referer) : $this->index(0,$action,$action_id);
} }
$parent = $this->bo->so->data;
$content['info_id'] = $info_id = 0;
$content['info_uid'] = ''; // ensure that we have our own UID
$content['caldav_name'] = ''; // ensure that we have our own caldav_name
$content['info_owner'] = $this->user;
$content['info_id_parent'] = $parent['info_id'];
/*
if ($parent['info_type']=='task' && $parent['info_status']=='offer')
{
$content['info_type'] = 'confirm'; // confirmation to parent
$content['info_responsible'] = $parent['info_owner'];
}
*/
$content['info_type'] = $parent['info_type'];
$content['info_status'] = $this->bo->status['defaults'][$content['info_type']];
$content['info_percent'] = $content['info_status'] == 'done' ? '100%' : '0%';
$content['info_datecompleted'] =$content['info_status'] == 'done' ? $this->bo->user_time_now : 0;
$content['info_confirm'] = 'not';
$config = config::read('infolog');
$content['info_subject']= lang(empty($config['sub_prefix']) ? 'Re:': $config['sub_prefix']).' '.$parent['info_subject'];
$content['info_des'] = '';
$content['info_lastmodified'] = '';
if ($content['info_startdate'] < $this->bo->user_time_now) // parent-startdate is in the past => today
{
$content['info_startdate'] = $set_startdate;
}
if ($content['info_enddate'] < $this->bo->user_time_now) // parent-enddate is in the past => empty
{
$content['info_enddate'] = '';
}
} }
else else
{ {
@ -1734,19 +1707,25 @@ class infolog_ui
'to_id' => $info_id, 'to_id' => $info_id,
'to_app' => 'infolog', 'to_app' => 'infolog',
); );
}
// new call via GET or some actions handled here, as they can happen both ways ($_GET[action] or button/action in GUI)
if (!$submit || in_array($action,array('sp','copy','schedule')))
{
switch ($action) switch ($action)
{ {
case 'sp': case 'schedule':
$links = egw_link::get_links('infolog',$parent['info_id'],'!'.egw_link::VFS_APPNAME); egw::redirect_link('/index.php',array(
foreach($links as $link) 'menuaction' => 'calendar.calendar_uiforms.edit',
{ 'link_app' => 'infolog',
$link_id = egw_link::link('infolog',$content['link_to']['to_id'],$link['app'],$link['id'],$link['remark']); 'link_id' => $info_id,
));
break;
if ($parent['info_link_id'] == $link['link_id']) case 'sp':
{ case 'copy':
$content['info_link_id'] = $link_id; $info_id = 0;
} $this->create_copy($content, $action == 'sp');
} unset($action); // it get stored in $content and will cause an other copy after [apply]
break; break;
case 'tracker': case 'tracker':
@ -1781,8 +1760,11 @@ class infolog_ui
egw_link::link('infolog',$content['link_to']['to_id'],$action,$id); egw_link::link('infolog',$content['link_to']['to_id'],$action,$id);
} }
$content['blur_title'] = egw_link::title($action,'$id').",..."; $content['blur_title'] = egw_link::title($action,'$id').",...";
} else { }
if ($action_id) { else
{
if ($action_id)
{
egw_link::link('infolog',$content['link_to']['to_id'],$action,$action_id); egw_link::link('infolog',$content['link_to']['to_id'],$action,$action_id);
$content['blur_title'] = egw_link::title($action,$action_id); $content['blur_title'] = egw_link::title($action,$action_id);
} }
@ -1815,58 +1797,6 @@ class infolog_ui
$content['info_type'] = 'note'; $content['info_type'] = 'note';
} }
} }
if ($action == 'copy') // get's called via actions selectbox or url (action=copy&info_id=123)
{
unset($content['info_id']);
unset ($info_id);
unset($content['info_datemodified']);
unset($content['info_modifier']);
foreach ($this->bo->copy_excludefields as $k => $f) if (isset($content[$f])) unset($content[$f]);
if (!isset($content['info_startdate']))
{
switch($this->prefs['set_start'])
{
case 'date': default: $set_startdate = mktime(0,0,0,date('m',$this->bo->user_time_now),date('d',$this->bo->user_time_now),date('Y',$this->bo->user_time_now)); break;
case 'datetime': $set_startdate = $this->bo->user_time_now; break;
case 'empty': $set_startdate = 0; break;
}
$content['info_startdate'] = $set_startdate;
}
$types = $this->get_validtypes();
$typekeys = array_keys($types);
if (!isset($content['info_type'])) $content['info_type'] = $typekeys[0];
if (!isset($content['info_status'])) $content['info_status'] = $this->bo->status['defaults'][$content['info_type']];
if (!isset($content['info_cat'])) $content['info_cat'] = $this->prefs['cat_add_default'];
// Get links to be copied
$content['link_to']['to_id'] = egw_link::get_links($content['link_to']['to_app'], $content['link_to']['to_id']);
// Special mangling for files so the files get copied
foreach($content['link_to']['to_id'] as $link_id => &$link)
{
if ($link['app'] == egw_link::VFS_APPNAME)
{
$link['id'] = $link + array(
'tmp_name' => egw_link::vfs_path($link['app2'], $link['id2']).'/'.$link['id'],
'name' => $link['id'],
);
}
}
if($content['info_link_id'])
{
$info_link_id = $content['info_link_id'];
// we need this if copy is triggered via context menu action
if (!isset($content['info_contact'])||empty($content['info_contact'])||$content['info_contact']==='copy:')
{
$linkinfos = egw_link::get_link($info_link_id);
$content['info_contact'] = $linkinfos['link_app1']=='infolog'? $linkinfos['link_app2'].':'.$linkinfos['link_id2']:$linkinfos['link_app1'].':'.$linkinfos['link_id1'];
if (stripos($content['info_contact'],'projectmanager')!==false) $content['pm_id'] = $linkinfos['link_app1']=='projectmanager'? $linkinfos['link_id1']:$linkinfos['link_id2'];
}
unset($content['info_link_id']);
}
$content['info_owner'] = !(int)$this->owner || !$this->bo->check_perms(EGW_ACL_ADD,0,$this->owner) ? $this->user : $this->owner;
$content['msg'] = lang('Infolog copied - the copy can now be edited');
$content['info_subject'] = ($content['info_subject']?lang('Copy of:').' ':'').$content['info_subject'];
unset($action); // it get stored in $content and will cause an other copy after [apply]
}
// group owners // group owners
$types = $this->bo->enums['type']; $types = $this->bo->enums['type'];
if ($this->bo->group_owners) if ($this->bo->group_owners)
@ -1999,6 +1929,22 @@ class infolog_ui
{ {
$readonlys[$tabs]['history'] = true; $readonlys[$tabs]['history'] = true;
} }
$sel_options = array(
'info_type' => $types,
'info_priority' => $this->bo->enums['priority'],
'info_confirm' => $this->bo->enums['confirm'],
'info_status' => $this->bo->status[$content['info_type']],
'status' => $history_stati,
'action' => array(
'copy' => array('label' => 'Copy', 'title' => 'Copy this Infolog'),
'sp' => 'Sub-entry',
'print' => array('label' => 'Print', 'title' => 'Print this Infolog'),
),
);
if ($GLOBALS['egw_info']['user']['apps']['calendar'])
{
$sel_options['action']['schedule'] = array('label' => 'Schedule', 'title' => 'Schedule appointment');
}
egw_framework::validate_file('.','edit','infolog'); egw_framework::validate_file('.','edit','infolog');
$GLOBALS['egw_info']['flags']['app_header'] = lang('InfoLog').' - '. $GLOBALS['egw_info']['flags']['app_header'] = lang('InfoLog').' - '.
($content['status_only'] ? lang('Edit Status') : lang('Edit')); ($content['status_only'] ? lang('Edit Status') : lang('Edit'));
@ -2006,17 +1952,7 @@ class infolog_ui
//error_log(substr($content['info_des'],1793,10)); //error_log(substr($content['info_des'],1793,10));
//$content['info_des'] = substr($content['info_des'],0,1793); //$content['info_des'] = substr($content['info_des'],0,1793);
//echo "<p>infolog_ui.edit(info_id='$info_id',action='$action',action_id='$action_id') readonlys="; print_r($readonlys); echo ", content = "; _debug_array($content); //echo "<p>infolog_ui.edit(info_id='$info_id',action='$action',action_id='$action_id') readonlys="; print_r($readonlys); echo ", content = "; _debug_array($content);
$this->tmpl->exec('infolog.infolog_ui.edit',$content,array( $this->tmpl->exec('infolog.infolog_ui.edit',$content,$sel_options,$readonlys,$preserv+array( // preserved values
'info_type' => $types,
'info_priority' => $this->bo->enums['priority'],
'info_confirm' => $this->bo->enums['confirm'],
'info_status' => $this->bo->status[$content['info_type']],
'status' => $history_stati,
'action' => array(
'copy' => array('label' => 'Copy', 'title' => 'Copy this Infolog'),
'print' => array('label' => 'Print', 'title' => 'Print this Infolog'),
),
),$readonlys,$preserv+array( // preserved values
'info_id' => $info_id, 'info_id' => $info_id,
'action' => $action, 'action' => $action,
'action_id' => $action_id, 'action_id' => $action_id,
@ -2026,6 +1962,110 @@ class infolog_ui
),$no_popup ? 0 : 2); ),$no_popup ? 0 : 2);
} }
/**
* Create copy or sub-entry from an entry currently read into $content
*
* Taking into account prefs and config about what to copy
*
* @param array &$content
* @param boolean $create_sub=false true: create a sub-entry instead of a copy, default false to create a copy
*/
private function create_copy(array &$content, $create_sub=false)
{
$info_id = $content['info_id']; // it will be unset by exclude-fields
// empty fields configured to be excluded (also contains id, uid, ...)
$exclude_fields = $create_sub ? $this->bo->sub_excludefields : $this->bo->copy_excludefields;
foreach ($exclude_fields as $field)
{
unset($content[$field]);
if ($field == 'info_from') unset($content['info_link_id']); // both together is called contact in UI
}
if ($create_sub)
{
$content['info_id_parent'] = $info_id;
}
// no startdate or startdate in the past --> set startdate from pref
if (!isset($content['info_startdate']) || $content['info_startdate'] < $this->bo->user_time_now)
{
switch($this->prefs['set_start'])
{
case 'date': default: $set_startdate = mktime(0,0,0,date('m',$this->bo->user_time_now),date('d',$this->bo->user_time_now),date('Y',$this->bo->user_time_now)); break;
case 'datetime': $set_startdate = $this->bo->user_time_now; break;
case 'empty': $set_startdate = 0; break;
}
$content['info_startdate'] = $set_startdate;
}
// enddate in the past --> uset it
if (isset($content['info_enddate']) || $content['info_enddate'] < $this->bo->user_time_now)
{
unset($content['info_enddate']);
}
if (!isset($content['info_type']))
{
$types = array_keys($this->get_validtypes());
$content['info_type'] = $types[0];
}
// get a consistent status, percent and date-completed
if (!isset($content['info_status'])) $content['info_status'] = $this->bo->status['defaults'][$content['info_type']];
if (!isset($content['info_percent'])) $content['info_percent'] = $content['info_status'] == 'done' ? '100%' : '0%';
$content['info_datecompleted'] =$content['info_status'] == 'done' ? $this->bo->user_time_now : 0;
if (!isset($content['info_cat'])) $content['info_cat'] = $this->prefs['cat_add_default'];
$content['link_to']['to_app'] = 'infolog';
$content['link_to']['to_id'] = 0;
// Get links to be copied, if not excluded
if (!in_array('link_to',$exclude_fields))
{
$content['link_to']['to_id'] = egw_link::get_links($content['link_to']['to_app'], $info_id);
// Special mangling for files so the files get copied
foreach($content['link_to']['to_id'] as $link_id => &$link)
{
if ($link['app'] == egw_link::VFS_APPNAME)
{
$link['id'] = $link + array(
'tmp_name' => egw_link::vfs_path($link['app2'], $link['id2']).'/'.$link['id'],
'name' => $link['id'],
);
}
}
}
$content['links'] = $content['link_to'];
if ($content['info_link_id'])
{
$info_link_id = $content['info_link_id'];
// we need this if copy is triggered via context menu action
if (!isset($content['info_contact']) || empty($content['info_contact']) || $content['info_contact'] === 'copy:')
{
$linkinfos = egw_link::get_link($info_link_id);
$content['info_contact'] = $linkinfos['link_app1']=='infolog'? $linkinfos['link_app2'].':'.$linkinfos['link_id2']:$linkinfos['link_app1'].':'.$linkinfos['link_id1'];
if (stripos($content['info_contact'],'projectmanager')!==false) $content['pm_id'] = $linkinfos['link_app1']=='projectmanager'? $linkinfos['link_id1']:$linkinfos['link_id2'];
}
unset($content['info_link_id']);
}
$content['info_owner'] = !(int)$this->owner || !$this->bo->check_perms(EGW_ACL_ADD,0,$this->owner) ? $this->user : $this->owner;
if (!empty($content['info_subject']))
{
if ($create_sub)
{
$config = config::read('infolog');
$prefix = lang(empty($config['sub_prefix']) ? 'Re:': $config['sub_prefix']);
}
else
{
$prefix = lang('Copy of:');
}
$content['info_subject'] = $prefix.' '.$content['info_subject'];
}
if (!$create_sub)
{
$content['msg'] .= ($content['msg']?"\n":'').lang('Infolog copied - the copy can now be edited');
}
}
function icon($cat,$id,$status='') function icon($cat,$id,$status='')
{ {
if (!$status || !($icon = $this->icons[$cat][$id.'_'.$status])) if (!$status || !($icon = $this->icons[$cat][$id.'_'.$status]))
@ -2097,7 +2137,6 @@ class infolog_ui
'info_id_parent' => 'Parent', 'info_id_parent' => 'Parent',
'info_status' => 'Status', 'info_status' => 'Status',
'info_confirm' => 'Confirm', 'info_confirm' => 'Confirm',
'info_link_id' => 'primary link',
'pl_id' => 'pricelist', 'pl_id' => 'pricelist',
'info_price' => 'price', 'info_price' => 'price',
'info_percent' => 'completed', 'info_percent' => 'completed',
@ -2111,6 +2150,9 @@ class infolog_ui
{ {
$excludefields['#'.$name] = $data['label']; $excludefields['#'.$name] = $data['label'];
} }
$sub_excludefields = $excludefields;
unset($sub_excludefields['info_id_parent']); // always set to parent!
$config_data = config::read('infolog'); $config_data = config::read('infolog');
if($_POST['save'] || $_POST['apply']) if($_POST['save'] || $_POST['apply'])
@ -2134,6 +2176,7 @@ class infolog_ui
$this->bo->copy_excludefields = array_merge($this->bo->copy_excludefields,$extra); $this->bo->copy_excludefields = array_merge($this->bo->copy_excludefields,$extra);
} }
config::save_value('copy_excludefields',$this->bo->copy_excludefields,'infolog'); config::save_value('copy_excludefields',$this->bo->copy_excludefields,'infolog');
config::save_value('sub_excludefields',$this->bo->sub_excludefields,'infolog');
config::save_value('responsible_edit',$this->bo->responsible_edit,'infolog'); config::save_value('responsible_edit',$this->bo->responsible_edit,'infolog');
config::save_value('implicit_rights',$this->bo->implicit_rights = $_POST['implicit_rights'] == 'edit' ? 'edit' : 'read','infolog'); config::save_value('implicit_rights',$this->bo->implicit_rights = $_POST['implicit_rights'] == 'edit' ? 'edit' : 'read','infolog');
config::save_value('history',$this->bo->history = $_POST['history'],'infolog'); config::save_value('history',$this->bo->history = $_POST['history'],'infolog');
@ -2159,9 +2202,13 @@ class infolog_ui
'edit' => 'edit rights (full edit rights incl. making someone else responsible!)', 'edit' => 'edit rights (full edit rights incl. making someone else responsible!)',
)), )),
'lang_responsible_edit' => lang('Which additional fields should the responsible be allowed to edit without having edit rights?<br />Status, percent and date completed are always allowed.'), 'lang_responsible_edit' => lang('Which additional fields should the responsible be allowed to edit without having edit rights?<br />Status, percent and date completed are always allowed.'),
'responsible_edit' => html::checkbox_multiselect('responsible_edit',$this->bo->responsible_edit,$fields,false,'',11), 'responsible_edit' => html::checkbox_multiselect('responsible_edit',$this->bo->responsible_edit,$fields,false,'',6),
'lang_copy_excludefields' => lang('Fields to exclude from copy when copying an infolog? (some fields like id, uid, created, createdby, modified and modifiedby are excluded by default)'), 'lang_copy_excludefields' => lang('Fields to exclude when copying an infolog:').'<p>'.
'copy_excludefields' => html::checkbox_multiselect('copy_excludefields',$this->bo->copy_excludefields,$excludefields,false,'',11), lang('Fields id, uid, created, createdby, modified and modifier are always excluded.'),
'copy_excludefields' => html::checkbox_multiselect('copy_excludefields',$this->bo->copy_excludefields,$excludefields,false,'',6),
'lang_sub_excludefields' => lang('Fields to exclude when creating a sub-entry:').'<p>'.
lang('Fields id, uid, created, createdby, modified and modifier are always excluded.'),
'sub_excludefields' => html::checkbox_multiselect('sub_excludefields',$this->bo->sub_excludefields,$sub_excludefields,false,'',6),
'text' => lang('<b>file-attachments via symlinks</b> instead of uploads and retrieval via file:/path for direct lan-clients'), 'text' => lang('<b>file-attachments via symlinks</b> instead of uploads and retrieval via file:/path for direct lan-clients'),
'action_url' => html::link('/index.php',array('menuaction'=>'infolog.infolog_ui.admin')), 'action_url' => html::link('/index.php',array('menuaction'=>'infolog.infolog_ui.admin')),
'save_button' => html::submit_button('save','Save'), 'save_button' => html::submit_button('save','Save'),

View File

@ -41,6 +41,12 @@
{sub_prefix} {sub_prefix}
</td> </td>
</tr> </tr>
<tr class="row_on">
<td colspan="3">{lang_sub_excludefields}</td>
<td>
{sub_excludefields}
</td>
</tr>
<tr> <tr>
<td colspan="4" align="left"> <td colspan="4" align="left">
{save_button} &nbsp; {apply_button} &nbsp; {cancel_button} {save_button} &nbsp; {apply_button} &nbsp; {cancel_button}