notifications::get_available_chains()   F
last analyzed

Complexity

Conditions 22
Paths 2688

Size

Total Lines 84
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 22
eloc 57
nc 2688
nop 1
dl 0
loc 84
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * EGroupware - Notifications
4
 *
5
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
6
 * @package notifications
7
 * @link http://www.egroupware.org
8
 * @author Cornelius Weiss <[email protected]>
9
 * @version $Id$
10
 */
11
12
use EGroupware\Api;
13
14
/**
15
 * Notifies users according to their preferences.
16
 *
17
 * @abstract NOTE: This is for instant notifications. If you need time dependend notifications use the
18
 * asyncservices wrapper!
19
 *
20
 * This class takes care about the notification-routing. It chooses one or more backends for each
21
 * given recipient depending on its prefs or falls back to self::_fallback
22
 *
23
 * The classes doing the notifications are called notifications_<backend> and should only be
24
 * called from this class. The backend's job is to deliver ONE message to ONE recipient.
25
 *
26
 */
27
class notifications {
28
29
	/**
30
	 * Appname
31
	 */
32
	const _appname = 'notifications';
0 ignored issues
show
Coding Style introduced by
This class constant is not uppercase (expected _APPNAME).
Loading history...
33
34
	/**
35
	 * backend to use for fallback reasons
36
	 */
37
	const _fallback = 'email_only';
0 ignored issues
show
Coding Style introduced by
This class constant is not uppercase (expected _FALLBACK).
Loading history...
38
39
	/**
40
	 * backend to use if EGroupware user has no preferenc set and no default preference set
41
	 */
42
	const user_fallback = 'popup_or_email';
0 ignored issues
show
Coding Style introduced by
This class constant is not uppercase (expected USER_FALLBACK).
Loading history...
43
44
	/**
45
	 * registered backends
46
	 * @var array
47
	 */
48
	protected $backends = array('popup', 'winpopup', 'email', 'jpopup');
49
50
	/**
51
	 * backends to skip even if the user has chosen it
52
	 * this could be set by the calling application
53
	 * @var array
54
	 */
55
	protected $skip_backends = array();
56
57
	/**
58
	 * pre-defined notificaton chains
59
	 * @abstract
60
	 * arrays with name => chain pairs
61
	 * the chain itself consists of an array with framework => action pairs
62
	 * where action defines what to do after the framework has been executed:
63
	 * stop: stop executing notifications
64
	 * fail: do not stop if framework fails, otherwise stop
65
	 * continue: execute next framework
66
	 *
67
	 * @var array
68
	 */
69
	protected $notification_chains = array(
70
		'disable' 				=> false, // will be created by $this->get_available_chains
71
		'email_only' 			=> false, // will be created by $this->get_available_chains
72
		'all' 					=> false, // will be created by $this->get_available_chains
73
 		'popup_only' 			=> array('popup' => 'stop'),
74
 		'popup_or_email' 		=> array('popup' => 'fail', 'email' => 'stop'),
75
 		'popup_and_email' 		=> array('popup' => 'continue', 'email' => 'stop'),
76
 		'popup_and_winpopup'	=> array('popup' => 'continue', 'winpopup' => 'stop'),
77
		'winpopup_only' 		=> array('winpopup' => 'stop'),
78
		'winpopup_or_email'		=> array('winpopup' => 'fail', 'email' => 'stop'),
79
		'winpopup_and_email' 	=> array('winpopup' => 'continue', 'email' => 'stop'),
80
		'jpopup_only'			=> array('jpopup' => 'continue', 'popup' => 'stop'),
81
		'jpopup_and_email'		=> array('jpopup' => 'continue', 'popup' => 'continue', 'email' => 'stop'),
82
	);
83
84
	/**
85
	 * human readable descriptions for the notification chains
86
	 * @var array
87
	 */
88
	protected $chains_descriptions = array(
89
		'disable' 				=> 'do not notify me at all',
90
		'email_only' 			=> 'E-Mail only',
91
		'all' 					=> 'all possible notification backends',
92
		'popup_only' 			=> 'eGroupWare-Popup only',
93
		'popup_or_email' 		=> 'Email notifications only, if user is not logged in',
94
		'popup_and_email' 		=> 'eGroupWare-Popup and E-Mail',
95
		'popup_and_winpopup'	=> 'eGroupWare-Popup and Windows-Popup',
96
		'winpopup_only' 		=> 'Windows-Popup only',
97
		'winpopup_or_email' 	=> 'Windows-Popup first, if that fails notify me by E-Mail',
98
		'winpopup_and_email' 	=> 'Windows-Popup and E-Mail',
99
		'jpopup_only'			=> 'Java-Windows-Popup and eGroupWare-Popup only',
100
		'jpopup_and_email'		=> 'Java-Windows-Popup, eGroupWare-Popup and Email'
101
	);
102
103
	/**
104
	 * array with objects of receivers
105
	 * @var array
106
	 */
107
	protected $receivers = array();
108
109
	/**
110
	 * object of sender
111
	 * @var object
112
	 */
113
	protected $sender;
114
115
	/**
116
	 * email address for reply to
117
	 * @var string
118
	 */
119
	protected $reply_to;
120
121
	/**
122
	 * holds notification subject
123
	 * @var string
124
	 */
125
	protected $subject = '';
126
127
	/**
128
	 * holds notification subject for popup
129
	 * @var string
130
	 */
131
	protected $popupsubject = '';
132
133
	/**
134
	 * holds notification message in plaintext
135
	 * @var string
136
	 */
137
	protected $message_plain = '';
138
139
	/**
140
	 * holds notification message in html
141
	 * @var string
142
	 */
143
	protected $message_html = '';
144
145
	/**
146
	 * holds notification message for popup
147
	 * @var string
148
	 */
149
	protected $message_popup = '';
150
151
	/**
152
	 * array with objects of links
153
	 * @var array
154
	 */
155
	protected $links = array();
156
157
	/**
158
	 * array with objects of links
159
	 * @var array
160
	 */
161
	protected $popup_links = array();
162
163
	/**
164
	 * array with objects of data
165
	 * @var array
166
	 */
167
	protected $popup_data = array();
168
169
	/**
170
	 * array with objects of attachments
171
	 * @var array
172
	 */
173
	protected $attachments = array();
174
175
	/**
176
	 * holds config object (sitewide configuration of app)
177
	 *
178
	 * @var object
179
	 */
180
	protected $config;
181
182
	/**
183
	 * Error-message cat be read and reset via notifications::errors($reset=false)
184
	 *
185
	 * @var array
186
	 */
187
	protected static $errors = array();
188
189
	/**
190
	 * constructor of notifications
191
	 *
192
	 */
193
	public function __construct() {
194
		$this->config = (object) Api\Config::read(self::_appname);
195
	}
196
197
	/**
198
	 * Return notification errors
199
	 *
200
	 * @param boolean $reset =false true: reset all errors
201
	 * @return array
202
	 */
203
	public static function errors($reset=false)
204
	{
205
		$ret = self::$errors;
206
		if ($reset) self::$errors = array();
207
		return $ret;
208
	}
209
210
	/**
211
	 * Set sender for the current notification
212
	 *
213
	 * @param $_sender object of account
214
	 * as long as the accounts class isn't a nice object,
215
	 * it's an int with the account id or the e-mail address of a non-eGW user
216
	 */
217
	public function set_sender($_sender) {
218
		if(is_object($_sender)) {
219
			$this->sender = $_sender;
220
			return true;
221
		} else {
222
			// no object atm, we have to handle this and make a pseudo-object
223
			if(is_numeric($_sender)) {
224
				$this->sender = (object) $GLOBALS['egw']->accounts->read($_sender);
225
				return true;
226
			}
227
			if(is_string($_sender) && strpos($_sender,'@')) {
228
				$this->sender = (object) array (
229
									'account_email' => $this->get_addresspart($_sender,'email'),
230
									'account_fullname' => $this->get_addresspart($_sender,'fullname'),
231
									);
232
				return true;
233
			}
234
		}
235
		return false;
236
	}
237
238
	/**
239
	 * Set reply_to for the current notification
240
	 *
241
	 * @param $_reply_to string for email address to reply to
242
	 */
243
	public function set_reply_to($_reply_to) {
244
		$this->reply_to = $_reply_to;
245
		return true;
246
	}
247
248
	/**
249
	 * Set receivers for the current notification
250
	 *
251
	 * @param array $_receivers array with objects of accounts
252
	 * as long as the accounts class isn't a nice object,
253
	 * it's an array with the int of the account id or the e-mail address of a non-eGW user
254
	 */
255
	public function set_receivers(array $_receivers) {
256
		$this->receivers = array();
257
		foreach ($_receivers as $receiver) {
258
			$this->add_receiver($receiver);
259
		}
260
	}
261
262
	/**
263
	 * Add single receiver for the current notification
264
	 *
265
	 * @param $_receiver object of account
266
	 * as long as the accounts class isn't a nice object,
267
	 * it's an int with the account id or the e-mail address of a non-eGW user
268
	 */
269
	public function add_receiver($_receiver) {
270
		if(is_object($_receiver)) {
271
			$this->receivers[] = $_receiver;
272
			return true;
273
		} else {
274
			// no object atm, we have to handle this and make a pseudo-object
275
			if(is_numeric($_receiver)) {
276
				$this->receivers[] = (object) $GLOBALS['egw']->accounts->read($_receiver);
277
				return true;
278
			}
279
			if(is_string($_receiver) && strpos($_receiver,'@')) {
280
				$this->receivers[] = (object) array (
281
									'account_email' => $this->get_addresspart($_receiver,'email'),
282
									'account_fullname' => $this->get_addresspart($_receiver,'fullname'),
283
									);
284
				return true;
285
			}
286
		}
287
		return false;
288
	}
289
290
	/**
291
	 * sets notification subject
292
	 *
293
	 * @param string $_subject
294
	 */
295
	public function set_subject($_subject) {
296
		$this->subject = $_subject;
297
		return true;
298
	}
299
300
	/**
301
	 * sets notification subject for popup
302
	 *
303
	 * @param string $_subject
304
	 */
305
	public function set_popupsubject($_subject) {
306
		$this->popupsubject = $_subject;
307
		return true;
308
	}
309
310
	/**
311
	 * sets notification message
312
	 * @abstract $_message accepts plaintext or html
313
	 * NOTE: There is no XSS prevention in notifications framework!
314
	 * You have to filter userinputs yourselve (e.g. htmlspechialchars() )
315
	 * If you want to set plain AND html messages, just call this function
316
	 * two times, it autodetects the type of your input, or pass $type to be
317
	 * explicit.
318
	 *
319
	 * @param string $_message
320
	 * @param string $_type Type of message, 'plain' or 'html'
321
	 */
322
	public function set_message($_message, $_type = false) {
323
		if(!$_type)
324
		{
325
			$_type = strlen($_message) == strlen(strip_tags($_message)) ? 'plain' : 'html';
326
		}
327
		if($_type == 'plain') {
328
			$this->message_plain = $_message;
329
		} else {
330
			$this->message_html = $_message;
331
		}
332
		return true;
333
	}
334
335
	/**
336
	 * sets specific popup notification message
337
	 * @abstract $_message accepts plaintext or html
338
	 * NOTE: There is no XSS prevention in notifications framework!
339
	 * You have to filter userinputs yourselve (e.g. htmlspechialchars() )
340
	 *
341
	 * @param string $_message
342
	 */
343
	public function set_popupmessage($_message) {
344
		//popup requires html
345
		if(strlen($_message) == strlen(strip_tags($_message))) $_message = self::plain2html($_message);
346
		$this->message_popup = $_message;
347
		return true;
348
	}
349
350
	/**
351
	 * sets the notification links
352
	 *
353
	 * @param array $_links link array (like defined in $this->add_link)
354
	 */
355
	public function set_links(array $_links) {
356
		$this->links = array(); // clear array if set
357
		foreach($_links as $link) {
358
			if(is_array($link)) {
359
				$this->add_link($link['text'], $link['view'], $link['popup'], $link['app'],$link['id']);
360
			}
361
		}
362
		return true;
363
	}
364
365
	/**
366
	 * sets the notification links for popups
367
	 *
368
	 * @param array $_links link array (like defined in $this->add_link)
369
	 */
370
	public function set_popuplinks(array $_links) {
371
		$this->popup_links = array(); // clear array if set
372
		foreach($_links as $link) {
373
			if(is_array($link)) {
374
				$this->add_popuplink($link['text'], $link['view'], $link['popup'], $link['app']);
375
			}
376
		}
377
		return true;
378
	}
379
380
	/**
381
	 * adds a notification link
382
	 *
383
	 * @param string $_text a descriptive text for the link
384
	 * @param array $_view all params needed to view the link (name => value pairs)
385
	 * @param string $_popup if link can be viewed in a popup something like '300x200' otherwise false
386
	 * @param string $_app Application name, to use link registry (popup & view ignored)
387
	 * @param string $_id Application ID, to use link registry (popup & view ignored)
388
	 */
389
	public function add_link($_text, $_view, $_popup = false, $_app = false, $_id = false) {
390
		if(!$_view || !$_text) { return false; }
0 ignored issues
show
Bug Best Practice introduced by
The expression $_view of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
391
		$this->links[] = (object)array(
392
			'text'	=> $_text,
393
			'view'	=> $_view,
394
			'popup'	=> $_popup,
395
			'app'	=> $_app,
396
			'id'	=> $_id
397
		);
398
		return true;
399
	}
400
401
	/**
402
	 * adds a notification link for popups
403
	 *
404
	 * @param string $_text a descriptive text for the link
405
	 * @param array $_view all params needed to view the link (name => value pairs)
406
	 * @param string $_popup if link can be viewed in a popup something like '300x200' otherwise false
407
	 * @param string $_app application name
408
	 */
409
	public function add_popuplink($_text, $_view, $_popup = false, $_app = '') {
410
		if(!$_view || !$_text) { return false; }
0 ignored issues
show
Bug Best Practice introduced by
The expression $_view of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
411
		$this->popup_links[] = (object)array(
412
										'text'	=> $_text,
413
										'view'	=> $_view,
414
										'popup'	=> $_popup,
415
										'app'	=> $_app
416
										);
417
		return true;
418
	}
419
420
	/**
421
	 * sets the notification attachments
422
	 *
423
	 * @param array $_attachments attachment array (like defined in $this->add_attachment)
424
	 */
425
	public function set_attachments(array $_attachments) {
426
		$this->attachments = array(); // clear array if set
427
		foreach($_attachments as $attachment) {
428
			if(is_array($attachment)) {
429
				$this->add_attachment(
430
					$attachment['string'],
431
					$attachment['filename'],
432
					$attachment['encoding'],
433
					$attachment['type'],
434
					$attachment['path']
435
				);
436
			}
437
		}
438
		return true;
439
	}
440
441
	/**
442
	 * adds a notification attachment
443
	 * This method can be used to attach ascii or binary data,
444
	 * such as a BLOB record from a database.
445
	 *
446
	 * @param string $_string Attachment data or null to use $_path
447
	 * @param string $_filename Name of the attachment.
448
	 * @param string $_encoding File encoding (see $Encoding).
449
	 * @param string $_type File extension (MIME) type.
450
	 * @param string $_path optional path to attachment, if !$_string
451
	 */
452
	public function add_attachment($_string, $_filename, $_encoding = "base64", $_type = "application/octet-stream", $_path=null) {
453
		if(!$_string && (!$_path || !file_exists($_path)) || !$_filename) return false;
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (! $_string && ! $_path ..._path)) || ! $_filename, Probably Intended Meaning: ! $_string && (! $_path ..._path) || ! $_filename)
Loading history...
454
		$this->attachments[] = (object)array(
455
			'string' => $_string,
456
			'filename' => $_filename,
457
			'encoding' => $_encoding ? $_encoding : "base64",
458
			'type' => $_type ? $_type : "application/octet-stream",
459
			'path' => $_path,
460
		);
