enabled class autoloading for notifications, let admins enable or disable notification backends, security fixes for email and egwpopup backend, unified link arrays used for notifications

This commit is contained in:
Christian Binder 2008-01-30 18:58:00 +00:00
parent e657227035
commit 5b699573e4
15 changed files with 406 additions and 175 deletions

View File

@ -605,9 +605,8 @@ class bocalupdate extends bocal
}
// send via notification_app
if($GLOBALS['egw_info']['apps']['notifications']['enabled']) {
require_once(EGW_INCLUDE_ROOT. '/notifications/inc/class.notification.inc.php');
try {
$notification = new notification();
$notification = new notifications();
$notification->set_receivers(array($userid));
$notification->set_message($body);
$notification->set_sender($senderid);
@ -621,7 +620,7 @@ class bocalupdate extends bocal
continue;
}
} else {
error_log('calendar: cannot send any notifications because notification-app is not installed');
error_log('calendar: cannot send any notifications because notifications is not installed');
}
}
}
@ -869,13 +868,15 @@ class bocalupdate extends bocal
/* this is needed for notification-app
* notification-app creates the link individual for
* every user, so we must provide a neutral link-style
* if calendar implements tracking in near future, this part can be deleted
*/
$link_arr = array();
$link_arr['menuaction'] = 'calendar.uiforms.edit';
$link_arr['params'] = array( 'cal_id' => $event['id'],
'date' => $eventStart_arr['full'],
);
$link_arr['text'] = $event['title'];
$link_arr['view'] = array( 'menuaction' => 'calendar.uiforms.edit',
'cal_id' => $event['id'],
'date' => $eventStart_arr['full'],
);
$link_arr['popup'] = '750x400';
$details['link_arr'] = $link_arr;
$dis = array();

View File

