- Code consolidation for merging links

- Cache notifications per date-time & lang preferences instead of generating for each user
- Custom notifications for Infolog
This commit is contained in:
Nathan Gray 2013-03-19 15:07:53 +00:00
commit a00c37f3d0
15 changed files with 349 additions and 164 deletions

View File

@ -54,15 +54,7 @@ class addressbook_merge extends bo_merge
}
// Links
$replacements += array(
'$$links$$' => $this->get_links('addressbook', $id, '!'.egw_link::VFS_APPNAME),
'$$attachments$$' => $this->get_links('addressbook', $id, egw_link::VFS_APPNAME),
'$$links_attachments$$' => $this->get_links('addressbook', $id)
);
foreach(array_keys($GLOBALS['egw_info']['user']['apps']) as $app)
{
$replacements['$$links/'.$app.'$$'] = $this->get_links('addressbook',$id, $app);
}
$replacements += $this->get_all_links('addressbook', $id, $prefix, $content);
if (!(strpos($content,'$$calendar/') === false))
{
$replacements += $this->calendar_replacements($id,!(strpos($content,'$$calendar/-1/') === false));

View File

@ -215,13 +215,7 @@ class calendar_merge extends bo_merge
}
// Links
$replacements['$$'.($prefix?$prefix.'/':'').'links$$'] = $this->get_links('calendar', $event['id'], '!'.egw_link::VFS_APPNAME);
$replacements['$$'.($prefix?$prefix.'/':'').'attachments$$'] = $this->get_links('calendar', $event['id'], egw_link::VFS_APPNAME);
$replacements['$$'.($prefix?$prefix.'/':'').'links_attachments$$'] = $this->get_links('calendar', $event['id']);
foreach(array_keys($GLOBALS['egw_info']['user']['apps']) as $app)
{
$replacements["$$".($prefix?$prefix.'/':'')."links/{$app}$$"] = $this->get_links('calendar',$event['id'], $app);
}
$replacements += $this->get_all_links('calendar', $event['id'], $prefix, $content);
return $replacements;
}

View File