461
		return true;
462
	}
463
464
	/**
465
	 * Sets backends that should be skipped even if the user
466
	 * defined them in its chain
467
	 *
468
	 * @param array $_skip_backends array with names of the backends to be skipped
469
	 * e.g. array('popup', 'winpopup')
470
	 */
471
	public function set_skip_backends(array $_skip_backends) {
472
		$this->skip_backends = $_skip_backends;
473
	}
474
475
	/**
476
	 * sends notifications
477
	 */
478
	public function send() {
479
		if (!is_object($this->sender)) {
480
			throw new Exception('Error: cannot send notifications. No sender supplied');
481
		}
482
		if (!is_array($this->receivers) || count($this->receivers) == 0) {
0 ignored issues
show
introduced by
The condition is_array($this->receivers) is always true.
Loading history...
483
			throw new Exception('Error: cannot send notifications. No receivers supplied');
484
		}
485
		if(!$messages = $this->create_messages($this->message_plain, $this->message_html, $this->message_popup)) {
486
			throw new Exception('Error: cannot send notifications. No valid messages supplied');
487
		}
488
489
		Api\Translation::add_app('notifications');
490
491
		$available_chains = $this->get_available_chains('routing');
492
493
		foreach ($this->receivers as $receiver) {
494
			$user_notified = false;
495
			$prepend_message = '';
496
			$backend_errors = array();
497
			try {
498
				// system or non-system user
499
				if($receiver->account_id && is_numeric($receiver->account_id)) {
500
					// system user, collect data and check for Status and expire state, skip notification if expired or not active
501
					$userData = $GLOBALS['egw']->accounts->read($receiver->account_id);
502
					//error_log(__METHOD__.__LINE__." fetched data for User:".array2string($userData['account_lid']).'#'.$userData['account_type'].'#'.$userData['account_status'].'#'.$GLOBALS['egw']->accounts->is_expired($userData).'#');
503
					if ($userData && $userData['account_type'] === 'u' &&
504
						($userData['account_status'] != 'A' || $GLOBALS['egw']->accounts->is_expired($userData)))
505
					{
506
						//error_log(__METHOD__.__LINE__." skipped notification for User with Data:".array2string($userData));
507
						$notification_chain = 'disable';
508
						continue;
509
					}
510
					$receiver->handle = $receiver->account_lid;
511
					// check if the receiver has rights to run the notifcation app
512
					$ids = $GLOBALS['egw']->accounts->memberships($receiver->account_id,true);
513
					$ids[] = $receiver->account_id;
514
					if ($GLOBALS['egw']->acl->get_specific_rights_for_account($ids,'run','notifications')) {
515
						// read the users notification chain
516
						$prefs = new Api\Preferences($receiver->account_id);
517
						$preferences_all = $prefs->read();
518
						$preferences = (object)$preferences_all[self::_appname];
519
						if($preferences->notification_chain) {
520
							// fallback: admin disabled user-chosen chain
521
							if(!$notification_chain = $available_chains[$preferences->notification_chain]) {
522
								$prepend_message .= lang(	'This eGroupWare notification has been sent to you by mail because your'
523
															.' chosen notification-chain has been disabled by the administrator.'
524
															.' Please choose another notification-chain in your preferences!');
525
								$notification_chain = $available_chains[self::_fallback];
526
							}
527
						} else {
528
							$notification_chain = $available_chains[self::user_fallback]; // fallback: no prefs
529
						}
530
					} else {
531
						$notification_chain = $available_chains[self::_fallback]; // fallback: no rights to app
532
					}
533
				} else {
534
					// non-system user
535
					$receiver->handle = $receiver->account_email;
536
					$notification_chain = $available_chains[self::_fallback]; // fallback: non-system user
537
				}
538
539
				if($notification_chain == 'disable') {
540
					continue; //user disabled notifications
541
				}
542
543
				foreach($notification_chain as $backend => $action) {
544
					$notification_backend = null;
545
					try {
546
						// check if backend should be skipped
547
						if( in_array($backend, $this->skip_backends) ) {
548
							// log as error just for the case too much skipping prevents user from being notified
549
							$backend_errors[] = $backend.' will be skipped (as defined by calling application)';
550
							continue;
551
						}
552
553
						$notification_backend = self::_appname.'_'.$backend;
554
						if(!file_exists(EGW_INCLUDE_ROOT.'/'. self::_appname.'/inc/class.'. $notification_backend. '.inc.php')) {
555
							throw new Exception('file for '.$notification_backend. ' does not exist');
556
						}
557
						$obj = new $notification_backend( $this->sender, $receiver, $this->config, $preferences );
558
						if ( !($obj instanceof notifications_iface) ) {
559
							unset ( $obj );
560
					 		throw new Exception($notification_backend. ' is no implementation of notifications_iface');
561
						}
562
						$lsubject = $this->subject;
563
						$llinks = $this->links;
564
						if ($backend == 'popup')
565
						{
566
							if (!empty($this->popupsubject)) $lsubject = $this->popupsubject;
567
							if ($this->popup_links) $llinks = $this->popup_links;
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->popup_links of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
568
							if (is_array($this->popup_data)) $popup_data = $this->popup_data;
569
						} elseif ($backend == 'email') {
570
							if (!empty($this->reply_to)) $popup_data = array( 'reply_to' => $this->reply_to );
571
						}
572
						$obj->send($this->prepend_message($messages, $prepend_message), $lsubject, $llinks, $this->attachments, $popup_data);
573
574
						// This is to make popup_or_email option sensfull since
575
						// we save popup notifications in database anyway, email
576
						// notifications should be based on user availability.
577
						if ($backend == 'popup' && $action== 'fail' && !Api\Session::notifications_active($receiver->account_id))
578
						{
579
							throw new Exception();
580
						}
581
					}
582
					catch (Exception $exception) {
583
						$backend_errors[] = $notification_backend.' failed: '.$exception->getMessage();
584
						// try next backend
585
						if($action == 'fail' || $action == 'continue') {
586
							continue;
587
						}
588
						break; // stop running through chain
589
					}
590
					// backend sucseeded
591
					$user_notified = true;
592
					if($action == 'stop' || $action == 'fail') { break; } // stop running through chain
593
				}
594
				// check if the user has been notified at all
595
				if(!$user_notified) {
596
					/*error_log('Error: notification of receiver '.$receiver->handle.' failed for the following reasons:');
597
					foreach($backend_errors as $id=>$backend_error) {
598
						error_log($backend_error);
599
					}*/
600
					$error = implode(', ', $backend_errors);
601
					if (stripos($error, (string)$receiver->handle) !== false) $error = $receiver->handle.': '.$error;
602
					self::$errors[] = $error;
603
				}
604
			}
605
			catch (Exception $exception_user) {
606
				error_log('Error: notification of receiver '.$receiver->handle.' failed: '.$exception_user->getMessage());
607
				self::$errors[] = $receiver->handle.': '.$exception_user->getMessage();
608
			}
609
		}
610
		return true;
611
	}
