diff --git a/addressbook/inc/class.addressbook_merge.inc.php b/addressbook/inc/class.addressbook_merge.inc.php
index f623fc97de..9b62ff74fc 100644
--- a/addressbook/inc/class.addressbook_merge.inc.php
+++ b/addressbook/inc/class.addressbook_merge.inc.php
@@ -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));
diff --git a/calendar/inc/class.calendar_merge.inc.php b/calendar/inc/class.calendar_merge.inc.php
index 46c67b3de1..593abef136 100644
--- a/calendar/inc/class.calendar_merge.inc.php
+++ b/calendar/inc/class.calendar_merge.inc.php
@@ -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;
}
diff --git a/etemplate/inc/class.bo_merge.inc.php b/etemplate/inc/class.bo_merge.inc.php
index 0a24b127e6..18f6ace144 100644
--- a/etemplate/inc/class.bo_merge.inc.php
+++ b/etemplate/inc/class.bo_merge.inc.php
@@ -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
*
diff --git a/etemplate/inc/class.bo_tracking.inc.php b/etemplate/inc/class.bo_tracking.inc.php
index da64ae21e6..50f55bc913 100644
--- a/etemplate/inc/class.bo_tracking.inc.php
+++ b/etemplate/inc/class.bo_tracking.inc.php
@@ -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 ? '
':'') . "\n$sig";
+ }
+ return $body;
+ }
if ($html_email)
{
$body = '
'."\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");
+ }
+ }
}
diff --git a/infolog/inc/class.infolog_customfields.inc.php b/infolog/inc/class.infolog_customfields.inc.php
index 56df21d3a5..c3c8f81ed9 100644
--- a/infolog/inc/class.infolog_customfields.inc.php
+++ b/infolog/inc/class.infolog_customfields.inc.php
@@ -16,7 +16,7 @@
class infolog_customfields
{
var $public_functions = array(
- 'edit' => True
+ 'edit' => True,
);
/**
* Instance of the infolog BO class
diff --git a/infolog/inc/class.infolog_egw_record.inc.php b/infolog/inc/class.infolog_egw_record.inc.php
index 6a9545cba6..3561714e5f 100644
--- a/infolog/inc/class.infolog_egw_record.inc.php
+++ b/infolog/inc/class.infolog_egw_record.inc.php
@@ -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'),
);
diff --git a/infolog/inc/class.infolog_export_csv.inc.php b/infolog/inc/class.infolog_export_csv.inc.php
index b9f4de232e..93efec8d53 100644
--- a/infolog/inc/class.infolog_export_csv.inc.php
+++ b/infolog/inc/class.infolog_export_csv.inc.php
@@ -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'
);
}
diff --git a/infolog/inc/class.infolog_hooks.inc.php b/infolog/inc/class.infolog_hooks.inc.php
index 32250b8419..b1c91252b1 100644
--- a/infolog/inc/class.infolog_hooks.inc.php
+++ b/infolog/inc/class.infolog_hooks.inc.php
@@ -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')
{
diff --git a/infolog/inc/class.infolog_merge.inc.php b/infolog/inc/class.infolog_merge.inc.php
index 9de6553cd7..5d526e030a 100644
--- a/infolog/inc/class.infolog_merge.inc.php
+++ b/infolog/inc/class.infolog_merge.inc.php
@@ -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'),
diff --git a/infolog/inc/class.infolog_tracking.inc.php b/infolog/inc/class.infolog_tracking.inc.php
index c7716706e2..037c4269bc 100644
--- a/infolog/inc/class.infolog_tracking.inc.php
+++ b/infolog/inc/class.infolog_tracking.inc.php
@@ -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;
}
diff --git a/infolog/inc/class.infolog_ui.inc.php b/infolog/inc/class.infolog_ui.inc.php
index f90e53b269..c2ac2b7c60 100644
--- a/infolog/inc/class.infolog_ui.inc.php
+++ b/infolog/inc/class.infolog_ui.inc.php
@@ -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?
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('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'),
- '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);
}
/**
diff --git a/infolog/setup/etemplates.inc.php b/infolog/setup/etemplates.inc.php
index eb90c61f38..959017a374 100644
--- a/infolog/setup/etemplates.inc.php
+++ b/infolog/setup/etemplates.inc.php
@@ -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?
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',);
diff --git a/infolog/templates/default/admin.tpl b/infolog/templates/default/admin.tpl
deleted file mode 100644
index 06c9ebd9dc..0000000000
--- a/infolog/templates/default/admin.tpl
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
diff --git a/infolog/templates/default/config.xet b/infolog/templates/default/config.xet
new file mode 100644
index 0000000000..b6a516e041
--- /dev/null
+++ b/infolog/templates/default/config.xet
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ select {
+ min-width: 30em;
+}
+
+
\ No newline at end of file
diff --git a/timesheet/inc/class.timesheet_merge.inc.php b/timesheet/inc/class.timesheet_merge.inc.php
index 26749d2564..8a10323ac4 100644
--- a/timesheet/inc/class.timesheet_merge.inc.php
+++ b/timesheet/inc/class.timesheet_merge.inc.php
@@ -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)