@ -22,7 +22,7 @@ require_once(EGW_API_INC.'/class.html.inc.php');
* 1. set the required class-vars: app, id_field
* 2. optional set class-vars: creator_field, assigned_field, check2prefs
* 3. implement the required methods: get_config, get_details
* 4. optionally re-implement: get_subject, get_body, get_attachments, get_link, get_message
* 4. optionally re-implement: get_title, get_subject, get_body, get_attachments, get_link, get_notification_link, get_message
* They are all documented in this file via phpDocumentor comments.
*/
class bo_tracking
@ -370,16 +370,14 @@ class bo_tracking
if ($GLOBALS['egw_info']['apps']['notifications']['enabled']) {
// send via notification_app
$receiver = is_numeric($user_or_lang) ? $user_or_lang : $email;
require_once(EGW_INCLUDE_ROOT. '/notifications/inc/class.notification.inc.php');
try {
$notification = new notification();
$notification = new notifications();
$notification->set_receivers(array($receiver));
$notification->set_message($this->get_body(false,$data,$old)); // set message as plaintext
$notification->set_message($this->get_body(true,$data,$old)); // and html
$notification->set_message($this->get_body(false,$data,$old,false)); // set message as plaintext
$notification->set_message($this->get_body(true,$data,$old,false)); // and html
$notification->set_sender($this->get_sender($data,$old,true));
$notification->set_subject($this->get_subject($data,$old));
// does not work atm
//$notification->set_links(array($this->get_notification_link($data,$old)));
$notification->set_links(array($this->get_notification_link($data,$old)));
$attachments = $this->get_attachments($data,$old);
if(is_array($attachments)) { $notification->set_attachments($attachments); }
$notification->send();
@ -389,7 +387,7 @@ class bo_tracking
return false;
}
} else {
error_log('tracking: cannot send any notifications because notification-app is not installed');
error_log('tracking: cannot send any notifications because notifications is not installed');
}
return true;
@ -450,6 +448,23 @@ class bo_tracking
//echo "<p>bo_tracking::get_sender()='".htmlspecialchars($sender)."'</p>\n";
return $sender;
}
/**
* Get the title for a given entry, can be reimplemented
*
* @param array $data
* @param array $old
* @return string
*/
function get_title($data,$old)
{
if (!is_object($GLOBALS['egw']->link))
{
require_once(EGW_API_INC.'/class.bolink.inc.php');
$GLOBALS['egw']->link =& new bolink();
}
return $GLOBALS['egw']->link->title($this->app,$data[$this->id_field]);
}
/**
* Get the subject for a given entry, can be reimplemented
@ -532,7 +547,7 @@ class bo_tracking
}
/**
* Get a link for notifications to view the entry
* Get a link for notifications to view the entry, can be reimplemented
*
* @param array $data
* @param array $old
@ -542,21 +557,16 @@ class bo_tracking
{
if (!is_object($GLOBALS['egw']->link))
{
require_once(EGW_API_INC.'/class.bolink.inc.php');
$GLOBALS['egw']->link =& new bolink();
$GLOBALS['egw']->link = new bolink();
}
if($view = $GLOBALS['egw']->link->view($this->app,$data[$this->id_field])) {
return array( 'menuaction' => $view['menuaction'],
'params' => array ( 'action' => $view['action'],
'action_id' => $view['action_id'],
),
'text' => $data['info_subject'],
return array( 'text' => $this->get_title($data,$old),
'view' => $view,
'popup' => $GLOBALS['egw']->link->is_popup($this->app,'view'),
);
} else {
return false;
}
}
return false;
}
/**
* Get the body of the notification message, can be reimplemented
@ -564,9 +574,10 @@ class bo_tracking
* @param boolean $html_email
* @param array $data
* @param array $old
* @param boolean $integrate_link to have links embedded inside the body
* @return string
*/
function get_body($html_email,$data,$old)
function get_body($html_email,$data,$old,$integrate_link = true)
{
$body = '';
if ($html_email)
@ -578,7 +589,7 @@ class bo_tracking
{
$body .= $this->format_line($html_email,'message',false,$message);
}
if (($link = $this->get_link($data,$old)))
if ($integrate_link && ($link = $this->get_link($data,$old)))
{
$body .= $this->format_line($html_email,'link',false,lang('You can respond by visiting:'),$link);
}
@ -621,7 +632,7 @@ class bo_tracking
if (!$this->html_content_allow) $line = $this->html->htmlspecialchars($line); // XSS
$color = $modified ? 'red' : false;
$size = '120%';
$size = '110%';
$bold = false;
$background = '#FFFFF1';
switch($type)
@ -686,7 +697,7 @@ class bo_tracking
}
/**
* Get the attachments for a notification mail
* Get the attachments for a notification
*
* @param array $data
* @param array $old

View File

@ -20,11 +20,11 @@ require_once(EGW_INCLUDE_ROOT.'/phpgwapi/inc/class.config.inc.php');
* This class takes care about the notification-routing. It chooses one or more backends for each
* given recipient depending on its prefs or falls back to self::_fallback
*
* The classes doing the notifications are called notification_<backend> and should only be
* The classes doing the notifications are called notifications_<backend> and should only be
* called from this class. The backend's job is to deliver ONE message to ONE recipient.
*
*/
final class notification {
final class notifications {
/**
* Appname
@ -36,29 +36,58 @@ final class notification {
*/
const _fallback = 'email_only';
/**
* registered backends
* @var array
*/
private $backends = array('popup', 'winpopup', 'email');
/**
* pre-defined notificaton chains
* @abstract
* arrays with name => chain pairs
* the chain itself consists of an array with framework => action pairs
* where action defines what to do after the framework has been executed:
* stop: stop executing notifications
* fail: do not stop if framework fails, otherwise stop
* continue: execute next framework
*
* @var array
*/
* pre-defined notificaton chains
* @abstract
* arrays with name => chain pairs
* the chain itself consists of an array with framework => action pairs
* where action defines what to do after the framework has been executed:
* stop: stop executing notifications
* fail: do not stop if framework fails, otherwise stop
* continue: execute next framework
*
* @var array
*/
private $notification_chains = array(
'disable' => false,
'popup_only' => array('popup' => 'stop'),
'winpopup_only' => array('winpopup' => 'stop'),
'email_only' => array('email' => 'stop'),
'popup_or_email' => array('popup' => 'fail', 'email' => 'stop'),
'winpopup_or_email' => array('winpopup' => 'fail', 'email' => 'stop'),
'popup_and_email' => array('popup' => 'continue', 'email' => 'stop'),
'winpopup_and_email' => array('winpopup' => 'continue', 'email' => 'stop'),
'egwpopup_and_winpopup' => array('popup' => 'continue', 'winpopup' => 'stop'),
'all' => array('popup' => 'continue', 'winpopup' => 'continue', 'email' => 'stop'),
'disable' => false, // will be created by $this->get_available_chains
'email_only' => false, // will be created by $this->get_available_chains
'all' => false, // will be created by $this->get_available_chains
'popup_only' => array('popup' => 'stop'),
'popup_or_email' => array('popup' => 'fail', 'email' => 'stop'),
//'popup_or_sms' => array('popup' => 'fail', 'sms' => 'stop'),
'popup_and_email' => array('popup' => 'continue', 'email' => 'stop'),
'popup_and_winpopup' => array('popup' => 'continue', 'winpopup' => 'stop'),
'winpopup_only' => array('winpopup' => 'stop'),
'winpopup_or_email' => array('winpopup' => 'fail', 'email' => 'stop'),
//'winpopup_or_sms' => array('winpopup' => 'fail', 'sms' => 'stop'),
'winpopup_and_email' => array('winpopup' => 'continue', 'email' => 'stop'),
//'sms_only' => array('sms' => 'stop'),
);
/**
* human readable descriptions for the notification chains
* @var array
*/
private $chains_descriptions = array(
'disable' => 'do not notify me at all',
'email_only' => 'E-Mail only',
'all' => 'all possible notification backends',
'popup_only' => 'eGroupWare-Popup only',
'popup_or_email' => 'eGroupWare-Popup first, if that fails notify me by E-Mail',
//'popup_or_sms' => 'eGroupware-Popup first, if that fails notify me by SMS',
'popup_and_email' => 'eGroupWare-Popup and E-Mail',
'popup_and_winpopup' => 'eGroupWare-Popup and Windows-Popup',
'winpopup_only' => 'Windows-Popup only',
'winpopup_or_email' => 'Windows-Popup first, if that fails notify me by E-Mail',
//'winpopup_or_sms' => 'Windows-Popup first, if that fails notify me by SMS',
'winpopup_and_email' => 'Windows-Popup and E-Mail',
//'sms_only' => 'SMS only',
);
/**
@ -111,7 +140,7 @@ final class notification {
private $config;
/**
* constructor of notification
* constructor of notifications
*
*/
public function __construct() {
@ -221,13 +250,13 @@ final class notification {
/**
* sets the notification links
*
* @param array $links link array (like defined in $this->add_link)
* @param array $_links link array (like defined in $this->add_link)
*/
public function set_links(array $_links) {
$this->links = array(); // clear array if set
foreach($_links as $link) {
if(is_array($link)) {
$this->add_link($link['menuaction'], $link['params'], $link['text']);
$this->add_link($link['text'], $link['view'], $link['popup']);
}
}
return true;
@ -235,16 +264,16 @@ final class notification {
/**
* adds a notification link
*
* @param string $menuaction egw menuaction (appname.classname.functionname)
* @param array $params params to append (name => value pairs)
* @param string $text a descriptive text for the link
*
* @param string $_text a descriptive text for the link
* @param array $_view all params needed to view the link (name => value pairs)
* @param string $_popup if link can be viewed in a popup something like '300x200' otherwise false
*/
public function add_link($_menuaction, $_params, $_text) {
if(!$_menuaction || !$_params || !$_text) { return false; }
$this->links[] = (object)array( 'menuaction' => $_menuaction,
'params' => $_params,
'text' => $_text,
public function add_link($_text, $_view, $_popup = false) {
if(!$_view || !$_text) { return false; }
$this->links[] = (object)array( 'text' => $_text,
'view' => $_view,
'popup' => $_popup,
);
return true;
}
@ -252,7 +281,7 @@ final class notification {
/**
* sets the notification attachments
*
* @param array $attachments attachment array (like defined in $this->add_attachment
* @param array $_attachments attachment array (like defined in $this->add_attachment)
*/
public function set_attachments(array $_attachments) {
$this->attachments = array(); // clear array if set
@ -273,10 +302,10 @@ final class notification {
* This method can be used to attach ascii or binary data,
* such as a BLOB record from a database.
*
* @param string $string Attachment data.
* @param string $filename Name of the attachment.
* @param string $encoding File encoding (see $Encoding).
* @param string $type File extension (MIME) type.
* @param string $_string Attachment data.
* @param string $_filename Name of the attachment.
* @param string $_encoding File encoding (see $Encoding).
* @param string $_type File extension (MIME) type.
*/
public function add_attachment($_string, $_filename, $_encoding = "base64", $_type = "application/octet-stream") {
if(!$_string || !$_filename) { return false; }
@ -289,20 +318,24 @@ final class notification {
}
/**
* sends notification
* sends notifications
*/
public function send() {
if (!is_object($this->sender)) {
throw new Exception('Error: cannot send notification. No sender supplied');
throw new Exception('Error: cannot send notifications. No sender supplied');
}
if (!is_array($this->receivers) || count($this->receivers) == 0) {
throw new Exception('Error: cannot send notification. No receivers supplied');
throw new Exception('Error: cannot send notifications. No receivers supplied');
}
if(!$messages = $this->create_messages($this->message_plain, $this->message_html)) {
throw new Exception('Error: cannot send notification. No valid messages supplied');
throw new Exception('Error: cannot send notifications. No valid messages supplied');
}
$available_chains = $this->get_available_chains('routing');
foreach ($this->receivers as $receiver) {
$user_notified = false;
$prepend_message = '';
$backend_errors = array();
try {
// system or non-system user
@ -318,37 +351,42 @@ final class notification {
$preferences = $prefs->read();
$preferences = (object)$preferences[self::_appname];
if($preferences->notification_chain) {
$notification_chain = $this->notification_chains[$preferences->notification_chain];
// fallback: admin disabled user-chosen chain
if(!$notification_chain = $available_chains[$preferences->notification_chain]) {
$prepend_message .= lang( 'This eGroupWare notification has been sent to you by mail because your'
.' chosen notification-chain has been disabled by the administrator.'
.' Please choose another notification-chain in your preferences!');
$notification_chain = $available_chains[self::_fallback];
}
} else {
$notification_chain = $this->notification_chains[self::_fallback]; // fallback: no prefs
$notification_chain = $available_chains[self::_fallback]; // fallback: no prefs
}
} else {
$notification_chain = $this->notification_chains[self::_fallback]; // fallback: no rights to app
$notification_chain = $available_chains[self::_fallback]; // fallback: no rights to app
}
} else {
// non-system user
$receiver->handle = $receiver->account_email;
$notification_chain = $this->notification_chains[self::_fallback]; // fallback: non-system user
$notification_chain = $available_chains[self::_fallback]; // fallback: non-system user
}
if($notification_chain === false) {
if($notification_chain == 'disable') {
continue; //user disabled notifications
}
foreach($notification_chain as $notification_backend => $action) {
try {
$notification_backend = 'notification_'.$notification_backend;
$notification_backend = self::_appname.'_'.$notification_backend;
if(!file_exists(EGW_INCLUDE_ROOT. SEP. self::_appname. SEP. 'inc'. SEP. 'class.'. $notification_backend. '.inc.php')) {
throw new Exception('file for '.$notification_backend. ' does not exist');
}
require_once(EGW_INCLUDE_ROOT. SEP. self::_appname. SEP. 'inc'. SEP. 'class.'. $notification_backend. '.inc.php');
$obj = @new $notification_backend( $this->sender, $receiver, $this->config, $preferences );
if ( !is_a( $obj, iface_notification )) {
$obj = new $notification_backend( $this->sender, $receiver, $this->config, $preferences );
if ( !($obj instanceof notifications_iface) ) {
unset ( $obj );
throw new Exception($notification_backend. ' is no implementation of iface_notification');
throw new Exception($notification_backend. ' is no implementation of notifications_iface');
}
$obj->send($messages, $this->subject, $this->links, $this->attachments);
$obj->send($this->prepend_message($messages, $prepend_message), $this->subject, $this->links, $this->attachments);
}
catch (Exception $exception) {
$backend_errors[] = $notification_backend.' failed: '.$exception->getMessage();
@ -378,18 +416,15 @@ final class notification {
}
/**
* this function creates an array with the message as plaintext and html
* creates an array with the message as plaintext and html
*
* @param string $message_plain
* @param string $message_html
* @param array $links
* @return array $messages
* @param string $_message_plain
* @param string $_message_html
* @return plain and html message in one array, $messages['plain'] and $messages['html']
*/
private function create_messages($_message_plain = '', $_message_html = '') {
if(empty($_message_plain) && empty($_message_html)) { return false; } // no message set
$messages = array();
$messages['plain'] = array();
$messages['html'] = array();
// create the messages
if(!empty($_message_plain)) {
@ -407,6 +442,33 @@ final class notification {
return $messages;
}
/**
* prepends another message to the messages array
*
* @param array $_messages the messages array from create_messages()
* @param string $_prepend just a plain message to prepend, no html!
* @return plain and html message in one array including the prepended message, $messages['plain'] and $messages['html']
*/
private function prepend_message(array $_messages, $_prepend = null) {
if(strlen($_prepend) > 0) {
foreach($_messages as $key => $value) {
switch($key) {
case 'plain':
$_messages[$key] = $_prepend."\n\n".$value;
break;
case 'html':
// ToDo: move stylesheet to a nicer place
$_messages[$key] = '<div style="margin:0; padding:1em; margin-bottom: 1em; background-color:orange; border:1px solid red;">'.$_prepend.'</div>'.$value;
break;
default:
break;
}
}
}
return $_messages;
}
/**
* returns specified part from a given mailaddress
*
@ -434,5 +496,99 @@ final class notification {
}
return false;
}
/**
* returns notification chains based on admin prefs
* @abstract the available chains can be retrieved in two different output formats:
* routing: array with common and enabled chains, chain-name as key and the chain-array as value (used for message-routing)
* human: array with common, enabled and disabled chains, chain-name as key and a human-readable description as value (used for config)
*
* @param string $_output one of: 'routing' or 'human', defaults to 'routing'
* @return array containing notification chains, output like given in $_output
*/
public function get_available_chains($_output = 'routing') {
// determine enabled backends from config
$enabled_backends = array();
foreach($this->backends as $id => $backend) {
switch($backend) {
case 'email':
$enabled_backends[$backend] = true; // fallback must always be enabled
break;
default:
$param = $backend.'_enable';
$enabled_backends[$backend] = $this->config->{$param} == true ? true : false;
break;
}
}
$enabled_chains = array();
$disabled_chains = array();
foreach($this->notification_chains as $key => $chain) {
$allow_chain = true;
if(is_array($chain)) {
foreach($chain as $name => $action) {
if(!$enabled_backends[$name]) {
$allow_chain = false; // disable whole chain if one backend is disabled
}
}
if($allow_chain) {
$enabled_chains[$key] = $chain;
} else {
$disabled_chains[$key] = $chain;
}
}
}
// common chain
$common_chains = array();
$common_chains['disable'] = 'disable';
$common_chains['email_only'] = array('email' => 'stop');
// create the 'all' chain from the enabled backends
$chain_all = array();
$backend_count = 1;
foreach($enabled_backends as $backend => $enabled) {
if($enabled) {
$chain_all[$backend] = count($enabled_backends) == $backend_count ? 'stop' : 'continue';
}
$backend_count++;
}
$common_chains['all'] = $chain_all;
switch($_output) {
case 'human':
$chain_groups = array(
lang('Common chains') => 'common_chains',
lang('Enabled chains') => 'enabled_chains',
lang('Disabled chains') => 'disabled_chains',
);
$suffix = '_human';
// create descriptions for each chain key in each group
foreach($chain_groups as $name => $arr_name) {
${$arr_name.$suffix} = array();
foreach(${$arr_name} as $key => $value) {
if($arr_name == 'disabled_chains') {
${$arr_name.$suffix}[$key] = '('.lang('Disabled').') '.lang($this->chains_descriptions[$key]);
} else {
${$arr_name.$suffix}[$key] = lang($this->chains_descriptions[$key]);
}
}
}
// summarize all groups with minimum one chain to the final array
$chains_final = array();
foreach($chain_groups as $name => $arr_name) {
if(is_array(${$arr_name.$suffix}) && count(${$arr_name.$suffix}) > 0) {
$chains_final[$name] = ${$arr_name.$suffix};
}
}
return $chains_final;
break;
case 'routing':
default:
return array_merge($common_chains, $enabled_chains);
break;
}
return false;
}
}

View File

@ -9,14 +9,10 @@
* @author Christian Binder <christian@jaytraxx.de>
*/
require_once('class.iface_notification.inc.php');
require_once(EGW_INCLUDE_ROOT.'/phpgwapi/inc/class.html.inc.php');
require_once(EGW_INCLUDE_ROOT. '/phpgwapi/inc/class.send.inc.php');
/**
* User notification via email.
*/
class notification_email implements iface_notification {
class notifications_email implements notifications_iface {
/**
* Appname
@ -66,7 +62,7 @@ class notification_email implements iface_notification {
private $html;
/**
* constructor of notification_email
* constructor of notifications_email
*
* @param object $_sender
* @param object $_recipient
@ -84,7 +80,7 @@ class notification_email implements iface_notification {
{
$this->mail = new send();
}
$this->html = & html::singleton();
$this->html = html::singleton();
}
/**
@ -97,7 +93,7 @@ class notification_email implements iface_notification {
*/
public function send(array $_messages, $_subject = false, $_links = false, $_attachments = false) {
$body_plain = $_messages['plain'].$this->render_links($_links, false, $this->preferences->external_mailclient);
$body_html = "<html>\n<body>\n".$_messages['html'].$this->render_links($_links, true, $this->preferences->external_mailclient)."</body>\n</html>\n";
$body_html = "<html><body>\n".$_messages['html'].$this->render_links($_links, true, $this->preferences->external_mailclient)."</body>\n</html>\n";
$this->mail->ClearAddresses();
$this->mail->ClearAttachments();
@ -118,7 +114,7 @@ class notification_email implements iface_notification {
throw new Exception("Failed sending notification message via email.$error");
}
}
/**
* renders plaintext/html links from given link array
*
@ -134,18 +130,24 @@ class notification_email implements iface_notification {
// php distinguishes between missing and present(null) arguments
if(is_null($_render_html)) { $_render_html = false; }
if(is_null($_render_external)) { $_render_external = true; }
$newline = $_render_html ? "<br />" : "\n";
$hruler = $_render_html ? $this->html->hr() : '';
$newline = $_render_html ? "<br />" : "\n";
$link_array = array();
$rendered_links = array();
foreach($_links as $link) {
if($_render_external) {
$link->params['no_popup'] = 1;
if($_render_external || ! $link->popup) { $link->view['no_popup'] = 1; }
$url = $this->html->link('/index.php', $link->view);
// do not expose sensitive data
$url = preg_replace('/(sessionid|kp3|domain)=[^&]+&?/','',$url);
// complete missing protocol and domain part if needed
if ($url{0} == '/' && $_render_external) {
$url = ($_SERVER['HTTPS'] || $GLOBALS['egw_info']['server']['enforce_ssl'] ? 'https://' : 'http://').
($GLOBALS['egw_info']['server']['hostname'] ? $GLOBALS['egw_info']['server']['hostname'] : $_SERVER['HTTP_HOST']).$url;
}
$url = $this->html->link('/index.php?menuaction='.$link->menuaction, $link->params);
$link_array[] = $_render_html ? $this->html->a_href($link->text, $url) : $url;
$rendered_links[] = $_render_html ? $this->html->a_href($link->text, $url, false, 'target="_blank"') : $url;
}
return lang('Linked entries:').$newline.implode($newline,$link_array);
return $hruler.$newline.lang('Linked entries:').$newline.implode($newline,$rendered_links);
}
}

View File

@ -12,7 +12,7 @@
/**
* Instant user notification
*/
interface iface_notification {
interface notifications_iface {
/**
* constructor
@ -25,7 +25,7 @@ interface iface_notification {
public function __construct($_sender, $_recipient, $_config = null, $_preferences = null);
/**
* sends notification
* sends one notification to one recipient
*
* @abstract NOTE, $_messages is an array that contains
* the notification message in plain and html

View File

@ -6,25 +6,31 @@
* @package notifications
* @subpackage backends
* @link http://www.egroupware.org
* @author Cornelius Weiss <nelius@cwtech.de>
* @author Cornelius Weiss <nelius@cwtech.de>, Christian Binder <christian@jaytraxx.de>
* @version $Id$
*/
require_once('class.iface_notification.inc.php');
require_once(EGW_INCLUDE_ROOT.'/phpgwapi/inc/class.html.inc.php');
/**
* Instant user notification with egroupware popup.
*
* @abstract egwpopup is a two stage notification. In the first stage
* notification is written into self::_notification_egwpopup
* table. In the second stage a request from the client reads
* notification is written into self::_notification_table.
* In the second stage a request from the client reads
* out the table to look if there is a notificaton for this
* client. The second stage is done in class.ajaxnotifications.inc.php
*
* Todo:
* - save the messages by uid instead of sessionid into the notification table, this
* has several advantages (users poll the messages via ajax from multiple logins, and
* do not have to read one message twice, poll after re-login with different sessionid)
* - delete message from the table only if the user has really seen it
* - if the above things are done we should get rid of rendering the links here,
* instead it should be done by the ajax class, so sessionids in links could be possible then
*
* (multidisplay is supported)
*
*/
class notification_popup implements iface_notification {
class notifications_popup implements notifications_iface {
/**
* Appname
@ -79,7 +85,7 @@ class notification_popup implements iface_notification {
private $html;
/**
* constructor of notification_egwpopup
* constructor of notifications_egwpopup
*
* @param object $_sender
* @param object $_recipient
@ -95,7 +101,7 @@ class notification_popup implements iface_notification {
$this->preferences = $_preferences;
$this->db = &$GLOBALS['egw']->db;
$this->db->set_app( self::_appname );
$this->html = & html::singleton();
$this->html = html::singleton();
}
/**
@ -126,8 +132,7 @@ class notification_popup implements iface_notification {
}
/**
* saves notification into database so that the client can fetch it from
* there via notification->get
* saves notification into database so that the client can fetch it from there
*
* @param string $_message
* @param array $_user_sessions
@ -145,24 +150,41 @@ class notification_popup implements iface_notification {
/**
* renders plaintext/html links from given link array
* should be moved to the ajax class later - like mentioned in the Todo
*
* @param array $_links
* @return html rendered link(s) as complete string (jspopup)
* @return html rendered link(s) as complete string with jspopup or a new window
*/
private function render_links($_links = false) {
if(!is_array($_links) || count($_links) == 0) { return false; }
$newline = "<br />";
$newline = "<br />";
$link_array = array();
$rendered_links = array();
foreach($_links as $link) {
$url = $this->html->link('/index.php?menuaction='.$link->menuaction, $link->params);
$menuaction_arr = explode('.',$link->menuaction);
$application = $menuaction_arr[0];
$image = $application ? $this->html->image($application,'navbar',$link->text,'align="middle" style="width: 24px; margin-right: 0.5em;"') : '';
$link_array[] = $this->html->div($image.$link->text,'onclick="'.$this->jspopup($url).'"','jspopup');
if(!$link->popup) { $link->view['no_popup'] = 1; }
$url = $this->html->link('/index.php', $link->view);
// do not expose sensitive data
$url = preg_replace('/(sessionid|kp3|domain)=[^&]+&?/','',$url);
// extract application-icon from menuaction
if($link->view['menuaction']) {
$menuaction_arr = explode('.',$link->view['menuaction']);
$application = $menuaction_arr[0];
$image = $application ? $this->html->image($application,'navbar',$link->text,'align="middle" style="width: 24px; margin-right: 0.5em;"') : '';
} else {
$image = '';
}
if($link->popup) {
$dimensions = explode('x', $link->popup);
$rendered_links[] = $this->html->div($image.$link->text,'onclick="'.$this->jspopup($url, '_blank', $dimensions[0], $dimensions[1]).'"','link');
} else {
$rendered_links[] = $this->html->div($this->html->a_href($image.$link->text, $url, false, 'target="_blank"'),'','link');
}
}
if(count($rendered_links) > 0) {
return $this->html->bold(lang('Linked entries:')).$newline.implode($newline,$rendered_links);
}
return $this->html->bold(lang('Linked entries:')).$newline.implode($newline,$link_array);
}
/**

View File

@ -9,12 +9,10 @@
* @author Christian Binder <christian@jaytraxx.de>
*/
require_once('class.iface_notification.inc.php');
/**
* User notification via winpopup.
*/
class notification_winpopup implements iface_notification {
class notifications_winpopup implements notifications_iface {
/**
* Appname
@ -69,10 +67,10 @@ class notification_winpopup implements iface_notification {
*
* @var string
*/
private $netbios_command;
private $netbios_command = "/bin/echo [MESSAGE] >> /Users/jaytraxx/winpopup.out";
/**
* constructor of notification_winpopup
* constructor of notifications_winpopup
*
* @param object $_sender
* @param object $_recipient
@ -85,7 +83,7 @@ class notification_winpopup implements iface_notification {
if(!$this->netbios_command) {
throw new Exception( 'Winpopup plugin not configured yet. Skipped sending notification message. '.
'Please check var "netbios_command" in winpopup backend '.
'('.EGW_INCLUDE_ROOT. SEP. self::_appname. SEP. 'inc'. SEP. 'class.notification_winpopup.inc.php).');
'('.EGW_INCLUDE_ROOT. SEP. self::_appname. SEP. 'inc'. SEP. 'class.notifications_winpopup.inc.php).');
}
$this->sender = $_sender;
$this->recipient = $_recipient;

View File

@ -8,9 +8,10 @@
* @author Christian Binder <christian@jaytraxx.de>
* @version $Id: hook_preferences.inc.php 22498 2006-09-25 10:20:46Z jaytraxx $
*/
$title = $appname;
$file = Array( 'Site Configuration' => $GLOBALS['egw']->link('/index.php','menuaction=admin.uiconfig.index&appname=notifications'));
display_section($appname,$title,$file);
$file = Array( 'Site Configuration' => $GLOBALS['egw']->link('/index.php', array(
'menuaction' => 'admin.uiconfig.index',
'appname' => $appname,
)));
display_section($appname,$file);
?>

View File

@ -8,10 +8,10 @@
* @author Cornelius Weiss <nelius@cwtech.de>
* @version $Id$
*/
$title = $appname;
$file = Array( 'Preferences' => $GLOBALS['egw']->link('/index.php',array('menuaction'=>'preferences.uisettings.index','appname'=>'notifications')),
);
display_section($appname,$title,$file);
$file = Array( 'Preferences' => $GLOBALS['egw']->link('/index.php',array(
'menuaction' => 'preferences.uisettings.index',
'appname' => $appname,
)));
display_section($appname,$file);
?>

View File

@ -1,6 +1,6 @@
<?php
/**
* eGroupWare - Notification - Preferences
* eGroupWare - Notifications - Preferences
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package notifications
@ -8,29 +8,24 @@
* @author Christian Binder <christian@jaytraxx.de>
*/
$notification_chains = array( 'disable' => lang('do not notify me at all'),
'popup_only' => lang('eGroupware-Popup only'),
'winpopup_only' => lang('Windows-Popup only'),
'email_only' => lang('E-Mail only'),
'popup_or_email' => lang('eGroupware-Popup first, if that fails notify me by E-Mail'),
'winpopup_or_email' => lang('Windows-Popup first, if that fails notify me by E-Mail'),
'popup_and_email' => lang('eGroupware-Popup and E-Mail'),
'winpopup_and_email' => lang('Windows-Popup and E-Mail'),
'egwpopup_and_winpopup' => lang('eGroupware-Poupup and Windows-Popup'),
'all' => lang('all possible notification extensions'),
);
$verbosity_values = array( 'low' => lang('low'),
'medium' => lang('medium'),
'high' => lang('high'),
);
$notifications = new notifications();
$available_chains = $notifications->get_available_chains('human');
$verbosity_values = array(
'low' => lang('low'),
'medium' => lang('medium'),
'high' => lang('high'),
);
$GLOBALS['settings'] = array(
'notification_chain' => array(
'type' => 'select',
'label' => 'Notify me by',
'name' => 'notification_chain',
'values' => $notification_chains,
'help' => 'Choose a notification-chain. You will be notified over the chosen extensions.',
'values' => $available_chains,
'help' => 'Choose a notification-chain. You will be notified over the backends included in the chain.<br />'
.'Note: If a notification-chain is marked as "disabled", your Administrator does not allow one or'
.' more of the backends included in the chain and notifications falls back to "E-Mail" while notifying you.',
'xmlrpc' => True,
'admin' => False
),

View File

@ -27,7 +27,7 @@ $setup_info[NOTIFICATION_APP]['maintainer'] = array(
);
$setup_info[NOTIFICATION_APP]['license'] = 'GPL';
$setup_info[NOTIFICATION_APP]['description'] =
'Instant norification of users via various channels.';
'Instant notification of users via various channels.';
/* The hooks this app includes, needed for hooks registration */
$setup_info[NOTIFICATION_APP]['hooks'][] = 'after_navbar';

View File

@ -11,9 +11,54 @@
<!-- END header -->
<!-- BEGIN body -->
<tr class="th">
<td colspan="2">&nbsp;<b>{lang_Notification_backends</b>_(Preferences_for_enabling/disabling_will_follow_soon)}</td>
<td colspan="2">&nbsp;<b>{lang_eGroupware-Popup_backend}</b></td>
</tr>
<!-- END body -->
<tr bgcolor="{row_on}">
<td>{lang_Enable_eGroupWare-Popup_backend}</td>
<td>
<select name="newsettings[popup_enable]">
<option value=""{selected_popup_enable_False}>{lang_No}</option>
<option value="True"{selected_popup_enable_True}>{lang_Yes}</option>
</select>
</td>
</tr>
<tr class="th">
<td colspan="2">&nbsp;<b>{lang_Windows-Popup_backend}</b></td>
</tr>
<tr bgcolor="{row_on}">
<td>{lang_Enable_Windows-Popup_backend}</td>
<td>
<select name="newsettings[winpopup_enable]">
<option value=""{selected_winpopup_enable_False}>{lang_No}</option>
<option value="True"{selected_winpopup_enable_True}>{lang_Yes}</option>
</select>
</td>
</tr>
<!-- future SMS backend - currently disabled
<tr class="th">
<td colspan="2">&nbsp;<b>{lang_SMS_backend}</b></td>
</tr>
<tr bgcolor="{row_on}">
<td>{lang_Enable_SMS_backend}</td>
<td>
<select name="newsettings[sms_enable]">
<option value=""{selected_sms_enable_False}>{lang_No}</option>
<option value="True"{selected_sms_enable_True}>{lang_Yes}</option>
</select>
</td>
</tr>
<tr bgcolor="{row_off}">
<td>{lang_Maximum_SMS_messages_per_notification}</td>
<td>
<select name="newsettings[sms_maxmessages]">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</td>
</tr>
-->
<!-- END body -->
<!-- BEGIN footer -->
<tr valign="bottom" style="height: 30px;">
<td colspan="2" align="center">

View File

@ -463,7 +463,7 @@ Preferences tabs
*/
#notificationwindow_message > table
{
font-size: 90%;
font-size: 95%;
}
#notificationwindow_message hr
@ -473,7 +473,7 @@ Preferences tabs
height: 1px;
}
#notificationwindow_message .jspopup
#notificationwindow_message .link
{
cursor: pointer;
}

View File

@ -722,7 +722,7 @@ body {
*/
#notificationwindow_message > table
{
font-size: 90%;
font-size: 95%;
}
#notificationwindow_message hr
@ -732,7 +732,7 @@ body {
height: 1px;
}
#notificationwindow_message .jspopup
#notificationwindow_message .link
{
cursor: pointer;
}

View File

@ -646,7 +646,7 @@ body {
*/
#notificationwindow_message > table
{
font-size: 90%;
font-size: 95%;
}
#notificationwindow_message hr
@ -656,7 +656,7 @@ body {
height: 1px;
}
#notificationwindow_message .jspopup
#notificationwindow_message .link
{
cursor: pointer;
}