612
613
	/**
614
	 * creates an array with the message as plaintext and html, and optional a html popup message
615
	 *
616
	 * @param string $_message_plain
617
	 * @param string $_message_html
618
	 * @param string $_message_popup
619
	 * @return plain and html message in one array, $messages['plain'] and $messages['html'] and, if exists $messages['popup']
0 ignored issues
show
Bug introduced by
The type plain was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
620
	 */
621
	private function create_messages($_message_plain = '', $_message_html = '', $_message_popup = '') {
622
		if(empty($_message_plain) && empty($_message_html) && empty($_message_popup)) { return false; } // no message set
623
		$messages = array();
624
625
		// create the messages
626
		if(!empty($_message_plain)) {
627
			$messages['plain'] = $_message_plain;
628
		} else {
629
			$messages['plain'] = Api\Mail\Html::convertHTMLToText($_message_html, false, true);
630
		}
631
632
		if(!empty($_message_html)) {
633
			$messages['html'] = $_message_html;
634
		} else {
635
			$messages['html'] = self::plain2html($_message_plain);
636
		}
637
		if (!empty($_message_popup)) $messages['popup']=$_message_popup;
638
		return $messages;
639
	}
640
641
	/**
642
	 * Create html from plaintext message
643
	 *
644
	 * @param string $_plain
645
	 * @return string html message
646
	 */
