Elgg  Version 1.9
notification.php
Go to the documentation of this file.
1 <?php
59 function elgg_register_notification_event($object_type, $object_subtype, array $actions = array()) {
60  _elgg_services()->notifications->registerEvent($object_type, $object_subtype, $actions);
61 }
62 
71 function elgg_unregister_notification_event($object_type, $object_subtype) {
72  return _elgg_services()->notifications->unregisterEvent($object_type, $object_subtype);
73 }
74 
88  _elgg_services()->notifications->registerMethod($name);
89 }
90 
100  return _elgg_services()->notifications->unregisterMethod($name);
101 }
102 
112 function elgg_add_subscription($user_guid, $method, $target_guid) {
113  $methods = _elgg_services()->notifications->getMethods();
114  $db = _elgg_services()->db;
115  $subs = new Elgg_Notifications_SubscriptionsService($db, $methods);
116  return $subs->addSubscription($user_guid, $method, $target_guid);
117 }
118 
128 function elgg_remove_subscription($user_guid, $method, $target_guid) {
129  $methods = _elgg_services()->notifications->getMethods();
130  $db = _elgg_services()->db;
131  $subs = new Elgg_Notifications_SubscriptionsService($db, $methods);
132  return $subs->removeSubscription($user_guid, $method, $target_guid);
133 }
134 
149 function elgg_get_subscriptions_for_container($container_guid) {
150  $methods = _elgg_services()->notifications->getMethods();
151  $db = _elgg_services()->db;
152  $subs = new Elgg_Notifications_SubscriptionsService($db, $methods);
153  return $subs->getSubscriptionsForContainer($container_guid);
154 }
155 
172  _elgg_services()->notifications->enqueueEvent($action, $type, $object);
173 }
174 
179  // calculate when we should stop
180  // @todo make configurable?
181  $stop_time = time() + 45;
182  _elgg_services()->notifications->processQueue($stop_time);
183 }
184 
196  /* @var Elgg_Notifications_Notification $message */
197  $message = $params['notification'];
198 
199  $sender = $message->getSender();
200  $recipient = $message->getRecipient();
201 
202  if (!$sender) {
203  return false;
204  }
205 
206  if (!$recipient || !$recipient->email) {
207  return false;
208  }
209 
210  $to = $recipient->email;
211 
213  // If there's an email address, use it - but only if it's not from a user.
214  if (!($sender instanceof ElggUser) && $sender->email) {
215  $from = $sender->email;
216  } else if ($site->email) {
217  $from = $site->email;
218  } else {
219  // If all else fails, use the domain of the site.
220  $from = 'noreply@' . $site->getDomain();
221  }
222 
223  return elgg_send_email($from, $to, $message->subject, $message->body, $params);
224 }
225 
237 function _elgg_notifications_smtp_thread_headers($hook, $type, $returnvalue, $params) {
238 
239  $notificationParams = elgg_extract('params', $returnvalue, array());
241  $notification = elgg_extract('notification', $notificationParams);
242 
243  if (!($notification instanceof Elgg_Notifications_Notification)) {
244  return $returnvalue;
245  }
246 
247  $hostname = parse_url(elgg_get_site_url(), PHP_URL_HOST);
248  $urlPath = parse_url(elgg_get_site_url(), PHP_URL_PATH);
249 
250  $object = elgg_extract('object', $notification->params);
252  $event = elgg_extract('event', $notification->params);
253 
254  if (($object instanceof ElggEntity) && ($event instanceof Elgg_Notifications_Event)) {
255  if ($event->getAction() === 'create') {
256  // create event happens once per entity and we need to guarantee message id uniqueness
257  // and at the same time have thread message id that we don't need to store
258  $messageId = "<{$urlPath}.entity.{$object->guid}@{$hostname}>";
259  } else {
260  $mt = microtime(true);
261  $messageId = "<{$urlPath}.entity.{$object->guid}.$mt@{$hostname}>";
262  }
263  $returnvalue['headers']["Message-ID"] = $messageId;
264  $container = $object->getContainerEntity();
265 
266  // let's just thread comments by default
267  if (($container instanceof ElggEntity) && ($object instanceof ElggComment)) {
268 
269  $threadMessageId = "<{$urlPath}.entity.{$container->guid}@{$hostname}>";
270  $returnvalue['headers']['In-Reply-To'] = $threadMessageId;
271  $returnvalue['headers']['References'] = $threadMessageId;
272  }
273  }
274 
275  return $returnvalue;
276 }
277 
282  elgg_register_plugin_hook_handler('cron', 'minute', '_elgg_notifications_cron', 100);
283  elgg_register_event_handler('all', 'all', '_elgg_enqueue_notification_event');
284 
285  // add email notifications
287  elgg_register_plugin_hook_handler('send', 'notification:email', '_elgg_send_email_notification');
288  elgg_register_plugin_hook_handler('email', 'system', '_elgg_notifications_smtp_thread_headers');
289 
290  // add ability to set personal notification method
291  elgg_extend_view('forms/account/settings', 'core/settings/account/notifications');
292  elgg_register_plugin_hook_handler('usersettings:save', 'user', '_elgg_save_notification_user_settings');
293 }
294 
295 elgg_register_event_handler('init', 'system', '_elgg_notifications_init');
296 
297 
298 
314 function _elgg_notify_user($to, $from, $subject, $message, array $params = null, $methods_override = "") {
315 
316  $notify_service = _elgg_services()->notifications;
317 
318  // Sanitise
319  if (!is_array($to)) {
320  $to = array((int)$to);
321  }
322  $from = (int)$from;
323  //$subject = sanitise_string($subject);
324 
325  // Get notification methods
326  if (($methods_override) && (!is_array($methods_override))) {
327  $methods_override = array($methods_override);
328  }
329 
330  $result = array();
331 
332  foreach ($to as $guid) {
333  // Results for a user are...
334  $result[$guid] = array();
335 
336  if ($guid) { // Is the guid > 0?
337  // Are we overriding delivery?
338  $methods = $methods_override;
339  if (!$methods) {
340  $tmp = get_user_notification_settings($guid);
341  $methods = array();
342  // $tmp may be false. don't cast
343  if (is_object($tmp)) {
344  foreach ($tmp as $k => $v) {
345  // Add method if method is turned on for user!
346  if ($v) {
347  $methods[] = $k;
348  }
349  }
350  }
351  }
352 
353  if ($methods) {
354  // Deliver
355  foreach ($methods as $method) {
356 
357  $handler = $notify_service->getDeprecatedHandler($method);
358  /* @var callable $handler */
359  if (!$handler || !is_callable($handler)) {
360  error_log("No handler registered for the method $method", 'WARNING');
361  continue;
362  }
363 
364  elgg_log("Sending message to $guid using $method");
365 
366  // Trigger handler and retrieve result.
367  try {
368  $result[$guid][$method] = call_user_func($handler,
369  $from ? get_entity($from) : null,
370  get_entity($guid),
371  $subject,
372  $message,
373  $params
374  );
375  } catch (Exception $e) {
376  error_log($e->getMessage());
377  }
378  }
379  }
380  }
381  }
382 
383  return $result;
384 }
385 
386 
436 function notify_user($to, $from, $subject, $message, array $params = array(), $methods_override = "") {
437 
438  if (!is_array($to)) {
439  $to = array((int)$to);
440  }
441  $from = (int)$from;
442  $from = get_entity($from) ? $from : elgg_get_site_entity()->guid;
443  $sender = get_entity($from);
444  $summary = elgg_extract('summary', $params, '');
445 
446  // Get notification methods
447  if (($methods_override) && (!is_array($methods_override))) {
448  $methods_override = array($methods_override);
449  }
450 
451  $result = array();
452 
453  $available_methods = _elgg_services()->notifications->getMethods();
454  if (!$available_methods) {
455  // There are no notifications methods to use
456  return $result;
457  }
458 
459  // temporary backward compatibility for 1.8 and earlier notifications
460  $event = null;
461  if (isset($params['object']) && isset($params['action'])) {
462  $event = new Elgg_Notifications_Event($params['object'], $params['action'], $sender);
463  }
464  $params['event'] = $event;
465 
466  foreach ($to as $guid) {
467  // Results for a user are...
468  $result[$guid] = array();
469 
470  if ($guid) { // Is the guid > 0?
471  // Are we overriding delivery?
472  $methods = $methods_override;
473  if (!$methods) {
474  $tmp = (array)get_user_notification_settings($guid);
475  $methods = array();
476  foreach ($tmp as $k => $v) {
477  // Add method if method is turned on for user!
478  if ($v) {
479  $methods[] = $k;
480  }
481  }
482  }
483 
484  if ($methods) {
485  // Deliver
486  foreach ($methods as $method) {
487  if (!in_array($method, $available_methods)) {
488  // This method was available the last time the user saved their
489  // notification settings. It's however currently disabled.
490  continue;
491  }
492 
493  if (_elgg_services()->hooks->hasHandler('send', "notification:$method")) {
494  // 1.9 style notification handler
495  $recipient = get_entity($guid);
496  if (!$recipient) {
497  continue;
498  }
499  $language = $recipient->language;
500  $notification = new Elgg_Notifications_Notification($sender, $recipient, $language, $subject, $message, $summary, $params);
501  $params['notification'] = $notification;
502  $result[$guid][$method] = _elgg_services()->hooks->trigger('send', "notification:$method", $params, false);
503  } else {
504  $result[$guid][$method] = _elgg_notify_user($guid, $from, $subject, $message, $params, array($method));
505  }
506  }
507  }
508  }
509  }
510 
511  return $result;
512 }
513 
522  $user_guid = (int)$user_guid;
523 
524  if ($user_guid == 0) {
526  }
527 
528  // @todo: there should be a better way now that metadata is cached. E.g. just query for MD names, then
529  // query user object directly
530  $all_metadata = elgg_get_metadata(array(
531  'guid' => $user_guid,
532  'limit' => 0
533  ));
534  if ($all_metadata) {
535  $prefix = "notification:method:";
536  $return = new stdClass;
537 
538  foreach ($all_metadata as $meta) {
539  $name = substr($meta->name, strlen($prefix));
540  $value = $meta->value;
541 
542  if (strpos($meta->name, $prefix) === 0) {
543  $return->$name = $value;
544  }
545  }
546 
547  return $return;
548  }
549 
550  return false;
551 }
552 
563  $user_guid = (int)$user_guid;
565 
567  if (!$user) {
569  }
570 
571  if (($user) && ($user instanceof ElggUser)) {
572  $prefix = "notification:method:$method";
573  $user->$prefix = $value;
574  $user->save();
575 
576  return true;
577  }
578 
579  return false;
580 }
581 
595 function elgg_send_email($from, $to, $subject, $body, array $params = null) {
596  global $CONFIG;
597 
598  if (!$from) {
599  $msg = "Missing a required parameter, '" . 'from' . "'";
600  throw new NotificationException($msg);
601  }
602 
603  if (!$to) {
604  $msg = "Missing a required parameter, '" . 'to' . "'";
605  throw new NotificationException($msg);
606  }
607 
608  $headers = array(
609  "Content-Type" => "text/plain; charset=UTF-8; format=flowed",
610  "MIME-Version" => "1.0",
611  "Content-Transfer-Encoding" => "8bit",
612  );
613 
614  // return true/false to stop elgg_send_email() from sending
615  $mail_params = array(
616  'to' => $to,
617  'from' => $from,
618  'subject' => $subject,
619  'body' => $body,
620  'headers' => $headers,
621  'params' => $params,
622  );
623 
624  // $mail_params is passed as both params and return value. The former is for backwards
625  // compatibility. The latter is so handlers can now alter the contents/headers of
626  // the email by returning the array
627  $result = elgg_trigger_plugin_hook('email', 'system', $mail_params, $mail_params);
628  if (is_array($result)) {
629  foreach (array('to', 'from', 'subject', 'body', 'headers') as $key) {
630  if (isset($result[$key])) {
631  ${$key} = $result[$key];
632  }
633  }
634  } elseif ($result !== null) {
635  return $result;
636  }
637 
638  $header_eol = "\r\n";
639  if (isset($CONFIG->broken_mta) && $CONFIG->broken_mta) {
640  // Allow non-RFC 2822 mail headers to support some broken MTAs
641  $header_eol = "\n";
642  }
643 
644  // Windows is somewhat broken, so we use just address for to and from
645  if (strtolower(substr(PHP_OS, 0, 3)) == 'win') {
646  // strip name from to and from
647  if (strpos($to, '<')) {
648  preg_match('/<(.*)>/', $to, $matches);
649  $to = $matches[1];
650  }
651  if (strpos($from, '<')) {
652  preg_match('/<(.*)>/', $from, $matches);
653  $from = $matches[1];
654  }
655  }
656 
657  // make sure From is set
658  if (empty($headers['From'])) {
659  $headers['From'] = $from;
660  }
661 
662  // stringify headers
663  $headers_string = '';
664  foreach ($headers as $key => $value) {
665  $headers_string .= "$key: $value{$header_eol}";
666  }
667 
668  // Sanitise subject by stripping line endings
669  $subject = preg_replace("/(\r\n|\r|\n)/", " ", $subject);
670  // this is because Elgg encodes everything and matches what is done with body
671  $subject = html_entity_decode($subject, ENT_QUOTES, 'UTF-8'); // Decode any html entities
672  if (is_callable('mb_encode_mimeheader')) {
673  $subject = mb_encode_mimeheader($subject, "UTF-8", "B");
674  }
675 
676  // Format message
677  $body = html_entity_decode($body, ENT_QUOTES, 'UTF-8'); // Decode any html entities
678  $body = elgg_strip_tags($body); // Strip tags from message
679  $body = preg_replace("/(\r\n|\r)/", "\n", $body); // Convert to unix line endings in body
680  $body = preg_replace("/^From/", ">From", $body); // Change lines starting with From to >From
681  $body = wordwrap($body);
682 
683  return mail($to, $subject, $body, $headers_string);
684 }
685 
693  $method = get_input('method');
694 
695  $current_settings = get_user_notification_settings();
696 
697  $result = false;
698  foreach ($method as $k => $v) {
699  // check if setting has changed and skip if not
700  if ($current_settings->$k == ($v == 'yes')) {
701  continue;
702  }
703 
704  $result = set_user_notification_setting(elgg_get_logged_in_user_guid(), $k, ($v == 'yes') ? true : false);
705 
706  if (!$result) {
707  register_error(elgg_echo('notifications:usersettings:save:fail'));
708  }
709  }
710 
711  if ($result) {
712  system_message(elgg_echo('notifications:usersettings:save:ok'));
713  }
714 }
715 
719 function _elgg_notifications_test($hook, $type, $tests) {
720  global $CONFIG;
721  $tests[] = "{$CONFIG->path}engine/tests/ElggCoreDatabaseQueueTest.php";
722  return $tests;
723 }
724 
725 elgg_register_plugin_hook_handler('unit_test', 'system', '_elgg_notifications_test');
elgg_get_site_entity($site_guid=0)
Get an ElggSite entity (default is current site)
Definition: sites.php:18
get_input($variable, $default=null, $filter_result=true)
Get some input from variables passed submitted through GET or POST.
Definition: input.php:27
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
$method
Definition: form.php:25
$e
Definition: metadata.php:12
$object
Definition: upgrade.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:29
$return
Definition: opendd.php:15
$guid
Removes an admin notice.
elgg parse_url
Parse a URL into its parts.
Definition: elgglib.js:432
elgg_extract($key, array $array, $default=null, $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Definition: elgglib.php:1464
elgg_register_plugin_hook_handler($hook, $type, $callback, $priority=500)
Register a callback as a plugin hook handler.
Definition: elgglib.php:853
elgg_remove_subscription($user_guid, $method, $target_guid)
Unsubscribe a user to notifications about a target entity.
$action
$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.
elgg_echo($message_key, $args=array(), $language="")
Given a message key, returns an appropriately translated full-text string.
Definition: languages.php:21
$key
Definition: summary.php:34
_elgg_services()
Definition: autoloader.php:14
global $CONFIG
sanitise_string($string)
Wrapper function for alternate English spelling (.
Definition: database.php:150
elgg_extend_view($view, $view_extension, $priority=501, $viewtype= '')
Extends a view with another view.
Definition: views.php:401
$user
Definition: ban.php:13
set_user_notification_setting($user_guid, $method, $value)
Set a user notification pref.
elgg_trigger_plugin_hook($hook, $type, $params=null, $returnvalue=null)
Trigger a Plugin Hook and run all handler callbacks registered to that hook:type. ...
Definition: elgglib.php:925
elgg global
Pointer to the global context.
Definition: elgglib.js:12
elgg_get_site_url($site_guid=0)
Get the URL for the current (or specified) site.
$type
Definition: add.php:8
elgg system_message
Wrapper function for system_messages.
Definition: elgglib.js:374
elgg_register_event_handler($event, $object_type, $callback, $priority=500)
Register a callback as an Elgg event handler.
Definition: elgglib.php:669
elgg_log($message, $level= 'NOTICE')
Display or log a message.
Definition: elgglib.php:1083
_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 register_error
Wrapper function for system_messages.
Definition: elgglib.js:383
elgg_get_metadata(array $options=array())
Returns metadata.
Definition: metadata.php:282
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
$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.
$language
$vars[&#39;language&#39;] $vars[&#39;lc&#39;] if present, client will be sent long expires headers ...
Definition: languages.php:7
elgg_send_email($from, $to, $subject, $body, array $params=null)
Send an email to any email address.
$container
Definition: access.php:30
elgg_get_logged_in_user_guid()
Return the current logged in user by guid.
Definition: sessions.php:42
$actions
Provides common Elgg services.
Definition: user_hover.php:12
_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:604