You are here

message_subscribe_example.module in Message Subscribe 8

Holds hook implementation for the Message Subscribe Example module.

File

message_subscribe_example/message_subscribe_example.module
View source
<?php

/**
 * @file
 * Holds hook implementation for the Message Subscribe Example module.
 */
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\node\Entity\Node;
use Drupal\comment\Entity\Comment;
use Drupal\user\Entity\User;
use Drupal\message\Entity\Message;
use Drupal\message\MessageInterface;
use Drupal\message_subscribe\Subscribers\DeliveryCandidate;

/**
 * Implements hook_message_subscribe_get_subscribers_alter().
 *
 * Alter the subscribers list.
 *
 * @param \Drupal\message_subscribe\Subscribers\DeliveryCandidateInterface[] &$uids
 *   The array of delivery candidates as defined by
 *   `hook_message_subscribe_get_subscribers()`.
 * @param array $values
 *   A keyed array of values containing:
 *   - 'context' - The context array.
 *   - 'entity_type' - The entity type ID.
 *   - 'entity' - The entity object
 *   - 'subscribe_options' - The subscribe options array.
 */
function message_subscribe_example_message_subscribe_get_subscribers_alter(array &$uids, array $values) {

  // Update each subscriber to use the only available delivery method, email.
  // This code could be adjusted later if other delivery methods are added.
  // For instance, you could add a field to the user to allow each user to
  // set their own preferred notification method, then implement it here.
  // Alternatively, enable the message_subscription_email module and skip this
  // line. That module will create a second 'email' flag on each piece of
  // content and then require users to select both 'subscribe' and 'email' if
  // they want to be notified by email. But if we want everyone to be notified
  // by email skipping that module and doing it this way is simpler all around.
  foreach ($uids as $uid => $delivery_candidate) {
    $delivery_candidate
      ->addNotifier('email');
  }

  // Add administrators to every subscription list. Doing it this way
  // means they won't be able to unsubscribe, so use this judiciously.
  // Perhaps create a special role for users who should always be subscribed
  // to everything so that role can be removed for those who don't want this.
  // There are other ways to solve this problem. You could automatically flag
  // them to all new content in hook_ENTITY_TYPE_insert(), or send messages to
  // a custom list (see hook_user_insert() below). This is just an
  // illustration of another solution.
  $query = \Drupal::entityQuery('user')
    ->condition('status', 1);
  $query
    ->condition('roles', 'administrators');
  $admin_uids = $query
    ->execute();
  foreach ($admin_uids as $uid) {
    $uids[$uid] = new DeliveryCandidate([], [
      'email',
    ], $uid);
  }
  return $uids;
}

/**
 * Implements hook_node_insert().
 */
function message_subscribe_example_node_insert(Node $node) {
  $subscribers = \Drupal::service('message_subscribe.subscribers');

  // Add a message for the node author.
  $template = $node
    ->isPublished() ? 'publish_node' : 'create_node';
  $message = Message::create([
    'template' => $template,
    'uid' => $node
      ->getOwnerId(),
  ]);
  $message
    ->set('field_node_reference', $node);
  $message
    ->set('field_published', $node
    ->isPublished());
  $message
    ->save();

  // Automatically subscribe all active users to new articles. They can
  // unsubscribe later if they want to. This is one work-around to the
  // fact that nobody can subscribe to content until it's published, so they
  // won't otherwise get notified about new content.
  // You could create a field on the user profile where users could choose
  // whether to be automatically subscribed to new content, then check the
  // value of that field here before flagging them.
  if (in_array($node
    ->bundle(), [
    'article',
  ])) {

    // Find all active users.
    $query = \Drupal::entityQuery('user')
      ->condition('status', 1);
    $uids = $query
      ->execute();
    $users = User::loadMultiple($uids);

    // Add a content subscription flag for each user.
    // If there are a lot of users this should probably be queued, which would
    // require more custom code. For this example we'll assume the list is
    // a manageable size.
    $flag_service = \Drupal::service('flag');
    foreach ($users as $account) {
      $flag_id = 'subscribe_node';
      $flag = $flag_service
        ->getFlagById($flag_id);

      // Check if already flagged to avoid exception error.
      $flagging = $flag_service
        ->getFlagging($flag, $node, $account);
      if (!$flagging) {
        $flag_service
          ->flag($flag, $node, $account);
      }
    }
  }

  // Do nothing more for unpublished nodes.
  if (!$node
    ->isPublished()) {
    return;
  }

  // Queue messages to notify all the node subscribers about published node.
  $subscribers
    ->sendMessage($node, $message);
}

/**
 * Implements hook_node_update().
 */