@ -335,6 +335,53 @@ abstract class bo_merge
return implode("\n",$link_titles);
}
/**
* Get all link placeholders
*
* Calls get_links() repeatedly to get all the combinations for the content.
*
* @param app String appname
* @param id String ID of record
* @param content String document content
*/
protected function get_all_links($app, $id, $prefix, &$content)
{
$array = array();
$pattern = '@\$(links|attachments|links_attachments)\/?(title|href|link)?\/?([a-z]*)\$@';
static $link_cache;
if(preg_match_all($pattern, $content, $matches))
{
foreach($matches[0] as $i => $placeholder)
{
$placeholder = substr($placeholder, 1, -1);
if($link_cache[$id][$placeholder])
{
$array[$placeholder] = $link_cache[$id][$placeholder];
continue;
}
switch($matches[1][$i])
{
case 'links':
$array[($prefix?$prefix.'/':'').$placeholder] = $this->get_links($app, $id, '!'.egw_link::VFS_APPNAME, array(),$matches[2][$i]);
break;
case 'attachments':
$array[($prefix?$prefix.'/':'').$placeholder] = $this->get_links($app, $id, egw_link::VFS_APPNAME,array(),$matches[2][$i]);
break;
default:
$array[($prefix?$prefix.'/':'').$placeholder] = $this->get_links($app, $id, $matches[3][$i], array(), $matches[2][$i]);
break;
}
$link_cache[$id][$placeholder] = $array[$placeholder];
}
}
// Need to set each app, to make sure placeholders are removed
foreach(array_keys($GLOBALS['egw_info']['user']['apps']) as $_app)
{
$array[($prefix?$prefix.'/':'')."links/$app"] = $this->get_links($app,$id,$_app);
}
return $array;
}
/**
* Format a datetime
*

View File

@ -180,6 +180,11 @@ abstract class bo_tracking
*/
const ONE2N_SEPERATOR = '~|~';
/**
* Config name for custom notification message
*/
const CUSTOM_NOTIFICATION = 'custom_notification';
/**
* Constructor
*
@ -271,6 +276,7 @@ abstract class bo_tracking
* - 'link' string of link to view $data
* - 'sender' sender of email
* - 'skip_notify' array of email addresses that should _not_ be notified
* - CUSTOM_NOTIFICATION string notification body message. Merge print placeholders are allowed.
* @param array $data current entry
* @param array $old=null old/last state of the entry or null for a new entry
* @return mixed
@ -629,6 +635,9 @@ abstract class bo_tracking
$GLOBALS['egw']->preferences->__construct($GLOBALS['egw_info']['user']['account_id']);
$GLOBALS['egw_info']['user']['preferences'] = $GLOBALS['egw']->preferences->read_repository(false); // no session prefs!
unset($this->save_prefs);
// Re-load date/time preferences
egw_time::init();
}
if ($GLOBALS['egw_info']['user']['preferences']['common']['lang'] != translation::$userlang)
{
@ -689,6 +698,26 @@ abstract class bo_tracking
translation::init();
}
// Load date/time preferences into egw_time
egw_time::init();
// Cache message body to not have to re-generate it every time
static $body_cache = array();
$lang = translation::$userlang;
$date_format = $GLOBALS['egw_info']['user']['preferences']['common']['dateformat'] .
$GLOBALS['egw_info']['user']['preferences']['common']['timeformat'];
// Cache text body
if(!$body_cache[$lang][$date_format][false])
{
$body_cache[$lang][$date_format][false] = $this->get_body(false,$data,$old,false,$receiver);
}
// Cache HTML body
if(!$body_cache[$lang][$date_format][true])
{
$body_cache[$lang][$date_format][true] = $this->get_body(true,$data,$old,false,$receiver);
}
// send over notification_app
if ($GLOBALS['egw_info']['apps']['notifications']['enabled']) {
// send via notification_app
@ -696,8 +725,8 @@ abstract class bo_tracking
try {
$notification = new notifications();
$notification->set_receivers(array($receiver));
$notification->set_message($this->get_body(false,$data,$old,false,$receiver)); // set message as plaintext
$notification->set_message($this->get_body(true,$data,$old,false,$receiver)); // and html
$notification->set_message($body_cache[$lang][$date_format][false]);
$notification->set_message($body_cache[$lang][$date_format][true]);
$notification->set_sender($this->get_sender($data,$old,true,$receiver));
$notification->set_subject($this->get_subject($data,$old,$deleted,$receiver));
$notification->set_links(array($this->get_notification_link($data,$old,$receiver)));
@ -707,7 +736,8 @@ abstract class bo_tracking
}
$notification->send();
}
catch (Exception $exception) {
catch (Exception $exception)
{
$this->errors[] = $exception->getMessage();
return false;
}
@ -902,6 +932,15 @@ abstract class bo_tracking
public function get_body($html_email,$data,$old,$integrate_link = true,$receiver=null)
{
$body = '';
if($this->get_config(self::CUSTOM_NOTIFICATION, $data, $old))
{
$body = $this->get_custom_message($data,$old);
if($sig = $this->get_signature($data,$old,$receiver))
{
$body .= ($html_email ? '<br />':'') . "\n$sig";
}
return $body;
}
if ($html_email)
{
$body = '<table cellspacing="2" cellpadding="0" border="0" width="100%">'."\n";
@ -1065,4 +1104,43 @@ abstract class bo_tracking
}
return $config['signature'];
}
/**
* Get a custom notification message to be used instead of the standard one.
* It can use merge print placeholders to include data.
*/
protected function get_custom_message($data, $old, $merge_class = null)
{
$message = $this->get_config(self::CUSTOM_NOTIFICATION, $data, $old);
if(!$message)
{
return '';
}
// Automatically set merge class from naming conventions
if($merge_class == null)
{
$merge_class = $this->app.'_merge';
}
if(!isset($data[$this->id_field]))
{
error_log($this->app . ' did not properly implement bo_tracking->id_field. Merge skipped.');
return $message;
}
elseif(class_exists($merge_class))
{
$merge = new $merge_class();
$merged_message = $merge->merge_string($message, array($data[$this->id_field]), $error, 'text/html');
if($error)
{
error_log($error);
return $message;
}
return $merged_message;
}
else
{
throw new egw_exception_wrong_parameter("Invalid merge class '$merge_class' for {$this->app} custom notification");
}
}
}

View File

