You are here

function _notify_send in Notify 8

Same name and namespace in other branches
  1. 5.2 notify.module \_notify_send()
  2. 5 notify.module \_notify_send()
  3. 6 notify.module \_notify_send()
  4. 7 notify.module \_notify_send()
  5. 2.0.x notify.module \_notify_send()
  6. 1.0.x notify.module \_notify_send()

Helper function to send the notification e-mail batch.

2 calls to _notify_send()
notify_cron in ./notify.module
Implements hook_cron().
QueueForm::submitForm in src/Form/QueueForm.php
Form submission handler.

File

./notify.module, line 542
Notify module sends e-mail digests of new content and comments.

Code

function _notify_send() {
  $user = \Drupal::currentUser();
  $config = \Drupal::config('notify.settings');
  $separator = "------------------------------------------------------------------------------<br />";
  $mini_separator = "----<br />";
  $send_start = $config
    ->get('notify_send_start');
  $num_sent = 0;
  $num_fail = 0;
  list($res_nodes, $res_comms, $res_nopub, $res_copub, $res_nounp, $res_counp) = _notify_select_content();
  _notify_get_content_types($defaultlist, TRUE);

  // Get the nodes and comments queued.
  $count = 0;
  $nodes = $comments = array();

  // Ordinary nodes
  foreach ($res_nodes as $row) {
    $nodes[$row->nid] = Node::load($row->nid);
    $count++;
  }

  // Ordinary comments
  if ($res_comms) {
    foreach ($res_nopub as $row) {
      if (!isset($nodes[$row->nid])) {
        $nodes[$row->nid] = Node::load($row->nid);
        $count++;
      }
    }
    foreach ($res_comms as $row) {
      $comment = Comment::load($row->cid);
      $comments[$comment
        ->get('entity_id')->target_id][$row->cid] = $comment;
      $count++;
    }
    foreach ($res_copub as $row) {
      if (!isset($comments[$row->nid][$row->cid])) {
        $comments[$row
          ->get('entity_id')->target_id][$row->cid] = Comment::load($row->cid);
        $count++;
      }
    }
  }

  // Published nodes in unpublished queue
  foreach ($res_nopub as $row) {
    if (!isset($nodes[$row->nid])) {
      $nodes[$row->nid] = Node::load($row->nid);
      $count++;
    }
  }

  // Unpublished nodes in unpublished queue
  foreach ($res_nounp as $row) {
    if (!isset($nodes[$row->nid])) {
      $nodes[$row->nid] = Node::load($row->nid);
      $count++;
    }
  }
  if ($count) {
    $uresult = $config
      ->get('notify_users');
    if (empty($uresult)) {

      // Set up for sending a new batch. Init all variables.
      $result = \Drupal::database()
        ->select('notify', 'n');
      $result
        ->join('users', 'u', 'n.uid = u.uid');
      $result
        ->join('users_field_data', 'v', 'n.uid = v.uid');
      $result
        ->fields('u', array(
        'uid',
      ));
      $result
        ->fields('v', array(
        'name',
        'mail',
      ));
      $result
        ->fields('n', array(
        'node',
        'teasers',
        'comment',
        'status',
      ));
      $result
        ->condition('v.status', 1);
      $result
        ->condition('n.status', 1);
      $result
        ->condition('n.attempts', 5, '<=');
      $result->allowRowCount = TRUE;
      $uresult = $result
        ->execute()
        ->fetchAll(PDO::FETCH_ASSOC);
      \Drupal::configFactory()
        ->getEditable('notify.settings')
        ->set('notify_send_start', \Drupal::time()
        ->getRequestTime())
        ->set('notify_users', $uresult)
        ->set('notify_num_sent', 0)
        ->set('notify_num_failed', 0)
        ->save();
    }
    $batchlimit = $config
      ->get('notify_batch');
    $batchcount = 0;

    // Allow to safely impersonate the recipient so that the node is rendered
    // with correct field permissions.
    $original_user = $user;

    //TODO: Fix drupal_save_session() issue
    if (NULL !== $config
      ->get('notify_skip_nodes')) {
      $notify_skip_nodes = $config
        ->get('notify_skip_nodes');
    }
    else {
      $notify_skip_nodes = array();
    }
    if (NULL !== $config
      ->get('notify_skip_comments')) {
      $notify_skip_comments = $config
        ->get('notify_skip_comments');
    }
    else {
      $notify_skip_comments = [];
    }
    foreach ($uresult as $index => $userrow) {
      if (++$batchcount > $batchlimit) {
        break;
      }
      $userobj = User::load($userrow['uid']);

      // Intentionally replacing the Global $user.
      $user = $userobj;
      $upl = $userobj
        ->getPreferredLangcode();
      $node_body = $comment_body = '';

      // Consider new node content if user has permissions and nodes are ready.
      // $userrow['node']: user subscribes to nodes.
      if ($userrow['node'] && $userobj
        ->hasPermission('access content') && count($nodes)) {
        $node_count = 0;

        // Look at the node
        foreach ($nodes as $node) {

          // Skip to next if skip flag set for node.
          if (in_array($node
            ->id(), $notify_skip_nodes)) {
            continue;
          }

          // Skip to next if user is not allowed to view this node.
          if (!$userobj
            ->hasPermission('administer nodes') && 0 == $node
            ->isPublished()) {
            continue;
          }
          if (!$userobj
            ->hasPermission('administer nodes') && !in_array($node
            ->getType(), $defaultlist)) {
            continue;
          }
          if (!$config
            ->get('notify_unpublished') && 0 == $node
            ->isPublished()) {
            continue;
          }
          if (!$node
            ->access('view', $userobj)) {
            continue;
          }
          if (_notify_user_has_subscriptions($userrow['uid'])) {

            // Custom subscriptions exists, use those.
            $field = \Drupal::database()
              ->select('notify_subscriptions', 'n')
              ->fields('n', array(
              'uid',
              'type',
            ))
              ->condition('uid', $userrow['uid'])
              ->condition('type', $node
              ->getType())
              ->execute()
              ->fetchObject();
            $default = $field ? TRUE : FALSE;
            if (!$default) {
              continue;
            }
          }
          $ml_level = $config
            ->get('notify_multilingual');
          if (!$userobj
            ->hasPermission('administer notify')) {
            if ($ml_level && $node->tnid) {
              if ($node->language != $upl) {
                continue;
              }
            }
            if (2 == $ml_level && 0 == $node->tnid && 'und' != $node->language) {
              continue;
            }
            $ignore_unverified = $config
              ->get('notify_unverified');
            if ($ignore_unverified && !$node->uid) {
              continue;
            }
          }
          $node_revs_list = \Drupal::entityTypeManager()
            ->getStorage('node')
            ->revisionIds($node);
          $nrl_vals = array_values($node_revs_list);
          $vers = array_shift($nrl_vals);
          $node_revision = \Drupal::entityTypeManager()
            ->getStorage('node')
            ->loadRevision($vers);
          $node_body .= '<strong>' . ++$node_count . '.</strong> ' . $node
            ->label() . '. ';
          if (count($node_revs_list) > 1) {
            $update = '(' . t('last updated by @author', array(
              '@author' => $node_revision
                ->getOwner()
                ->getDisplayName() ? $node_revision
                ->getOwner()
                ->getDisplayName() : $config
                ->get('anonymous'),
            ), array(
              'langcode' => $upl,
            )) . ') ';
          }
          else {
            $update = '';
          }
          if ($userobj
            ->hasPermission('administer nodes')) {
            $status = $node
              ->isPublished() == 1 ? t('[Published]', array(), array(
              'langcode' => $upl,
            )) : t('[Unpublished]', array(), array(
              'langcode' => $upl,
            ));
          }
          else {
            $status = '';
          }
          $alias = \Drupal::languageManager()
            ->isMultilingual() ? TRUE : FALSE;
          $options = array(
            'alias' => $alias,
            'attributes' => [
              'class' => [
                'read-more',
              ],
            ],
            'absolute' => TRUE,
          );
          $link = Link::fromTextAndUrl(t('Read more'), Url::fromUri('internal:/node/' . $node
            ->id(), $options))
            ->toString();
          $node_body .= $link;
          $node_body .= _notify_content($node, NULL, $userrow['teasers']) . "<br />";
        }

        // Prepend e-mail header as long as user could access at least one node.
        if ($node_count > 0) {
          $node_body = '<h3>' . t('Recent nodes - @count', array(
            '@count' => \Drupal::translation()
              ->formatPlural($node_count, '1 new post', '@count new posts', array(), array(
              'langcode' => $upl,
            )),
          ), array(
            'langcode' => $upl,
          )) . "<br />" . '</h3>' . $node_body;
        }
      }

      // Consider new comments if user has permissions and comments are ready.
      if ($userrow['comment'] && $userobj
        ->hasPermission('access comments') && count($comments)) {
        $total_comment_count = 0;
        $node_comment_count = 0;

        // Look at the comment
        foreach ($comments as $nid => $value) {

          // If we don't already have the node, fetch it.
          if (isset($nodes[$nid])) {
            $node = $nodes[$nid];
          }
          else {
            $node = \Drupal::entityTypeManager()
              ->getStorage('node')
              ->load($nid);
          }
          if (!$node
            ->access('view', $userobj)) {
            continue;
          }
          $comment_count = 0;
          $onecomment = '';

          // Look at the comment
          foreach ($value as $commobj) {
            if (in_array($commobj
              ->id(), $notify_skip_comments)) {
              continue;
            }
            if (!$userobj
              ->hasPermission('administer comments') && 0 == $commobj
              ->isPublished()) {
              continue;
            }
            if (!$userobj
              ->hasPermission('administer comments') && !in_array($node
              ->getType(), $defaultlist)) {
              continue;
            }
            if (!$config
              ->get('notify_unpublished') && 0 == $commobj
              ->isPublished()) {
              continue;
            }

            // Determine whether to show comment status.
            if ($userobj
              ->hasPermission('administer comments')) {
              $status = $commobj
                ->isPublished() == 1 ? t('[Published]', array(), array(
                'langcode' => $upl,
              )) : t('[Unpublished]', array(), array(
                'langcode' => $upl,
              ));
            }
            else {
              $status = '';
            }
            $options = array(
              'attributes' => [
                'class' => [
                  'read-more',
                ],
              ],
              'fragment' => 'comment-' . $commobj
                ->id(),
              'absolute' => TRUE,
            );
            $link = Link::fromTextAndUrl(t('Read more'), Url::fromUri('internal:/node/' . $nid, $options))
              ->toString();
            $options2 = array(
              'attributes' => [
                'class' => [
                  'read-more',
                ],
              ],
              'fragment' => 'comments-title',
              'absolute' => TRUE,
            );
            $shortlink = Link::fromTextAndUrl(t('Read more'), Url::fromUri('internal:/node/' . $nid, $options2))
              ->toString();
            $onecomment .= '   ' . ++$comment_count . '. ' . t('@title by @author @status', array(
              '@title' => $commobj
                ->label(),
              '@author' => $commobj
                ->getOwner()
                ->getDisplayName() ? $commobj
                ->getOwner()
                ->getDisplayName() : \Drupal::config('anonymous'),
              '@status' => $status,
            ), array(
              'langcode' => $upl,
            )) . $link . "<br />";
            $total_comment_count++;
            $onecomment .= _notify_content($node, $commobj, $userrow['teasers']);
          }
          if ($comment_count) {
            $comment_body .= '<strong>' . ++$node_comment_count . '.</strong> ';
            $comment_body .= t('@title <span class="counter">(@count)</span>', array(
              '@count' => \Drupal::translation()
                ->formatPlural($comment_count, '1 new comment', '@count new comments'),
              '@title' => $node
                ->label(),
              '@type' => $node->type->entity
                ->label(),
              '@author' => $node
                ->getOwner()
                ->getDisplayName() ? $node
                ->getOwner()
                ->getDisplayName() : \Drupal::config('anonymous'),
            ), array(
              'langcode' => $upl,
            )) . ' ' . (isset($shortlink) ? $shortlink : '') . "<br />";
          }
        }
        if ($total_comment_count > 0) {
          $comment_body = '<h3>' . t('Recent comments - @count', array(
            '@count' => \Drupal::translation()
              ->formatPlural($total_comment_count, '1 new comment', '@count new comments'),
          ), array(
            'langcode' => $upl,
          )) . "<br />" . '</h3>' . $comment_body;
        }
      }
      $body = $node_body . $comment_body;

      // If there was anything new, send mail.
      if ($body) {
        $watchdog_level = $config
          ->get('notify_watchdog');
        if (\Drupal::service('plugin.manager.mail')
          ->mail('notify', 'notice', $userrow['mail'], $upl, array(
          'content' => $body,
          'user' => $userobj,
          'viewmode' => $userrow['teasers'],
        ), NULL, true)) {
          if ($watchdog_level == 0) {
            \Drupal::logger('notify')
              ->notice('User %name (%mail) notified successfully.', array(
              '%name' => $userrow['name'],
              '%mail' => $userrow['mail'],
            ));
          }
          $num_sent++;
        }
        else {
          $num_fail++;
          $q = \Drupal::database()
            ->update('notify');
          $q
            ->expression('attempts', 'attempts + 1');
          $q
            ->condition('uid', $userrow['uid']);
          $q
            ->execute();
          if ($watchdog_level <= 2) {
            \Drupal::logger('notify')
              ->notice('User %name (%mail) could not be notified. Mail error.', array(
              '%name' => $userrow['name'],
              '%mail' => $userrow['mail'],
            ));
          }
        }
      }
      unset($uresult[$index]);
      \Drupal::configFactory()
        ->getEditable('notify.settings')
        ->set('notify_users', $uresult)
        ->save();
    }

    // Restore the original user session.
    $user = $original_user;
  }
  $users = $config
    ->get('notify_users');
  $rest = $users ? count($users) : 0;

  // If $rest is empty, then set notify_send_last.
  if (!$rest) {
    $send_start = $config
      ->get('notify_send_start');
    \Drupal::configFactory()
      ->getEditable('notify.settings')
      ->set('notify_send_last', $send_start)
      ->set('notify_cron_next', 0)
      ->save();
    list($res_nodes, $res_comms, $res_nopub, $res_copub, $res_nounp, $res_counp) = _notify_select_content();
    foreach ($res_nopub as $row) {
      $q = \Drupal::database()
        ->delete('notify_unpublished_queue');
      $q
        ->condition('cid', 0);
      $q
        ->condition('nid', $row->nid);
      $q
        ->execute();
    }
    if ($res_copub) {
      foreach ($res_copub as $row) {
        $q = \Drupal::database()
          ->delete('notify_unpublished_queue');
        $q
          ->condition('cid', $row->cid);
        $q
          ->condition('nid', $row->nid);
        $q
          ->execute();
      }
    }
  }
  return array(
    $num_sent,
    $num_fail,
  );
}