From ec694d4a4f9d4d20124a968e9a167ef27a40b81a Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Fri, 24 Feb 2012 09:29:27 +0000 Subject: [PATCH] * 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 --- infolog/inc/class.infolog_bo.inc.php | 16 +- infolog/inc/class.infolog_hooks.inc.php | 2 +- infolog/inc/class.infolog_ui.inc.php | 279 ++++++++++++++---------- infolog/templates/default/admin.tpl | 6 + 4 files changed, 184 insertions(+), 119 deletions(-) diff --git a/infolog/inc/class.infolog_bo.inc.php b/infolog/inc/class.infolog_bo.inc.php index c74e328c58..d6d40c24d1 100644 --- a/infolog/inc/class.infolog_bo.inc.php +++ b/infolog/inc/class.infolog_bo.inc.php @@ -60,11 +60,17 @@ class infolog_bo */ 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 $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 * @@ -236,6 +242,11 @@ class infolog_bo { $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') { $this->implicit_rights = 'edit'; @@ -802,7 +813,8 @@ class infolog_bo } // Check required custom fields - if($throw_exception) { + if($throw_exception) + { $custom = config::get_customfields('infolog'); foreach($custom as $c_name => $c_field) { diff --git a/infolog/inc/class.infolog_hooks.inc.php b/infolog/inc/class.infolog_hooks.inc.php index 917b89c528..4997d90c17 100644 --- a/infolog/inc/class.infolog_hooks.inc.php +++ b/infolog/inc/class.infolog_hooks.inc.php @@ -5,7 +5,7 @@ * @link http://www.egroupware.org * @author Ralf Becker * @package infolog - * @copyright (c) 2003-10 by Ralf Becker + * @copyright (c) 2003-12 by Ralf Becker * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @version $Id$ */ diff --git a/infolog/inc/class.infolog_ui.inc.php b/infolog/inc/class.infolog_ui.inc.php index 31311bef53..1cdf072c65 100644 --- a/infolog/inc/class.infolog_ui.inc.php +++ b/infolog/inc/class.infolog_ui.inc.php @@ -1466,7 +1466,7 @@ class infolog_ui function edit($content = null,$action = '',$action_id=0,$type='',$referer='') { $tabs = 'description|links|delegation|project|customfields|history'; - if (is_array($content)) + if (($submit = is_array($content))) { //echo "infolog_ui::edit: content="; _debug_array($content); $info_id = $content['info_id']; @@ -1483,9 +1483,12 @@ class infolog_ui unset($content['button']); if ($button) { - //Copy Infolog - if ($button == 'copy') $action = 'copy'; - + // Copy or schedule Infolog + if (in_array($button,array('copy','schedule'))) + { + $action = $button; + if (!$info_id) $button = 'apply'; // need to store infolog first + } if ($button == 'print') { $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'])) { $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) { @@ -1531,7 +1534,7 @@ class infolog_ui 'no_popup' => $no_popup, 'referer' => $referer, ))).'">',''); - $button = ''; // not exiting edit + $button = $action = ''; // not exiting edit $info_id = $content['info_id']; } else @@ -1626,7 +1629,7 @@ class infolog_ui if ($content['info_status'] != 'done') $content['info_datecompleted'] = ''; } } - else + else // new call via GET { //echo "

infolog_ui::edit: info_id=$info_id, action='$action', action_id='$action_id', type='$type', referer='$referer'

\n"; $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); } - $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 { @@ -1734,19 +1707,25 @@ class infolog_ui 'to_id' => $info_id, '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) { - case 'sp': - $links = egw_link::get_links('infolog',$parent['info_id'],'!'.egw_link::VFS_APPNAME); - foreach($links as $link) - { - $link_id = egw_link::link('infolog',$content['link_to']['to_id'],$link['app'],$link['id'],$link['remark']); + case 'schedule': + egw::redirect_link('/index.php',array( + 'menuaction' => 'calendar.calendar_uiforms.edit', + 'link_app' => 'infolog', + 'link_id' => $info_id, + )); + break; - if ($parent['info_link_id'] == $link['link_id']) - { - $content['info_link_id'] = $link_id; - } - } + case 'sp': + case 'copy': + $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; case 'tracker': @@ -1781,8 +1760,11 @@ class infolog_ui egw_link::link('infolog',$content['link_to']['to_id'],$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); $content['blur_title'] = egw_link::title($action,$action_id); } @@ -1815,58 +1797,6 @@ class infolog_ui $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 $types = $this->bo->enums['type']; if ($this->bo->group_owners) @@ -1999,6 +1929,22 @@ class infolog_ui { $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'); $GLOBALS['egw_info']['flags']['app_header'] = lang('InfoLog').' - '. ($content['status_only'] ? lang('Edit Status') : lang('Edit')); @@ -2006,17 +1952,7 @@ class infolog_ui //error_log(substr($content['info_des'],1793,10)); //$content['info_des'] = substr($content['info_des'],0,1793); //echo "

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( - '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 + $this->tmpl->exec('infolog.infolog_ui.edit',$content,$sel_options,$readonlys,$preserv+array( // preserved values 'info_id' => $info_id, 'action' => $action, 'action_id' => $action_id, @@ -2026,6 +1962,110 @@ class infolog_ui ),$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='') { if (!$status || !($icon = $this->icons[$cat][$id.'_'.$status])) @@ -2097,7 +2137,6 @@ class infolog_ui 'info_id_parent' => 'Parent', 'info_status' => 'Status', 'info_confirm' => 'Confirm', - 'info_link_id' => 'primary link', 'pl_id' => 'pricelist', 'info_price' => 'price', 'info_percent' => 'completed', @@ -2111,6 +2150,9 @@ class infolog_ui { $excludefields['#'.$name] = $data['label']; } + $sub_excludefields = $excludefields; + unset($sub_excludefields['info_id_parent']); // always set to parent! + $config_data = config::read('infolog'); if($_POST['save'] || $_POST['apply']) @@ -2134,6 +2176,7 @@ class infolog_ui $this->bo->copy_excludefields = array_merge($this->bo->copy_excludefields,$extra); } 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('implicit_rights',$this->bo->implicit_rights = $_POST['implicit_rights'] == 'edit' ? 'edit' : 'read','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!)', )), 'lang_responsible_edit' => lang('Which additional fields should the responsible be allowed to edit without having edit rights?
Status, percent and date completed are always allowed.'), - 'responsible_edit' => html::checkbox_multiselect('responsible_edit',$this->bo->responsible_edit,$fields,false,'',11), - '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)'), - 'copy_excludefields' => html::checkbox_multiselect('copy_excludefields',$this->bo->copy_excludefields,$excludefields,false,'',11), + 'responsible_edit' => html::checkbox_multiselect('responsible_edit',$this->bo->responsible_edit,$fields,false,'',6), + 'lang_copy_excludefields' => lang('Fields to exclude when copying an infolog:').'

'. + 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:').'

'. + 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('file-attachments via symlinks instead of uploads and retrieval via file:/path for direct lan-clients'), 'action_url' => html::link('/index.php',array('menuaction'=>'infolog.infolog_ui.admin')), 'save_button' => html::submit_button('save','Save'), diff --git a/infolog/templates/default/admin.tpl b/infolog/templates/default/admin.tpl index f8c175e5ae..06c9ebd9dc 100644 --- a/infolog/templates/default/admin.tpl +++ b/infolog/templates/default/admin.tpl @@ -41,6 +41,12 @@ {sub_prefix} + + {lang_sub_excludefields} + + {sub_excludefields} + + {save_button}   {apply_button}   {cancel_button}