mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-07 16:44:20 +01:00
merged infolog notifications from trunc
This commit is contained in:
parent
46cd0a687f
commit
a5ea718ec7
@ -11,6 +11,8 @@
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
require_once(EGW_API_INC.'/class.html.inc.php');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for trackering:
|
* Abstract base class for trackering:
|
||||||
* - logging all modifications of an entry
|
* - logging all modifications of an entry
|
||||||
@ -69,6 +71,14 @@ class bo_tracking
|
|||||||
* @var boolean
|
* @var boolean
|
||||||
*/
|
*/
|
||||||
var $prefer_user_as_sender = true;
|
var $prefer_user_as_sender = true;
|
||||||
|
/**
|
||||||
|
* Should the current user be email-notified (about change he made himself)
|
||||||
|
*
|
||||||
|
* Popup notifications are never send to the current user!
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
var $notify_current_user = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array with error-messages if track($data,$old) returns false
|
* Array with error-messages if track($data,$old) returns false
|
||||||
@ -111,6 +121,22 @@ class bo_tracking
|
|||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
var $tz_offset_s;
|
var $tz_offset_s;
|
||||||
|
/**
|
||||||
|
* Reference to the html class
|
||||||
|
*
|
||||||
|
* @var html
|
||||||
|
*/
|
||||||
|
var $html;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @return bo_tracking
|
||||||
|
*/
|
||||||
|
function bo_tracking()
|
||||||
|
{
|
||||||
|
$this->html =& html::singleton();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a config value, which can depend on $data and $old
|
* Get a config value, which can depend on $data and $old
|
||||||
@ -137,19 +163,21 @@ class bo_tracking
|
|||||||
* @param array $data current entry
|
* @param array $data current entry
|
||||||
* @param array $old=null old/last state of the entry or null for a new entry
|
* @param array $old=null old/last state of the entry or null for a new entry
|
||||||
* @param int $user=null user who made the changes, default to current user
|
* @param int $user=null user who made the changes, default to current user
|
||||||
|
* @param boolean $deleted=null can be set to true to let the tracking know the item got deleted or undelted
|
||||||
* @return int/boolean false on error, integer number of changes logged or true for new entries ($old == null)
|
* @return int/boolean false on error, integer number of changes logged or true for new entries ($old == null)
|
||||||
*/
|
*/
|
||||||
function track($data,$old=null,$user=null)
|
function track($data,$old=null,$user=null,$deleted=null)
|
||||||
{
|
{
|
||||||
$this->user = !is_null($user) ? $user : $GLOBALS['egw_info']['user']['account_id'];
|
$this->user = !is_null($user) ? $user : $GLOBALS['egw_info']['user']['account_id'];
|
||||||
|
|
||||||
$changes = true;
|
$changes = true;
|
||||||
|
|
||||||
if ($old)
|
if ($old && $this->field2history)
|
||||||
{
|
{
|
||||||
$changes = $this->save_history($data,$old);
|
$changes = $this->save_history($data,$old,$deleted);
|
||||||
}
|
}
|
||||||
if (!$this->do_notifications($data,$old))
|
// do not run do_notifications if we have no changes
|
||||||
|
if ($changes && !$this->do_notifications($data,$old,$deleted))
|
||||||
{
|
{
|
||||||
$changes = false;
|
$changes = false;
|
||||||
}
|
}
|
||||||
@ -162,21 +190,24 @@ class bo_tracking
|
|||||||
* @internal use only track($data,$old)
|
* @internal use only track($data,$old)
|
||||||
* @param array $data current entry
|
* @param array $data current entry
|
||||||
* @param array $old=null old/last state of the entry or null for a new entry
|
* @param array $old=null old/last state of the entry or null for a new entry
|
||||||
* @param int number of log-entries made
|
* @param boolean $deleted=null can be set to true to let the tracking know the item got deleted or undelted
|
||||||
|
* @return int number of log-entries made
|
||||||
*/
|
*/
|
||||||
function save_history($data,$old)
|
function save_history($data,$old,$deleted=null)
|
||||||
{
|
{
|
||||||
$changes = 0;
|
$changes = 0;
|
||||||
foreach($this->field2history as $name => $status)
|
foreach($this->field2history as $name => $status)
|
||||||
{
|
{
|
||||||
if ($old[$name] != $data[$name])
|
if ($old[$name] != $data[$name] && !(!$old[$name] && !$data[$name]))
|
||||||
{
|
{
|
||||||
if (!is_object($this->historylog))
|
if (!is_object($this->historylog))
|
||||||
{
|
{
|
||||||
require_once(EGW_API_INC.'/class.historylog.inc.php');
|
require_once(EGW_API_INC.'/class.historylog.inc.php');
|
||||||
$this->historylog =& new historylog($this->app);
|
$this->historylog =& new historylog($this->app);
|
||||||
}
|
}
|
||||||
$this->historylog->add($status,$data[$this->id_field],$data[$name],$old[$name]);
|
$this->historylog->add($status,$data[$this->id_field],
|
||||||
|
is_array($data[$name]) ? implode(',',$data[$name]) : $data[$name],
|
||||||
|
is_array($old[$name]) ? implode(',',$old[$name]) : $old[$name]);
|
||||||
++$changes;
|
++$changes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,12 +220,19 @@ class bo_tracking
|
|||||||
* @internal use only track($data,$old,$user)
|
* @internal use only track($data,$old,$user)
|
||||||
* @param array $data current entry
|
* @param array $data current entry
|
||||||
* @param array $old=null old/last state of the entry or null for a new entry
|
* @param array $old=null old/last state of the entry or null for a new entry
|
||||||
|
* @param boolean $deleted=null can be set to true to let the tracking know the item got deleted or undelted
|
||||||
* @return boolean true on success, false on error (error messages are in $this->errors)
|
* @return boolean true on success, false on error (error messages are in $this->errors)
|
||||||
*/
|
*/
|
||||||
function do_notifications($data,$old)
|
function do_notifications($data,$old,$deleted=null)
|
||||||
{
|
{
|
||||||
$this->errors = $email_sent = array();
|
$this->errors = $email_sent = array();
|
||||||
|
|
||||||
|
if (!$this->notify_current_user) // should we notify the current user about his own changes
|
||||||
|
{
|
||||||
|
//error_log("do_notificaton() adding user=$this->user to email_sent, to not notify him");
|
||||||
|
$email_sent[] = $GLOBALS['egw']->accounts->id2name($this->user,'account_email');
|
||||||
|
}
|
||||||
|
|
||||||
// entry creator
|
// entry creator
|
||||||
if ($this->creator_field && ($email = $GLOBALS['egw']->accounts->id2name($data[$this->creator_field],'account_email')) &&
|
if ($this->creator_field && ($email = $GLOBALS['egw']->accounts->id2name($data[$this->creator_field],'account_email')) &&
|
||||||
!in_array($email, $email_sent))
|
!in_array($email, $email_sent))
|
||||||
@ -206,6 +244,7 @@ class bo_tracking
|
|||||||
// assigned / responsible users
|
// assigned / responsible users
|
||||||
if ($this->assigned_field)
|
if ($this->assigned_field)
|
||||||
{
|
{
|
||||||
|
//error_log("bo_tracking::do_notifications() data[$this->assigned_field]=".print_r($data[$this->assigned_field],true).", old[$this->assigned_field]=".print_r($old[$this->assigned_field],true));
|
||||||
$assignees = $old_assignees = array();
|
$assignees = $old_assignees = array();
|
||||||
if ($data[$this->assigned_field]) // current assignments
|
if ($data[$this->assigned_field]) // current assignments
|
||||||
{
|
{
|
||||||
@ -219,6 +258,7 @@ class bo_tracking
|
|||||||
}
|
}
|
||||||
foreach(array_unique(array_merge($assignees,$old_assignees)) as $assignee)
|
foreach(array_unique(array_merge($assignees,$old_assignees)) as $assignee)
|
||||||
{
|
{
|
||||||
|
//error_log("bo_tracking::do_notifications() assignee=$assignee, type=".$GLOBALS['egw']->accounts->get_type($assignee).", email=".$GLOBALS['egw']->accounts->id2name($assignee,'account_email'));
|
||||||
if (!$assignee) continue;
|
if (!$assignee) continue;
|
||||||
|
|
||||||
// item assignee is a user
|
// item assignee is a user
|
||||||
@ -226,7 +266,8 @@ class bo_tracking
|
|||||||
{
|
{
|
||||||
if (($email = $GLOBALS['egw']->accounts->id2name($assignee,'account_email')) && !in_array($email, $email_sent))
|
if (($email = $GLOBALS['egw']->accounts->id2name($assignee,'account_email')) && !in_array($email, $email_sent))
|
||||||
{
|
{
|
||||||
$this->send_notification($old,$email,$data['tr_assigned'],'notify_assigned');
|
$this->send_notification($data,$old,$email,$assignee,'notify_assigned',
|
||||||
|
in_array($assignee,$assignees) !== in_array($assignee,$old_assignees) || $deleted); // assignment changed
|
||||||
$email_sent[] = $email;
|
$email_sent[] = $email;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,9 +275,10 @@ class bo_tracking
|
|||||||
{
|
{
|
||||||
foreach($GLOBALS['egw']->accounts->members($assignee,true) as $u)
|
foreach($GLOBALS['egw']->accounts->members($assignee,true) as $u)
|
||||||
{
|
{
|
||||||
if ($email = $GLOBALS['egw']->accounts->id2name($u,'account_email') && !in_array($email, $email_sent))
|
if (($email = $GLOBALS['egw']->accounts->id2name($u,'account_email')) && !in_array($email, $email_sent))
|
||||||
{
|
{
|
||||||
$this->send_notification($old,$email,$u,'notify_assigned');
|
$this->send_notification($data,$old,$email,$u,'notify_assigned',
|
||||||
|
in_array($u,$assignees) !== in_array($u,$old_assignees) || $deleted); // assignment changed
|
||||||
$email_sent[] = $email;
|
$email_sent[] = $email;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,23 +335,22 @@ class bo_tracking
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sending a notification to the given email-address
|
* Sending a notification to the given email-address
|
||||||
|
*
|
||||||
|
* Called by track() or externally for sending async notifications
|
||||||
*
|
*
|
||||||
* @internal use only track($data,$old,$user)
|
|
||||||
* @param array $data current entry
|
* @param array $data current entry
|
||||||
* @param array $old=null old/last state of the entry or null for a new entry
|
* @param array $old=null old/last state of the entry or null for a new entry
|
||||||
* @param string $email address to send the notification to
|
* @param string $email address to send the notification to
|
||||||
* @param string $user_or_lang='en' user-id or 2 char lang-code for a non-system user
|
* @param string $user_or_lang='en' user-id or 2 char lang-code for a non-system user
|
||||||
* @param string $check=null pref. to check if a notification is wanted
|
* @param string $check=null pref. to check if a notification is wanted
|
||||||
|
* @param boolean $assignment_changed=true the assignment of the user $user_or_lang changed
|
||||||
* @return boolean true on success or false on error (error-message is in $this->errors)
|
* @return boolean true on success or false on error (error-message is in $this->errors)
|
||||||
*/
|
*/
|
||||||
function send_notification($data,$old,$email,$user_or_lang,$check=null)
|
function send_notification($data,$old,$email,$user_or_lang,$check=null,$assignment_changed=true)
|
||||||
{
|
{
|
||||||
|
//error_log("bo_trackering::send_notification(,,'$email',$user_or_lang,$check)");
|
||||||
if (!$email) return false;
|
if (!$email) return false;
|
||||||
|
|
||||||
//echo "<p>botracker::send_notification(,'$email',$user_or_lang)</p>\n";
|
|
||||||
//echo "old"; _debug_array($old);
|
|
||||||
//echo "data"; _debug_array($data);
|
|
||||||
|
|
||||||
if (!$this->save_prefs) $this->save_prefs = $GLOBALS['egw_info']['user'];
|
if (!$this->save_prefs) $this->save_prefs = $GLOBALS['egw_info']['user'];
|
||||||
|
|
||||||
if (is_numeric($user_or_lang)) // user --> read everything from his prefs
|
if (is_numeric($user_or_lang)) // user --> read everything from his prefs
|
||||||
@ -319,12 +360,15 @@ class bo_tracking
|
|||||||
$GLOBALS['egw']->preferences->preferences($user_or_lang);
|
$GLOBALS['egw']->preferences->preferences($user_or_lang);
|
||||||
$GLOBALS['egw_info']['user']['preferences'] = $GLOBALS['egw']->preferences->read_repository();
|
$GLOBALS['egw_info']['user']['preferences'] = $GLOBALS['egw']->preferences->read_repository();
|
||||||
}
|
}
|
||||||
if ($check && !$GLOBALS['egw_info']['user']['preferences'][$this->app][$this->check2pref ? $this->check2pref[$check] : $check])
|
if ($check && $this->check2pref) $check = $this->check2pref[$check];
|
||||||
|
if ($check && !$GLOBALS['egw_info']['user']['preferences'][$this->app][$check])
|
||||||
{
|
{
|
||||||
return false; // no notification requested
|
return false; // no notification requested
|
||||||
}
|
}
|
||||||
// notification via notification app.
|
if ($check && $GLOBALS['egw_info']['user']['preferences'][$this->app][$check] === 'assignment' && !$assignment_changed)
|
||||||
$this->popup_notification($user_or_lang,$this->get_subject($data,$old));
|
{
|
||||||
|
return false; // only notification about changed assignment requested
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -332,15 +376,16 @@ class bo_tracking
|
|||||||
$GLOBALS['egw_info']['user']['preferences'] = $GLOBALS['egw']->preferences->default;
|
$GLOBALS['egw_info']['user']['preferences'] = $GLOBALS['egw']->preferences->default;
|
||||||
$GLOBALS['egw_info']['user']['preferences']['common']['lang'] = $user_or_lang;
|
$GLOBALS['egw_info']['user']['preferences']['common']['lang'] = $user_or_lang;
|
||||||
}
|
}
|
||||||
$this->datetime_format = $GLOBALS['egw_info']['user']['preferences']['common']['dateformat'].' '.
|
|
||||||
($GLOBALS['egw_info']['user']['preferences']['common']['timeformat'] != 12 ? 'H:i' : 'h:i a');
|
|
||||||
$this->tz_offset_s = 3600 * $GLOBALS['egw_info']['user']['preferences']['common']['tz_offset'];
|
|
||||||
|
|
||||||
if ($lang != $GLOBALS['egw']->translation->userlang) // load the right language if needed
|
if ($lang != $GLOBALS['egw']->translation->userlang) // load the right language if needed
|
||||||
{
|
{
|
||||||
$GLOBALS['egw']->translation->init();
|
$GLOBALS['egw']->translation->init();
|
||||||
}
|
}
|
||||||
|
// send popup notification
|
||||||
|
if (is_numeric($user_or_lang) && $this->user != $user_or_lang) // no popup for own actions
|
||||||
|
{
|
||||||
|
//die('sending popup notification'.$this->html->htmlspecialchars($this->get_popup_message($data,$old)));
|
||||||
|
$this->popup_notification($user_or_lang,$this->get_popup_message($data,$old));
|
||||||
|
}
|
||||||
// PHPMailer aka send-class, seems not to be able to send more then one mail, IF we need to authenticate to the SMTP server
|
// PHPMailer aka send-class, seems not to be able to send more then one mail, IF we need to authenticate to the SMTP server
|
||||||
// There for the object is newly created for ever mail, 'til this get fixed in PHPMailer.
|
// There for the object is newly created for ever mail, 'til this get fixed in PHPMailer.
|
||||||
//if(!is_object($GLOBALS['egw']->send))
|
//if(!is_object($GLOBALS['egw']->send))
|
||||||
@ -366,7 +411,7 @@ class bo_tracking
|
|||||||
}
|
}
|
||||||
$send->AddCustomHeader("X-eGroupWare-type: {$this->app}update");
|
$send->AddCustomHeader("X-eGroupWare-type: {$this->app}update");
|
||||||
|
|
||||||
$sender = $this->get_sender($user,$data,$old);
|
$sender = $this->get_sender($data,$old);
|
||||||
if (preg_match('/^(.+) *<(.+)>/',$sender,$matches)) // allow to use eg. "Ralf Becker <ralf@egw.org>" as sender
|
if (preg_match('/^(.+) *<(.+)>/',$sender,$matches)) // allow to use eg. "Ralf Becker <ralf@egw.org>" as sender
|
||||||
{
|
{
|
||||||
$send->From = $matches[2];
|
$send->From = $matches[2];
|
||||||
@ -380,7 +425,7 @@ class bo_tracking
|
|||||||
$send->Subject = $this->get_subject($data,$old);
|
$send->Subject = $this->get_subject($data,$old);
|
||||||
|
|
||||||
$send->Body = $this->get_body($html_email,$data,$old);
|
$send->Body = $this->get_body($html_email,$data,$old);
|
||||||
|
|
||||||
foreach($this->get_attachments($data,$old) as $attachment)
|
foreach($this->get_attachments($data,$old) as $attachment)
|
||||||
{
|
{
|
||||||
if (isset($attachment['content']))
|
if (isset($attachment['content']))
|
||||||
@ -393,6 +438,7 @@ class bo_tracking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//echo "<p>bo_trackering::send_notification(): sending <pre>".print_r($send,true)."</pre>\n";
|
||||||
if (!$send->Send())
|
if (!$send->Send())
|
||||||
{
|
{
|
||||||
$this->errors[] = lang('Error while notifying %1: %2',$email,$send->ErrorInfo);
|
$this->errors[] = lang('Error while notifying %1: %2',$email,$send->ErrorInfo);
|
||||||
@ -402,14 +448,23 @@ class bo_tracking
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return date+time formatted for the currently notified user (send_notification)
|
* Return date+time formatted for the currently notified user (prefs in $GLOBALS['egw_info']['user']['preferences'])
|
||||||
*
|
*
|
||||||
* @param int $timestamp
|
* @param int $timestamp
|
||||||
|
* @param boolean $do_time=true true=allways (default), false=never print the time, null=print time if != 00:00
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function datetime($timestamp)
|
function datetime($timestamp,$do_time=true)
|
||||||
{
|
{
|
||||||
return date($this->datetime_format,$timestamp+$this->tz_offset_s);
|
if (is_null($do_time))
|
||||||
|
{
|
||||||
|
$do_time = date('H:i',$timestamp+$this->tz_offset_s) != '00:00';
|
||||||
|
}
|
||||||
|
$format = $GLOBALS['egw_info']['user']['preferences']['common']['dateformat'];
|
||||||
|
if ($do_time) $format .= ' '.($GLOBALS['egw_info']['user']['preferences']['common']['timeformat'] != 12 ? 'H:i' : 'h:i a');
|
||||||
|
|
||||||
|
//error_log("bo_tracking::datetime($timestamp,$do_time)=date('$format',$timestamp+$this->tz_offset_s)='".date($format,$timestamp+$this->tz_offset_s).'\')');
|
||||||
|
return date($format,$timestamp+3600 * $GLOBALS['egw_info']['user']['preferences']['common']['tz_offset']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -418,6 +473,7 @@ class bo_tracking
|
|||||||
* The default implementation prefers depending on the prefer_user_as_sender class-var the user over
|
* The default implementation prefers depending on the prefer_user_as_sender class-var the user over
|
||||||
* what is returned by get_config('sender').
|
* what is returned by get_config('sender').
|
||||||
*
|
*
|
||||||
|
* @param int $user account_lid of user
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @param array $old
|
* @param array $old
|
||||||
* @return string
|
* @return string
|
||||||
@ -425,15 +481,21 @@ class bo_tracking
|
|||||||
function get_sender($data,$old)
|
function get_sender($data,$old)
|
||||||
{
|
{
|
||||||
$sender = $this->get_config('sender',$data,$old);
|
$sender = $this->get_config('sender',$data,$old);
|
||||||
|
//echo "<p>bo_tracking::get_sender() get_config('sender',...)='".htmlspecialchars($sender)."'</p>\n";
|
||||||
|
|
||||||
if (($this->prefer_user_as_sender || !$sender) && $this->user &&
|
if (($this->prefer_user_as_sender || !$sender) && $this->user &&
|
||||||
($email = $GLOBALS['egw']->accounts->id2name($this->user,'account_email')))
|
($email = $GLOBALS['egw']->accounts->id2name($this->user,'account_email')))
|
||||||
{
|
{
|
||||||
$name = $GLOBALS['egw']->accounts->id2name($this->user,'account_fullname');
|
$name = $GLOBALS['egw']->accounts->id2name($this->user,'account_fullname');
|
||||||
|
|
||||||
return $name ? $name.' <'.$email.'>' : $email;
|
$sender = $name ? $name.' <'.$email.'>' : $email;
|
||||||
}
|
}
|
||||||
return $sender ? $sender : 'eGroupWare '.lang($this->app).' <noreply@'.$GLOBALS['egw_info']['server']['mail_suffix'];
|
elseif(!$sender)
|
||||||
|
{
|
||||||
|
$sender = 'eGroupWare '.lang($this->app).' <noreply@'.$GLOBALS['egw_info']['server']['mail_suffix'].'>';
|
||||||
|
}
|
||||||
|
//echo "<p>bo_tracking::get_sender()='".htmlspecialchars($sender)."'</p>\n";
|
||||||
|
return $sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -476,9 +538,10 @@ class bo_tracking
|
|||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @param array $old
|
* @param array $old
|
||||||
* @return string
|
* @param string $allow_popup=false if true return array(link,popup-size) incl. session info an evtl. partial url (no host-part)
|
||||||
|
* @return string/array string with link (!$allow_popup) or array(link,popup-size), popup size is something like '640x480'
|
||||||
*/
|
*/
|
||||||
function get_link($data,$old)
|
function get_link($data,$old,$allow_popup=false)
|
||||||
{
|
{
|
||||||
if (($link = $this->get_config('link',$data,$old)))
|
if (($link = $this->get_config('link',$data,$old)))
|
||||||
{
|
{
|
||||||
@ -487,18 +550,32 @@ class bo_tracking
|
|||||||
$link .= '&'.$this->id_field.'='.$data[$this->id_field];
|
$link .= '&'.$this->id_field.'='.$data[$this->id_field];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif (($view = $GLOBALS['egw']->link->view($this->app,$data[$this->id_field])))
|
else
|
||||||
{
|
{
|
||||||
$link = preg_replace('/(sessionid|kp3|domain)=[^&]+&?/','',$GLOBALS['egw']->link('/index.php',$view));
|
if (!is_object($GLOBALS['egw']->link))
|
||||||
|
|
||||||
if ($link{0} == '/')
|
|
||||||
{
|
{
|
||||||
$link = ($_SERVER['HTTPS'] || $GLOBALS['egw_info']['server']['enforce_ssl'] ? 'https://' : 'http://').
|
require_once(EGW_API_INC.'/class.bolink.inc.php');
|
||||||
($GLOBALS['egw_info']['server']['hostname'] ? $GLOBALS['egw_info']['server']['hostname'] : $_SERVER['HTTP_HOST']).$link;
|
$GLOBALS['egw']->link =& new bolink();
|
||||||
|
}
|
||||||
|
if (($view = $GLOBALS['egw']->link->view($this->app,$data[$this->id_field])))
|
||||||
|
{
|
||||||
|
$link = $GLOBALS['egw']->link('/index.php',$view);
|
||||||
|
$popup = $GLOBALS['egw']->link->is_popup($this->app,'view');
|
||||||
}
|
}
|
||||||
if ($GLOBALS['egw']->link->is_popup($this->app,'view')) $link .= '&nopopup=1';
|
|
||||||
}
|
}
|
||||||
return $link;
|
if ($link{0} == '/')
|
||||||
|
{
|
||||||
|
$link = ($_SERVER['HTTPS'] || $GLOBALS['egw_info']['server']['enforce_ssl'] ? 'https://' : 'http://').
|
||||||
|
($GLOBALS['egw_info']['server']['hostname'] ? $GLOBALS['egw_info']['server']['hostname'] : $_SERVER['HTTP_HOST']).$link;
|
||||||
|
}
|
||||||
|
if (!$allow_popup)
|
||||||
|
{
|
||||||
|
// remove the session-id in the notification mail!
|
||||||
|
$link = preg_replace('/(sessionid|kp3|domain)=[^&]+&?/','',$link);
|
||||||
|
|
||||||
|
if ($popup) $link .= '&nopopup=1';
|
||||||
|
}
|
||||||
|
return $allow_popup ? array($link,$popup) : $link;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -527,8 +604,10 @@ class bo_tracking
|
|||||||
}
|
}
|
||||||
foreach($this->get_details($data) as $name => $detail)
|
foreach($this->get_details($data) as $name => $detail)
|
||||||
{
|
{
|
||||||
$modified = $old && $data[$name] != $old[$name];
|
// if there's no old entry, the entry is not modified by definition
|
||||||
if ($modified) error_log("data[$name]='{$data[$name]}', old[$name]='{$old[$name]}' --> modified=".(int)$modified);
|
// if both values are '', 0 or null, we count them as equal too
|
||||||
|
$modified = $old && $data[$name] != $old[$name] && !(!$data[$name] && !$old[$name]);
|
||||||
|
//if ($modified) error_log("data[$name]=".print_r($data[$name],true).", old[$name]=".print_r($old[$name],true)." --> modified=".(int)$modified);
|
||||||
if (empty($detail['value']) && !$modified) continue; // skip unchanged, empty values
|
if (empty($detail['value']) && !$modified) continue; // skip unchanged, empty values
|
||||||
|
|
||||||
$body .= $this->format_line($html_email,$detail['type'],$modified,
|
$body .= $this->format_line($html_email,$detail['type'],$modified,
|
||||||
@ -558,8 +637,10 @@ class bo_tracking
|
|||||||
|
|
||||||
if ($html_mail)
|
if ($html_mail)
|
||||||
{
|
{
|
||||||
|
$line = $this->html->htmlspecialchars($line); // XSS
|
||||||
|
|
||||||
$color = $modified ? 'red' : false;
|
$color = $modified ? 'red' : false;
|
||||||
$size = 'small';
|
$size = $html_mail == 'medium' ? 'medium' : 'small';
|
||||||
$bold = false;
|
$bold = false;
|
||||||
$background = '#FFFFF1';
|
$background = '#FFFFF1';
|
||||||
switch($type)
|
switch($type)
|
||||||
@ -582,7 +663,7 @@ class bo_tracking
|
|||||||
$background = '#F1F1F1';
|
$background = '#F1F1F1';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$size = 'x-small';
|
$size = $size == 'small' ? 'x-small' : 'small';
|
||||||
}
|
}
|
||||||
$style = ($bold ? 'font-weight:bold;' : '').($size ? 'font-size:'.$size.';' : '').($color?'color:'.$color:'');
|
$style = ($bold ? 'font-weight:bold;' : '').($size ? 'font-size:'.$size.';' : '').($color?'color:'.$color:'');
|
||||||
|
|
||||||
@ -591,16 +672,23 @@ class bo_tracking
|
|||||||
else // text-mail
|
else // text-mail
|
||||||
{
|
{
|
||||||
if ($type == 'reply') $content = str_repeat('-',64)."\n";
|
if ($type == 'reply') $content = str_repeat('-',64)."\n";
|
||||||
|
|
||||||
if ($modified) $content .= '> ';
|
if ($modified) $content .= '> ';
|
||||||
}
|
}
|
||||||
$content .= $line;
|
$content .= $line;
|
||||||
|
|
||||||
if ($link)
|
if ($link)
|
||||||
{
|
{
|
||||||
$content .= ' ';
|
$content .= ' ';
|
||||||
if ($html_mail) $content .= '<a href="'.$link.'" target="_blank">';
|
|
||||||
$content .= $link;
|
if ($html_mail)
|
||||||
if ($html_mail) $content .= '</a>';
|
{
|
||||||
|
$content .= $this->html->a_href($link,$link,'','target="_blank"');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$content .= $link;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($html_mail) $content .= '</td></tr>';
|
if ($html_mail) $content .= '</td></tr>';
|
||||||
|
|
||||||
@ -620,4 +708,37 @@ class bo_tracking
|
|||||||
{
|
{
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message for the popup
|
||||||
|
*
|
||||||
|
* Default implementation uses get_subject() with get_link() and get_message() as an extra line
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @param array $old
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function get_popup_message($data,$old)
|
||||||
|
{
|
||||||
|
$message = $this->html->htmlspecialchars($this->get_subject($data,$old));
|
||||||
|
|
||||||
|
if ((list($link,$popup) = $this->get_link($data,$old,true)))
|
||||||
|
{
|
||||||
|
if ($popup)
|
||||||
|
{
|
||||||
|
list($width,$height) = explode('x',$popup);
|
||||||
|
$options = 'onclick="egw_openWindowCentered2(this.href,\'_blank\', \''.$width.'\', \''.$height.'\', \'yes\'); return false;"';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$options = 'target="_blank"';
|
||||||
|
}
|
||||||
|
$message = $this->html->a_href($this->html->htmlspecialchars($message),$link,'',$options);
|
||||||
|
}
|
||||||
|
if (($extra = $this->get_message($data,$old)))
|
||||||
|
{
|
||||||
|
$message .= '<br />'.$this->html->htmlspecialchars($extra);
|
||||||
|
}
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
}
|
}
|
@ -76,4 +76,28 @@ class admin_prefs_sidebox_hooks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verification hook called if settings / preferences get stored
|
||||||
|
*
|
||||||
|
* Installs a task to send async infolog notifications at 2h everyday
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*/
|
||||||
|
function verify_settings($data)
|
||||||
|
{
|
||||||
|
if ($data['prefs']['notify_due_delegated'] || $data['prefs']['notify_due_responsible'] ||
|
||||||
|
$data['prefs']['notify_start_delegated'] || $data['prefs']['notify_start_responsible'])
|
||||||
|
{
|
||||||
|
require_once(EGW_API_INC.'/class.asyncservice.inc.php');
|
||||||
|
|
||||||
|
$async =& new asyncservice();
|
||||||
|
//$async->cancel_timer('infolog-async-notification');
|
||||||
|
|
||||||
|
if (!$async->read('infolog-async-notification'))
|
||||||
|
{
|
||||||
|
$async->set_timer(array('hour' => 2),'infolog-async-notification','infolog.boinfolog.async_notification',null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
include_once(EGW_INCLUDE_ROOT.'/infolog/inc/class.soinfolog.inc.php');
|
include_once(EGW_INCLUDE_ROOT.'/infolog/inc/class.soinfolog.inc.php');
|
||||||
|
|
||||||
|
define('EGW_ACL_UNDELETE',EGW_ACL_CUSTOM_1); // undelete right
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is the BO-layer of InfoLog, it also handles xmlrpc requests
|
* This class is the BO-layer of InfoLog, it also handles xmlrpc requests
|
||||||
*/
|
*/
|
||||||
@ -32,7 +34,7 @@ class boinfolog
|
|||||||
var $link;
|
var $link;
|
||||||
var $vfs;
|
var $vfs;
|
||||||
var $vfs_basedir='/infolog';
|
var $vfs_basedir='/infolog';
|
||||||
var $valid_pathes = array();
|
var $link_pathes = array();
|
||||||
var $send_file_ips = array();
|
var $send_file_ips = array();
|
||||||
|
|
||||||
var $xmlrpc_methods = array();
|
var $xmlrpc_methods = array();
|
||||||
@ -111,6 +113,18 @@ class boinfolog
|
|||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
var $user;
|
var $user;
|
||||||
|
/**
|
||||||
|
* History loggin: ''=no, 'history'=history & delete allowed, 'history_admin_delete', 'history_no_delete'
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $history;
|
||||||
|
/**
|
||||||
|
* Instance of infolog_tracking, only instaciated if needed!
|
||||||
|
*
|
||||||
|
* @var infolog_tracking
|
||||||
|
*/
|
||||||
|
var $tracking;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor Infolog BO
|
* Constructor Infolog BO
|
||||||
@ -151,11 +165,11 @@ class boinfolog
|
|||||||
'billed' => 'billed' ), // --> DONE
|
'billed' => 'billed' ), // --> DONE
|
||||||
'note' => array(
|
'note' => array(
|
||||||
'ongoing' => 'ongoing', // iCal has no status on notes
|
'ongoing' => 'ongoing', // iCal has no status on notes
|
||||||
'done' => 'done'),
|
'done' => 'done' ),
|
||||||
'email' => array(
|
'email' => array(
|
||||||
'ongoing' => 'ongoing', // iCal has no status on notes
|
'ongoing' => 'ongoing', // iCal has no status on notes
|
||||||
'done' => 'done'
|
'done' => 'done' ),
|
||||||
));
|
);
|
||||||
|
|
||||||
if (!is_object($GLOBALS['egw']->link) && $instanciate_link)
|
if (!is_object($GLOBALS['egw']->link) && $instanciate_link)
|
||||||
{
|
{
|
||||||
@ -211,14 +225,15 @@ class boinfolog
|
|||||||
}
|
}
|
||||||
if ($save_config) $this->config->save_repository();
|
if ($save_config) $this->config->save_repository();
|
||||||
}
|
}
|
||||||
if (count(explode(',',$this->config->config_data['responsible_edit'])))
|
if (is_array($this->config->config_data['responsible_edit']))
|
||||||
{
|
{
|
||||||
$this->responsible_edit = array_merge($this->responsible_edit,explode(',',$this->config->config_data['responsible_edit']));
|
$this->responsible_edit = array_merge($this->responsible_edit,$this->config->config_data['responsible_edit']);
|
||||||
}
|
}
|
||||||
if ($this->config->config_data['implicit_rights'] == 'edit')
|
if ($this->config->config_data['implicit_rights'] == 'edit')
|
||||||
{
|
{
|
||||||
$this->implicit_rights = 'edit';
|
$this->implicit_rights = 'edit';
|
||||||
}
|
}
|
||||||
|
$this->history = $this->config->config_data['history'];
|
||||||
}
|
}
|
||||||
// sort types by there translation
|
// sort types by there translation
|
||||||
foreach($this->enums['type'] as $key => $val)
|
foreach($this->enums['type'] as $key => $val)
|
||||||
@ -305,6 +320,33 @@ class boinfolog
|
|||||||
{
|
{
|
||||||
return $cache[$info_id][$required_rights];
|
return $cache[$info_id][$required_rights];
|
||||||
}
|
}
|
||||||
|
// handle delete for the various history modes
|
||||||
|
if ($this->history)
|
||||||
|
{
|
||||||
|
if (!is_array($info) && !($info = $this->so->read($info_id))) return false;
|
||||||
|
|
||||||
|
if ($info['info_status'] == 'deleted' &&
|
||||||
|
($required_rights == EGW_ACL_EDIT || // no edit rights for deleted entries
|
||||||
|
$required_rights == EGW_ACL_ADD || // no add rights for deleted entries
|
||||||
|
$required_rights == EGW_ACL_DELETE && ($this->history == 'history_no_delete' || // no delete at all!
|
||||||
|
$this->history == 'history_admin_delete' && !isset($GLOBALS['egw_info']['user']['apps']['admin'])))) // delete only for admins
|
||||||
|
{
|
||||||
|
return $cache[$info_id][$required_rights] = false;
|
||||||
|
}
|
||||||
|
if ($required_rights == EGW_ACL_UNDELETE)
|
||||||
|
{
|
||||||
|
if ($info['info_status'] != 'deleted')
|
||||||
|
{
|
||||||
|
return $cache[$info_id][$required_rights] = false; // can only undelete deleted items
|
||||||
|
}
|
||||||
|
// undelete requires edit rights
|
||||||
|
return $cache[$info_id][$required_rights] = $this->so->check_access( $info,EGW_ACL_EDIT,$this->implicit_rights == 'edit' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($required_rights == EGW_ACL_UNDELETE)
|
||||||
|
{
|
||||||
|
return $cache[$info_id][$required_rights] = false;
|
||||||
|
}
|
||||||
return $cache[$info_id][$required_rights] = $this->so->check_access( $info,$required_rights,$this->implicit_rights == 'edit' );
|
return $cache[$info_id][$required_rights] = $this->so->check_access( $info,$required_rights,$this->implicit_rights == 'edit' );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,18 +509,61 @@ class boinfolog
|
|||||||
}
|
}
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
// check if we have children and delete or re-parent them
|
||||||
$this->link->unlink(0,'infolog',$info_id);
|
if (($children = $this->so->get_children($info_id)))
|
||||||
|
{
|
||||||
$info = $this->read($info_id);
|
foreach($children as $id => $owner)
|
||||||
|
{
|
||||||
$this->so->delete($info_id,$delete_children,$new_parent);
|
if ($delete_children && $this->so->grants[$owner] & EGW_ACL_DELETE)
|
||||||
|
{
|
||||||
$GLOBALS['egw']->contenthistory->updateTimeStamp('infolog_'.$info['info_type'], $info_id, 'delete', time());
|
$this->delete($id,$delete_children,$new_parent); // call ourself recursive to delete the child
|
||||||
|
}
|
||||||
|
else // dont delete or no rights to delete the child --> re-parent it
|
||||||
|
{
|
||||||
|
$this->so->write(array(
|
||||||
|
'info_id' => $id,
|
||||||
|
'info_parent_id' => $new_parent,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!($info = $this->read($info_id))) return false; // should not happen
|
||||||
|
|
||||||
|
$deleted = $info;
|
||||||
|
$deleted['info_status'] = 'deleted';
|
||||||
|
$deleted['info_datemodified'] = time();
|
||||||
|
$deleted['info_modifier'] = $this->user;
|
||||||
|
|
||||||
|
// if we have history switched on and not an already deleted item --> set only status deleted
|
||||||
|
if ($this->history && $info['info_status'] != 'deleted')
|
||||||
|
{
|
||||||
|
if ($info['info_status'] == 'deleted') return false; // entry already deleted
|
||||||
|
|
||||||
|
$this->so->write($deleted);
|
||||||
|
|
||||||
|
$this->link->unlink(0,'infolog',$info_id,'','!file'); // keep the file attachments, only delete the rest
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->so->delete($info_id,false); // we delete the children via bo to get all notifications!
|
||||||
|
|
||||||
|
$this->link->unlink(0,'infolog',$info_id);
|
||||||
|
}
|
||||||
|
if ($info['info_status'] != 'deleted') // dont notify of final purge of already deleted items
|
||||||
|
{
|
||||||
|
$GLOBALS['egw']->contenthistory->updateTimeStamp('infolog_'.$info['info_type'], $info_id, 'delete', time());
|
||||||
|
|
||||||
|
// send email notifications and do the history logging
|
||||||
|
require_once(EGW_INCLUDE_ROOT.'/infolog/inc/class.infolog_tracking.inc.php');
|
||||||
|
if (!is_object($this->tracking))
|
||||||
|
{
|
||||||
|
$this->tracking =& new infolog_tracking($this);
|
||||||
|
}
|
||||||
|
$this->tracking->track($deleted,$info,$this->user,true);
|
||||||
|
}
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* writes the given $values to InfoLog, a new entry gets created if info_id is not set or 0
|
* writes the given $values to InfoLog, a new entry gets created if info_id is not set or 0
|
||||||
*
|
*
|
||||||
@ -517,6 +602,10 @@ class boinfolog
|
|||||||
{
|
{
|
||||||
$status_only = !!array_intersect($responsible,array_keys($GLOBALS['egw']->accounts->memberships($this->user)));
|
$status_only = !!array_intersect($responsible,array_keys($GLOBALS['egw']->accounts->memberships($this->user)));
|
||||||
}
|
}
|
||||||
|
if (!$status_only && $values['info_status'] != 'deleted')
|
||||||
|
{
|
||||||
|
$status_only = $undelete = $this->check_access($values['info_id'],EGW_ACL_UNDELETE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($values['info_id'] && !$this->check_access($values['info_id'],EGW_ACL_EDIT) && !$status_only ||
|
if ($values['info_id'] && !$this->check_access($values['info_id'],EGW_ACL_EDIT) && !$status_only ||
|
||||||
!$values['info_id'] && $values['info_id_parent'] && !$this->check_access($values['info_id_parent'],EGW_ACL_ADD))
|
!$values['info_id'] && $values['info_id_parent'] && !$this->check_access($values['info_id_parent'],EGW_ACL_ADD))
|
||||||
@ -531,7 +620,7 @@ class boinfolog
|
|||||||
{
|
{
|
||||||
$values = $this->xmlrpc2data($values);
|
$values = $this->xmlrpc2data($values);
|
||||||
}
|
}
|
||||||
if ($status_only) // make sure only status gets writen
|
if ($status_only && !$undelete) // make sure only status gets writen
|
||||||
{
|
{
|
||||||
$set_completed = !$values['info_datecompleted'] && // set date completed of finished job, only if its not already set
|
$set_completed = !$values['info_datecompleted'] && // set date completed of finished job, only if its not already set
|
||||||
(in_array($values['info_status'],array('done','billed','cancelled')) || (int)$values['info_percent'] == 100);
|
(in_array($values['info_status'],array('done','billed','cancelled')) || (int)$values['info_percent'] == 100);
|
||||||
@ -606,7 +695,7 @@ class boinfolog
|
|||||||
$values['info_modifier'] = $this->so->user;
|
$values['info_modifier'] = $this->so->user;
|
||||||
}
|
}
|
||||||
$to_write = $values;
|
$to_write = $values;
|
||||||
if ($status_only) $values = array_merge($backup_values,$values);
|
if ($status_only && !$undelete) $values = array_merge($backup_values,$values);
|
||||||
// convert user- to system-time
|
// convert user- to system-time
|
||||||
foreach($this->timestamps as $time)
|
foreach($this->timestamps as $time)
|
||||||
{
|
{
|
||||||
@ -623,7 +712,7 @@ class boinfolog
|
|||||||
{
|
{
|
||||||
$values = $this->read($info_id);
|
$values = $this->read($info_id);
|
||||||
}
|
}
|
||||||
if($values['info_id'])
|
if($values['info_id'] && $old['info_status'] != 'deleted')
|
||||||
{
|
{
|
||||||
// update
|
// update
|
||||||
$GLOBALS['egw']->contenthistory->updateTimeStamp(
|
$GLOBALS['egw']->contenthistory->updateTimeStamp(
|
||||||
@ -640,7 +729,11 @@ class boinfolog
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
$values['info_id'] = $info_id;
|
$values['info_id'] = $info_id;
|
||||||
|
|
||||||
|
if (!is_array($values['info_responsible'])) // this should not happen, bug it does ;-)
|
||||||
|
{
|
||||||
|
$values['info_responsible'] = $values['info_responsible'] ? explode(',',$values['info_responsible']) : array();
|
||||||
|
}
|
||||||
// create (and remove) links in custom fields
|
// create (and remove) links in custom fields
|
||||||
$this->update_customfield_links($values,$old);
|
$this->update_customfield_links($values,$old);
|
||||||
|
|
||||||
@ -653,7 +746,7 @@ class boinfolog
|
|||||||
{
|
{
|
||||||
$this->tracking =& new infolog_tracking($this);
|
$this->tracking =& new infolog_tracking($this);
|
||||||
}
|
}
|
||||||
$this->tracking->track($values,$old,$this->user);
|
$this->tracking->track($values,$old,$this->user,$values['info_status'] == 'deleted' || $old['info_status'] == 'deleted');
|
||||||
}
|
}
|
||||||
if ($info_from_set) $values['info_from'] = '';
|
if ($info_from_set) $values['info_from'] = '';
|
||||||
|
|
||||||
@ -1164,4 +1257,85 @@ class boinfolog
|
|||||||
}
|
}
|
||||||
return $icons;
|
return $icons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send all async infolog notification
|
||||||
|
*
|
||||||
|
* Called via the async service job 'infolog-async-notification'
|
||||||
|
*/
|
||||||
|
function async_notification()
|
||||||
|
{
|
||||||
|
if (!($users = $this->so->users_with_open_entries()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
error_log("boinfolog::async_notification() users with open entries: ".implode(', ',$users));
|
||||||
|
|
||||||
|
$save_account_id = $GLOBALS['egw_info']['user']['account_id'];
|
||||||
|
$save_prefs = $GLOBALS['egw_info']['user']['preferences'];
|
||||||
|
foreach($users as $user)
|
||||||
|
{
|
||||||
|
if (!($email = $GLOBALS['egw']->accounts->id2name($user,'account_email'))) continue;
|
||||||
|
// create the enviroment for $user
|
||||||
|
$this->user = $GLOBALS['egw_info']['user']['account_id'] = $user;
|
||||||
|
$GLOBALS['egw']->preferences->preferences($user);
|
||||||
|
$GLOBALS['egw_info']['user']['preferences'] = $GLOBALS['egw']->preferences->read_repository();
|
||||||
|
$GLOBALS['egw']->acl->acl($user);
|
||||||
|
$GLOBALS['egw']->acl->read_repository();
|
||||||
|
$this->grants = $GLOBALS['egw']->acl->get_grants('infolog',$this->group_owners ? $this->group_owners : true);
|
||||||
|
$this->so =& new soinfolog($this->grants); // so caches it's filters
|
||||||
|
|
||||||
|
$notified_info_ids = array();
|
||||||
|
foreach(array(
|
||||||
|
'notify_due_responsible' => 'open-responsible-enddate',
|
||||||
|
'notify_due_delegated' => 'open-delegated-enddate',
|
||||||
|
'notify_start_responsible' => 'open-responsible-date',
|
||||||
|
'notify_start_delegated' => 'open-delegated-date',
|
||||||
|
) as $pref => $filter)
|
||||||
|
{
|
||||||
|
if (!($pref_value = $GLOBALS['egw_info']['user']['preferences']['infolog'][$pref])) continue;
|
||||||
|
|
||||||
|
$filter .= date('Y-m-d',time()+24*60*60*(int)$pref_value);
|
||||||
|
error_log("boinfolog::async_notification() checking with filter '$filter' ($pref_value) for user $user ($email)");
|
||||||
|
|
||||||
|
$params = array('filter' => $filter);
|
||||||
|
foreach($this->so->search($params) as $info)
|
||||||
|
{
|
||||||
|
// check if we already send a notification for that infolog entry, eg. starting and due on same day
|
||||||
|
if (in_array($info['info_id'],$notified_info_ids)) continue;
|
||||||
|
|
||||||
|
if (is_null($tracking) || $tracking->user != $user)
|
||||||
|
{
|
||||||
|
require_once(EGW_INCLUDE_ROOT.'/infolog/inc/class.infolog_tracking.inc.php');
|
||||||
|
$tracking = new infolog_tracking($this);
|
||||||
|
}
|
||||||
|
switch($pref)
|
||||||
|
{
|
||||||
|
case 'notify_due_responsible':
|
||||||
|
$info['message'] = lang('%1 you are responsible for is due at %2',$this->enums['type'][$info['info_type']],
|
||||||
|
$tracking->datetime($info['info_enddate']-$this->tz_offset_s,false));
|
||||||
|
break;
|
||||||
|
case 'notify_due_delegated':
|
||||||
|
$info['message'] = lang('%1 you delegated is due at %2',$this->enums['type'][$info['info_type']],
|
||||||
|
$tracking->datetime($info['info_enddate']-$this->tz_offset_s,false));
|
||||||
|
break;
|
||||||
|
case 'notify_start_responsible':
|
||||||
|
$info['message'] = lang('%1 you are responsible for is starting at %2',$this->enums['type'][$info['info_type']],
|
||||||
|
$tracking->datetime($info['info_startdate']-$this->tz_offset_s,null));
|
||||||
|
break;
|
||||||
|
case 'notify_start_delegated':
|
||||||
|
$info['message'] = lang('%1 you delegated is starting at %2',$this->enums['type'][$info['info_type']],
|
||||||
|
$tracking->datetime($info['info_startdate']-$this->tz_offset_s,null));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
error_log("notifiying $user($email) about $info[info_subject]: $info[message]");
|
||||||
|
$tracking->send_notification($info,null,$email,$user,$pref);
|
||||||
|
|
||||||
|
$notified_info_ids[] = $info['info_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$GLOBALS['egw_info']['user']['account_id'] = $save_account_id;
|
||||||
|
$GLOBALS['egw_info']['user']['preferences'] = $save_prefs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,33 @@ class infolog_tracking extends bo_tracking
|
|||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
var $field2history = array();
|
var $field2history = array(
|
||||||
|
'info_type' => 'Ty',
|
||||||
|
'info_from' => 'Fr',
|
||||||
|
'info_addr' => 'Ad',
|
||||||
|
'info_link_id' => 'Li',
|
||||||
|
'info_cat' => 'Ca',
|
||||||
|
'info_priority' => 'Pr',
|
||||||
|
'info_owner' => 'Ow',
|
||||||
|
'info_access' => 'Ac',
|
||||||
|
'info_status' => 'St',
|
||||||
|
'info_percent' => 'Pe',
|
||||||
|
'info_datecompleted' => 'Co',
|
||||||
|
'info_location' => 'Lo',
|
||||||
|
'info_startdate' => 'st',
|
||||||
|
'info_enddate' => 'En',
|
||||||
|
'info_responsible' => 'Re',
|
||||||
|
'info_subject' => 'Su',
|
||||||
|
'info_des' => 'De',
|
||||||
|
'info_location' => 'Lo',
|
||||||
|
// PM fields
|
||||||
|
'info_planned_time' => 'pT',
|
||||||
|
'info_used_time' => 'uT',
|
||||||
|
'pl_id' => 'pL',
|
||||||
|
'info_price' => 'pr',
|
||||||
|
// all custom fields together
|
||||||
|
'custom' => '#c',
|
||||||
|
);
|
||||||
/**
|
/**
|
||||||
* Translate field-names to labels
|
* Translate field-names to labels
|
||||||
*
|
*
|
||||||
@ -56,9 +82,11 @@ class infolog_tracking extends bo_tracking
|
|||||||
'info_type' => 'Type',
|
'info_type' => 'Type',
|
||||||
'info_from' => 'Contact',
|
'info_from' => 'Contact',
|
||||||
'info_addr' => 'Phone/Email',
|
'info_addr' => 'Phone/Email',
|
||||||
|
'info_link_id' => 'primary link',
|
||||||
'info_cat' => 'Category',
|
'info_cat' => 'Category',
|
||||||
'info_priority' => 'Priority',
|
'info_priority' => 'Priority',
|
||||||
'info_owner' => 'Owner',
|
'info_owner' => 'Owner',
|
||||||
|
'info_access' => 'Access',
|
||||||
'info_status' => 'Status',
|
'info_status' => 'Status',
|
||||||
'info_percent' => 'Completed',
|
'info_percent' => 'Completed',
|
||||||
'info_datecompleted' => 'Date completed',
|
'info_datecompleted' => 'Date completed',
|
||||||
@ -67,6 +95,14 @@ class infolog_tracking extends bo_tracking
|
|||||||
'info_enddate' => 'Enddate',
|
'info_enddate' => 'Enddate',
|
||||||
'info_responsible' => 'Responsible',
|
'info_responsible' => 'Responsible',
|
||||||
'info_subject' => 'Subject',
|
'info_subject' => 'Subject',
|
||||||
|
'info_des' => 'Description',
|
||||||
|
// PM fields
|
||||||
|
'info_planned_time' => 'planned time',
|
||||||
|
'info_used_time' => 'used time',
|
||||||
|
'pl_id' => 'pricelist',
|
||||||
|
'info_price' => 'price',
|
||||||
|
// custom fields
|
||||||
|
'custom' => 'custom fields'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,32 +121,11 @@ class infolog_tracking extends bo_tracking
|
|||||||
*/
|
*/
|
||||||
function infolog_tracking(&$boinfolog)
|
function infolog_tracking(&$boinfolog)
|
||||||
{
|
{
|
||||||
|
$this->bo_tracking(); // calling the constructor of the extended class
|
||||||
|
|
||||||
$this->infolog =& $boinfolog;
|
$this->infolog =& $boinfolog;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks the changes in one entry $data, by comparing it with the last version in $old
|
|
||||||
*
|
|
||||||
* Reimplemented to fix some fields, who otherwise allways show up as modified
|
|
||||||
*
|
|
||||||
* @param array $data current entry
|
|
||||||
* @param array $old=null old/last state of the entry or null for a new entry
|
|
||||||
* @param int $user=null user who made the changes, default to current user
|
|
||||||
* @return int/boolean false on error, integer number of changes logged or true for new entries ($old == null)
|
|
||||||
*/
|
|
||||||
function track($data,$old=null,$user=null)
|
|
||||||
{
|
|
||||||
if ($old)
|
|
||||||
{
|
|
||||||
foreach($this->infolog->timestamps as $name)
|
|
||||||
{
|
|
||||||
if (!$old[$name]) $old[$name] = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parent::track($data,$old,$user);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a notification-config value
|
* Get a notification-config value
|
||||||
*
|
*
|
||||||
@ -127,20 +142,54 @@ class infolog_tracking extends bo_tracking
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the subject for a given entry
|
||||||
|
*
|
||||||
|
* Reimpleneted to use a New|deleted|modified prefix.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @param array $old
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function get_subject($data,$old)
|
||||||
|
{
|
||||||
|
if (!$old || $old['info_status'] == 'deleted')
|
||||||
|
{
|
||||||
|
$prefix = lang('New %1',lang($this->infolog->enums['type'][$data['info_type']]));
|
||||||
|
}
|
||||||
|
elseif($data['info_status'] == 'deleted')
|
||||||
|
{
|
||||||
|
$prefix = lang('%1 deleted',lang($this->infolog->enums['type'][$data['info_type']]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$prefix = lang('%1 modified',lang($this->infolog->enums['type'][$data['info_type']]));
|
||||||
|
}
|
||||||
|
return $prefix.': '.$data['info_subject'];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the modified / new message (1. line of mail body) for a given entry, can be reimplemented
|
* Get the modified / new message (1. line of mail body) for a given entry, can be reimplemented
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @param array $old
|
* @param array $old
|
||||||
* @return array/string array(message,user-id,timestamp-in-servertime) or string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function get_message($data,$old)
|
function get_message($data,$old)
|
||||||
{
|
{
|
||||||
if (!$data['info_datemodified'] || !$old)
|
if ($data['message']) return $data['message']; // async notification
|
||||||
|
|
||||||
|
if (!$old || $old['info_status'] == 'deleted')
|
||||||
{
|
{
|
||||||
return lang('New %1 created by %2 at %3',lang($this->infolog->enums['type'][$data['info_type']]),
|
return lang('New %1 created by %2 at %3',lang($this->infolog->enums['type'][$data['info_type']]),
|
||||||
$GLOBALS['egw']->common->grab_owner_name($this->infolog->user),$this->datetime(time()));
|
$GLOBALS['egw']->common->grab_owner_name($this->infolog->user),$this->datetime(time()));
|
||||||
}
|
}
|
||||||
|
elseif($data['info_status'] == 'deleted')
|
||||||
|
{
|
||||||
|
return lang('%1 deleted by %2 at %3',lang($this->infolog->enums['type'][$data['info_type']]),
|
||||||
|
$GLOBALS['egw']->common->grab_owner_name($data['info_modifier']),
|
||||||
|
$this->datetime($data['info_datemodified']-$this->infolog->tz_offset_s));
|
||||||
|
}
|
||||||
return lang('%1 modified by %2 at %3',lang($this->infolog->enums['type'][$data['info_type']]),
|
return lang('%1 modified by %2 at %3',lang($this->infolog->enums['type'][$data['info_type']]),
|
||||||
$GLOBALS['egw']->common->grab_owner_name($data['info_modifier']),
|
$GLOBALS['egw']->common->grab_owner_name($data['info_modifier']),
|
||||||
$this->datetime($data['info_datemodified']-$this->infolog->tz_offset_s));
|
$this->datetime($data['info_datemodified']-$this->infolog->tz_offset_s));
|
||||||
@ -180,12 +229,12 @@ class infolog_tracking extends bo_tracking
|
|||||||
'info_cat' => $data['info_cat'] ? $GLOBALS['egw']->categories->id2name($data['info_cat']) : '',
|
'info_cat' => $data['info_cat'] ? $GLOBALS['egw']->categories->id2name($data['info_cat']) : '',
|
||||||
'info_priority' => lang($this->infolog->enums['priority'][$data['info_priority']]),
|
'info_priority' => lang($this->infolog->enums['priority'][$data['info_priority']]),
|
||||||
'info_owner' => $GLOBALS['egw']->common->grab_owner_name($data['info_owner']),
|
'info_owner' => $GLOBALS['egw']->common->grab_owner_name($data['info_owner']),
|
||||||
'info_status' => lang($this->infolog->status[$data['info_type']][$data['info_status']]),
|
'info_status' => lang($data['info_status']=='deleted'?'deleted':$this->infolog->status[$data['info_type']][$data['info_status']]),
|
||||||
'info_percent' => (int)$data['info_percent'].'%',
|
'info_percent' => (int)$data['info_percent'].'%',
|
||||||
'info_datecompleted' => $data['info_datecomplete'] ? $this->datetime($data['info_datecompleted']-$this->infolog->tz_offset_s) : '',
|
'info_datecompleted' => $data['info_datecomplete'] ? $this->datetime($data['info_datecompleted']-$this->infolog->tz_offset_s) : '',
|
||||||
'info_location' => $data['info_location'],
|
'info_location' => $data['info_location'],
|
||||||
'info_startdate' => $data['info_startdate'] ? $this->datetime($data['info_startdate']-$this->infolog->tz_offset_s) : '',
|
'info_startdate' => $data['info_startdate'] ? $this->datetime($data['info_startdate']-$this->infolog->tz_offset_s,null) : '',
|
||||||
'info_enddate' => $data['info_enddate'] ? $this->datetime($data['info_enddate']-$this->infolog->tz_offset_s) : '',
|
'info_enddate' => $data['info_enddate'] ? $this->datetime($data['info_enddate']-$this->infolog->tz_offset_s,false) : '',
|
||||||
'info_responsible' => implode(', ',$responsible),
|
'info_responsible' => implode(', ',$responsible),
|
||||||
'info_subject' => $data['info_subject'],
|
'info_subject' => $data['info_subject'],
|
||||||
) as $name => $value)
|
) as $name => $value)
|
||||||
@ -205,7 +254,7 @@ class infolog_tracking extends bo_tracking
|
|||||||
{
|
{
|
||||||
foreach($this->infolog->customfields as $name => $field)
|
foreach($this->infolog->customfields as $name => $field)
|
||||||
{
|
{
|
||||||
if ($field['type2'] && $field['type2'] != $data['info_type']) continue; // different type
|
if ($field['type2'] && !in_array($data['info_type'],explode(',',$field['type2']))) continue; // different type
|
||||||
|
|
||||||
if (!$header_done)
|
if (!$header_done)
|
||||||
{
|
{
|
||||||
@ -215,7 +264,7 @@ class infolog_tracking extends bo_tracking
|
|||||||
);
|
);
|
||||||
$header_done = true;
|
$header_done = true;
|
||||||
}
|
}
|
||||||
$details[$name] = array(
|
$details['#'.$name] = array(
|
||||||
'label' => $field['label'],
|
'label' => $field['label'],
|
||||||
'value' => $data['#'.$name],
|
'value' => $data['#'.$name],
|
||||||
);
|
);
|
||||||
@ -223,4 +272,27 @@ class infolog_tracking extends bo_tracking
|
|||||||
}
|
}
|
||||||
return $details;
|
return $details;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save changes to the history log
|
||||||
|
*
|
||||||
|
* Reimplemented to store all customfields in a single field, as the history-log has only 2-char field-ids
|
||||||
|
*
|
||||||
|
* @param array $data current entry
|
||||||
|
* @param array $old=null old/last state of the entry or null for a new entry
|
||||||
|
* @param int number of log-entries made
|
||||||
|
*/
|
||||||
|
function save_history($data,$old)
|
||||||
|
{
|
||||||
|
$data_custom = $old_custom = array();
|
||||||
|
foreach($this->infolog->customfields as $name => $custom)
|
||||||
|
{
|
||||||
|
if (isset($data['#'.$name]) && (string)$data['#'.$name]!=='') $data_custom[] = $custom['label'].': '.$data['#'.$name];
|
||||||
|
if (isset($old['#'.$name]) && (string)$old['#'.$name]!=='') $old_custom[] = $custom['label'].': '.$old['#'.$name];
|
||||||
|
}
|
||||||
|
$data['custom'] = implode("\n",$data_custom);
|
||||||
|
$old['custom'] = implode("\n",$old_custom);
|
||||||
|
|
||||||
|
return parent::save_history($data,$old);
|
||||||
|
}
|
||||||
}
|
}
|
@ -178,13 +178,15 @@ class soinfolog // DB-Layer
|
|||||||
/**
|
/**
|
||||||
* generate sql to be AND'ed into a query to ensure ACL is respected (incl. _PRIVATE)
|
* generate sql to be AND'ed into a query to ensure ACL is respected (incl. _PRIVATE)
|
||||||
*
|
*
|
||||||
* @param $filter: none|all - list all entrys user have rights to see<br>
|
* @param string $filter: none|all - list all entrys user have rights to see<br>
|
||||||
* private|own - list only his personal entrys (incl. those he is responsible for !!!), my = entries the user is responsible for
|
* private|own - list only his personal entrys (incl. those he is responsible for !!!),
|
||||||
|
* responsible|my = entries the user is responsible for
|
||||||
|
* delegated = entries the user delegated to someone else
|
||||||
* @return string the necesary sql
|
* @return string the necesary sql
|
||||||
*/
|
*/
|
||||||
function aclFilter($filter = False)
|
function aclFilter($filter = False)
|
||||||
{
|
{
|
||||||
preg_match('/(my|own|privat|all|none|user)([0-9]*)/',$filter_was=$filter,$vars);
|
preg_match('/(my|responsible|delegated|own|privat|all|none|user)([0-9]*)/',$filter_was=$filter,$vars);
|
||||||
$filter = $vars[1];
|
$filter = $vars[1];
|
||||||
$f_user = intval($vars[2]);
|
$f_user = intval($vars[2]);
|
||||||
|
|
||||||
@ -193,96 +195,107 @@ class soinfolog // DB-Layer
|
|||||||
return $this->acl_filter[$filter.$f_user]; // used cached filter if found
|
return $this->acl_filter[$filter.$f_user]; // used cached filter if found
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_array($this->grants))
|
|
||||||
{
|
|
||||||
foreach($this->grants as $user => $grant)
|
|
||||||
{
|
|
||||||
// echo "<p>grants: user=$user, grant=$grant</p>";
|
|
||||||
if ($grant & (EGW_ACL_READ|EGW_ACL_EDIT))
|
|
||||||
{
|
|
||||||
$public_user_list[] = $user;
|
|
||||||
}
|
|
||||||
if ($grant & EGW_ACL_PRIVATE)
|
|
||||||
{
|
|
||||||
$private_user_list[] = $user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (count($private_user_list))
|
|
||||||
{
|
|
||||||
$has_private_access = 'info_owner IN ('.implode(',',$private_user_list).')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$filtermethod = " (info_owner=$this->user"; // user has all rights
|
$filtermethod = " (info_owner=$this->user"; // user has all rights
|
||||||
|
|
||||||
if ($filter == 'my')
|
if ($filter == 'my' || $filter == 'responsible')
|
||||||
{
|
{
|
||||||
$filtermethod .= " AND info_responsible='0'";
|
$filtermethod .= " AND info_responsible='0'";
|
||||||
}
|
}
|
||||||
// implicit read-rights for responsible user
|
if ($filter == 'delegated')
|
||||||
$filtermethod .= " OR (".$this->responsible_filter($this->user)." AND info_access='public')";
|
|
||||||
|
|
||||||
// private: own entries plus the one user is responsible for
|
|
||||||
if ($filter == 'private' || $filter == 'own')
|
|
||||||
{
|
{
|
||||||
$filtermethod .= " OR (".$this->responsible_filter($this->user).
|
$filtermethod .= " AND info_responsible<>'0')";
|
||||||
($filter == 'own' && count($public_user_list) ? // offer's should show up in own, eg. startpage, but need read-access
|
|
||||||
" OR info_status = 'offer' AND info_owner IN(" . implode(',',$public_user_list) . ')' : '').")".
|
|
||||||
" AND (info_access='public'".($has_private_access?" OR $has_private_access":'').')';
|
|
||||||
}
|
}
|
||||||
elseif ($filter != 'my') // none --> all entrys user has rights to see
|
else
|
||||||
{
|
{
|
||||||
if ($has_private_access)
|
if (is_array($this->grants))
|
||||||
{
|
{
|
||||||
$filtermethod .= " OR $has_private_access";
|
foreach($this->grants as $user => $grant)
|
||||||
|
{
|
||||||
|
// echo "<p>grants: user=$user, grant=$grant</p>";
|
||||||
|
if ($grant & (EGW_ACL_READ|EGW_ACL_EDIT))
|
||||||
|
{
|
||||||
|
$public_user_list[] = $user;
|
||||||
|
}
|
||||||
|
if ($grant & EGW_ACL_PRIVATE)
|
||||||
|
{
|
||||||
|
$private_user_list[] = $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count($private_user_list))
|
||||||
|
{
|
||||||
|
$has_private_access = 'info_owner IN ('.implode(',',$private_user_list).')';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (count($public_user_list))
|
// implicit read-rights for responsible user
|
||||||
{
|
$filtermethod .= " OR (".$this->responsible_filter($this->user)." AND info_access='public')";
|
||||||
$filtermethod .= " OR (info_access='public' AND info_owner IN(" . implode(',',$public_user_list) . '))';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$filtermethod .= ') ';
|
|
||||||
|
|
||||||
if ($filter == 'user' && $f_user > 0)
|
// private: own entries plus the one user is responsible for
|
||||||
{
|
if ($filter == 'private' || $filter == 'own')
|
||||||
$filtermethod .= " AND (info_owner=$f_user AND info_responsible=0 OR ".$this->responsible_filter($f_user).')';
|
{
|
||||||
|
$filtermethod .= " OR (".$this->responsible_filter($this->user).
|
||||||
|
($filter == 'own' && count($public_user_list) ? // offer's should show up in own, eg. startpage, but need read-access
|
||||||
|
" OR info_status = 'offer' AND info_owner IN(" . implode(',',$public_user_list) . ')' : '').")".
|
||||||
|
" AND (info_access='public'".($has_private_access?" OR $has_private_access":'').')';
|
||||||
|
}
|
||||||
|
elseif ($filter != 'my' && $filter != 'responsible') // none --> all entrys user has rights to see
|
||||||
|
{
|
||||||
|
if ($has_private_access)
|
||||||
|
{
|
||||||
|
$filtermethod .= " OR $has_private_access";
|
||||||
|
}
|
||||||
|
if (count($public_user_list))
|
||||||
|
{
|
||||||
|
$filtermethod .= " OR (info_access='public' AND info_owner IN(" . implode(',',$public_user_list) . '))';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$filtermethod .= ') ';
|
||||||
|
|
||||||
|
if ($filter == 'user' && $f_user > 0)
|
||||||
|
{
|
||||||
|
$filtermethod .= " AND (info_owner=$f_user AND info_responsible=0 OR ".$this->responsible_filter($f_user).')';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//echo "<p>aclFilter(filter='$filter_was',user='$user') = '$filtermethod', privat_user_list=".print_r($privat_user_list,True).", public_user_list=".print_r($public_user_list,True)."</p>\n";
|
//echo "<p>aclFilter(filter='$filter_was',user='$user') = '$filtermethod', privat_user_list=".print_r($privat_user_list,True).", public_user_list=".print_r($public_user_list,True)."</p>\n";
|
||||||
|
|
||||||
return $this->acl_filter[$filter.$f_user] = $filtermethod; // cache the filter
|
return $this->acl_filter[$filter.$f_user] = $filtermethod; // cache the filter
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generate sql to filter based on the status of the log-entry
|
* generate sql to filter based on the status of the log-entry
|
||||||
*
|
*
|
||||||
* @param $filter done = done or billed, open = not ()done or billed), offer = offer
|
* @param string $filter done = done or billed, open = not (done, billed, cancelled or deleted), offer = offer
|
||||||
|
* @param boolean $prefix_and=true if true prefix the fileter with ' AND '
|
||||||
* @return string the necesary sql
|
* @return string the necesary sql
|
||||||
*/
|
*/
|
||||||
function statusFilter($filter = '')
|
function statusFilter($filter = '',$prefix_and=true)
|
||||||
{
|
{
|
||||||
preg_match('/(done|open|offer)/',$filter,$vars);
|
preg_match('/(done|open|offer|deleted)/',$filter,$vars);
|
||||||
$filter = $vars[1];
|
$filter = $vars[1];
|
||||||
|
|
||||||
switch ($filter)
|
switch ($filter)
|
||||||
{
|
{
|
||||||
case 'done': return " AND info_status IN ('done','billed','cancelled')";
|
case 'done': $filter = "info_status IN ('done','billed','cancelled')"; break;
|
||||||
case 'open': return " AND NOT (info_status IN ('done','billed','cancelled'))";
|
case 'open': $filter = "NOT (info_status IN ('done','billed','cancelled','deleted'))"; break;
|
||||||
case 'offer': return " AND info_status = 'offer'";
|
case 'offer': $filter = "info_status = 'offer'"; break;
|
||||||
|
case 'deleted': $filter = "info_status = 'deleted'"; break;
|
||||||
|
default: $filter = "info_status <> 'deleted'"; break;
|
||||||
}
|
}
|
||||||
return '';
|
return ($prefix_and ? ' AND ' : '').$filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generate sql to filter based on the start- and enddate of the log-entry
|
* generate sql to filter based on the start- and enddate of the log-entry
|
||||||
*
|
*
|
||||||
* @param $filter upcoming = startdate is in the future<br>
|
* @param string $filter upcoming = startdate is in the future
|
||||||
* today startdate < tomorrow<br>
|
* today: startdate < tomorrow
|
||||||
* overdue enddate < tomorrow<br>
|
* overdue: enddate < tomorrow
|
||||||
|
* date: today <= startdate && startdate < tomorrow
|
||||||
|
* enddate: today <= enddate && enddate < tomorrow
|
||||||
* limitYYYY/MM/DD not older or open
|
* limitYYYY/MM/DD not older or open
|
||||||
* @return string the necesary sql
|
* @return string the necesary sql
|
||||||
*/
|
*/
|
||||||
function dateFilter($filter = '')
|
function dateFilter($filter = '')
|
||||||
{
|
{
|
||||||
preg_match('/(upcoming|today|overdue|date)([-\\/.0-9]*)/',$filter,$vars);
|
preg_match('/(upcoming|today|overdue|date|enddate)([-\\/.0-9]*)/',$filter,$vars);
|
||||||
$filter = $vars[1];
|
$filter = $vars[1];
|
||||||
|
|
||||||
if (isset($vars[2]) && !empty($vars[2]) && ($date = split('[-/.]',$vars[2])))
|
if (isset($vars[2]) && !empty($vars[2]) && ($date = split('[-/.]',$vars[2])))
|
||||||
@ -309,6 +322,12 @@ class soinfolog // DB-Layer
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return " AND ($today <= info_startdate AND info_startdate < $tomorrow)";
|
return " AND ($today <= info_startdate AND info_startdate < $tomorrow)";
|
||||||
|
case 'enddate':
|
||||||
|
if (!$today || !$tomorrow)
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return " AND ($today <= info_enddate AND info_enddate < $tomorrow)";
|
||||||
case 'limit':
|
case 'limit':
|
||||||
return " AND (info_modified >= '$today' OR NOT (info_status IN ('done','billed','cancelled')))";
|
return " AND (info_modified >= '$today' OR NOT (info_status IN ('done','billed','cancelled')))";
|
||||||
}
|
}
|
||||||
@ -428,6 +447,26 @@ class soinfolog // DB-Layer
|
|||||||
// set parent_id to $new_parent or 0 for all not deleted children
|
// set parent_id to $new_parent or 0 for all not deleted children
|
||||||
$this->db->update($this->info_table,array('info_id_parent'=>$new_parent),array('info_id_parent'=>$info_id),__LINE__,__FILE__);
|
$this->db->update($this->info_table,array('info_id_parent'=>$new_parent),array('info_id_parent'=>$info_id),__LINE__,__FILE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return array with children of $info_id as info_id => info_owner pairs
|
||||||
|
*
|
||||||
|
* @param int $info_id
|
||||||
|
* @return array with info_id => info_owner pairs
|
||||||
|
*/
|
||||||
|
function get_children($info_id)
|
||||||
|
{
|
||||||
|
$this->db->select($this->info_table,'info_id,info_owner',array(
|
||||||
|
'info_id_parent' => $info_id,
|
||||||
|
),__LINE__,__FILE__);
|
||||||
|
|
||||||
|
$children = array();
|
||||||
|
while (($row = $this->db->row(true)))
|
||||||
|
{
|
||||||
|
$children[$row['info_id']] = $row['info_owner'];
|
||||||
|
}
|
||||||
|
return $children;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* changes or deletes entries with a spezified owner (for hook_delete_account)
|
* changes or deletes entries with a spezified owner (for hook_delete_account)
|
||||||
@ -450,6 +489,7 @@ class soinfolog // DB-Layer
|
|||||||
{
|
{
|
||||||
$this->db->update($this->info_table,array('info_owner'=>$new_owner),array('info_owner'=>$owner),__LINE__,__FILE__);
|
$this->db->update($this->info_table,array('info_owner'=>$new_owner),array('info_owner'=>$owner),__LINE__,__FILE__);
|
||||||
}
|
}
|
||||||
|
// ToDo: does not work with multiple owners!!!
|
||||||
$this->db->update($this->info_table,array('info_responsible'=>$new_owner),array('info_responsible'=>$owner),__LINE__,__FILE__);
|
$this->db->update($this->info_table,array('info_responsible'=>$new_owner),array('info_responsible'=>$owner),__LINE__,__FILE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,7 +584,7 @@ class soinfolog // DB-Layer
|
|||||||
//echo "<p>anzSubs($info_id) = ".$this->db->f(0)." ($sql)</p>\n";
|
//echo "<p>anzSubs($info_id) = ".$this->db->f(0)." ($sql)</p>\n";
|
||||||
return $this->db->f(0);
|
return $this->db->f(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* searches InfoLog for a certain pattern in $query
|
* searches InfoLog for a certain pattern in $query
|
||||||
*
|
*
|
||||||
@ -705,4 +745,46 @@ class soinfolog // DB-Layer
|
|||||||
}
|
}
|
||||||
return $ids;
|
return $ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query infolog for users with open entries, either own or responsible, with start or end within 4 days
|
||||||
|
*
|
||||||
|
* This functions tries to minimize the users really checked with the complete filters, as creating a
|
||||||
|
* user enviroment and running the specific check costs ...
|
||||||
|
*
|
||||||
|
* @return array with acount_id's groups get resolved to there memebers
|
||||||
|
*/
|
||||||
|
function users_with_open_entries()
|
||||||
|
{
|
||||||
|
$users = array();
|
||||||
|
|
||||||
|
$this->db->select($this->info_table,'DISTINCT info_owner',array(
|
||||||
|
str_replace(' AND ','',$this->statusFilter('open')),
|
||||||
|
'(ABS(info_startdate-'.time().')<'.(4*24*60*60).' OR '. // start_day within 4 days
|
||||||
|
'ABS(info_enddate-'.time().')<'.(4*24*60*60).')', // end_day within 4 days
|
||||||
|
),__LINE__,__FILE__);
|
||||||
|
while ($this->db->next_record())
|
||||||
|
{
|
||||||
|
$users[] = $this->db->f(0);
|
||||||
|
}
|
||||||
|
$this->db->select($this->info_table,'DISTINCT info_responsible',$this->statusFilter('open',false),__LINE__,__FILE__);
|
||||||
|
while ($this->db->next_record())
|
||||||
|
{
|
||||||
|
foreach(explode(',',$this->db->f(0)) as $responsible)
|
||||||
|
{
|
||||||
|
if ($GLOBALS['egw']->accounts->get_type($responsible) == 'g')
|
||||||
|
{
|
||||||
|
$responsible = $GLOBALS['egw']->accounts->members($responsible,true);
|
||||||
|
}
|
||||||
|
if ($responsible)
|
||||||
|
{
|
||||||
|
foreach(is_array($responsible) ? $responsible : array($responsible) as $user)
|
||||||
|
{
|
||||||
|
if ($user && !in_array($user,$users)) $users[] = $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $users;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,19 +90,23 @@ class uiinfolog
|
|||||||
'offer' => 'offer.gif', 'offer_alt' => 'offer' )
|
'offer' => 'offer.gif', 'offer_alt' => 'offer' )
|
||||||
);
|
);
|
||||||
var $filters = array(
|
var $filters = array(
|
||||||
'none' => 'no Filter',
|
'none' => 'no Filter',
|
||||||
'done' => 'done',
|
'done' => 'done',
|
||||||
'my' => 'responsible',
|
'responsible' => 'responsible',
|
||||||
'my-open-today' => 'responsible open',
|
'responsible-open-today' => 'responsible open',
|
||||||
'my-open-overdue' => 'responsible overdue',
|
'responsible-open-overdue' => 'responsible overdue',
|
||||||
'my-upcoming' => 'responsible upcoming',
|
'responsible-upcoming' => 'responsible upcoming',
|
||||||
'own' => 'own',
|
'delegated' => 'delegated',
|
||||||
'own-open-today' => 'own open',
|
'delegated-open-today' => 'delegated open',
|
||||||
'own-open-overdue' => 'own overdue',
|
'delegated-open-overdue' => 'delegated overdue',
|
||||||
'own-upcoming' => 'own upcoming',
|
'delegated-upcoming' => 'delegated upcomming',
|
||||||
'open-today' => 'open',
|
'own' => 'own',
|
||||||
'open-overdue' => 'overdue',
|
'own-open-today' => 'own open',
|
||||||
'upcoming' => 'upcoming'
|
'own-open-overdue' => 'own overdue',
|
||||||
|
'own-upcoming' => 'own upcoming',
|
||||||
|
'open-today' => 'open',
|
||||||
|
'open-overdue' => 'overdue',
|
||||||
|
'upcoming' => 'upcoming',
|
||||||
);
|
);
|
||||||
var $messages = array(
|
var $messages = array(
|
||||||
'edit' => 'InfoLog - Edit',
|
'edit' => 'InfoLog - Edit',
|
||||||
@ -138,6 +142,28 @@ class uiinfolog
|
|||||||
$this->duration_format = str_replace(',','',$pm_config->config_data['duration_units']).','.$pm_config->config_data['hours_per_workday'];
|
$this->duration_format = str_replace(',','',$pm_config->config_data['duration_units']).','.$pm_config->config_data['hours_per_workday'];
|
||||||
unset($pm_config);
|
unset($pm_config);
|
||||||
}
|
}
|
||||||
|
if ($this->bo->history)
|
||||||
|
{
|
||||||
|
$this->filters['deleted'] = 'deleted';
|
||||||
|
}
|
||||||
|
/* these are just for testing of the notifications
|
||||||
|
for($i = -1; $i <= 3; ++$i)
|
||||||
|
{
|
||||||
|
$this->filters['delegated-open-enddate'.date('Y-m-d',time()+$i*24*60*60)] = "delegated due in $i day(s)";
|
||||||
|
}
|
||||||
|
for($i = -1; $i <= 3; ++$i)
|
||||||
|
{
|
||||||
|
$this->filters['responsible-open-enddate'.date('Y-m-d',time()+$i*24*60*60)] = "responsible due in $i day(s)";
|
||||||
|
}
|
||||||
|
for($i = -1; $i <= 3; ++$i)
|
||||||
|
{
|
||||||
|
$this->filters['delegated-open-date'.date('Y-m-d',time()+$i*24*60*60)] = "delegated starting in $i day(s)";
|
||||||
|
}
|
||||||
|
for($i = -1; $i <= 3; ++$i)
|
||||||
|
{
|
||||||
|
$this->filters['responsible-open-date'.date('Y-m-d',time()+$i*24*60*60)] = "responsible starting in $i day(s)";
|
||||||
|
}
|
||||||
|
*/
|
||||||
$GLOBALS['uiinfolog'] =& $this; // make ourself availible for ExecMethod of get_rows function
|
$GLOBALS['uiinfolog'] =& $this; // make ourself availible for ExecMethod of get_rows function
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +200,8 @@ class uiinfolog
|
|||||||
$readonlys["close[$id]"] = $done || ($readonlys["edit_status[$id]"] =
|
$readonlys["close[$id]"] = $done || ($readonlys["edit_status[$id]"] =
|
||||||
!($this->bo->check_access($info,EGW_ACL_EDIT) || $this->bo->is_responsible($info)));
|
!($this->bo->check_access($info,EGW_ACL_EDIT) || $this->bo->is_responsible($info)));
|
||||||
$readonlys["edit_status[$id]"] = $readonlys["edit_percent[$id]"] =
|
$readonlys["edit_status[$id]"] = $readonlys["edit_percent[$id]"] =
|
||||||
!$this->bo->check_access($info,EGW_ACL_EDIT) && !$this->bo->is_responsible($info);
|
!$this->bo->check_access($info,EGW_ACL_EDIT) && !$this->bo->is_responsible($info) &&
|
||||||
|
!$this->bo->check_access($info,EGW_ACL_UNDELETE); // undelete is handled like status edit
|
||||||
$readonlys["delete[$id]"] = !$this->bo->check_access($info,EGW_ACL_DELETE);
|
$readonlys["delete[$id]"] = !$this->bo->check_access($info,EGW_ACL_DELETE);
|
||||||
$readonlys["sp[$id]"] = !$this->bo->check_access($info,EGW_ACL_ADD);
|
$readonlys["sp[$id]"] = !$this->bo->check_access($info,EGW_ACL_ADD);
|
||||||
$readonlys["view[$id]"] = $info['info_anz_subs'] < 1;
|
$readonlys["view[$id]"] = $info['info_anz_subs'] < 1;
|
||||||
@ -215,7 +242,8 @@ class uiinfolog
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info['info_type_label'] = $this->bo->enums['type'][$info['info_type']];
|
$info['info_type_label'] = $this->bo->enums['type'][$info['info_type']];
|
||||||
$info['info_status_label'] = $this->bo->status[$info['info_type']][$info['info_status']];
|
$info['info_status_label'] = isset($this->bo->status[$info['info_type']][$info['info_status']]) ?
|
||||||
|
$this->bo->status[$info['info_type']][$info['info_status']] : $info['info_status'];
|
||||||
|
|
||||||
if (!$this->prefs['show_percent'] || $this->prefs['show_percent'] == 2 && !$details)
|
if (!$this->prefs['show_percent'] || $this->prefs['show_percent'] == 2 && !$details)
|
||||||
{
|
{
|
||||||
@ -669,7 +697,7 @@ class uiinfolog
|
|||||||
*/
|
*/
|
||||||
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';
|
$tabs = 'description|links|delegation|project|customfields|history';
|
||||||
|
|
||||||
if (is_array($content))
|
if (is_array($content))
|
||||||
{
|
{
|
||||||
@ -700,9 +728,10 @@ class uiinfolog
|
|||||||
{
|
{
|
||||||
$old = $this->bo->read($info_id);
|
$old = $this->bo->read($info_id);
|
||||||
$status_only = $this->bo->is_responsible($old);
|
$status_only = $this->bo->is_responsible($old);
|
||||||
|
$undelete = $this->bo->check_access($old,EGW_ACL_UNDELETE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (($button == 'save' || $button == 'apply') && (!$info_id || $edit_acl || $status_only))
|
if (($button == 'save' || $button == 'apply') && (!$info_id || $edit_acl || $status_only || $undelete))
|
||||||
{
|
{
|
||||||
if ($content['info_contact'])
|
if ($content['info_contact'])
|
||||||
{
|
{
|
||||||
@ -890,7 +919,9 @@ class uiinfolog
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ($info_id && !$this->bo->check_access($info_id,EGW_ACL_EDIT) && !$this->bo->is_responsible($content))
|
if ($info_id && !$this->bo->check_access($info_id,EGW_ACL_EDIT) &&
|
||||||
|
!($undelete = $this->bo->check_access($info_id,EGW_ACL_UNDELETE)) &&
|
||||||
|
!$this->bo->is_responsible($content))
|
||||||
{
|
{
|
||||||
if ($no_popup)
|
if ($no_popup)
|
||||||
{
|
{
|
||||||
@ -996,7 +1027,7 @@ class uiinfolog
|
|||||||
}
|
}
|
||||||
$preserv = $content;
|
$preserv = $content;
|
||||||
// for implizit edit of responsible user make all fields readonly, but status and percent
|
// for implizit edit of responsible user make all fields readonly, but status and percent
|
||||||
if ($info_id && !$this->bo->check_access($info_id,EGW_ACL_EDIT) && $this->bo->is_responsible($content))
|
if ($info_id && !$this->bo->check_access($info_id,EGW_ACL_EDIT) && $this->bo->is_responsible($content) && !$undelete)
|
||||||
{
|
{
|
||||||
$content['status_only'] = !in_array('link_to',$this->bo->responsible_edit);
|
$content['status_only'] = !in_array('link_to',$this->bo->responsible_edit);
|
||||||
foreach(array_diff(array_merge(array_keys($content),array('pm_id')),$this->bo->responsible_edit) as $name)
|
foreach(array_diff(array_merge(array_keys($content),array('pm_id')),$this->bo->responsible_edit) as $name)
|
||||||
@ -1010,6 +1041,9 @@ class uiinfolog
|
|||||||
$readonlys['#'.$name] = true;
|
$readonlys['#'.$name] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ToDo: use the old status before the delete
|
||||||
|
if ($undelete) $content['info_status'] = $this->bo->status['defaults'][$content['info_type']];
|
||||||
|
|
||||||
$content['hide_from_css'] = $content['info_custom_from'] ? '' : 'hideFrom';
|
$content['hide_from_css'] = $content['info_custom_from'] ? '' : 'hideFrom';
|
||||||
|
|
||||||
if (!($readonlys['button[delete]'] = !$info_id || !$this->bo->check_access($info_id,EGW_ACL_DELETE)))
|
if (!($readonlys['button[delete]'] = !$info_id || !$this->bo->check_access($info_id,EGW_ACL_DELETE)))
|
||||||
@ -1029,7 +1063,7 @@ class uiinfolog
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$readonlys[$tabs] = array('customfields' => true);
|
$readonlys[$tabs]['customfields'] = true;
|
||||||
}
|
}
|
||||||
if (!isset($GLOBALS['egw_info']['user']['apps']['projectmanager']))
|
if (!isset($GLOBALS['egw_info']['user']['apps']['projectmanager']))
|
||||||
{
|
{
|
||||||
@ -1044,6 +1078,44 @@ class uiinfolog
|
|||||||
$old_pm_id = is_array($pm_links) ? array_shift($pm_links) : $content['old_pm_id'];
|
$old_pm_id = is_array($pm_links) ? array_shift($pm_links) : $content['old_pm_id'];
|
||||||
if (!isset($content['pm_id']) && $old_pm_id) $content['pm_id'] = $old_pm_id;
|
if (!isset($content['pm_id']) && $old_pm_id) $content['pm_id'] = $old_pm_id;
|
||||||
|
|
||||||
|
if ($info_id && $this->bo->history)
|
||||||
|
{
|
||||||
|
$content['history'] = array(
|
||||||
|
'id' => $info_id,
|
||||||
|
'app' => 'infolog',
|
||||||
|
'status-widgets' => array(
|
||||||
|
'Ty' => $types,
|
||||||
|
//'Li', // info_link_id
|
||||||
|
'Ca' => 'select-cat',
|
||||||
|
'Pr' => $this->bo->enums['priority'],
|
||||||
|
'Ow' => 'select-account',
|
||||||
|
//'Ac', // info_access: private||public
|
||||||
|
'St' => $this->bo->status[$content['info_type']]+array('deleted' => 'deleted'),
|
||||||
|
'Pe' => 'select-percent',
|
||||||
|
'Co' => 'date-time',
|
||||||
|
'st' => 'date-time',
|
||||||
|
'En' => 'date',
|
||||||
|
'Re' => 'select-account',
|
||||||
|
// PM fields, ToDo: access control!!!
|
||||||
|
'pT' => 'date-duration',
|
||||||
|
'uT' => 'date-duration',
|
||||||
|
// 'pL' => 'projectmanager-pricelist',
|
||||||
|
'pr' => 'float',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$history_stati = array();
|
||||||
|
require_once(EGW_INCLUDE_ROOT.'/infolog/inc/class.infolog_tracking.inc.php');
|
||||||
|
$tracking = new infolog_tracking($this);
|
||||||
|
foreach($tracking->field2history as $field => $history)
|
||||||
|
{
|
||||||
|
$history_stati[$history] = $tracking->field2label[$field];
|
||||||
|
}
|
||||||
|
unset($tracking);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$readonlys[$tabs]['history'] = true;
|
||||||
|
}
|
||||||
$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'));
|
||||||
$GLOBALS['egw_info']['flags']['params']['manual'] = array('page' => ($info_id ? 'ManualInfologEdit' : 'ManualInfologAdd'));
|
$GLOBALS['egw_info']['flags']['params']['manual'] = array('page' => ($info_id ? 'ManualInfologEdit' : 'ManualInfologAdd'));
|
||||||
@ -1052,7 +1124,8 @@ class uiinfolog
|
|||||||
'info_type' => $types,
|
'info_type' => $types,
|
||||||
'info_priority' => $this->bo->enums['priority'],
|
'info_priority' => $this->bo->enums['priority'],
|
||||||
'info_confirm' => $this->bo->enums['confirm'],
|
'info_confirm' => $this->bo->enums['confirm'],
|
||||||
'info_status' => $this->bo->status[$content['info_type']]
|
'info_status' => $this->bo->status[$content['info_type']],
|
||||||
|
'status' => $history_stati,
|
||||||
),$readonlys,$preserv+array( // preserved values
|
),$readonlys,$preserv+array( // preserved values
|
||||||
'info_id' => $info_id,
|
'info_id' => $info_id,
|
||||||
'action' => $action,
|
'action' => $action,
|
||||||
@ -1088,6 +1161,33 @@ class uiinfolog
|
|||||||
return $icon ? $this->html->image('infolog',$icon,lang($alt),'border=0') : lang($alt);
|
return $icon ? $this->html->image('infolog',$icon,lang($alt),'border=0') : lang($alt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* stripping slashes from an array
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @param array $arr
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function array_stripslashes($arr)
|
||||||
|
{
|
||||||
|
foreach($arr as $key => $val)
|
||||||
|
{
|
||||||
|
if (is_array($val))
|
||||||
|
{
|
||||||
|
$arr[$key] = self::array_stripslashes($var);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$arr[$key] = stripslashes($val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Infolog's site configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
function admin( )
|
function admin( )
|
||||||
{
|
{
|
||||||
$fields = array(
|
$fields = array(
|
||||||
@ -1104,41 +1204,43 @@ class uiinfolog
|
|||||||
);
|
);
|
||||||
if($_POST['save'] || $_POST['apply'])
|
if($_POST['save'] || $_POST['apply'])
|
||||||
{
|
{
|
||||||
$this->link_pathes = $this->bo->send_file_ips = array();
|
if (get_magic_quotes_gpc())
|
||||||
|
{
|
||||||
|
$_POST = self::array_stripslashes($_POST);
|
||||||
|
}
|
||||||
|
$this->bo->config->config_data['link_pathes'] = $this->bo->link_pathes = array();
|
||||||
|
$this->bo->config->config_data['send_file_ips'] = $this->bo->send_file_ips = array();
|
||||||
|
|
||||||
$valid = get_var('valid',Array('POST'));
|
$valid = get_var('valid',Array('POST'));
|
||||||
$trans = get_var('trans',Array('POST'));
|
$trans = get_var('trans',Array('POST'));
|
||||||
$ip = get_var('ip',Array('POST'));
|
$ip = get_var('ip',Array('POST'));
|
||||||
while(list($key,$val) = each($valid))
|
foreach($valid as $key => $val)
|
||||||
{
|
{
|
||||||
if($val = stripslashes($val))
|
if($val)
|
||||||
{
|
{
|
||||||
$this->link_pathes[$val] = stripslashes($trans[$key]);
|
$this->bo->config->config_data['link_pathes'][$val] = $this->bo->link_pathes[$val] = $trans[$key];
|
||||||
$this->bo->send_file_ips[$val] = stripslashes($ip[$key]);
|
$this->bo->config->config_data['send_file_ips'][$val] = $this->bo->send_file_ips[$val] = $ip[$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$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'])
|
if ($_POST['responsible_edit'])
|
||||||
{
|
{
|
||||||
$extra = array_intersect($_POST['responsible_edit'],array_keys($fields));
|
$extra = array_intersect($_POST['responsible_edit'],array_keys($fields));
|
||||||
$this->bo->responsible_edit = array_merge($this->bo->responsible_edit,$extra);
|
$this->bo->config->config_data['responsible_edit'] = $this->bo->responsible_edit = array_merge($this->bo->responsible_edit,$extra);
|
||||||
}
|
}
|
||||||
$this->bo->implicit_rights = $_POST['implicit_rights'] == 'edit' ? 'edit' : 'read';
|
$this->bo->config->config_data['implicit_rights'] = $this->bo->implicit_rights = $_POST['implicit_rights'] == 'edit' ? 'edit' : 'read';
|
||||||
|
|
||||||
|
$this->bo->config->config_data['history'] = $this->bo->history = $_POST['history'];
|
||||||
|
|
||||||
$this->bo->config->config_data += array( // only "adding" the changed items, to not delete other config like custom fields
|
|
||||||
'link_pathes' => $this->link_pathes,
|
|
||||||
'send_file_ips' => $this->bo->send_file_ips,
|
|
||||||
'implicit_rights' => $this->bo->implicit_rights,
|
|
||||||
'responsible_edit' => is_array($extra) ? implode(',',$extra) : $extra,
|
|
||||||
);
|
|
||||||
$this->bo->config->save_repository(True);
|
$this->bo->config->save_repository(True);
|
||||||
}
|
}
|
||||||
if($_POST['cancel'] || $_POST['save'])
|
if($_POST['cancel'] || $_POST['save'])
|
||||||
{
|
{
|
||||||
$GLOBALS['egw']->redirect_link('/admin/index.php');
|
$GLOBALS['egw']->redirect_link('/infolog/index.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
$GLOBALS['egw_info']['flags']['app_header'] = lang('InfoLog').' - '.lang('Configuration');
|
$GLOBALS['egw_info']['flags']['app_header'] = lang('InfoLog').' - '.lang('Site configuration');
|
||||||
$GLOBALS['egw']->common->egw_header();
|
$GLOBALS['egw']->common->egw_header();
|
||||||
|
|
||||||
$GLOBALS['egw']->template->set_file(array('info_admin_t' => 'admin.tpl'));
|
$GLOBALS['egw']->template->set_file(array('info_admin_t' => 'admin.tpl'));
|
||||||
@ -1161,16 +1263,24 @@ class uiinfolog
|
|||||||
'cancel_button' => $this->html->submit_button('cancel','Cancel'),
|
'cancel_button' => $this->html->submit_button('cancel','Cancel'),
|
||||||
'lang_valid' => lang('valid path on clientside<br>eg. \\\\Server\\Share or e:\\'),
|
'lang_valid' => lang('valid path on clientside<br>eg. \\\\Server\\Share or e:\\'),
|
||||||
'lang_trans' => lang('path on (web-)serverside<br>eg. /var/samba/Share'),
|
'lang_trans' => lang('path on (web-)serverside<br>eg. /var/samba/Share'),
|
||||||
'lang_ip' => lang('reg. expr. for local IP\'s<br>eg. ^192\\.168\\.1\\.')
|
'lang_ip' => lang('reg. expr. for local IP\'s<br>eg. ^192\\.168\\.1\\.'),
|
||||||
|
'lang_history'=> lang('History logging'),
|
||||||
|
'lang_history2'=> lang('History logging and deleting of items'),
|
||||||
|
'history' => $this->html->select('history',$this->bo->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'),
|
||||||
|
))
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!is_array($this->bo->send_file_ips))
|
if (!is_array($this->bo->send_file_ips))
|
||||||
{
|
{
|
||||||
$this->bo->send_file_ips = $this->link_pathes = array();
|
$this->bo->send_file_ips = $this->bo->link_pathes = array();
|
||||||
}
|
}
|
||||||
$i = 0; @reset($this->link_pathes);
|
$i = 0; @reset($this->bo->link_pathes);
|
||||||
do {
|
do {
|
||||||
list($valid,$trans) = @each($this->link_pathes);
|
list($valid,$trans) = @each($this->bo->link_pathes);
|
||||||
$GLOBALS['egw']->template->set_var(array(
|
$GLOBALS['egw']->template->set_var(array(
|
||||||
'tr_color' => $i & 1 ? 'row_off' : 'row_on',
|
'tr_color' => $i & 1 ? 'row_off' : 'row_on',
|
||||||
'num' => $i+1,
|
'num' => $i+1,
|
||||||
@ -1300,23 +1410,6 @@ class uiinfolog
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* writes langfile with all templates and messages registered here
|
|
||||||
*
|
|
||||||
* called via [write Langfile] in the etemplate-editor or as http://domain/egroupware/index.php?menuaction=infolog.uiinfolog.writeLangFile
|
|
||||||
*/
|
|
||||||
function writeLangFile()
|
|
||||||
{
|
|
||||||
$extra = $this->messages + $this->filters;
|
|
||||||
$enums = $this->bo->enums + $this->bo->status;
|
|
||||||
unset($enums['defaults']);
|
|
||||||
foreach($enums as $key => $msg_arr)
|
|
||||||
{
|
|
||||||
$extra += $msg_arr;
|
|
||||||
}
|
|
||||||
return $this->tmpl->writeLangFile('infolog','en',$extra);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shows infolog in other applications
|
* shows infolog in other applications
|
||||||
*
|
*
|
||||||
|
@ -21,7 +21,7 @@ $have_custom_fields = count($ui->bo->customfields) > 0;
|
|||||||
unset($ui);
|
unset($ui);
|
||||||
|
|
||||||
// migrage old filter-pref 1,2 to the filter one 'own-open-today'
|
// migrage old filter-pref 1,2 to the filter one 'own-open-today'
|
||||||
if (in_array($GLOBALS['egw']->preferences->{$GLOBALS['type']}['homeShowEvents'],array('1','2')))
|
if (isset($GLOBALS['type']) && in_array($GLOBALS['egw']->preferences->{$GLOBALS['type']}['homeShowEvents'],array('1','2')))
|
||||||
{
|
{
|
||||||
$GLOBALS['egw']->preferences->add('infolog','homeShowEvents','own-open-today',$GLOBALS['type']);
|
$GLOBALS['egw']->preferences->add('infolog','homeShowEvents','own-open-today',$GLOBALS['type']);
|
||||||
$GLOBALS['egw']->preferences->save_repository();
|
$GLOBALS['egw']->preferences->save_repository();
|
||||||
@ -136,23 +136,80 @@ $GLOBALS['settings']['notify_creator'] = array(
|
|||||||
'type' => 'check',
|
'type' => 'check',
|
||||||
'label' => 'Receive notifications about own items',
|
'label' => 'Receive notifications about own items',
|
||||||
'name' => 'notify_creator',
|
'name' => 'notify_creator',
|
||||||
'help' => 'Do you want a notification mail, if items you created get updated?',
|
'help' => 'Do you want a notification, if items you created get updated?',
|
||||||
'xmlrpc' => True,
|
'xmlrpc' => True,
|
||||||
'admin' => False,
|
'admin' => False,
|
||||||
);
|
);
|
||||||
$GLOBALS['settings']['notify_assigned'] = array(
|
$GLOBALS['settings']['notify_assigned'] = array(
|
||||||
'type' => 'check',
|
'type' => 'select',
|
||||||
'label' => 'Receive notifications about items assigned to you',
|
'label' => 'Receive notifications about items assigned to you',
|
||||||
'name' => 'notify_assigned',
|
'name' => 'notify_assigned',
|
||||||
'help' => 'Do you want a notification mails, if items get assigned to you or assigned items get updated?',
|
'help' => 'Do you want a notification, if items get assigned to you or assigned items get updated?',
|
||||||
|
'values' => array(
|
||||||
|
'0' => lang('No'),
|
||||||
|
'1' => lang('Yes'),
|
||||||
|
'assignment' => lang('Only if I get assigned or removed'),
|
||||||
|
),
|
||||||
'xmlrpc' => True,
|
'xmlrpc' => True,
|
||||||
'admin' => False,
|
'admin' => False,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// to add options for more then 3 days back or in advance, you need to update soinfolog::users_with_open_entries()!
|
||||||
|
$options = array(
|
||||||
|
'0' => lang('No'),
|
||||||
|
'-1d' => lang('one day after'),
|
||||||
|
'0d' => lang('same day'),
|
||||||
|
'1d' => lang('one day in advance'),
|
||||||
|
'2d' => lang('%1 days in advance',2),
|
||||||
|
'3d' => lang('%1 days in advance',3),
|
||||||
|
);
|
||||||
|
$GLOBALS['settings']['notify_due_delegated'] = array(
|
||||||
|
'type' => 'select',
|
||||||
|
'label' => 'Receive notifications about due entries you delegated',
|
||||||
|
'name' => 'notify_due_delegated',
|
||||||
|
'help' => 'Do you want a notification, if items you delegated are due?',
|
||||||
|
'values' => $options,
|
||||||
|
'xmlrpc' => True,
|
||||||
|
'admin' => False,
|
||||||
|
);
|
||||||
|
$GLOBALS['settings']['notify_due_responsible'] = array(
|
||||||
|
'type' => 'select',
|
||||||
|
'label' => 'Receive notifications about due entries you are responsible for',
|
||||||
|
'name' => 'notify_due_responsible',
|
||||||
|
'help' => 'Do you want a notification, if items you are responsible for are due?',
|
||||||
|
'values' => $options,
|
||||||
|
'xmlrpc' => True,
|
||||||
|
'admin' => False,
|
||||||
|
);
|
||||||
|
$GLOBALS['settings']['notify_start_delegated'] = array(
|
||||||
|
'type' => 'select',
|
||||||
|
'label' => 'Receive notifications about starting entries you delegated',
|
||||||
|
'name' => 'notify_start_delegated',
|
||||||
|
'help' => 'Do you want a notification, if items you delegated are about to start?',
|
||||||
|
'values' => $options,
|
||||||
|
'xmlrpc' => True,
|
||||||
|
'admin' => False,
|
||||||
|
);
|
||||||
|
$GLOBALS['settings']['notify_start_responsible'] = array(
|
||||||
|
'type' => 'select',
|
||||||
|
'label' => 'Receive notifications about starting entries you are responsible for',
|
||||||
|
'name' => 'notify_start_responsible',
|
||||||
|
'help' => 'Do you want a notification, if items you are responsible for are about to start?',
|
||||||
|
'values' => $options,
|
||||||
|
'xmlrpc' => True,
|
||||||
|
'admin' => False,
|
||||||
|
);
|
||||||
|
|
||||||
$GLOBALS['settings']['notify_html'] = array(
|
$GLOBALS['settings']['notify_html'] = array(
|
||||||
'type' => 'check',
|
'type' => 'select',
|
||||||
'label' => 'Receive notifications as html-mails',
|
'label' => 'Receive notifications as html-mails',
|
||||||
'name' => 'notify_html',
|
'name' => 'notify_html',
|
||||||
'help' => 'Do you want to receive notifications as html-mails or plain text?',
|
'help' => 'Do you want to receive notifications as html-mails or plain text?',
|
||||||
|
'values' => array(
|
||||||
|
'0' => lang('No'),
|
||||||
|
'1' => lang('Yes'),
|
||||||
|
'medium' => lang('Yes, with larger fontsize'),
|
||||||
|
),
|
||||||
'xmlrpc' => True,
|
'xmlrpc' => True,
|
||||||
'admin' => False,
|
'admin' => False,
|
||||||
);
|
);
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,5 +1,14 @@
|
|||||||
|
%1 days in advance infolog de %1 Tage im Vorraus
|
||||||
|
%1 deleted infolog de %1 gelöscht
|
||||||
|
%1 deleted by %2 at %3 infolog de %1 wurde von %2 am %3 gelöscht
|
||||||
|
%1 modified infolog de %1 geändert
|
||||||
|
%1 modified by %2 at %3 infolog de %1 wurde von %2 am %3 geändert
|
||||||
%1 records imported infolog de %1 Datensätze importiert
|
%1 records imported infolog de %1 Datensätze importiert
|
||||||
%1 records read (not yet imported, you may go %2back%3 and uncheck test import) infolog de %1 Datensätze gelesen (noch nicht importiert, sie können %2zurück%3 gehen und Test Import ausschalten)
|
%1 records read (not yet imported, you may go %2back%3 and uncheck test import) infolog de %1 Datensätze gelesen (noch nicht importiert, sie können %2zurück%3 gehen und Test Import ausschalten)
|
||||||
|
%1 you are responsible for is due at %2 infolog de %1 für die Sie verantwortlich sind ist am %2 fällig
|
||||||
|
%1 you are responsible for is starting at %2 infolog de %1 für die Sie verantwortlich sind startet am %2
|
||||||
|
%1 you delegated is due at %2 infolog de %1 die Sie delegierten ist am %2 fällig
|
||||||
|
%1 you delegated is starting at %2 infolog de %1 die Sie delegierten startet am %2
|
||||||
- subprojects from infolog de - Untereinträge von
|
- subprojects from infolog de - Untereinträge von
|
||||||
0% infolog de 0%
|
0% infolog de 0%
|
||||||
10% infolog de 10%
|
10% infolog de 10%
|
||||||
@ -36,7 +45,7 @@ apply the changes infolog de
|
|||||||
are you shure you want to delete this entry ? infolog de Sind Sie sicher, dass Sie diesen Eintrag löschen wollen?
|
are you shure you want to delete this entry ? infolog de Sind Sie sicher, dass Sie diesen Eintrag löschen wollen?
|
||||||
attach a file infolog de Datei anhängen
|
attach a file infolog de Datei anhängen
|
||||||
attach file infolog de Datei anhängen
|
attach file infolog de Datei anhängen
|
||||||
attension: no contact with address %1 found. infolog de Achtung: Kein Kontakt mit der Adresse %1 gefunden!
|
attention: no contact with address %1 found. infolog de Achtung: Kein Kontakt mit der Adresse %1 gefunden!
|
||||||
back to main list infolog de Zurück zur Gesamtliste
|
back to main list infolog de Zurück zur Gesamtliste
|
||||||
billed infolog de abgerechnet
|
billed infolog de abgerechnet
|
||||||
both infolog de Annahme+erledigt
|
both infolog de Annahme+erledigt
|
||||||
@ -81,19 +90,31 @@ dates, status, access infolog de Daten, Status, Zugriff
|
|||||||
days infolog de Tage
|
days infolog de Tage
|
||||||
default filter for infolog infolog de Standard-Filter für InfoLog
|
default filter for infolog infolog de Standard-Filter für InfoLog
|
||||||
default status for a new log entry infolog de Vorgabe für den Status eines neuen Eintrags
|
default status for a new log entry infolog de Vorgabe für den Status eines neuen Eintrags
|
||||||
|
delegated infolog de delegiert
|
||||||
|
delegated open infolog de delegiert offen
|
||||||
|
delegated overdue infolog de delegiert überfällig
|
||||||
|
delegated upcomming infolog de delegiert zukünftig
|
||||||
delegation infolog de Delegation
|
delegation infolog de Delegation
|
||||||
delete infolog de Löschen
|
delete infolog de Löschen
|
||||||
delete one record by passing its id. infolog de Einen Datensatz spezifiziert durch seine id löschen.
|
delete one record by passing its id. infolog de Einen Datensatz spezifiziert durch seine id löschen.
|
||||||
delete the entry infolog de Eintrag löschen
|
delete the entry infolog de Eintrag löschen
|
||||||
delete this entry infolog de diesen Eintrag löschen
|
delete this entry infolog de diesen Eintrag löschen
|
||||||
delete this entry and all listed sub-entries infolog de Diesen Eintrag und all aufgelisteten Untereinträge löschen
|
delete this entry and all listed sub-entries infolog de Diesen Eintrag und all aufgelisteten Untereinträge löschen
|
||||||
|
deleted infolog de gelöscht
|
||||||
deletes the selected typ infolog de löscht den ausgewählten Typ
|
deletes the selected typ infolog de löscht den ausgewählten Typ
|
||||||
deletes this field infolog de löscht dieses Feld
|
deletes this field infolog de löscht dieses Feld
|
||||||
deletes this status infolog de löscht diesen Status
|
deletes this status infolog de löscht diesen Status
|
||||||
description infolog de Beschreibung
|
description infolog de Beschreibung
|
||||||
determines the order the fields are displayed infolog de legt die Reihenfolge fest in der die Felder angezeigt werden
|
determines the order the fields are displayed infolog de legt die Reihenfolge fest in der die Felder angezeigt werden
|
||||||
disables a status without deleting it infolog de deaktiviert einen Status ohne ihn zu löschen
|
disables a status without deleting it infolog de deaktiviert einen Status ohne ihn zu löschen
|
||||||
do you want a confirmation of the responsible on: accepting, finishing the task or both infolog de wollen Sie eine Bestätigung des Verantwortlichen bei: Annahme, Beendigung der Aufgabe oder bei beidem
|
do you want a confirmation of the responsible on: accepting, finishing the task or both infolog de Wollen Sie eine Bestätigung des Verantwortlichen bei: Annahme, Beendigung der Aufgabe oder bei beidem
|
||||||
|
do you want a notification, if items get assigned to you or assigned items get updated? infolog de Wollen Sie eine Benachrichtigung, wenn Einträge Ihnen zugewiesen werden oder zugewiesene Einträge geändert werden?
|
||||||
|
do you want a notification, if items you are responsible for are about to start? infolog de Wollen Sie eine Benachrichtigung, wenn Einträge für die Sie verantwortlich sind beginnen sollen?
|
||||||
|
do you want a notification, if items you are responsible for are due? infolog de Wollen Sie eine Benachrichtigung, wenn Einträge für die Sie verantwortlich sind fällig werden?
|
||||||
|
do you want a notification, if items you created get updated? infolog de Wollen Sie eine Benachrichtigung, wenn Einträge die Sie angelegt haben aktualisiert werden?
|
||||||
|
do you want a notification, if items you delegated are about to start? infolog de Wollen Sie eine Benachrichtigung, wenn Einträge die Sie delegiert haben beginnen sollen?
|
||||||
|
do you want a notification, if items you delegated are due? infolog de Wollen Sie eine Benachrichtigung, wenn Einträge die Sie delegiert haben fällig werden?
|
||||||
|
do you want to receive notifications as html-mails or plain text? infolog de Wollen Sie die Benachrichtigungen als HTML Mail oder reinen Text empfangen?
|
||||||
do you want to see custom infolog types in the calendar? infolog de Wollen Sie benutzerdefinierte Typen auch im Kalender sehen?
|
do you want to see custom infolog types in the calendar? infolog de Wollen Sie benutzerdefinierte Typen auch im Kalender sehen?
|
||||||
don't show infolog infolog de InfoLog NICHT anzeigen
|
don't show infolog infolog de InfoLog NICHT anzeigen
|
||||||
done infolog de erledigt
|
done infolog de erledigt
|
||||||
@ -125,6 +146,8 @@ from infolog de Von
|
|||||||
general infolog de Allgemein
|
general infolog de Allgemein
|
||||||
group owner for infolog de Gruppeneigentümer für
|
group owner for infolog de Gruppeneigentümer für
|
||||||
high infolog de hoch
|
high infolog de hoch
|
||||||
|
history logging infolog de Protokollierung der Historie
|
||||||
|
history logging and deleting of items infolog de Protokollierung der Historie und löschen von Einträgen
|
||||||
id infolog de Id
|
id infolog de Id
|
||||||
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! infolog de Wenn ein Typ einen Gruppeneigentümer hat, gehören alle Einträge dieses Typs der angegebenen Gruppe und NICHT dem Benutzer der sie angelegt hat!
|
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! infolog de Wenn ein Typ einen Gruppeneigentümer hat, gehören alle Einträge dieses Typs der angegebenen Gruppe und NICHT dem Benutzer der sie angelegt hat!
|
||||||
if not set, the line with search and filters is hidden for less entries then "max matches per page" (as defined in your common preferences). infolog de Falls nicht gesetzt, wird die Suche und die Filter ausgeblendet für weniger Einträge als "maximale Treffer pro Seite" (in ihren allg. Einstellungen definiert).
|
if not set, the line with search and filters is hidden for less entries then "max matches per page" (as defined in your common preferences). infolog de Falls nicht gesetzt, wird die Suche und die Filter ausgeblendet für weniger Einträge als "maximale Treffer pro Seite" (in ihren allg. Einstellungen definiert).
|
||||||
@ -164,6 +187,8 @@ max length of the input [, length of the inputfield (optional)] infolog de max.
|
|||||||
name must not be empty !!! infolog de Name darf nicht leer sein !!!
|
name must not be empty !!! infolog de Name darf nicht leer sein !!!
|
||||||
name of new type to create infolog de Name des neu anzulegenden Types
|
name of new type to create infolog de Name des neu anzulegenden Types
|
||||||
never hide search and filters infolog de Suche und Filter niemals ausblenden
|
never hide search and filters infolog de Suche und Filter niemals ausblenden
|
||||||
|
new %1 infolog de Neue %1
|
||||||
|
new %1 created by %2 at %3 infolog de Neue %1 wurde von %2 am %3 angelegt
|
||||||
new name infolog de neuer name
|
new name infolog de neuer name
|
||||||
new search infolog de Neue Suche
|
new search infolog de Neue Suche
|
||||||
no - cancel infolog de Nein - Abbruch
|
no - cancel infolog de Nein - Abbruch
|
||||||
@ -181,8 +206,11 @@ note infolog de Notiz
|
|||||||
number of records to read (%1) infolog de Anzahl Datensätze lesen (%1)
|
number of records to read (%1) infolog de Anzahl Datensätze lesen (%1)
|
||||||
number of row for a multiline inputfield or line of a multi-select-box infolog de Anzahl Zeilen für ein mehrzeiliges Eingabefeld oder eines mehrfachen Auswahlfeldes
|
number of row for a multiline inputfield or line of a multi-select-box infolog de Anzahl Zeilen für ein mehrzeiliges Eingabefeld oder eines mehrfachen Auswahlfeldes
|
||||||
offer infolog de Angebot
|
offer infolog de Angebot
|
||||||
|
one day after infolog de am nächsten Tag
|
||||||
|
one day in advance infolog de am Vortag
|
||||||
ongoing infolog de in Arbeit
|
ongoing infolog de in Arbeit
|
||||||
only for details infolog de Nur bei Details
|
only for details infolog de Nur bei Details
|
||||||
|
only if i get assigned or removed infolog de Nur wenn ich zugewiesen oder entfernt werde
|
||||||
only the attachments infolog de nur die Anhänge
|
only the attachments infolog de nur die Anhänge
|
||||||
only the links infolog de nur die Verknüpfungen
|
only the links infolog de nur die Verknüpfungen
|
||||||
open infolog de offen
|
open infolog de offen
|
||||||
@ -212,6 +240,13 @@ project settings: price, times infolog de Einstellungen zum Projekt: Preis, Zeit
|
|||||||
re: infolog de Re:
|
re: infolog de Re:
|
||||||
read one record by passing its id. infolog de Einen Datensatz spezifiziert durch seine id lesen.
|
read one record by passing its id. infolog de Einen Datensatz spezifiziert durch seine id lesen.
|
||||||
read rights (default) infolog de Leserechte (Vorgabe)
|
read rights (default) infolog de Leserechte (Vorgabe)
|
||||||
|
receive notifications about due entries you are responsible for infolog de Benachrichtigungen über fällige Einträge für die Sie verantwortlich sind
|
||||||
|
receive notifications about due entries you delegated infolog de Benachrichtigungen über fällige Einträge die Sie delegiert haben
|
||||||
|
receive notifications about items assigned to you infolog de Benachrichtigungen über Einträge für die Sie verantwortlich sind
|
||||||
|
receive notifications about own items infolog de Benachrichtigungen über eigene Einträge
|
||||||
|
receive notifications about starting entries you are responsible for infolog de Benachrichtigungen über zu startende Einträge für die Sie verantwortlich sind
|
||||||
|
receive notifications about starting entries you delegated infolog de Benachrichtigungen über zu startende Einträge die Sie delegiert haben
|
||||||
|
receive notifications as html-mails infolog de Benachrichtigungen als HTML Mails
|
||||||
reg. expr. for local ip's<br>eg. ^192.168.1. infolog de reg. Ausdr. für lokale IP's<br>^192\.168\.1\.
|
reg. expr. for local ip's<br>eg. ^192.168.1. infolog de reg. Ausdr. für lokale IP's<br>^192\.168\.1\.
|
||||||
reg. expr. for local ip's<br>eg. ^192\.168\.1\. infolog de reg. Ausdr. für lokale IP's<br>^192\.168\.1\.
|
reg. expr. for local ip's<br>eg. ^192\.168\.1\. infolog de reg. Ausdr. für lokale IP's<br>^192\.168\.1\.
|
||||||
remark infolog de Bemerkung
|
remark infolog de Bemerkung
|
||||||
@ -223,6 +258,7 @@ responsible upcoming infolog de verantwortlich zuk
|
|||||||
responsible user, priority infolog de Verantwortlicher, Priorität
|
responsible user, priority infolog de Verantwortlicher, Priorität
|
||||||
returns a list / search for records. infolog de Liefert eine Liste von / sucht nach Datensätzen.
|
returns a list / search for records. infolog de Liefert eine Liste von / sucht nach Datensätzen.
|
||||||
rights for the responsible infolog de Rechte für den Verantwortlichen
|
rights for the responsible infolog de Rechte für den Verantwortlichen
|
||||||
|
same day infolog de gleichen Tag
|
||||||
save infolog de Speichern
|
save infolog de Speichern
|
||||||
saves the changes made and leaves infolog de speichert die Änderungen und beendet
|
saves the changes made and leaves infolog de speichert die Änderungen und beendet
|
||||||
saves this entry infolog de diesen Eintrag speichern
|
saves this entry infolog de diesen Eintrag speichern
|
||||||
@ -308,6 +344,10 @@ will-call infolog de ruft zur
|
|||||||
write (add or update) a record by passing its fields. infolog de Schreiben (zufügen oder aktualisieren) eines Datensatzes durch Angabe seiner Felder.
|
write (add or update) a record by passing its fields. infolog de Schreiben (zufügen oder aktualisieren) eines Datensatzes durch Angabe seiner Felder.
|
||||||
yes - delete infolog de Ja - Löschen
|
yes - delete infolog de Ja - Löschen
|
||||||
yes - delete including sub-entries infolog de Ja - Löschen einschließlich Untereinträge
|
yes - delete including sub-entries infolog de Ja - Löschen einschließlich Untereinträge
|
||||||
|
yes, noone can purge deleted items infolog de Ja, niemand darf gelöschte Einträge bereinigen
|
||||||
|
yes, only admins can purge deleted items infolog de Ja, nur Admins dürfen gelöschte Einträge bereinigen
|
||||||
|
yes, with larger fontsize infolog de Ja, mit einer größeren Schrift
|
||||||
|
yes, with purging of deleted items possible infolog de Ja, jeder darf gelöschte Einträge bereinigen
|
||||||
you can't delete one of the stock types !!! infolog de Sie können keinen der Standardtypen löschen!!!
|
you can't delete one of the stock types !!! infolog de Sie können keinen der Standardtypen löschen!!!
|
||||||
you have entered an invalid ending date infolog de Sie haben ein ungültiges Fälligkeitsdatum eingegeben
|
you have entered an invalid ending date infolog de Sie haben ein ungültiges Fälligkeitsdatum eingegeben
|
||||||
you have entered an invalid starting date infolog de Sie haben ein ungültiges Startdatum eingegeben
|
you have entered an invalid starting date infolog de Sie haben ein ungültiges Startdatum eingegeben
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
|
%1 days in advance infolog en %1 days in advance
|
||||||
|
%1 deleted infolog en %1 deleted
|
||||||
|
%1 deleted by %2 at %3 infolog en %1 deleted by %2 at %3
|
||||||
|
%1 modified infolog en %1 modified
|
||||||
|
%1 modified by %2 at %3 infolog en %1 modified by %2 at %3
|
||||||
%1 records imported infolog en %1 records imported
|
%1 records imported infolog en %1 records imported
|
||||||
%1 records read (not yet imported, you may go %2back%3 and uncheck test import) infolog en %1 records read (not yet imported, you may go %2back%3 and uncheck Test Import)
|
%1 records read (not yet imported, you may go %2back%3 and uncheck test import) infolog en %1 records read (not yet imported, you may go %2back%3 and uncheck Test Import)
|
||||||
|
%1 you are responsible for is due at %2 infolog en %1 you are responsible for is due at %2
|
||||||
|
%1 you are responsible for is starting at %2 infolog en %1 you are responsible for is starting at %2
|
||||||
|
%1 you delegated is due at %2 infolog en %1 you delegated is due at %2
|
||||||
|
%1 you delegated is starting at %2 infolog en %1 you delegated is starting at %2
|
||||||
- subprojects from infolog en - Subprojects from
|
- subprojects from infolog en - Subprojects from
|
||||||
0% infolog en 0%
|
0% infolog en 0%
|
||||||
10% infolog en 10%
|
10% infolog en 10%
|
||||||
@ -36,7 +45,7 @@ apply the changes infolog en Apply the changes
|
|||||||
are you shure you want to delete this entry ? infolog en Are you sure you want to delete this entry ?
|
are you shure you want to delete this entry ? infolog en Are you sure you want to delete this entry ?
|
||||||
attach a file infolog en Attach a file
|
attach a file infolog en Attach a file
|
||||||
attach file infolog en Attach file
|
attach file infolog en Attach file
|
||||||
attension: no contact with address %1 found. infolog en Attension: No Contact with address %1 found.
|
attention: no contact with address %1 found. infolog en Attention: No Contact with address %1 found.
|
||||||
back to main list infolog en Back to main list
|
back to main list infolog en Back to main list
|
||||||
billed infolog en billed
|
billed infolog en billed
|
||||||
both infolog en both
|
both infolog en both
|
||||||
@ -81,12 +90,17 @@ dates, status, access infolog en Dates, Status, Access
|
|||||||
days infolog en days
|
days infolog en days
|
||||||
default filter for infolog infolog en Default Filter for InfoLog
|
default filter for infolog infolog en Default Filter for InfoLog
|
||||||
default status for a new log entry infolog en default status for a new log entry
|
default status for a new log entry infolog en default status for a new log entry
|
||||||
|
delegated infolog en delegated
|
||||||
|
delegated open infolog en delegated open
|
||||||
|
delegated overdue infolog en delegated overdue
|
||||||
|
delegated upcomming infolog en delegated upcomming
|
||||||
delegation infolog en Delegation
|
delegation infolog en Delegation
|
||||||
delete infolog en Delete
|
delete infolog en Delete
|
||||||
delete one record by passing its id. infolog en Delete one record by passing its id.
|
delete one record by passing its id. infolog en Delete one record by passing its id.
|
||||||
delete the entry infolog en Delete the entry
|
delete the entry infolog en Delete the entry
|
||||||
delete this entry infolog en delete this entry
|
delete this entry infolog en delete this entry
|
||||||
delete this entry and all listed sub-entries infolog en Delete this entry and all listed sub-entries
|
delete this entry and all listed sub-entries infolog en Delete this entry and all listed sub-entries
|
||||||
|
deleted infolog en deleted
|
||||||
deletes the selected typ infolog en deletes the selected type
|
deletes the selected typ infolog en deletes the selected type
|
||||||
deletes this field infolog en deletes this field
|
deletes this field infolog en deletes this field
|
||||||
deletes this status infolog en deletes this status
|
deletes this status infolog en deletes this status
|
||||||
@ -94,6 +108,13 @@ description infolog en Description
|
|||||||
determines the order the fields are displayed infolog en determines the order the fields are displayed
|
determines the order the fields are displayed infolog en determines the order the fields are displayed
|
||||||
disables a status without deleting it infolog en disables a status without deleting it
|
disables a status without deleting it infolog en disables a status without deleting it
|
||||||
do you want a confirmation of the responsible on: accepting, finishing the task or both infolog en do you want a confirmation of the responsible on: accepting, finishing the task or both
|
do you want a confirmation of the responsible on: accepting, finishing the task or both infolog en do you want a confirmation of the responsible on: accepting, finishing the task or both
|
||||||
|
do you want a notification, if items get assigned to you or assigned items get updated? infolog en Do you want a notification, if items get assigned to you or assigned items get updated?
|
||||||
|
do you want a notification, if items you are responsible for are about to start? infolog en Do you want a notification, if items you are responsible for are about to start?
|
||||||
|
do you want a notification, if items you are responsible for are due? infolog en Do you want a notification, if items you are responsible for are due?
|
||||||
|
do you want a notification, if items you created get updated? infolog en Do you want a notification, if items you created get updated?
|
||||||
|
do you want a notification, if items you delegated are about to start? infolog en Do you want a notification, if items you delegated are about to start?
|
||||||
|
do you want a notification, if items you delegated are due? infolog en Do you want a notification, if items you delegated are due?
|
||||||
|
do you want to receive notifications as html-mails or plain text? infolog en Do you want to receive notifications as html-mails or plain text?
|
||||||
do you want to see custom infolog types in the calendar? infolog en Do you want to see custom InfoLog types in the calendar?
|
do you want to see custom infolog types in the calendar? infolog en Do you want to see custom InfoLog types in the calendar?
|
||||||
don't show infolog infolog en DON'T show InfoLog
|
don't show infolog infolog en DON'T show InfoLog
|
||||||
done infolog en done
|
done infolog en done
|
||||||
@ -125,6 +146,8 @@ from infolog en From
|
|||||||
general infolog en General
|
general infolog en General
|
||||||
group owner for infolog en Group owner for
|
group owner for infolog en Group owner for
|
||||||
high infolog en high
|
high infolog en high
|
||||||
|
history logging infolog en History logging
|
||||||
|
history logging and deleting of items infolog en History logging and deleting of items
|
||||||
id infolog en Id
|
id infolog en Id
|
||||||
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! infolog en 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!
|
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! infolog en 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!
|
||||||
if not set, the line with search and filters is hidden for less entries then "max matches per page" (as defined in your common preferences). infolog en If not set, the line with search and filters is hidden for less entries then "max matches per page" (as defined in your common preferences).
|
if not set, the line with search and filters is hidden for less entries then "max matches per page" (as defined in your common preferences). infolog en If not set, the line with search and filters is hidden for less entries then "max matches per page" (as defined in your common preferences).
|
||||||
@ -164,6 +187,8 @@ max length of the input [, length of the inputfield (optional)] infolog en max l
|
|||||||
name must not be empty !!! infolog en Name must not be empty !!!
|
name must not be empty !!! infolog en Name must not be empty !!!
|
||||||
name of new type to create infolog en name of new type to create
|
name of new type to create infolog en name of new type to create
|
||||||
never hide search and filters infolog en Never hide search and filters
|
never hide search and filters infolog en Never hide search and filters
|
||||||
|
new %1 infolog en New %1
|
||||||
|
new %1 created by %2 at %3 infolog en New %1 created by %2 at %3
|
||||||
new name infolog en new name
|
new name infolog en new name
|
||||||
new search infolog en New search
|
new search infolog en New search
|
||||||
no - cancel infolog en No - Cancel
|
no - cancel infolog en No - Cancel
|
||||||
@ -181,8 +206,11 @@ note infolog en Note
|
|||||||
number of records to read (%1) infolog en Number of records to read (%1)
|
number of records to read (%1) infolog en Number of records to read (%1)
|
||||||
number of row for a multiline inputfield or line of a multi-select-box infolog en number of row for a multiline inputfield or line of a multi-select-box
|
number of row for a multiline inputfield or line of a multi-select-box infolog en number of row for a multiline inputfield or line of a multi-select-box
|
||||||
offer infolog en offer
|
offer infolog en offer
|
||||||
|
one day after infolog en one day after
|
||||||
|
one day in advance infolog en one day in advance
|
||||||
ongoing infolog en ongoing
|
ongoing infolog en ongoing
|
||||||
only for details infolog en Only for details
|
only for details infolog en Only for details
|
||||||
|
only if i get assigned or removed infolog en Only if I get assigned or removed
|
||||||
only the attachments infolog en only the attachments
|
only the attachments infolog en only the attachments
|
||||||
only the links infolog en only the links
|
only the links infolog en only the links
|
||||||
open infolog en open
|
open infolog en open
|
||||||
@ -212,6 +240,13 @@ project settings: price, times infolog en Project settings: price, times
|
|||||||
re: infolog en Re:
|
re: infolog en Re:
|
||||||
read one record by passing its id. infolog en Read one record by passing its id.
|
read one record by passing its id. infolog en Read one record by passing its id.
|
||||||
read rights (default) infolog en read rights (default)
|
read rights (default) infolog en read rights (default)
|
||||||
|
receive notifications about due entries you are responsible for infolog en Receive notifications about due entries you are responsible for
|
||||||
|
receive notifications about due entries you delegated infolog en Receive notifications about due entries you delegated
|
||||||
|
receive notifications about items assigned to you infolog en Receive notifications about items assigned to you
|
||||||
|
receive notifications about own items infolog en Receive notifications about own items
|
||||||
|
receive notifications about starting entries you are responsible for infolog en Receive notifications about starting entries you are responsible for
|
||||||
|
receive notifications about starting entries you delegated infolog en Receive notifications about starting entries you delegated
|
||||||
|
receive notifications as html-mails infolog en Receive notifications as html-mails
|
||||||
reg. expr. for local ip's<br>eg. ^192\.168\.1\. infolog en reg. expr. for local IP's<br>eg. ^192\.168\.1\.
|
reg. expr. for local ip's<br>eg. ^192\.168\.1\. infolog en reg. expr. for local IP's<br>eg. ^192\.168\.1\.
|
||||||
remark infolog en Remark
|
remark infolog en Remark
|
||||||
remove this link (not the entry itself) infolog en Remove this link (not the entry itself)
|
remove this link (not the entry itself) infolog en Remove this link (not the entry itself)
|
||||||
@ -222,6 +257,7 @@ responsible upcoming infolog en responsible upcoming
|
|||||||
responsible user, priority infolog en responsible user, priority
|
responsible user, priority infolog en responsible user, priority
|
||||||
returns a list / search for records. infolog en Returns a list / search for records.
|
returns a list / search for records. infolog en Returns a list / search for records.
|
||||||
rights for the responsible infolog en Rights for the responsible
|
rights for the responsible infolog en Rights for the responsible
|
||||||
|
same day infolog en same day
|
||||||
save infolog en Save
|
save infolog en Save
|
||||||
saves the changes made and leaves infolog en saves the changes made and leaves
|
saves the changes made and leaves infolog en saves the changes made and leaves
|
||||||
saves this entry infolog en Saves this entry
|
saves this entry infolog en Saves this entry
|
||||||
@ -306,6 +342,10 @@ will-call infolog en will call
|
|||||||
write (add or update) a record by passing its fields. infolog en Write (add or update) a record by passing its fields.
|
write (add or update) a record by passing its fields. infolog en Write (add or update) a record by passing its fields.
|
||||||
yes - delete infolog en Yes - Delete
|
yes - delete infolog en Yes - Delete
|
||||||
yes - delete including sub-entries infolog en Yes - Delete including sub-entries
|
yes - delete including sub-entries infolog en Yes - Delete including sub-entries
|
||||||
|
yes, noone can purge deleted items infolog en Yes, noone can purge deleted items
|
||||||
|
yes, only admins can purge deleted items infolog en Yes, only admins can purge deleted items
|
||||||
|
yes, with larger fontsize infolog en Yes, with larger fontsize
|
||||||
|
yes, with purging of deleted items possible infolog en Yes, with purging of deleted items possible
|
||||||
you can't delete one of the stock types !!! infolog en You can't delete one of the stock types !!!
|
you can't delete one of the stock types !!! infolog en You can't delete one of the stock types !!!
|
||||||
you have entered an invalid ending date infolog en You have entered an invalid due date
|
you have entered an invalid ending date infolog en You have entered an invalid due date
|
||||||
you have entered an invalid starting date infolog en You have entered an invalid starting date
|
you have entered an invalid starting date infolog en You have entered an invalid starting date
|
||||||
|
@ -44,11 +44,12 @@ $setup_info['infolog']['note'] =
|
|||||||
expressions and direct calls to php-functions (e.g. to link the phone calls
|
expressions and direct calls to php-functions (e.g. to link the phone calls
|
||||||
(again) to the addressbook entrys).</p>
|
(again) to the addressbook entrys).</p>
|
||||||
<p><b>More information</b> about InfoLog and the current development-status can be found on the
|
<p><b>More information</b> about InfoLog and the current development-status can be found on the
|
||||||
<a href="http://www.egroupware.org/infolog" target="_blank">InfoLog page on our Website</a>.</p>';
|
<a href="http://www.egroupware.org/wiki/infolog" target="_blank">InfoLog page on our Website</a>.</p>';
|
||||||
|
|
||||||
/* The hooks this app includes, needed for hooks registration */
|
/* The hooks this app includes, needed for hooks registration */
|
||||||
$setup_info['infolog']['hooks']['preferences'] = 'infolog.admin_prefs_sidebox_hooks.all_hooks';
|
$setup_info['infolog']['hooks']['preferences'] = 'infolog.admin_prefs_sidebox_hooks.all_hooks';
|
||||||
$setup_info['infolog']['hooks'][] = 'settings';
|
$setup_info['infolog']['hooks'][] = 'settings';
|
||||||
|
$setup_info['infolog']['hooks']['verify_settings'] = 'infolog.admin_prefs_sidebox_hooks.verify_settings';
|
||||||
$setup_info['infolog']['hooks']['admin'] = 'infolog.admin_prefs_sidebox_hooks.all_hooks';
|
$setup_info['infolog']['hooks']['admin'] = 'infolog.admin_prefs_sidebox_hooks.all_hooks';
|
||||||
$setup_info['infolog']['hooks'][] = 'deleteaccount';
|
$setup_info['infolog']['hooks'][] = 'deleteaccount';
|
||||||
$setup_info['infolog']['hooks'][] = 'home';
|
$setup_info['infolog']['hooks'][] = 'home';
|
||||||
|
@ -126,7 +126,19 @@
|
|||||||
</rows>
|
</rows>
|
||||||
</grid>
|
</grid>
|
||||||
</template>
|
</template>
|
||||||
<template id="infolog.edit" template="" lang="" group="0" version="1.3.001">
|
<template id="infolog.edit.history" template="" lang="" group="0" version="1.3.002">
|
||||||
|
<grid width="100%" height="250" overflow="auto">
|
||||||
|
<columns>
|
||||||
|
<column/>
|
||||||
|
</columns>
|
||||||
|
<rows>
|
||||||
|
<row valign="top">
|
||||||
|
<historylog id="history"/>
|
||||||
|
</row>
|
||||||
|
</rows>
|
||||||
|
</grid>
|
||||||
|
</template>
|
||||||
|
<template id="infolog.edit" template="" lang="" group="0" version="1.3.002">
|
||||||
<grid width="100%">
|
<grid width="100%">
|
||||||
<columns>
|
<columns>
|
||||||
<column width="103"/>
|
<column width="103"/>
|
||||||
@ -180,6 +192,7 @@
|
|||||||
<tab label="Delegation" statustext="responsible user, priority"/>
|
<tab label="Delegation" statustext="responsible user, priority"/>
|
||||||
<tab label="Projectmanager" statustext="Project settings: price, times"/>
|
<tab label="Projectmanager" statustext="Project settings: price, times"/>
|
||||||
<tab label="Customfields" statustext="Custom fields"/>
|
<tab label="Customfields" statustext="Custom fields"/>
|
||||||
|
<tab label="History" statustext="Change history"/>
|
||||||
</tabs>
|
</tabs>
|
||||||
<tabpanels>
|
<tabpanels>
|
||||||
<template id="infolog.edit.description"/>
|
<template id="infolog.edit.description"/>
|
||||||
@ -187,6 +200,7 @@
|
|||||||
<template id="infolog.edit.delegation"/>
|
<template id="infolog.edit.delegation"/>
|
||||||
<template id="infolog.edit.project"/>
|
<template id="infolog.edit.project"/>
|
||||||
<template id="infolog.edit.customfields"/>
|
<template id="infolog.edit.customfields"/>
|
||||||
|
<template id="infolog.edit.history"/>
|
||||||
</tabpanels>
|
</tabpanels>
|
||||||
</tabbox>
|
</tabbox>
|
||||||
</row>
|
</row>
|
||||||
|
BIN
infolog/templates/default/images/deleted.png
Normal file
BIN
infolog/templates/default/images/deleted.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 295 B |
Loading…
Reference in New Issue
Block a user