function message_subscribe_example_node_update(Node $node) {
  $notifier = \Drupal::service('message_notify.sender');
  $subscribers = \Drupal::service('message_subscribe.subscribers');

  // Match publication status of message to status of source entity.
  message_subscribe_example_update_message_status($node);

  // Create a message for the node author.
  // See if this is a newly-published node.
  if ($node
    ->isPublished() && !empty($node->original) && !$node->original
    ->isPublished()) {
    $template = 'publish_node';
  }
  else {
    $template = 'update_node';
  }
  $message = Message::create([
    'template' => $template,
    'uid' => $node
      ->getOwnerId(),
  ]);
  $message
    ->set('field_node_reference', $node);
  $message
    ->set('field_published', $node
    ->isPublished());
  $message
    ->save();

  // Immediately notify message creator (node author) about update.
  // This is probably most interesting if someone else made updated or
  // published it.
  $notifier
    ->send($message, [], 'email');

  // Do nothing more for unpublished node.
  if (!$node
    ->isPublished()) {
    return;
  }

  // Queue messages to the regular node subscribers about changes in published
  // nodes.
  $subscribers
    ->sendMessage($node, $message);
}

/**
 * Implements hook_comment_insert().
 */
function message_subscribe_example_comment_insert(Comment $comment) {
  $notifier = \Drupal::service('message_notify.sender');
  $subscribers = \Drupal::service('message_subscribe.subscribers');

  // Create a message for the node author.
  $node = $comment
    ->get('entity_id')
    ->first()
    ->get('entity')
    ->getTarget()
    ->getValue();
  $message = Message::create([
    'template' => 'create_comment',
    'uid' => $node
      ->getOwnerId(),
  ]);
  $message
    ->set('field_comment_reference', $comment);
  $message
    ->set('field_published', $comment
    ->isPublished());
  $message
    ->save();

  // Immediately notify message creator (node author) about new comment.
  $notifier
    ->send($message, [], 'email');

  // Queue messages to notify all the node subscribers about new comment.
  $subscribers
    ->sendMessage($comment, $message);
}

/**
 * Implements hook_user_insert().
 */
function message_subscribe_example_user_insert(User $account) {
  $subscribers = \Drupal::service('message_subscribe.subscribers');

  // Create a custom subscriber list to notify administrators about new users.
  // This is an end run around the normal flag subscription system.
  // Hard-coding 'uids' in $subscribe_options will cause message_subscribe to
  // skip other subscribers and send to just this list, so this allows us
  // to create a custom subscription list for this purpose.
  // This is not needed if you're automatically adding administrators in either
  // hook_subscribe_get_subscribers() or hook_subscribe_get_subscribers_alter(),
  // or if you're automatically flagging administrators. It's just another
  // illustration of things that can be done.
  $query = \Drupal::entityQuery('user')
    ->condition('status', 1);
  $query
    ->condition('roles', 'administrator');
  $admin_uids = $query
    ->execute();
  $flags = [
    'subscribe_user',
  ];
  $notifiers = [
    'email',
  ];
  $notify_options = [];
  $subscribe_options = [
    'notify message owner' => FALSE,
    'uids' => [],
  ];
  foreach ($admin_uids as $uid) {
    $subscribe_options['uids'][$uid] = new DeliveryCandidate($flags, $notifiers, $uid);
  }

  // Queue messages to our custom list of subscribers.
  $message = Message::create([
    'template' => 'user_register',
    'uid' => $account
      ->id(),
  ]);
  $message
    ->set('field_user', $account);
  $message
    ->set('field_published', $account
    ->isActive());
  $message
    ->save();
  $subscribers
    ->sendMessage($account, $message, $notify_options, $subscribe_options);
}

/**
 * Set message entity published field when it changes in the related entity.
 *
 * @param \Drupal\Core\Entity\ContentEntityBase $entity
 *   The entity object.
 */
function message_subscribe_example_update_message_status(ContentEntityBase $entity) {
  if (!empty($entity->original) && $entity
    ->isPublished() == $entity->original
    ->isPublished()) {
    return;
  }
  $query = \Drupal::entityQuery('message');
  $field = 'field_' . $entity
    ->getEntityType()
    ->id() . '_reference';
  $query
    ->condition($field . '.target_id', $entity
    ->id());
  $results = $query
    ->execute();
  if (empty($results)) {
    return;
  }
  $messages = Message::loadMultiple($results);
  foreach ($messages as $message) {
    $message
      ->set('field_published', $entity
      ->isPublished());
    $message
      ->save();
  }
}

Functions

Namesort descending Description
message_subscribe_example_comment_insert Implements hook_comment_insert().
message_subscribe_example_message_subscribe_get_subscribers_alter Implements hook_message_subscribe_get_subscribers_alter().
message_subscribe_example_node_insert Implements hook_node_insert().
message_subscribe_example_node_update Implements hook_node_update().
message_subscribe_example_update_message_status Set message entity published field when it changes in the related entity.
message_subscribe_example_user_insert Implements hook_user_insert().