647
	public static function plain2html($_plain)
648
	{
649
		return Api\Html::activate_links(nl2br(Api\Html::htmlspecialchars($_plain, true)));
650
	}
651
652
	/**
653
	 * prepends another message to the messages array
654
	 *
655
	 * @param array $_messages the messages array from create_messages()
656
	 * @param string $_prepend just a plain message to prepend, no html!
657
	 * @return plain and html message in one array including the prepended message, $messages['plain'] and $messages['html']
658
	 */
659
	 private function prepend_message(array $_messages, $_prepend = null) {
660
		if(strlen($_prepend) > 0) {
661
			foreach($_messages as $key => $value) {
662
				switch($key) {
663
					case 'plain':
664
						$_messages[$key] = $_prepend."\n\n".$value;
665
						break;
666
					case 'html':
667
						// ToDo: move stylesheet to a nicer place
668
						$_messages[$key] = '<div style="margin:0; padding:1em; margin-bottom: 1em; background-color:orange; border:1px solid red;">'.$_prepend.'</div>'.$value;
669
						break;
670
					default:
671
						break;
672
				}
673
			}
674
		}
675
676
		return $_messages;
677
	}
678
679
	/**
680
	 * returns specified part from a given mailaddress
681
	 *
682
	 * @param string $_address
683
	 * @param string $_part
684
	 * @return string chosen part of the address
685
	 */
