2006-09-07 09:04:15 +02:00
< ? php
/**
2012-03-13 09:59:05 +01:00
* EGroupware - Notifications
2006-09-07 09:04:15 +02:00
*
* @ license http :// opensource . org / licenses / gpl - license . php GPL - GNU General Public License
* @ package notifications
* @ link http :// www . egroupware . org
* @ author Cornelius Weiss < nelius @ cwtech . de >
2006-09-25 12:20:46 +02:00
* @ version $Id $
2006-09-07 09:04:15 +02:00
*/
2016-05-06 11:19:36 +02:00
use EGroupware\Api ;
2010-05-03 08:44:26 +02:00
2006-09-07 09:04:15 +02:00
/**
* Notifies users according to their preferences .
2010-05-03 08:44:26 +02:00
*
* @ abstract NOTE : This is for instant notifications . If you need time dependend notifications use the
2006-09-07 09:04:15 +02:00
* asyncservices wrapper !
2007-12-18 16:53:38 +01:00
*
* This class takes care about the notification - routing . It chooses one or more backends for each
2010-05-03 08:44:26 +02:00
* given recipient depending on its prefs or falls back to self :: _fallback
*
* The classes doing the notifications are called notifications_ < backend > and should only be
2007-12-18 16:53:38 +01:00
* called from this class . The backend ' s job is to deliver ONE message to ONE recipient .
2006-09-07 09:04:15 +02:00
*
*/
2017-10-21 10:39:08 +02:00
class notifications {
2006-09-07 09:04:15 +02:00
/**
* Appname
*/
const _appname = 'notifications' ;
2010-05-03 08:44:26 +02:00
2007-12-13 13:52:35 +01:00
/**
* backend to use for fallback reasons
*/
const _fallback = 'email_only' ;
2010-05-03 08:44:26 +02:00
2011-06-14 15:55:06 +02:00
/**
* backend to use if EGroupware user has no preferenc set and no default preference set
*/
const user_fallback = 'popup_or_email' ;
2008-01-30 19:58:00 +01:00
/**
* registered backends
* @ var array
*/
2017-10-21 10:39:08 +02:00
protected $backends = array ( 'popup' , 'winpopup' , 'email' , 'jpopup' );
2010-05-03 08:44:26 +02:00
2008-12-10 20:47:22 +01:00
/**
* backends to skip even if the user has chosen it
* this could be set by the calling application
* @ var array
*/
2017-10-21 10:39:08 +02:00
protected $skip_backends = array ();
2010-05-03 08:44:26 +02:00
/**
2008-01-30 19:58:00 +01:00
* pre - defined notificaton chains
* @ abstract
* arrays with name => chain pairs
2010-05-03 08:44:26 +02:00
* the chain itself consists of an array with framework => action pairs
2008-01-30 19:58:00 +01:00
* 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
*/
2017-10-21 10:39:08 +02:00
protected $notification_chains = array (
2008-01-30 19:58:00 +01:00
'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_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_and_email' => array ( 'winpopup' => 'continue' , 'email' => 'stop' ),
2012-12-09 06:56:42 +01:00
'jpopup_only' => array ( 'jpopup' => 'continue' , 'popup' => 'stop' ),
'jpopup_and_email' => array ( 'jpopup' => 'continue' , 'popup' => 'continue' , 'email' => 'stop' ),
2008-01-30 19:58:00 +01:00
);
2010-05-03 08:44:26 +02:00
/**
2008-01-30 19:58:00 +01:00
* human readable descriptions for the notification chains
* @ var array
*/
2017-10-21 10:39:08 +02:00
protected $chains_descriptions = array (
2008-01-30 19:58:00 +01:00
'disable' => 'do not notify me at all' ,
'email_only' => 'E-Mail only' ,
'all' => 'all possible notification backends' ,
'popup_only' => 'eGroupWare-Popup only' ,
2018-02-27 16:23:46 +01:00
'popup_or_email' => 'Email notifications only, if user is not logged in' ,
2008-01-30 19:58:00 +01:00
'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_and_email' => 'Windows-Popup and E-Mail' ,
2012-12-09 06:56:42 +01:00
'jpopup_only' => 'Java-Windows-Popup and eGroupWare-Popup only' ,
'jpopup_and_email' => 'Java-Windows-Popup, eGroupWare-Popup and Email'
2007-11-22 09:29:16 +01:00
);
2010-05-03 08:44:26 +02:00
2006-09-07 09:04:15 +02:00
/**
* array with objects of receivers
* @ var array
*/
2017-10-21 10:39:08 +02:00
protected $receivers = array ();
2010-05-03 08:44:26 +02:00
2007-11-22 09:29:16 +01:00
/**
2007-12-18 16:53:38 +01:00
* object of sender
2007-11-22 09:29:16 +01:00
* @ var object
*/
2017-10-21 10:39:08 +02:00
protected $sender ;
2010-05-03 08:44:26 +02:00
2019-03-12 22:24:02 +01:00
/**
* email address for reply to
* @ var string
*/
protected $reply_to ;
2007-11-22 09:29:16 +01:00
/**
* holds notification subject
* @ var string
*/
2017-10-21 10:39:08 +02:00
protected $subject = '' ;
2010-05-03 08:44:26 +02:00
2012-06-13 16:50:41 +02:00
/**
* holds notification subject for popup
* @ var string
*/
2017-10-21 10:39:08 +02:00
protected $popupsubject = '' ;
2012-06-13 16:50:41 +02:00
2006-09-07 09:04:15 +02:00
/**
2007-11-30 06:38:31 +01:00
* holds notification message in plaintext
2006-09-07 09:04:15 +02:00
* @ var string
*/
2017-10-21 10:39:08 +02:00
protected $message_plain = '' ;
2010-05-03 08:44:26 +02:00
2007-11-30 06:38:31 +01:00
/**
* holds notification message in html
* @ var string
*/
2017-10-21 10:39:08 +02:00
protected $message_html = '' ;
2010-05-03 08:44:26 +02:00
2012-06-13 16:50:41 +02:00
/**
* holds notification message for popup
* @ var string
*/
2017-10-21 10:39:08 +02:00
protected $message_popup = '' ;
2012-06-13 16:50:41 +02:00
2006-09-07 09:04:15 +02:00
/**
2007-11-22 09:29:16 +01:00
* array with objects of links
* @ var array
2006-09-07 09:04:15 +02:00
*/
2017-10-21 10:39:08 +02:00
protected $links = array ();
2010-05-03 08:44:26 +02:00
2012-09-04 14:10:37 +02:00
/**
* array with objects of links
* @ var array
*/
2017-10-21 10:39:08 +02:00
protected $popup_links = array ();
2012-09-04 14:10:37 +02:00
2017-05-23 16:54:20 +02:00
/**
2018-01-24 19:02:35 +01:00
* array with objects of data
2017-05-23 16:54:20 +02:00
* @ var array
*/
2018-01-24 19:02:35 +01:00
protected $popup_data = array ();
2017-05-23 16:54:20 +02:00
2007-11-22 09:29:16 +01:00
/**
* array with objects of attachments
* @ var array
*/
2017-10-21 10:39:08 +02:00
protected $attachments = array ();
2010-05-03 08:44:26 +02:00
2007-11-22 09:29:16 +01:00
/**
* holds config object ( sitewide configuration of app )
*
* @ var object
*/
2017-10-21 10:39:08 +02:00
protected $config ;
2010-05-03 08:44:26 +02:00
2014-06-05 13:03:12 +02:00
/**
* Error - message cat be read and reset via notifications :: errors ( $reset = false )
*
* @ var array
*/
2017-10-21 10:39:08 +02:00
protected static $errors = array ();
2014-06-05 13:03:12 +02:00
2007-11-22 09:29:16 +01:00
/**
2008-01-30 19:58:00 +01:00
* constructor of notifications
2007-11-22 09:29:16 +01:00
*
*/
public function __construct () {
2016-05-06 11:19:36 +02:00
$this -> config = ( object ) Api\Config :: read ( self :: _appname );
2007-11-22 09:29:16 +01:00
}
2010-05-03 08:44:26 +02:00
2014-06-05 13:03:12 +02:00
/**
* Return notification errors
*
2016-05-06 11:19:36 +02:00
* @ param boolean $reset = false true : reset all errors
2014-06-05 13:03:12 +02:00
* @ return array
*/
public static function errors ( $reset = false )
{
$ret = self :: $errors ;
if ( $reset ) self :: $errors = array ();
return $ret ;
}
2007-11-22 09:29:16 +01:00
/**
* Set sender for the current notification
*
* @ param $_sender object of account
2007-12-10 09:26:29 +01:00
* as long as the accounts class isn ' t a nice object ,
* it ' s an int with the account id or the e - mail address of a non - eGW user
2007-11-22 09:29:16 +01:00
*/
public function set_sender ( $_sender ) {
2022-02-09 21:48:16 +01:00
if ( is_object ( $_sender ))
2021-06-08 18:22:48 +02:00
{
2007-12-10 09:26:29 +01:00
$this -> sender = $_sender ;
return true ;
2022-02-09 21:48:16 +01:00
}
else
{
2007-12-10 09:26:29 +01:00
// no object atm, we have to handle this and make a pseudo-object
2022-02-09 21:48:16 +01:00
if ( is_numeric ( $_sender ))
{
$this -> sender = ( object ) $GLOBALS [ 'egw' ] -> accounts -> read ( $_sender );
2007-12-10 09:26:29 +01:00
return true ;
}
2022-02-09 21:48:16 +01:00
if ( is_string ( $_sender ) && strpos ( $_sender , '@' ))
{
$this -> sender = ( object ) array (
'account_email' => $this -> get_addresspart ( $_sender , 'email' ),
'account_fullname' => $this -> get_addresspart ( $_sender , 'fullname' ),
);
2007-12-10 09:26:29 +01:00
return true ;
}
}
return false ;
2006-09-07 09:04:15 +02:00
}
2010-05-03 08:44:26 +02:00
2019-03-12 22:24:02 +01:00
/**
* Set reply_to for the current notification
*
* @ param $_reply_to string for email address to reply to
*/
public function set_reply_to ( $_reply_to ) {
$this -> reply_to = $_reply_to ;
return true ;
}
2006-09-07 09:04:15 +02:00
/**
* Set receivers for the current notification
*
* @ param array $_receivers array with objects of accounts
2007-12-10 09:26:29 +01:00
* as long as the accounts class isn ' t a nice object ,
* it ' s an array with the int of the account id or the e - mail address of a non - eGW user
2006-09-07 09:04:15 +02:00
*/
public function set_receivers ( array $_receivers ) {
2007-12-10 09:26:29 +01:00
$this -> receivers = array ();
foreach ( $_receivers as $receiver ) {
$this -> add_receiver ( $receiver );
2006-09-07 09:04:15 +02:00
}
2007-12-10 09:26:29 +01:00
}
2010-05-03 08:44:26 +02:00
2007-12-10 09:26:29 +01:00
/**
* Add single receiver for the current notification
*
* @ param $_receiver object of account
* as long as the accounts class isn ' t a nice object ,
* it ' s an int with the account id or the e - mail address of a non - eGW user
*/
public function add_receiver ( $_receiver ) {
if ( is_object ( $_receiver )) {
$this -> receivers [] = $_receiver ;
return true ;
} else {
// no object atm, we have to handle this and make a pseudo-object
if ( is_numeric ( $_receiver )) {
$this -> receivers [] = ( object ) $GLOBALS [ 'egw' ] -> accounts -> read ( $_receiver );
return true ;
}
if ( is_string ( $_receiver ) && strpos ( $_receiver , '@' )) {
$this -> receivers [] = ( object ) array (
'account_email' => $this -> get_addresspart ( $_receiver , 'email' ),
2010-05-03 08:44:26 +02:00
'account_fullname' => $this -> get_addresspart ( $_receiver , 'fullname' ),
2007-12-10 09:26:29 +01:00
);
return true ;
}
}
return false ;
2007-11-22 09:29:16 +01:00
}
2010-05-03 08:44:26 +02:00
2007-11-22 09:29:16 +01:00
/**
* sets notification subject
2010-05-03 08:44:26 +02:00
*
2007-11-22 09:29:16 +01:00
* @ param string $_subject
*/
public function set_subject ( $_subject ) {
$this -> subject = $_subject ;
return true ;
}
2010-05-03 08:44:26 +02:00
2012-06-13 16:50:41 +02:00
/**
* sets notification subject for popup
*
* @ param string $_subject
*/
public function set_popupsubject ( $_subject ) {
$this -> popupsubject = $_subject ;
return true ;
}
2007-11-22 09:29:16 +01:00
/**
* sets notification message
2007-11-30 06:38:31 +01:00
* @ abstract $_message accepts plaintext or html
2010-05-03 08:44:26 +02:00
* NOTE : There is no XSS prevention in notifications framework !
2007-11-30 06:38:31 +01:00
* You have to filter userinputs yourselve ( e . g . htmlspechialchars () )
* If you want to set plain AND html messages , just call this function
2017-10-21 10:39:08 +02:00
* two times , it autodetects the type of your input , or pass $type to be
* explicit .
2010-05-03 08:44:26 +02:00
*
2007-11-22 09:29:16 +01:00
* @ param string $_message
2017-10-21 10:39:08 +02:00
* @ param string $_type Type of message , 'plain' or 'html'
2007-11-22 09:29:16 +01:00
*/
2017-10-21 10:39:08 +02:00
public function set_message ( $_message , $_type = false ) {
if ( ! $_type )
{
$_type = strlen ( $_message ) == strlen ( strip_tags ( $_message )) ? 'plain' : 'html' ;
}
if ( $_type == 'plain' ) {
2007-11-30 06:38:31 +01:00
$this -> message_plain = $_message ;
} else {
$this -> message_html = $_message ;
}
2007-11-22 09:29:16 +01:00
return true ;
}
2010-05-03 08:44:26 +02:00
2012-06-13 16:50:41 +02:00
/**
* sets specific popup notification message
* @ abstract $_message accepts plaintext or html
* NOTE : There is no XSS prevention in notifications framework !
* You have to filter userinputs yourselve ( e . g . htmlspechialchars () )
*
* @ param string $_message
*/
public function set_popupmessage ( $_message ) {
//popup requires html
2012-08-21 16:49:26 +02:00
if ( strlen ( $_message ) == strlen ( strip_tags ( $_message ))) $_message = self :: plain2html ( $_message );
2012-06-13 16:50:41 +02:00
$this -> message_popup = $_message ;
return true ;
}
2007-11-22 09:29:16 +01:00
/**
* sets the notification links
2010-05-03 08:44:26 +02:00
*
2012-09-04 14:10:37 +02:00
* @ param array $_links link array ( like defined in $this -> add_link )
*/
2007-11-22 09:29:16 +01:00
public function set_links ( array $_links ) {
$this -> links = array (); // clear array if set
foreach ( $_links as $link ) {
if ( is_array ( $link )) {
2014-12-15 20:09:22 +01:00
$this -> add_link ( $link [ 'text' ], $link [ 'view' ], $link [ 'popup' ], $link [ 'app' ], $link [ 'id' ]);
2007-11-22 09:29:16 +01:00
}
}
return true ;
}
2010-05-03 08:44:26 +02:00
2012-09-04 14:10:37 +02:00
/**
* sets the notification links for popups
*
* @ param array $_links link array ( like defined in $this -> add_link )
*/
public function set_popuplinks ( array $_links ) {
$this -> popup_links = array (); // clear array if set
foreach ( $_links as $link ) {
if ( is_array ( $link )) {
2017-05-23 16:54:20 +02:00
$this -> add_popuplink ( $link [ 'text' ], $link [ 'view' ], $link [ 'popup' ], $link [ 'app' ]);
2012-09-04 14:10:37 +02:00
}
}
return true ;
}
2007-11-22 09:29:16 +01:00
/**
* adds a notification link
2008-01-30 19:58:00 +01:00
*
* @ 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
2014-12-15 20:09:22 +01:00
* @ param string $_app Application name , to use link registry ( popup & view ignored )
* @ param string $_id Application ID , to use link registry ( popup & view ignored )
2007-11-22 09:29:16 +01:00
*/
2014-12-15 20:09:22 +01:00
public function add_link ( $_text , $_view , $_popup = false , $_app = false , $_id = false ) {
2008-01-30 19:58:00 +01:00
if ( ! $_view || ! $_text ) { return false ; }
2014-12-15 20:09:22 +01:00
$this -> links [] = ( object ) array (
'text' => $_text ,
'view' => $_view ,
'popup' => $_popup ,
'app' => $_app ,
'id' => $_id
);
2007-11-22 09:29:16 +01:00
return true ;
}
2010-05-03 08:44:26 +02:00
2012-09-04 14:10:37 +02:00
/**
* adds a notification link for popups
*
* @ 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
2017-05-23 16:54:20 +02:00
* @ param string $_app application name
2012-09-04 14:10:37 +02:00
*/
2017-05-23 16:54:20 +02:00
public function add_popuplink ( $_text , $_view , $_popup = false , $_app = '' ) {
2012-09-04 14:10:37 +02:00
if ( ! $_view || ! $_text ) { return false ; }
2017-05-23 16:54:20 +02:00
$this -> popup_links [] = ( object ) array (
'text' => $_text ,
2012-09-04 14:10:37 +02:00
'view' => $_view ,
'popup' => $_popup ,
2017-05-23 16:54:20 +02:00
'app' => $_app
2012-09-04 14:10:37 +02:00
);
return true ;
}
2007-11-22 09:29:16 +01:00
/**
* sets the notification attachments
2010-05-03 08:44:26 +02:00
*
2008-01-30 19:58:00 +01:00
* @ param array $_attachments attachment array ( like defined in $this -> add_attachment )
2007-11-22 09:29:16 +01:00
*/
public function set_attachments ( array $_attachments ) {
$this -> attachments = array (); // clear array if set
foreach ( $_attachments as $attachment ) {
if ( is_array ( $attachment )) {
2011-06-23 11:05:25 +02:00
$this -> add_attachment (
$attachment [ 'string' ],
$attachment [ 'filename' ],
$attachment [ 'encoding' ],
$attachment [ 'type' ],
$attachment [ 'path' ]
);
2007-11-22 09:29:16 +01:00
}
}
return true ;
}
2010-05-03 08:44:26 +02:00
2007-11-22 09:29:16 +01:00
/**
* adds a notification attachment
* This method can be used to attach ascii or binary data ,
* such as a BLOB record from a database .
2010-05-03 08:44:26 +02:00
*
2011-06-23 11:05:25 +02:00
* @ param string $_string Attachment data or null to use $_path
2008-01-30 19:58:00 +01:00
* @ param string $_filename Name of the attachment .
* @ param string $_encoding File encoding ( see $Encoding ) .
* @ param string $_type File extension ( MIME ) type .
2011-06-23 11:05:25 +02:00
* @ param string $_path optional path to attachment , if ! $_string
2007-11-22 09:29:16 +01:00
*/
2011-06-23 11:05:25 +02:00
public function add_attachment ( $_string , $_filename , $_encoding = " base64 " , $_type = " application/octet-stream " , $_path = null ) {
if ( ! $_string && ( ! $_path || ! file_exists ( $_path )) || ! $_filename ) return false ;
$this -> attachments [] = ( object ) array (
'string' => $_string ,
'filename' => $_filename ,
'encoding' => $_encoding ? $_encoding : " base64 " ,
'type' => $_type ? $_type : " application/octet-stream " ,
'path' => $_path ,
);
2007-11-22 09:29:16 +01:00
return true ;
2006-09-07 09:04:15 +02:00
}
2010-05-03 08:44:26 +02:00
2008-12-10 20:47:22 +01:00
/**
* Sets backends that should be skipped even if the user
* defined them in its chain
*
* @ param array $_skip_backends array with names of the backends to be skipped
* e . g . array ( 'popup' , 'winpopup' )
*/
public function set_skip_backends ( array $_skip_backends ) {
$this -> skip_backends = $_skip_backends ;
}
2010-05-03 08:44:26 +02:00
2006-09-07 09:04:15 +02:00
/**
2008-01-30 19:58:00 +01:00
* sends notifications
2006-09-07 09:04:15 +02:00
*/
public function send () {
2007-12-18 16:53:38 +01:00
if ( ! is_object ( $this -> sender )) {
2008-01-30 19:58:00 +01:00
throw new Exception ( 'Error: cannot send notifications. No sender supplied' );
2006-09-07 09:04:15 +02:00
}
2007-12-18 16:53:38 +01:00
if ( ! is_array ( $this -> receivers ) || count ( $this -> receivers ) == 0 ) {
2008-01-30 19:58:00 +01:00
throw new Exception ( 'Error: cannot send notifications. No receivers supplied' );
2007-12-18 16:53:38 +01:00
}
2012-06-13 16:50:41 +02:00
if ( ! $messages = $this -> create_messages ( $this -> message_plain , $this -> message_html , $this -> message_popup )) {
2008-01-30 19:58:00 +01:00
throw new Exception ( 'Error: cannot send notifications. No valid messages supplied' );
2007-11-30 06:38:31 +01:00
}
2010-05-03 08:44:26 +02:00
2018-01-23 22:07:27 +01:00
Api\Translation :: add_app ( 'notifications' );
2008-01-30 19:58:00 +01:00
$available_chains = $this -> get_available_chains ( 'routing' );
2020-07-31 17:50:01 +02:00
$push = new Api\Json\Push ();
2010-05-03 08:44:26 +02:00
2006-09-07 09:04:15 +02:00
foreach ( $this -> receivers as $receiver ) {
2007-11-30 06:38:31 +01:00
$user_notified = false ;
2008-01-30 19:58:00 +01:00
$prepend_message = '' ;
2007-11-30 06:38:31 +01:00
$backend_errors = array ();
2007-11-22 09:29:16 +01:00
try {
2007-12-13 13:52:35 +01:00
// system or non-system user
2022-04-26 21:04:16 +02:00
if ( ! empty ( $receiver -> account_id ) && is_numeric ( $receiver -> account_id )) {
2011-11-07 17:50:16 +01:00
// system user, collect data and check for Status and expire state, skip notification if expired or not active
$userData = $GLOBALS [ 'egw' ] -> accounts -> read ( $receiver -> account_id );
//error_log(__METHOD__.__LINE__." fetched data for User:".array2string($userData['account_lid']).'#'.$userData['account_type'].'#'.$userData['account_status'].'#'.$GLOBALS['egw']->accounts->is_expired($userData).'#');
2012-03-13 09:59:05 +01:00
if ( $userData && $userData [ 'account_type' ] === 'u' &&
2011-11-07 17:50:16 +01:00
( $userData [ 'account_status' ] != 'A' || $GLOBALS [ 'egw' ] -> accounts -> is_expired ( $userData )))
{
//error_log(__METHOD__.__LINE__." skipped notification for User with Data:".array2string($userData));
$notification_chain = 'disable' ;
continue ;
}
2007-12-10 09:26:29 +01:00
$receiver -> handle = $receiver -> account_lid ;
// check if the receiver has rights to run the notifcation app
$ids = $GLOBALS [ 'egw' ] -> accounts -> memberships ( $receiver -> account_id , true );
$ids [] = $receiver -> account_id ;
2007-12-13 13:52:35 +01:00
if ( $GLOBALS [ 'egw' ] -> acl -> get_specific_rights_for_account ( $ids , 'run' , 'notifications' )) {
// read the users notification chain
2016-05-06 11:19:36 +02:00
$prefs = new Api\Preferences ( $receiver -> account_id );
$preferences_all = $prefs -> read ();
$preferences = ( object ) $preferences_all [ self :: _appname ];
2007-12-13 13:52:35 +01:00
if ( $preferences -> notification_chain ) {
2008-01-30 19:58:00 +01:00
// 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 ];
}
2007-12-13 13:52:35 +01:00
} else {
2011-06-14 15:55:06 +02:00
$notification_chain = $available_chains [ self :: user_fallback ]; // fallback: no prefs
2007-12-13 13:52:35 +01:00
}
} else {
2008-01-30 19:58:00 +01:00
$notification_chain = $available_chains [ self :: _fallback ]; // fallback: no rights to app
2007-12-10 09:26:29 +01:00
}
} else {
2007-12-13 13:52:35 +01:00
// non-system user
2007-12-10 09:26:29 +01:00
$receiver -> handle = $receiver -> account_email ;
2008-01-30 19:58:00 +01:00
$notification_chain = $available_chains [ self :: _fallback ]; // fallback: non-system user
2007-11-22 09:29:16 +01:00
}
2010-05-03 08:44:26 +02:00
2008-01-30 19:58:00 +01:00
if ( $notification_chain == 'disable' ) {
2007-12-13 13:52:35 +01:00
continue ; //user disabled notifications
2007-11-22 09:29:16 +01:00
}
2008-12-10 20:47:22 +01:00
foreach ( $notification_chain as $backend => $action ) {
2016-05-06 11:19:36 +02:00
$notification_backend = null ;
2007-11-30 06:38:31 +01:00
try {
2008-12-10 20:47:22 +01:00
// check if backend should be skipped
if ( in_array ( $backend , $this -> skip_backends ) ) {
// log as error just for the case too much skipping prevents user from being notified
$backend_errors [] = $backend . ' will be skipped (as defined by calling application)' ;
continue ;
}
2010-05-03 08:44:26 +02:00
2008-12-10 20:47:22 +01:00
$notification_backend = self :: _appname . '_' . $backend ;
2016-05-06 11:19:36 +02:00
if ( ! file_exists ( EGW_INCLUDE_ROOT . '/' . self :: _appname . '/inc/class.' . $notification_backend . '.inc.php' )) {
2007-11-30 06:38:31 +01:00
throw new Exception ( 'file for ' . $notification_backend . ' does not exist' );
}
2022-04-26 21:04:16 +02:00
$obj = new $notification_backend ( $this -> sender , $receiver , $this -> config , $preferences ? ? null );
2008-01-30 19:58:00 +01:00
if ( ! ( $obj instanceof notifications_iface ) ) {
2007-11-30 06:38:31 +01:00
unset ( $obj );
2008-01-30 19:58:00 +01:00
throw new Exception ( $notification_backend . ' is no implementation of notifications_iface' );
2007-11-30 06:38:31 +01:00
}
2012-06-13 16:50:41 +02:00
$lsubject = $this -> subject ;
2012-09-04 14:10:37 +02:00
$llinks = $this -> links ;
if ( $backend == 'popup' )
{
if ( ! empty ( $this -> popupsubject )) $lsubject = $this -> popupsubject ;
if ( $this -> popup_links ) $llinks = $this -> popup_links ;
2018-01-24 19:02:35 +01:00
if ( is_array ( $this -> popup_data )) $popup_data = $this -> popup_data ;
2019-03-12 22:24:02 +01:00
} elseif ( $backend == 'email' ) {
if ( ! empty ( $this -> reply_to )) $popup_data = array ( 'reply_to' => $this -> reply_to );
2012-09-04 14:10:37 +02:00
}
2022-04-26 21:04:16 +02:00
$obj -> send ( $this -> prepend_message ( $messages , $prepend_message ), $lsubject , $llinks , $this -> attachments , $popup_data ? ? null );
2018-02-27 16:23:46 +01:00
// This is to make popup_or_email option sensfull since
// we save popup notifications in database anyway, email
// notifications should be based on user availability.
2020-07-31 17:50:01 +02:00
if ( $backend === 'popup' && $action === 'fail' && ! $push -> isOnline ( $receiver -> account_id ))
2018-02-27 16:23:46 +01:00
{
throw new Exception ();
}
2007-11-22 09:29:16 +01:00
}
2007-11-30 06:38:31 +01:00
catch ( Exception $exception ) {
$backend_errors [] = $notification_backend . ' failed: ' . $exception -> getMessage ();
// try next backend
if ( $action == 'fail' || $action == 'continue' ) {
continue ;
}
break ; // stop running through chain
2007-11-22 09:29:16 +01:00
}
2024-04-16 18:53:54 +02:00
// backend succeeded
2007-11-30 06:38:31 +01:00
$user_notified = true ;
2010-05-03 08:44:26 +02:00
if ( $action == 'stop' || $action == 'fail' ) { break ; } // stop running through chain
2006-09-07 09:04:15 +02:00
}
2008-12-10 20:47:22 +01:00
// check if the user has been notified at all
2014-06-05 13:03:12 +02:00
if ( ! $user_notified ) {
/* error_log ( 'Error: notification of receiver ' . $receiver -> handle . ' failed for the following reasons:' );
2008-12-10 20:47:22 +01:00
foreach ( $backend_errors as $id => $backend_error ) {
error_log ( $backend_error );
2014-06-05 13:03:12 +02:00
} */
$error = implode ( ', ' , $backend_errors );
if ( stripos ( $error , ( string ) $receiver -> handle ) !== false ) $error = $receiver -> handle . ': ' . $error ;
self :: $errors [] = $error ;
}
2007-11-30 06:38:31 +01:00
}
catch ( Exception $exception_user ) {
2011-09-15 12:39:27 +02:00
error_log ( 'Error: notification of receiver ' . $receiver -> handle . ' failed: ' . $exception_user -> getMessage ());
2014-06-05 13:03:12 +02:00
self :: $errors [] = $receiver -> handle . ': ' . $exception_user -> getMessage ();
2006-09-07 09:04:15 +02:00
}
}
2007-11-22 09:29:16 +01:00
return true ;
2006-09-07 09:04:15 +02:00
}
2010-05-03 08:44:26 +02:00
2007-06-01 13:43:08 +02:00
/**
2012-06-13 16:50:41 +02:00
* creates an array with the message as plaintext and html , and optional a html popup message
2007-06-01 13:43:08 +02:00
*
2008-01-30 19:58:00 +01:00
* @ param string $_message_plain
* @ param string $_message_html
2012-06-13 16:50:41 +02:00
* @ param string $_message_popup
* @ return plain and html message in one array , $messages [ 'plain' ] and $messages [ 'html' ] and , if exists $messages [ 'popup' ]
2007-06-01 13:43:08 +02:00
*/
2012-06-13 16:50:41 +02:00
private function create_messages ( $_message_plain = '' , $_message_html = '' , $_message_popup = '' ) {
if ( empty ( $_message_plain ) && empty ( $_message_html ) && empty ( $_message_popup )) { return false ; } // no message set
2007-11-22 09:29:16 +01:00
$messages = array ();
2010-05-03 08:44:26 +02:00
2007-12-10 09:26:29 +01:00
// create the messages
2007-11-30 06:38:31 +01:00
if ( ! empty ( $_message_plain )) {
2007-12-18 16:53:38 +01:00
$messages [ 'plain' ] = $_message_plain ;
2007-11-30 06:38:31 +01:00
} else {
2016-05-06 11:19:36 +02:00
$messages [ 'plain' ] = Api\Mail\Html :: convertHTMLToText ( $_message_html , false , true );
2007-11-30 06:38:31 +01:00
}
2010-05-03 08:44:26 +02:00
2007-11-30 06:38:31 +01:00
if ( ! empty ( $_message_html )) {
2007-12-18 16:53:38 +01:00
$messages [ 'html' ] = $_message_html ;
2007-11-24 15:01:27 +01:00
} else {
2012-08-21 16:49:26 +02:00
$messages [ 'html' ] = self :: plain2html ( $_message_plain );
2007-12-10 09:26:29 +01:00
}
2012-06-13 16:50:41 +02:00
if ( ! empty ( $_message_popup )) $messages [ 'popup' ] = $_message_popup ;
2007-11-22 09:29:16 +01:00
return $messages ;
}
2010-05-03 08:44:26 +02:00
2012-08-21 16:49:26 +02:00
/**
* Create html from plaintext message
*
* @ param string $_plain
* @ return string html message
*/
public static function plain2html ( $_plain )
{
2016-05-06 11:19:36 +02:00
return Api\Html :: activate_links ( nl2br ( Api\Html :: htmlspecialchars ( $_plain , true )));
2012-08-21 16:49:26 +02:00
}
2008-01-30 19:58:00 +01:00
/**
* 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 ;
}
}
}
2010-05-03 08:44:26 +02:00
2008-01-30 19:58:00 +01:00
return $_messages ;
}
2010-05-03 08:44:26 +02:00
2007-12-10 09:26:29 +01:00
/**
* returns specified part from a given mailaddress
*
* @ param string $_address
* @ param string $_part
* @ return string chosen part of the address
*/
2016-05-06 11:19:36 +02:00
private function get_addresspart ( $_address , $_part = 'email' )
{
$parts = null ;
2010-05-03 08:44:26 +02:00
if ( strpos ( $_address , '<' ) && preg_match ( '/^(.*)\S?\<(.*)\>/' , $_address , $parts )) { // _address contains a fullname part
2007-12-10 09:26:29 +01:00
$fullname = trim ( trim ( $parts [ 1 ]), '\"' );
$email = $parts [ 2 ];
} else {
$fullname = false ;
$email = $_address ;
}
switch ( $_part ) {
case 'fullname' :
return $fullname ;
case 'email' :
default :
return $email ;
}
return false ;
}
2010-05-03 08:44:26 +02:00
2008-01-30 19:58:00 +01:00
/**
* 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' ) {
2016-05-06 11:19:36 +02:00
// determine enabled backends from Api\Config
2008-01-30 19:58:00 +01:00
$enabled_backends = array ();
2016-05-06 11:19:36 +02:00
foreach ( $this -> backends as $backend ) {
2008-01-30 19:58:00 +01:00
switch ( $backend ) {
case 'email' :
2011-06-14 15:55:06 +02:00
case 'popup' :
2012-12-09 06:56:42 +01:00
case 'jpopup' :
2008-01-30 19:58:00 +01:00
$enabled_backends [ $backend ] = true ; // fallback must always be enabled
break ;
default :
$param = $backend . '_enable' ;
2022-04-26 21:04:16 +02:00
$enabled_backends [ $backend ] = ! empty ( $this -> config -> { $param });
2008-01-30 19:58:00 +01:00
break ;
}
}
2010-05-03 08:44:26 +02:00
2008-01-30 19:58:00 +01:00
$enabled_chains = array ();
$disabled_chains = array ();
foreach ( $this -> notification_chains as $key => $chain ) {
$allow_chain = true ;
if ( is_array ( $chain )) {
2016-05-06 11:19:36 +02:00
foreach ( array_keys ( $chain ) as $name ) {
2008-01-30 19:58:00 +01:00
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 ;
}
}
}
2010-05-03 08:44:26 +02:00
2008-01-30 19:58:00 +01:00
// 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 ) {
2010-05-03 08:44:26 +02:00
$chain_all [ $backend ] = count ( $enabled_backends ) == $backend_count ? 'stop' : 'continue' ;
2008-01-30 19:58:00 +01:00
}
$backend_count ++ ;
}
$common_chains [ 'all' ] = $chain_all ;
2010-05-03 08:44:26 +02:00
2008-01-30 19:58:00 +01:00
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 ();
2016-05-06 11:19:36 +02:00
foreach ( array_keys ( ${$arr_name} ) as $key ) {
2023-03-22 21:35:52 +01:00
$ { $arr_name . $suffix }[] = [
'value' => $key ,
'label' => lang ( $this -> chains_descriptions [ $key ]),
'disabled' => $arr_name == 'disabled_chains'
];
2008-01-30 19:58:00 +01:00
}
}
// summarize all groups with minimum one chain to the final array
$chains_final = array ();
foreach ( $chain_groups as $name => $arr_name ) {
2023-03-22 21:35:52 +01:00
if ( is_array ( $ { $arr_name . $suffix }) && count ( $ { $arr_name . $suffix }) > 0 )
{
$chains_final [] = array (
'label' => $name ,
'value' => $ { $arr_name . $suffix }
);
2008-01-30 19:58:00 +01:00
}
}
return $chains_final ;
2010-05-03 08:44:26 +02:00
2008-01-30 19:58:00 +01:00
case 'routing' :
default :
return array_merge ( $common_chains , $enabled_chains );
}
2010-05-03 08:44:26 +02:00
2008-01-30 19:58:00 +01:00
return false ;
}
2011-04-13 19:51:02 +02:00
/**
* Actions to take when an account is deleted
2011-06-14 15:55:06 +02:00
*
2011-04-13 19:51:02 +02:00
* @ param settings array with keys account_id and new_owner ( new_owner is optional )
*/
public function deleteaccount ( $settings ) {
foreach ( $this -> backends as $backend ) {
2011-04-14 17:09:36 +02:00
$backend_hook = array ( self :: _appname . '_' . $backend , 'deleteaccount' );
if ( is_callable ( $backend_hook )) {
call_user_func ( $backend_hook , $settings );
2011-04-13 19:51:02 +02:00
}
}
}
2017-05-23 16:54:20 +02:00
/**
2018-01-24 19:02:35 +01:00
* Set popup data
2017-05-23 16:54:20 +02:00
*
2018-01-24 19:02:35 +01:00
* @ param string $_appname
2024-04-16 18:53:54 +02:00
* @ param ? array $_data
*
2017-05-23 16:54:20 +02:00
* @ return boolean
*/
2024-04-16 18:53:54 +02:00
public function set_popupdata ( string $_appname , ? array $_data , ? int $_id = null )
2022-02-09 21:48:16 +01:00
{
2018-01-24 19:02:35 +01:00
$this -> popup_data = array (
'appname' => $_appname ,
2024-04-16 18:53:54 +02:00
'id' => $_id ? : $_data [ 'id' ] ? ? null ,
2022-02-09 21:48:16 +01:00
'data' => $_data
2018-01-24 19:02:35 +01:00
);
2018-02-27 16:23:46 +01:00
2017-05-23 16:54:20 +02:00
return true ;
}
2022-02-09 21:48:16 +01:00
/**
* Hook for site configuration
* Gets the appropriate mail accounts to offer to use for notifications
*
* @ param $data
* @ return void
*/
public function config ( $data )
{
$result = [ 'sel_options' => [ 'async_identity' => []]];
$identities = iterator_to_array ( EGroupware\Api\Mail\Account :: search ( false , 'params' , 'ABS(egw_ea_valid.account_id) ASC, ' ));
// We only want identities for all users, and prefer SMTP only
$smtp_only = [];
$others = [];
foreach ( $identities as $id => $identity )
{
// Identities should be sorted so all users are first. Stop when we get to the others.
if ( ! in_array ( '0' , $identity [ 'account_id' ]))
{
break ;
}
$destination = $identity [ 'acc_imap_host' ] ? 'others' : 'smtp_only' ;
$$destination [ $id ] = $identity [ 'acc_name' ];
}
// Put SMTP only identities first
$result [ 'sel_options' ][ 'async_identity' ] = $smtp_only + $others ;
return $result ;
}
2022-04-26 21:04:16 +02:00
}