Elgg  Version 2.2
 All Classes Namespaces Files Functions Variables Pages
notification.php
Go to the documentation of this file.
1 <?php
2 
4 use Zend\Mail\Message;
5 
65 function elgg_register_notification_event($object_type, $object_subtype, array $actions = array()) {
66  _elgg_services()->notifications->registerEvent($object_type, $object_subtype, $actions);
67 }
68 
77 function elgg_unregister_notification_event($object_type, $object_subtype) {
78  return _elgg_services()->notifications->unregisterEvent($object_type, $object_subtype);
79 }
80 
94  _elgg_services()->notifications->registerMethod($name);
95 }
96 
106  return _elgg_services()->notifications->unregisterMethod($name);
107 }
108 
118 function elgg_add_subscription($user_guid, $method, $target_guid) {
119  $methods = _elgg_services()->notifications->getMethods();
120  $db = _elgg_services()->db;
121  $subs = new \Elgg\Notifications\SubscriptionsService($db, $methods);
122  return $subs->addSubscription($user_guid, $method, $target_guid);
123 }
124 
134 function elgg_remove_subscription($user_guid, $method, $target_guid) {
135  $methods = _elgg_services()->notifications->getMethods();
136  $db = _elgg_services()->db;
137  $subs = new \Elgg\Notifications\SubscriptionsService($db, $methods);
138  return $subs->removeSubscription($user_guid, $method, $target_guid);
139 }
140 
156  $methods = _elgg_services()->notifications->getMethods();
157  $db = _elgg_services()->db;
158  $subs = new \Elgg\Notifications\SubscriptionsService($db, $methods);
159  return $subs->getSubscriptionsForContainer($container_guid);
160 }
161 
178  _elgg_services()->notifications->enqueueEvent($action, $type, $object);
179 }
180 
185  // calculate when we should stop
186  // @todo make configurable?
187  $stop_time = time() + 45;
188  _elgg_services()->notifications->processQueue($stop_time);
189 }
190 
202 
203  if ($result === true) {
204  // assume someone else already sent the message
205  return;
206  }
207 
208  /* @var \Elgg\Notifications\Notification $message */
209  $message = $params['notification'];
210 
211  $sender = $message->getSender();
212  $recipient = $message->getRecipient();
213 
214  if (!$sender) {
215  return false;
216  }
217 
218  if (!$recipient || !$recipient->email) {
219  return false;
220  }
221 
222  $to = $recipient->email;
223 
225  // If there's an email address, use it - but only if it's not from a user.
226  if (!($sender instanceof \ElggUser) && $sender->email) {
227  $from = $sender->email;
228  } else if ($site->email) {
229  $from = $site->email;
230  } else {
231  // If all else fails, use the domain of the site.
232  $from = 'noreply@' . $site->getDomain();
233  }
234 
235  return elgg_send_email($from, $to, $message->subject, $message->body, $params);
236 }
237 
253 
254  if (!is_array($returnvalue) || !is_array($returnvalue['params'])) {
255  // another hook handler returned a non-array, let's not override it
256  return;
257  }
258 
259  $hostname = parse_url(elgg_get_site_url(), PHP_URL_HOST);
260  $url_path = parse_url(elgg_get_site_url(), PHP_URL_PATH);
261 
262  $mt = microtime(true);
263 
264  $returnvalue['headers']['Message-ID'] = "<{$url_path}.default.{$mt}@{$hostname}>";
265 
266  return $returnvalue;
267 }
279 function _elgg_notifications_smtp_thread_headers($hook, $type, $returnvalue, $params) {
280 
281  if (!is_array($returnvalue) || !is_array($returnvalue['params'])) {
282  // another hook handler returned a non-array, let's not override it
283  return;
284  }
285 
286  $notificationParams = elgg_extract('params', $returnvalue, array());
288  $notification = elgg_extract('notification', $notificationParams);
289 
290  if (!($notification instanceof \Elgg\Notifications\Notification)) {
291  return $returnvalue;
292  }
293 
294  $hostname = parse_url(elgg_get_site_url(), PHP_URL_HOST);
295  $urlPath = parse_url(elgg_get_site_url(), PHP_URL_PATH);
296 
297  $object = elgg_extract('object', $notification->params);
299  $event = elgg_extract('event', $notification->params);
300 
301  if (($object instanceof \ElggEntity) && ($event instanceof \Elgg\Notifications\Event)) {
302  if ($event->getAction() === 'create') {
303  // create event happens once per entity and we need to guarantee message id uniqueness
304  // and at the same time have thread message id that we don't need to store
305  $messageId = "<{$urlPath}.entity.{$object->guid}@{$hostname}>";
306  } else {
307  $mt = microtime(true);
308  $messageId = "<{$urlPath}.entity.{$object->guid}.$mt@{$hostname}>";
309  }
310  $returnvalue['headers']["Message-ID"] = $messageId;
311  $container = $object->getContainerEntity();
312 
313  // let's just thread comments by default
314  if (($container instanceof \ElggEntity) && ($object instanceof \ElggComment)) {
315 
316  $threadMessageId = "<{$urlPath}.entity.{$container->guid}@{$hostname}>";
317  $returnvalue['headers']['In-Reply-To'] = $threadMessageId;
318  $returnvalue['headers']['References'] = $threadMessageId;
319  }
320  }
321 
322  return $returnvalue;
323 }
324 
329  elgg_register_plugin_hook_handler('cron', 'minute', '_elgg_notifications_cron', 100);
330  elgg_register_event_handler('all', 'all', '_elgg_enqueue_notification_event', 700);
331 
332  // add email notifications
334  elgg_register_plugin_hook_handler('send', 'notification:email', '_elgg_send_email_notification');
335  elgg_register_plugin_hook_handler('email', 'system', '_elgg_notifications_smtp_default_message_id_header', 1);
336  elgg_register_plugin_hook_handler('email', 'system', '_elgg_notifications_smtp_thread_headers');
337 
338  // add ability to set personal notification method
339  elgg_extend_view('forms/account/settings', 'core/settings/account/notifications');
340  elgg_register_plugin_hook_handler('usersettings:save', 'user', '_elgg_save_notification_user_settings');
341 }
342 
358 function _elgg_notify_user($to, $from, $subject, $message, array $params = null, $methods_override = "") {
359 
360  $notify_service = _elgg_services()->notifications;
361 
362  // Sanitise
363  if (!is_array($to)) {
364  $to = array((int)$to);
365  }
366  $from = (int)$from;
367  //$subject = sanitise_string($subject);
368 
369  // Get notification methods
370  if (($methods_override) && (!is_array($methods_override))) {
371  $methods_override = array($methods_override);
372  }
373 
374  $result = array();
375 
376  foreach ($to as $guid) {
377  // Results for a user are...
378  $result[$guid] = array();
379 
380  if ($guid) { // Is the guid > 0?
381  // Are we overriding delivery?
382  $methods = $methods_override;
383  if (!$methods) {
384  $tmp = get_user_notification_settings($guid);
385  $methods = array();
386  // $tmp may be false. don't cast
387  if (is_object($tmp)) {
388  foreach ($tmp as $k => $v) {
389  // Add method if method is turned on for user!
390  if ($v) {
391  $methods[] = $k;
392  }
393  }
394  }
395  }
396 
397  if ($methods) {
398  // Deliver
399  foreach ($methods as $method) {
400 
401  $handler = $notify_service->getDeprecatedHandler($method);
402  /* @var callable $handler */
403  if (!$handler || !is_callable($handler)) {
404  elgg_log("No handler registered for the method $method", 'WARNING');
405  continue;
406  }
407 
408  elgg_log("Sending message to $guid using $method");
409 
410  // Trigger handler and retrieve result.
411  try {
412  $result[$guid][$method] = call_user_func($handler,
413  $from ? get_entity($from) : null,
414  get_entity($guid),
415  $subject,
416  $message,
417  $params
418  );
419  } catch (Exception $e) {
420  error_log($e->getMessage());
421  }
422  }
423  }
424  }
425  }
426 
427  return $result;
428 }
429 
430 
480 function notify_user($to, $from, $subject, $message, array $params = array(), $methods_override = "") {
481 
482  if (!is_array($to)) {
483  $to = array((int)$to);
484  }
485  $from = (int)$from;
486  $from = get_entity($from) ? $from : elgg_get_site_entity()->guid;
487  $sender = get_entity($from);
488  $summary = elgg_extract('summary', $params, '');
489 
490  // Get notification methods
491  if (($methods_override) && (!is_array($methods_override))) {
492  $methods_override = array($methods_override);
493  }
494 
495  $result = array();
496 
497  $available_methods = _elgg_services()->notifications->getMethods();
498  if (!$available_methods) {
499  // There are no notifications methods to use
500  return $result;
501  }
502 
503  // temporary backward compatibility for 1.8 and earlier notifications
504  $event = null;
505  if (isset($params['object']) && isset($params['action'])) {
506  $event = new \Elgg\Notifications\Event($params['object'], $params['action'], $sender);
507  }
508  $params['event'] = $event;
509 
510  foreach ($to as $guid) {
511  // Results for a user are...
512  $result[$guid] = array();
513 
514  if ($guid) { // Is the guid > 0?
515  // Are we overriding delivery?
516  $methods = $methods_override;
517  if (!$methods) {
518  $tmp = (array)get_user_notification_settings($guid);
519  $methods = array();
520  foreach ($tmp as $k => $v) {
521  // Add method if method is turned on for user!
522  if ($v) {
523  $methods[] = $k;
524  }
525  }
526  }
527 
528  if ($methods) {
529  // Deliver
530  foreach ($methods as $method) {
531  if (!in_array($method, $available_methods)) {
532  // This method was available the last time the user saved their
533  // notification settings. It's however currently disabled.
534  continue;
535  }
536 
537  if (_elgg_services()->hooks->hasHandler('send', "notification:$method")) {
538  // 1.9 style notification handler
539  $recipient = get_entity($guid);
540  if (!$recipient) {
541  continue;
542  }
543  $language = $recipient->language;
544  $notification = new \Elgg\Notifications\Notification($sender, $recipient, $language, $subject, $message, $summary, $params);
545  $params['notification'] = $notification;
546  $result[$guid][$method] = _elgg_services()->hooks->trigger('send', "notification:$method", $params, false);
547  } else {
548  $result[$guid][$method] = _elgg_notify_user($guid, $from, $subject, $message, $params, array($method));
549  }
550  }
551  }
552  }
553  }
554 
555  return $result;
556 }
557 
566  $user_guid = (int)$user_guid;
567 
568  if ($user_guid == 0) {
570  }
571 
572  // @todo: there should be a better way now that metadata is cached. E.g. just query for MD names, then
573  // query user object directly
574  $all_metadata = elgg_get_metadata(array(
575  'guid' => $user_guid,
576  'limit' => 0
577  ));
578  if ($all_metadata) {
579  $prefix = "notification:method:";
580  $return = new \stdClass;
581 
582  foreach ($all_metadata as $meta) {
583  $name = substr($meta->name, strlen($prefix));
584  $value = $meta->value;
585 
586  if (strpos($meta->name, $prefix) === 0) {
587  $return->$name = $value;
588  }
589  }
590 
591  return $return;
592  }
593 
594  return false;
595 }
596 
607  $user_guid = (int)$user_guid;
609 
611  if (!$user) {
613  }
614 
615  if (($user) && ($user instanceof \ElggUser)) {
616  $prefix = "notification:method:$method";
617  $user->$prefix = $value;
618  $user->save();
619 
620  return true;
621  }
622 
623  return false;
624 }
625 
626 
640 function elgg_send_email($from, $to, $subject, $body, array $params = null) {
641  if (!$from) {
642  $msg = "Missing a required parameter, '" . 'from' . "'";
643  throw new \NotificationException($msg);
644  }
645 
646  if (!$to) {
647  $msg = "Missing a required parameter, '" . 'to' . "'";
648  throw new \NotificationException($msg);
649  }
650 
651  $headers = array(
652  "Content-Type" => "text/plain; charset=UTF-8; format=flowed",
653  "MIME-Version" => "1.0",
654  "Content-Transfer-Encoding" => "8bit",
655  );
656 
657  // return true/false to stop elgg_send_email() from sending
658  $mail_params = array(
659  'to' => $to,
660  'from' => $from,
661  'subject' => $subject,
662  'body' => $body,
663  'headers' => $headers,
664  'params' => $params,
665  );
666 
667  // $mail_params is passed as both params and return value. The former is for backwards
668  // compatibility. The latter is so handlers can now alter the contents/headers of
669  // the email by returning the array
670  $result = _elgg_services()->hooks->trigger('email', 'system', $mail_params, $mail_params);
671  if (!is_array($result)) {
672  // don't need null check: Handlers can't set a hook value to null!
673  return (bool)$result;
674  }
675 
676  // strip name from to and from
677 
678  $to_address = Address::fromString($result['to']);
679  $from_address = Address::fromString($result['from']);
680 
681 
682  $subject = elgg_strip_tags($result['subject']);
683  $subject = html_entity_decode($subject, ENT_QUOTES, 'UTF-8');
684  // Sanitise subject by stripping line endings
685  $subject = preg_replace("/(\r\n|\r|\n)/", " ", $subject);
686  $subject = trim($subject);
687 
688  $body = elgg_strip_tags($result['body']);
689  $body = html_entity_decode($body, ENT_QUOTES, 'UTF-8');
690  $body = wordwrap($body);
691 
692  $message = new Message();
693  $message->setEncoding('UTF-8');
694  $message->addFrom($from_address);
695  $message->addTo($to_address);
696  $message->setSubject($subject);
697  $message->setBody($body);
698 
699  foreach ($result['headers'] as $headerName => $headerValue) {
700  $message->getHeaders()->addHeaderLine($headerName, $headerValue);
701  }
702 
703  try {
704  _elgg_services()->mailer->send($message);
705  } catch (\Zend\Mail\Exception\RuntimeException $e) {
706  _elgg_services()->logger->error($e->getMessage());
707  return false;
708  }
709 
710  return true;
711 }
712 
720  $method = get_input('method');
721 
722  $current_settings = get_user_notification_settings();
723 
724  $result = false;
725  foreach ($method as $k => $v) {
726  // check if setting has changed and skip if not
727  if ($current_settings->$k == ($v == 'yes')) {
728  continue;
729  }
730 
731  $result = set_user_notification_setting(elgg_get_logged_in_user_guid(), $k, ($v == 'yes') ? true : false);
732 
733  if (!$result) {
734  register_error(elgg_echo('notifications:usersettings:save:fail'));
735  }
736  }
737 
738  if ($result) {
739  system_message(elgg_echo('notifications:usersettings:save:ok'));
740  }
741 }
742 
746 function _elgg_notifications_test($hook, $type, $tests) {
747  global $CONFIG;
748  $tests[] = "{$CONFIG->path}engine/tests/ElggCoreDatabaseQueueTest.php";
749  return $tests;
750 }
751 
752 return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
753  $events->registerHandler('init', 'system', '_elgg_notifications_init');
754 
755  $hooks->registerHandler('unit_test', 'system', '_elgg_notifications_test');
756 };
$object
These two snippets demonstrates triggering an event and how to register for that event.
Definition: trigger.php:7
elgg_get_site_entity($site_guid=0)
Get an entity (default is current site)
Definition: sites.php:18
$action
Definition: full.php:125
elgg_register_notification_method($name)
Register a delivery method for notifications.
$subject
Definition: exceptions.php:25
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
elgg_echo($message_key, $args=array(), $language="")
Given a message key, returns an appropriately translated full-text string.
Definition: languages.php:21
$method
Definition: form.php:25
$e
Definition: metadata.php:12
elgg_strip_tags($string, $allowable_tags=null)
Strip tags and offer plugins the chance.
Definition: output.php:478
_elgg_notifications_cron()
private
$headers
Definition: default.php:14
elgg_unregister_notification_event($object_type, $object_subtype)
Unregister a notification event.
_elgg_enqueue_notification_event($action, $type, $object)
Queue a notification event for later handling.
$value
Definition: longtext.php:26
$return
Definition: opendd.php:15
$guid
Removes an admin notice.
elgg_register_plugin_hook_handler($hook, $type, $callback, $priority=500)
Definition: elgglib.php:715
elgg_remove_subscription($user_guid, $method, $target_guid)
Unsubscribe a user to notifications about a target entity.
register_error($error)
Display an error on next page load.
Definition: elgglib.php:452
$actions
Definition: user_hover.php:12
$summary
Definition: full.php:21
$params
Definition: login.php:72
elgg_get_subscriptions_for_container($container_guid)
Get the subscriptions for the content created inside this container.
_elgg_notifications_init()
private
_elgg_save_notification_user_settings()
Save personal notification settings - input comes from request.
elgg_unregister_notification_method($name)
Unregister a delivery method for notifications.
$language
Definition: useradd.php:20
$container
Definition: delete.php:29
get_input($variable, $default=null, $filter_result=true)
Get some input from variables passed submitted through GET or POST.
Definition: input.php:27
global $CONFIG
sanitise_string($string)
Alias of sanitize_string.
Definition: database.php:166
$user
Definition: ban.php:13
_elgg_notifications_smtp_default_message_id_header($hook, $type, $returnvalue, $params)
Adds default Message-ID header to all e-mails.
set_user_notification_setting($user_guid, $method, $value)
Set a user notification pref.
elgg_get_site_url($site_guid=0)
Get the URL for the current (or specified) site.
elgg_extend_view($view, $view_extension, $priority=501)
Extends a view with another view.
Definition: views.php:386
_elgg_services(\Elgg\Di\ServiceProvider $services=null)
Get the global service provider.
Definition: autoloader.php:17
elgg_extract($key, $array, $default=null, $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Definition: elgglib.php:1310
elgg_register_event_handler($event, $object_type, $callback, $priority=500)
Definition: elgglib.php:538
elgg_log($message, $level= 'NOTICE')
Display or log a message.
Definition: elgglib.php:1000
_elgg_send_email_notification($hook, $type, $result, $params)
Send an email notification.
_elgg_notifications_test($hook, $type, $tests)
private
elgg_add_subscription($user_guid, $method, $target_guid)
Subscribe a user to notifications about a target entity.
elgg_register_notification_event($object_type, $object_subtype, array $actions=array())
Register a notification event.
elgg_get_metadata(array $options=array())
Returns metadata.
Definition: metadata.php:143
TODO(ewinslow): Contribute something like this back to Zend project.
Definition: Address.php:9
notify_user($to, $from, $subject, $message, array $params=array(), $methods_override="")
Notify a user via their preferences.
elgg_get_logged_in_user_entity()
Return the current logged in user, or null if no user is logged in.
Definition: sessions.php:32
$container_guid
$handler
Definition: add.php:10
$user_guid
Avatar remove action.
Definition: remove.php:6
get_user_notification_settings($user_guid=0)
Get the notification settings for a given user.
elgg_send_email($from, $to, $subject, $body, array $params=null)
Send an email to any email address.
system_message($message)
Display a system message on next page load.
Definition: elgglib.php:438
elgg_get_logged_in_user_guid()
Return the current logged in user by guid.
Definition: sessions.php:42
_elgg_notify_user($to, $from, $subject, $message, array $params=null, $methods_override="")
Notify a user via their preferences.
get_entity($guid)
Loads and returns an entity object from a guid.
Definition: entities.php:204
if(!$display_name) $type
Definition: delete.php:27