686
	private function get_addresspart($_address, $_part='email')
687
	{
688
		$parts = null;
689
	 	if(strpos($_address,'<') && preg_match('/^(.*)\S?\<(.*)\>/',$_address, $parts)) { // _address contains a fullname part
690
	 		$fullname = trim(trim($parts[1]),'\"');
691
	 		$email = $parts[2];
692
	 	} else {
693
	 		$fullname = false;
694
	 		$email = $_address;
695
	 	}
696
	 	switch($_part) {
697
	 		case 'fullname':
698
	 			return $fullname;
699
	 		case 'email':
700
	 		default:
701
	 			return $email;
702
	 	}
703
	 	return false;
0 ignored issues
show
Unused Code introduced by
return false is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
704
	 }
705
706
	 /**
707
	 * returns notification chains based on admin prefs
708
	 * @abstract the available chains can be retrieved in two different output formats:
709
	 * routing: array with common and enabled chains, chain-name as key and the chain-array as value (used for message-routing)
710
	 * human: array with common, enabled and disabled chains, chain-name as key and a human-readable description as value (used for config)
711
	 *
712
	 * @param string $_output one of: 'routing' or 'human', defaults to 'routing'
713
	 * @return array containing notification chains, output like given in $_output
714
	 */
715
	public function get_available_chains($_output = 'routing') {
716
		// determine enabled backends from Api\Config
717
		$enabled_backends = array();
718
		foreach($this->backends as $backend) {
719
			switch($backend) {
720
				case 'email':
721
				case 'popup':
722
				case 'jpopup':
723
					$enabled_backends[$backend] = true; // fallback must always be enabled
724
					break;
725
				default:
726
					$param = $backend.'_enable';
727
					$enabled_backends[$backend] = $this->config->{$param} == true ? true : false;
728
					break;
729
			}
730
		}
731
732
		$enabled_chains = array();
733
		$disabled_chains = array();
734
		foreach($this->notification_chains as $key => $chain) {
735
			$allow_chain = true;
736
			if(is_array($chain)) {
737
				foreach(array_keys($chain) as $name) {
738
					if(!$enabled_backends[$name]) {
739
						$allow_chain = false; // disable whole chain if one backend is disabled
740
					}
741
				}
742
				if($allow_chain) {
743
					$enabled_chains[$key] = $chain;
744
				} else {
745
					$disabled_chains[$key] = $chain;
746
				}
747
			}
748
		}
749
750
		// common chain
751
		$common_chains = array();
752
		$common_chains['disable'] = 'disable';
753
		$common_chains['email_only'] = array('email' => 'stop');
754
		// create the 'all' chain from the enabled backends
755
		$chain_all = array();
756
		$backend_count = 1;
757
		foreach($enabled_backends as $backend => $enabled) {
758
			if($enabled) {
759
				$chain_all[$backend] = count($enabled_backends) == $backend_count ? 'stop' : 'continue';
760
			}
761
			$backend_count++;
762
		}
763
		$common_chains['all'] = $chain_all;
764
765
		switch($_output) {
766
			case 'human':
767
				$chain_groups = array(
768
					lang('Common chains')	=> 'common_chains',
769
					lang('Enabled chains') 	=> 'enabled_chains',
770
					lang('Disabled chains') => 'disabled_chains',
771
					);
772
				$suffix = '_human';
773
				// create descriptions for each chain key in each group
774
				foreach($chain_groups as $name => $arr_name) {
775
					${$arr_name.$suffix} = array();
776
					foreach(array_keys(${$arr_name}) as $key) {
777
						if($arr_name == 'disabled_chains') {
778
							${$arr_name.$suffix}[$key] = '('.lang('Disabled').') '.lang($this->chains_descriptions[$key]);
779
						} else {
780
							${$arr_name.$suffix}[$key] = lang($this->chains_descriptions[$key]);
781
						}
782
					}
783
				}
784
				// summarize all groups with minimum one chain to the final array
785
				$chains_final = array();
786
				foreach($chain_groups as $name => $arr_name) {
787
					if(is_array(${$arr_name.$suffix}) && count(${$arr_name.$suffix}) > 0) {
788
						$chains_final[$name] = ${$arr_name.$suffix};
789
					}
790
				}
791
				return $chains_final;
792
793
			case 'routing':
794
			default:
795
				return array_merge($common_chains, $enabled_chains);
796
		}
797
798
		return false;
0 ignored issues
show
Unused Code introduced by
return false is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
799
	}
800
801
	/**
802
	 * Actions to take when an account is deleted
803
	 *
804
	 * @param settings array with keys account_id and new_owner (new_owner is optional)
805
	 */
806
	public function deleteaccount($settings) {
807
		foreach($this->backends as $backend) {
808
			$backend_hook = array(self::_appname.'_'.$backend,'deleteaccount');
809
			if (is_callable($backend_hook)) {
810
				call_user_func($backend_hook,$settings);
811
			}
812
		}
813
	}
814
815
816
	/**
817
	 * Set popup data
818
	 *
819
	 * @param string $_appname
820
	 * @param array $_data
821
	 * @return boolean
822
	 */
823
	public function set_popupdata($_appname, $_data) {
824
		$this->popup_data = array(
825
			'appname' => $_appname,
826
			'data' => $_data
827
		);
828
829
		return true;
830
	}
831
}
832