@ -16,7 +16,7 @@
class infolog_customfields
{
var $public_functions = array(
'edit' => True
'edit' => True,
);
/**
* Instance of the infolog BO class

View File

@ -26,7 +26,7 @@ class infolog_egw_record implements importexport_iface_egw_record
static $types = array(
'select' => array('info_type', 'info_status', 'info_priority', 'pl_id'),
'select-cat' => array('info_cat'),
'select-account' => array('info_owner','info_responsible','modifier'),
'select-account' => array('info_owner','info_responsible','info_modifier'),
'date-time' => array('info_startdate', 'info_enddate','info_datecompleted', 'info_datemodified','info_created'),
'links' => array('info_link_id'),
);

View File

@ -219,7 +219,6 @@ class infolog_export_csv implements importexport_iface_export_plugin {
public function get_selectors_etpl() {
return array(
'name' => 'infolog.export_csv_selectors',
'content' => 'search'
);
}

View File

@ -122,7 +122,7 @@ class infolog_hooks
'appname' => $appname,
'global_cats'=> True)),
'Custom fields, typ and status' => egw::link('/index.php',array(
'menuaction' => 'infolog.infolog_customfields.edit'))
'menuaction' => 'infolog.infolog_customfields.edit')),
);
if ($location == 'admin')
{

View File

@ -124,14 +124,7 @@ class infolog_merge extends bo_merge
}
// Links
$array['links'] = $this->get_links('infolog', $id, '!'.egw_link::VFS_APPNAME, array($array['info_link']['id']));
$array['attachments'] = $this->get_links('infolog', $id, egw_link::VFS_APPNAME);
$array['links_attachments'] = $this->get_links('infolog', $id, '', array($array['info_link']['id']));
// Need to set each app, to make sure placeholders are removed
foreach(array_keys($GLOBALS['egw_info']['user']['apps']) as $app)
{
$array["links/$app"] = $this->get_links('infolog',$id,$app, array($array['info_link']['id']));
}
$array += $this->get_all_links('infolog', $id, $prefix, $content);
// Check for linked project ID
$links = egw_link::get_links('infolog', $id, 'projectmanager');
@ -215,7 +208,9 @@ class infolog_merge extends bo_merge
foreach(array(
'links' => lang('Titles of any entries linked to the current record'),
'attachments' => lang('List of files linked to the current record'),
'links/[appname]' => lang('Links to specified application. Example: {{links/addressbook}}'),
'links/[appname]' => lang('Links to specified application. Example: {{links/infolog}}'),
'links/href' => lang('Links wrapped in an HREF tag with download link'),
'links/link' => lang('Download url for links'),
'date' => lang('Date'),
'user/n_fn' => lang('Name of current user, all other contact fields are valid too'),
'user/account_lid' => lang('Username'),

View File

@ -88,6 +88,7 @@ class infolog_tracking extends bo_tracking
'info_cat' => 'Category',
'info_priority' => 'Priority',
'info_owner' => 'Owner',
'info_modifier' => 'Modifier',
'info_access' => 'Access',
'info_status' => 'Status',
'info_percent' => 'Completed',
@ -317,6 +318,22 @@ class infolog_tracking extends bo_tracking
$config = array_merge($config,preg_split('/, ?/',$data['info_cc']));
}
break;
case self::CUSTOM_NOTIFICATION:
$info_config = config::read('infolog');
if(!$info_config[self::CUSTOM_NOTIFICATION])
{
return '';
}
// Per-type notification
$config = $info_config[self::CUSTOM_NOTIFICATION][$data['info_type']];
$global = $info_config[self::CUSTOM_NOTIFICATION]['~global~'];
// Disabled
if(!$config['use_custom'] && !$global['use_custom']) return '';
// Type or globabl
$config = trim(strip_tags($config['message'])) != '' && $config['use_custom'] ? $config['message'] : $global['message'];
break;
}
return $config;
}

View File

@ -2171,7 +2171,7 @@ class infolog_ui
* Infolog's site configuration
*
*/
function admin( )
public function admin($content = array())
{
$fields = array(
'info_cat' => 'Category',
@ -2222,91 +2222,97 @@ class infolog_ui
$sub_excludefields = $excludefields;
unset($sub_excludefields['info_id_parent']); // always set to parent!
$config_data = config::read('infolog');
$config = config::read('infolog');
if($_POST['save'] || $_POST['apply'])
if($content)
{
if (get_magic_quotes_gpc())
// Save
$button = key($content['button']);
if($button == 'save' || $button == 'apply')
{
$_POST = self::array_stripslashes($_POST);
}
$this->bo->responsible_edit = array('info_status','info_percent','info_datecompleted');
$this->bo->responsible_edit = array('info_status','info_percent','info_datecompleted');
if ($_POST['responsible_edit'])
{
$extra = array_intersect((array)$_POST['responsible_edit'],array_keys($fields));
$this->bo->responsible_edit = array_merge($this->bo->responsible_edit,$extra);
}
// some fields like id, uid, created, createdby, modified and modifiedby are excluded by default
foreach(array('copy_excludefields','sub_excludefields') as $name)
{
$efs = array_keys($name == 'sub_excludefields' ? $sub_excludefields : $excludefields);
$this->bo->$name = array_unique(array_diff($this->bo->$name, $efs, // restore default from bo
$name == 'sub_excludefields' ? $this->bo->default_sub_excludefields : array()));
if ($content['responsible_edit'])
{
$extra = array_intersect((array)$content['responsible_edit'],array_keys($fields));
$this->bo->responsible_edit = array_merge($this->bo->responsible_edit,$extra);
}
// some fields like id, uid, created, createdby, modified and modifiedby are excluded by default
foreach(array('copy_excludefields','sub_excludefields') as $name)
{
$efs = array_keys($name == 'sub_excludefields' ? $sub_excludefields : $excludefields);
$this->bo->$name = array_unique(array_diff($this->bo->$name, $efs, // restore default from bo
$name == 'sub_excludefields' ? $this->bo->default_sub_excludefields : array()));
if ($_POST[$name])
{
$this->bo->$name = array_merge($this->bo->$name, array_intersect((array)$_POST[$name], $efs));
}
elseif ($name == 'sub_excludefields' && !in_array('explicit-set',$this->bo->sub_excludefields))
{
$this->bo->sub_excludefields[] = 'explicit-set'; // otherwise we can NOT unset default info_des
if ($content[$name])
{
$this->bo->$name = array_merge($this->bo->$name, array_intersect((array)$content[$name], $efs));
}
elseif ($name == 'sub_excludefields' && !in_array('explicit-set',$this->bo->sub_excludefields))
{
$this->bo->sub_excludefields[] = 'explicit-set'; // otherwise we can NOT unset default info_des
}
}
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 = $content['implicit_rights'] == 'edit' ? 'edit' : 'read','infolog');
config::save_value('history',$this->bo->history = $content['history'],'infolog');
config::save_value('index_load_cfs',$config_data['index_load_cfs'] = $content['index_load_cfs'],'infolog');
config::save_value('sub_prefix',$config_data['sub_prefix'] = $content['sub_prefix'],'infolog');
// Notifications
$notifications =& $config[infolog_tracking::CUSTOM_NOTIFICATION];
$notifications[$content['notification_type']] = $content['notification'];
config::save_value(infolog_tracking::CUSTOM_NOTIFICATION, $notifications,'infolog');
}
if($button == 'save' || $button == 'cancel')
{
egw::redirect_link('/infolog/index.php');
}
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');
config::save_value('index_load_cfs',$config_data['index_load_cfs'] = $_POST['index_load_cfs'],'infolog');
config::save_value('sub_prefix',$config_data['sub_prefix'] = $_POST['sub_prefix'],'infolog');
}
if($_POST['cancel'] || $_POST['save'])
else
{
egw::redirect_link('/infolog/index.php');
// Load
$content = $config;
$content['implicit_rights'] = $this->bo->implicit_rights;
$content['responsible_edit'] = $this->bo->responsible_edit;
$content['copy_excludefields'] = $this->bo->copy_excludefields;
$content['sub_excludefields'] = $this->bo->sub_excludefields;
$content['history'] = $this->bo->history;
}
$GLOBALS['egw_info']['flags']['app_header'] = lang('InfoLog').' - '.lang('Site configuration');
common::egw_header();
$GLOBALS['egw']->template->set_file(array('info_admin_t' => 'admin.tpl'));
$GLOBALS['egw']->template->set_block('info_admin_t', 'info_admin');
$GLOBALS['egw']->template->set_var(Array(
'lang_responsible_rights' => lang('Rights for the responsible'),
'lang_implicit_rights' => lang('Which implicit ACL rights should the responsible get?'),
'implicit_rights' => html::select('implicit_rights',$this->bo->implicit_rights,array(
// Load selected custom notification
if(!$content['notification_type'])
{
$content['notification_type'] = '~global~';
}
$content['notification'] = $config[infolog_tracking::CUSTOM_NOTIFICATION][$content['notification_type']];
$sel_options = array(
'implicit_rights' => array(
'read' => 'read rights (default)',
'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.'),
'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:'),
'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:'),
'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'),
'action_url' => html::link('/index.php',array('menuaction'=>'infolog.infolog_ui.admin')),
'save_button' => html::submit_button('save','Save'),
'apply_button' => html::submit_button('apply','Apply'),
'cancel_button' => html::submit_button('cancel','Cancel'),
'lang_history'=> lang('History logging'),
'lang_history2'=> lang('History logging and deleting of items'),
'history' => html::select('history',$this->bo->history,array(
),
'responsible_edit' => $fields,
'copy_excludefields' => $excludefields,
'sub_excludefields' => $sub_excludefields,
'history' => array(
'' => lang('No'),
'history' => lang('Yes, with purging of deleted items possible'),
'history_admin_delete' => lang('Yes, only admins can purge deleted items'),
'history_no_delete' => lang('Yes, noone can purge deleted items'),
)),
'lang_other' => lang('Other configurations'),
'lang_index_load_cfs' => lang('Load custom fields in index, if filtered by selected types (eg. to display them in a type-specific index template)'),
'index_load_cfs' => html::checkbox_multiselect('index_load_cfs',$config_data['index_load_cfs'],$this->bo->enums['type'],true,'',5),
'lang_sub_prefix' => lang('Prefix for sub-entries (default: Re:)'),
'sub_prefix' => html::input('sub_prefix',$config_data['sub_prefix']),
));
echo parse_navbar();
$GLOBALS['egw']->template->pfp('phpgw_body','info_admin');
),
'index_load_cfs' => $this->bo->enums['type'],
'notification_type' => array('~global~' => 'all') + $this->bo->enums['type']
);
$preserve['notification_old_type'] = $content['notification_type'];
$this->tmpl->read('infolog.config');
$this->tmpl->exec('infolog.infolog_ui.admin',$content,$sel_options,$readonlys,$preserve);
}
/**

View File

@ -2,7 +2,7 @@
/**
* EGroupware - eTemplates for Application infolog
* http://www.egroupware.org
* generated by soetemplate::dump4setup() 2012-12-31 11:22
* generated by soetemplate::dump4setup() 2013-03-04 10:45
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package infolog
@ -14,6 +14,14 @@ $templ_version=1;
$templ_data[] = array('name' => 'infolog.close','template' => '','lang' => '','group' => '0','version' => '1.7.001','data' => 'a:1:{i:0;a:5:{s:4:"type";s:4:"grid";s:4:"data";a:6:{i:0;a:3:{s:2:"h3";s:2:"30";s:2:"h4";s:2:"50";s:2:"c3";s:7:",bottom";}i:1;a:1:{s:1:"A";a:1:{s:4:"type";s:5:"label";}}i:2;a:1:{s:1:"A";a:4:{s:4:"type";s:8:"template";s:4:"size";s:4:"main";s:5:"align";s:6:"center";s:4:"name";s:27:"infolog.index.rows-noheader";}}i:3;a:1:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:4:"span";s:11:",headertext";s:5:"label";s:44:"Are you shure you want to close this entry ?";s:5:"align";s:6:"center";}}i:4;a:1:{s:1:"A";a:6:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"3";i:1;a:4:{s:4:"type";s:6:"button";s:5:"label";s:11:"Yes - Close";s:4:"name";s:5:"close";s:4:"help";s:30:"Sub-entries will not be closed";}i:2;a:4:{s:4:"type";s:6:"button";s:5:"label";s:33:"Yes - Close including sub-entries";s:4:"name";s:10:"close_subs";s:4:"help";s:43:"Close this entry and all listed sub-entries";}s:5:"align";s:6:"center";i:3;a:4:{s:4:"type";s:6:"button";s:5:"label";s:11:"No - Cancel";s:4:"name";s:6:"cancel";s:4:"help";s:22:"Abort without deleting";}}}i:5;a:1:{s:1:"A";a:4:{s:4:"type";s:9:"nextmatch";s:4:"size";s:20:"infolog.index.rows,1";s:4:"span";s:3:"all";s:4:"name";s:2:"nm";}}}s:4:"rows";i:5;s:4:"cols";i:1;s:4:"size";s:12:"100%,,0,,0,0";}}','size' => '100%,,0,,0,0','style' => '','modified' => '1240392317',);
$templ_data[] = array('name' => 'infolog.config','template' => '','lang' => '','group' => '0','version' => '1.9.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:4:{i:0;a:3:{s:1:"A";s:4:"100%";s:2:"c2";s:4:",top";s:2:"h2";s:5:"350px";}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:11:"all,message";s:4:"name";s:3:"msg";}}i:2;a:1:{s:1:"A";a:3:{s:4:"type";s:3:"tab";s:5:"label";s:26:"Configuration|Notification";s:4:"name";s:26:"configuration|notification";}}i:3;a:1:{s:1:"A";a:6:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"3";i:1;a:3:{s:4:"type";s:6:"button";s:5:"label";s:4:"Save";s:4:"name";s:12:"button[save]";}i:2;a:3:{s:4:"type";s:6:"button";s:4:"name";s:13:"button[apply]";s:5:"label";s:5:"Apply";}i:3;a:3:{s:4:"type";s:6:"button";s:4:"name";s:14:"button[cancel]";s:5:"label";s:6:"Cancel";}s:4:"span";s:3:"all";}}}s:4:"rows";i:3;s:4:"cols";i:1;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => 'select {
min-width: 30em;
}','modified' => '1359652244',);
$templ_data[] = array('name' => 'infolog.config.configuration','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:11:{i:0;a:4:{s:2:"c1";s:2:"th";s:1:"A";s:3:"60%";s:2:"c4";s:2:"th";s:2:"c6";s:2:"th";}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:26:"Rights for the responsible";s:4:"span";s:3:"all";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:52:"Which implicit ACL rights should the responsible get";}s:1:"B";a:2:{s:4:"type";s:6:"select";s:4:"name";s:15:"implicit_rights";}}i:3;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:153:"Which additional fields should the responsible be allowed to edit without having edit rights?<br />Status, percent and date completed are always allowed.";}s:1:"B";a:3:{s:4:"type";s:6:"select";s:4:"size";s:9:"6,,,,,,,1";s:4:"name";s:16:"responsible_edit";}}i:4;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:15:"History logging";s:4:"span";s:3:"all";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:5;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:37:"History logging and deleting of items";}s:1:"B";a:2:{s:4:"type";s:6:"select";s:4:"name";s:7:"history";}}i:6;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:20:"Other configurations";s:4:"span";s:3:"all";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:7;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:42:"Fields to exclude when copying an infolog:";}s:1:"B";a:3:{s:4:"type";s:6:"select";s:4:"name";s:18:"copy_excludefields";s:4:"size";s:1:"6";}}i:8;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:114:"Load custom fields in index, if filtered by selected types (eg. to display them in a type-specific index template)";}s:1:"B";a:3:{s:4:"type";s:6:"select";s:4:"name";s:14:"index_load_cfs";s:4:"size";s:9:"6,,,,,,,1";}}i:9;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:37:"Prefix for sub-entries (default: Re:)";}s:1:"B";a:3:{s:4:"type";s:4:"text";s:7:"no_lang";s:1:"1";s:4:"name";s:10:"sub_prefix";}}i:10;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:44:"Fields to exclude when creating a sub-entry:";}s:1:"B";a:3:{s:4:"type";s:6:"select";s:4:"size";s:1:"6";s:4:"name";s:17:"sub_excludefields";}}}s:4:"rows";i:10;s:4:"cols";i:2;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '','modified' => '1359651611',);
$templ_data[] = array('name' => 'infolog.config.notification','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:4:{i:0;a:0:{}i:1;a:2:{s:1:"A";a:4:{s:4:"type";s:6:"select";s:4:"name";s:17:"notification_type";s:5:"label";s:4:"Type";s:8:"onchange";i:1;}s:1:"B";a:3:{s:4:"type";s:8:"checkbox";s:5:"label";s:31:"Use custom notification message";s:4:"name";s:24:"notification[use_custom]";}}i:2;a:2:{s:1:"A";a:4:{s:4:"type";s:8:"htmlarea";s:4:"name";s:21:"notification[message]";s:4:"size";s:17:",180px,100%,false";s:4:"span";s:3:"all";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:3;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"size";s:49:",infolog.infolog_merge.show_replacements,,,_blank";s:5:"label";s:30:"Full list of placeholder names";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:3;s:4:"cols";i:2;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '','modified' => '1359653982',);
$templ_data[] = array('name' => 'infolog.customfields','template' => '','lang' => '','group' => '0','version' => '1.3.002','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:8:{i:0;a:3:{s:2:"c2";s:6:"header";s:2:"c4";s:6:"header";s:1:"F";s:3:"80%";}i:1;a:6:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:3:"Typ";}s:1:"B";a:5:{s:4:"type";s:6:"select";s:4:"name";s:5:"type2";s:8:"onchange";i:1;s:4:"help";s:52:"select a typ to edit it\'s status-values or delete it";s:7:"no_lang";s:1:"1";}s:1:"C";a:4:{s:4:"type";s:6:"button";s:5:"label";s:6:"Delete";s:4:"name";s:14:"button[delete]";s:4:"help";s:24:"deletes the selected typ";}s:1:"D";a:5:{s:4:"type";s:4:"text";s:4:"size";s:5:"10,40";s:4:"name";s:8:"new_name";s:4:"help";s:26:"name of new type to create";s:4:"blur";s:8:"new name";}s:1:"E";a:4:{s:4:"type";s:6:"button";s:5:"label";s:6:"Create";s:4:"name";s:14:"button[create]";s:4:"help";s:37:"creates a new typ with the given name";}s:1:"F";a:5:{s:4:"type";s:5:"label";s:4:"span";s:10:",error_msg";s:7:"no_lang";s:1:"1";s:5:"align";s:6:"center";s:4:"name";s:9:"error_msg";}}i:2;a:6:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:21:"Custom status for typ";s:4:"name";s:3:"typ";}s:1:"B";a:1:{s:4:"type";s:5:"label";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}s:1:"E";a:1:{s:4:"type";s:5:"label";}s:1:"F";a:1:{s:4:"type";s:5:"label";}}i:3;a:6:{s:1:"A";a:4:{s:4:"type";s:8:"template";s:4:"size";s:6:"status";s:4:"span";s:3:"all";s:4:"name";s:6:"status";}s:1:"B";a:1:{s:4:"type";s:5:"label";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}s:1:"E";a:1:{s:4:"type";s:5:"label";}s:1:"F";a:1:{s:4:"type";s:5:"label";}}i:4;a:6:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:13:"Custom fields";}s:1:"B";a:1:{s:4:"type";s:5:"label";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}s:1:"E";a:1:{s:4:"type";s:5:"label";}s:1:"F";a:1:{s:4:"type";s:5:"label";}}i:5;a:6:{s:1:"A";a:4:{s:4:"type";s:8:"template";s:4:"size";s:6:"fields";s:4:"span";s:3:"all";s:4:"name";s:6:"fields";}s:1:"B";a:1:{s:4:"type";s:5:"label";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}s:1:"E";a:1:{s:4:"type";s:5:"label";}s:1:"F";a:1:{s:4:"type";s:5:"label";}}i:6;a:6:{s:1:"A";a:5:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,0,0";i:1;a:4:{s:4:"type";s:5:"label";s:4:"span";s:7:",header";s:5:"label";s:15:"Group owner for";s:4:"name";s:5:"type2";}i:2;a:5:{s:4:"type";s:14:"select-account";s:4:"size";s:11:"None,groups";s:4:"name";s:11:"group_owner";s:4:"help";s:119:"If a type has a group owner, all entries of that type will be owned by the given group and NOT the user who created it!";s:4:"span";s:10:",lpadding5";}s:4:"span";s:3:"all";}s:1:"B";a:1:{s:4:"type";s:5:"label";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}s:1:"E";a:1:{s:4:"type";s:5:"label";}s:1:"F";a:1:{s:4:"type";s:5:"label";}}i:7;a:6:{s:1:"A";a:6:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"3";s:4:"span";s:3:"all";i:1;a:4:{s:4:"type";s:6:"button";s:5:"label";s:4:"Save";s:4:"name";s:12:"button[save]";s:4:"help";s:33:"saves the changes made and leaves";}i:2;a:4:{s:4:"type";s:6:"button";s:5:"label";s:5:"Apply";s:4:"name";s:13:"button[apply]";s:4:"help";s:17:"apply the changes";}i:3;a:4:{s:4:"type";s:6:"button";s:5:"label";s:6:"Cancel";s:4:"name";s:14:"button[cancel]";s:4:"help";s:22:"leaves without saveing";}}s:1:"B";a:1:{s:4:"type";s:5:"label";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}s:1:"E";a:1:{s:4:"type";s:5:"label";}s:1:"F";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:7;s:4:"cols";i:6;}}','size' => '','style' => '.header { font-weight: bold; font-size: 120%; }
.error_msg { color: red; font-style: italics; }','modified' => '1173687088',);

View File

@ -1,57 +0,0 @@
<!-- BEGIN info_admin -->
<br>
<form action="{action_url}" method="POST">
<table border="0">
<tr class="th">
<td colspan="4"><b>{lang_responsible_rights}</b></td>
</tr>
<tr class="row_off">
<td colspan="3">{lang_implicit_rights}</td>
<td>{implicit_rights}</td>
</tr>
<tr class="row_on">
<td colspan="3">{lang_responsible_edit}</td>
<td>{responsible_edit}</td>
</tr>
<tr class="th">
<td colspan="4"><b>{lang_history}</b></td>
</tr>
<tr class="row_off">
<td colspan="3">{lang_history2}</td>
<td>{history}</td>
</tr>
<tr class="th">
<td colspan="4"><b>{lang_other}</b></td>
</tr>
<tr class="row_off">
<td colspan="3">{lang_copy_excludefields}</td>
<td>
{copy_excludefields}
</td>
</tr>
<tr class="row_on">
<td colspan="3">{lang_index_load_cfs}</td>
<td>
{index_load_cfs}
</td>
</tr>
<tr class="row_off">
<td colspan="3">{lang_sub_prefix}</td>
<td>
{sub_prefix}
</td>
</tr>
<tr class="row_on">
<td colspan="3">{lang_sub_excludefields}</td>
<td>
{sub_excludefields}
</td>
</tr>
<tr>
<td colspan="4" align="left">
{save_button} &nbsp; {apply_button} &nbsp; {cancel_button}
</td>
</tr>
</table>
</form>
<!-- END info_admin -->

View File

@ -0,0 +1,112 @@
<?xml version="1.0"?>
<!-- $Id$ -->
<overlay>
<template id="infolog.config.configuration" template="" lang="" group="0" version="">
<grid width="100%">
<columns>
<column width="60%"/>
<column/>
</columns>
<rows>
<row class="th">
<description value="Rights for the responsible" span="all"/>
</row>
<row>
<description value="Which implicit ACL rights should the responsible get"/>
<menulist>
<menupopup id="implicit_rights"/>
</menulist>
</row>
<row>
<description value="Which additional fields should the responsible be allowed to edit without having edit rights?&lt;br /&gt;Status, percent and date completed are always allowed."/>
<listbox id="responsible_edit" rows="6" options=",,,,,,1"/>
</row>
<row class="th">
<description value="History logging" span="all"/>
</row>
<row>
<description value="History logging and deleting of items"/>
<menulist>
<menupopup id="history"/>
</menulist>
</row>
<row class="th">
<description value="Other configurations" span="all"/>
</row>
<row>
<description value="Fields to exclude when copying an infolog:"/>
<listbox id="copy_excludefields" rows="6"/>
</row>
<row>
<description value="Load custom fields in index, if filtered by selected types (eg. to display them in a type-specific index template)"/>
<listbox id="index_load_cfs" rows="6" options=",,,,,,1"/>
</row>
<row>
<description value="Prefix for sub-entries (default: Re:)"/>
<textbox id="sub_prefix" no_lang="1"/>
</row>
<row>
<description value="Fields to exclude when creating a sub-entry:"/>
<listbox id="sub_excludefields" rows="6"/>
</row>
</rows>
</grid>
</template>
<template id="infolog.config.notification" template="" lang="" group="0" version="">
<grid width="100%">
<columns>
<column/>
<column/>
</columns>
<rows>
<row>
<menulist>
<menupopup label="Type" id="notification_type" onchange="1"/>
</menulist>
<checkbox label="Use custom notification message" id="notification[use_custom]"/>
</row>
<row>
<htmlarea id="notification[message]" height="180px" width="100%" toolbar="false" span="all"/>
</row>
<row>
<description value="Full list of placeholder names" href="infolog.infolog_merge.show_replacements" extra_link_target="_blank"/>
<description/>
</row>
</rows>
</grid>
</template>
<template id="infolog.config" template="" lang="" group="0" version="1.9.001">
<grid width="100%">
<columns>
<column width="100%"/>
</columns>
<rows>
<row>
<description id="msg" span="all" class="message"/>
</row>
<row valign="top" height="350px">
<tabbox id="configuration|notification">
<tabs>
<tab id="configuration" label="Configuration"/>
<tab id="notification" label="Notification"/>
</tabs>
<tabpanels>
<template id="infolog.config.configuration"/>
<template id="infolog.config.notification"/>
</tabpanels>
</tabbox>
</row>
<row>
<hbox span="all">
<button label="Save" id="button[save]"/>
<button label="Apply" id="button[apply]"/>
<button label="Cancel" id="button[cancel]"/>
</hbox>
</row>
</rows>
</grid>
<styles>select {
min-width: 30em;
}</styles>
</template>
</overlay>

View File

@ -135,13 +135,7 @@ class timesheet_merge extends bo_merge
}
// Links
$array['links'] = $this->get_links('timesheet', $id, '!'.egw_link::VFS_APPNAME);
$array['attachments'] = $this->get_links('timesheet', $id, egw_link::VFS_APPNAME);
$array['links_attachments'] = $this->get_links('timesheet', $id);
foreach(array_keys($GLOBALS['egw_info']['user']['apps']) as $app)
{
$array["links/{$app}"] = $this->get_links('timesheet',$id, $app);
}
$array += $this->get_all_links('timesheet', $id, $prefix, $content);
// Add markers
foreach($array as $key => &$value)