You are here

function subscriptions_mail_cron in Subscriptions 5.2

Same name and namespace in other branches
  1. 6 subscriptions_mail.module \subscriptions_mail_cron()
  2. 7 subscriptions_mail.module \subscriptions_mail_cron()
  3. 2.0.x subscriptions_mail/subscriptions_mail.module \subscriptions_mail_cron()

Implementation of hook_cron().

Takes items from {subscriptions_queue} and generates notification emails.

File

./subscriptions_mail.module, line 13
Subscriptions module mail gateway.

Code

function subscriptions_mail_cron() {
  global $user, $locale;
  include_once drupal_get_path('module', 'subscriptions_mail') . '/subscriptions_mail.templates.inc';
  $mails_allowed = variable_get('subscriptions_number_of_mails', 0);
  $from = _subscriptions_mail_site_mail();
  $old_uid = 0;
  $single_count = 0;
  $digest_count = 0;
  $loaded_objects = array();
  $users = array();
  $fields = array();
  $mails = array();

  // Strategy for cron:
  // Use 50% of the remaining time to process queue items, send single messages, and assemble digest messages;
  // send the digest messages in the other half and hopefully leave some time for other modules.
  $total_seconds = ini_get('max_execution_time');
  $lost_seconds = timer_read('page') / 1000;
  $available_seconds = $total_seconds - $lost_seconds;

  //TEST: watchdog('cron', "Subscriptions has $available_seconds of $total_seconds seconds available.");
  while (($mails_allowed <= 0 || $single_count + count($mails) < $mails_allowed) && $total_seconds - timer_read('page') / 1000 > $available_seconds * variable_get('subscriptions_cron_percent', 50) / 100) {
    subscriptions_mail_mail_edit_variables($null = NULL);

    // clear cache
    $result = db_query_range('SELECT * FROM {subscriptions_queue} WHERE last_sent + send_interval < %d ORDER BY sqid', time(), 0, 1);
    if (!($s = db_fetch_array($result))) {
      break;

      // No more subscriptions, terminate loop.
    }
    if (!isset($users[$s['uid']])) {
      $users[$s['uid']] = user_load(array(
        'uid' => $s['uid'],
      ));
    }
    $saved_user = $user;
    session_save_session(FALSE);
    $user = $users[$s['uid']];
    $locale = locale_initialize();
    do {

      // once and repeat while adding to a digest
      if ($user->status && $user->access) {
        $cids = array();
        $load_function = $s['load_function'];
        $index = $load_args = $s['load_args'];
        if (!isset($loaded_objects[$user->uid][$load_function][$load_args])) {
          if (is_numeric($load_args)) {
            $object = $load_function($load_args, $s['sqid'], $s['is_new']);
          }
          else {
            $load_args = unserialize($load_args);
            $load_args[] = $s['is_new'];
            $object = call_user_func_array($load_function, $load_args);
          }
          if (!empty($object)) {
            $access = module_invoke_all('subscriptions', 'access', $load_function, $load_args, $object);

            // One FALSE vote is enough to deny. Also, we need a non-empty array.
            $allow = !empty($access) && array_search(FALSE, $access) === FALSE;
            $loaded_objects[$user->uid][$load_function][$index] = $allow ? $object : FALSE;
          }
        }
        if ($object = $loaded_objects[$user->uid][$load_function][$index]) {
          if (!isset($users[$object->uid])) {
            $users[$object->uid] = user_load(array(
              'uid' => $object->uid,
            ));
          }
          $sender = $users[$object->uid];
          $module = $s['module'];
          $ori_field = $field = $s['field'];
          $ori_value = $value = $s['value'];
          if (!isset($fields[$locale][$module])) {
            $fields[$locale][$module] = module_invoke_all('subscriptions', 'fields', $module);
          }
          if ($module == 'node' && $field == 'nid' && (!empty($object->_subscriptions_is_updated) || !empty($object->_subscriptions_is_new)) && user_access('subscribe to content types', $user)) {
            $unlisteds = variable_get('subscriptions_unlisted_content_types', array());
            if (isset($object->type) && !in_array($object->type, $unlisteds)) {
              $field = 'type';
              $value = $object->type;
            }
          }
          $mailvars_function = $fields[$locale][$module][$field]['mailvars_function'];
          $mailkey = 'subscriptions-' . $module . '-' . $field;
          if (!is_numeric($value)) {
            $mailkey .= '-' . $value;
          }
          $digest = $s['digest'] > 0 || $s['digest'] == -1 && _subscriptions_get_setting('digest', 0) > 0;
          if ($digest) {
            if (!($body_template = db_result(db_query("SELECT item_body FROM {subscriptions_mail_edit} WHERE mailkey = '%s'", SUBSCRIPTIONS_DIGEST_MAILKEY . '-item')))) {
              $body_template = subscriptions_mail_template('DITEM');
            }
          }
          else {
            $body_template = variable_get('subscriptions_email_body', subscriptions_mail_template('BODY'));
            $subject_template = variable_get('subscriptions_email_subject', subscriptions_mail_template('SUBJ'));
          }
          init_theme();
          $show_node_info = isset($object->type) ? theme_get_setting('toggle_node_info_' . $object->type) : TRUE;
          $base = 'user/' . $s['uid'] . '/';
          $mailvars = array(
            '!site' => variable_get('site_name', 'drupal'),
            '!sender_name' => $show_node_info ? $sender->uid ? $sender->name : variable_get('anonymous', '!sender_name') : '!sender_name',
            '!sender_page' => $show_node_info && $sender->uid ? url("user/{$sender->uid}", NULL, NULL, TRUE) : '!sender_page',
            '!sender_contact_page' => $show_node_info ? empty($sender->contact) ? t('(disabled)') : url("user/{$sender->uid}/contact", NULL, NULL, TRUE) : '!sender_contact_page',
            '!sender_has_contact_page' => $show_node_info ? empty($sender->contact) ? 0 : 1 : 0,
            '!manage_url' => url($base . 'subscriptions', NULL, NULL, TRUE),
            '!name' => $s['name'],
            '!subs_type' => $fields[$locale][$module][$field]['!subs_type'],
            '!unsubscribe_url' => url("s/del/{$module}/{$ori_field}/{$ori_value}/" . $s['author_uid'] . '/' . $s['uid'] . '/' . md5(drupal_get_private_key() . $module . $ori_field . $ori_value . $s['author_uid'] . $s['uid']), NULL, NULL, TRUE),
          );
          $mailvars_function($mailvars, $object, $field, $s);
          $mailvars += module_invoke_all('subscriptions_get_mailvars', $object);
          if ($digest && !empty($object->_subscriptions_comments) && module_exists('subscriptions_content')) {
            static $digest_comment_template;
            if (!$digest_comment_template) {
              $digest_comment_template = db_result(db_query("SELECT item_body FROM {subscriptions_mail_edit} WHERE mailkey = '%s'", SUBSCRIPTIONS_DIGEST_MAILKEY . '-item-comment'));
              $digest_comment_template = $digest_comment_template ? $digest_comment_template : subscriptions_mail_template('DITEMCMT');
            }
            $mailvars['!comments'] = _subscriptions_content_format_comments($object, $digest_comment_template, '');
          }
          $body = strtr(subscriptions_mail_template_preprocess($body_template, $mailvars), $mailvars);
          $subject = strtr(subscriptions_mail_template_preprocess($subject_template, $mailvars), $mailvars);
          if ($digest) {
            $mails[$s['uid']]['bodies'][] = $body;
            $mails[$s['uid']]['send'] = array(
              'name' => $s['name'],
              'mail' => $s['mail'],
              'from' => $from,
              '!name' => $mailvars['!name'],
              '!manage_url' => $mailvars['!manage_url'],
            );
          }
          else {
            subscriptions_mail_mail_edit_variables($mailvars);
            _subscriptions_mail_send($mailkey, $s['name'], $s['mail'], $subject, $body, $from, $s['uid']);
            ++$single_count;
          }
        }
      }
      db_query("DELETE FROM {subscriptions_queue} WHERE load_function = '%s' AND load_args = '%s' AND uid = %d", $s['load_function'], $s['load_args'], $s['uid']);
      if ($digest) {

        // TODO: Get the next queue item for this user and finish off this user's digest
        // before moving on to the next user. All messages in one digest together count
        // as one mail, and if the number of mails is limited (per cron run), we must
        // not let this cause a split up of the digest.
        // Issue: We must know which notifications to send according to their send_interval.
      }
    } while (FALSE);

    // TODO: while adding to a digest
    $user = $saved_user;
    $locale = locale_initialize();
    session_save_session(TRUE);
  }
  if ($mails) {
    static $separator;
    if (!isset($separator)) {
      $separator = db_result(db_query("SELECT item_body FROM {subscriptions_mail_edit} WHERE mailkey = '%s'", SUBSCRIPTIONS_DIGEST_MAILKEY . '-separator'));
      $separator = $separator ? $separator : subscriptions_mail_template('SEP');
    }
    session_save_session(FALSE);
    foreach ($mails as $uid => $user_mails) {
      $user = $users[$uid];
      $locale = locale_initialize();
      $s = $user_mails['send'];
      if ($templates = db_fetch_object(db_query("SELECT * FROM {mail_edit} WHERE mailkey = '%s'", SUBSCRIPTIONS_DIGEST_MAILKEY))) {
        $subject_template = $templates->subject;
        $body_template = $templates->body;
      }
      else {
        $subject_template = subscriptions_mail_template('DSUBJ');
        $body_template = subscriptions_mail_template('DBODY');
      }
      $mailvars['!bodies'] = implode($separator, $user_mails['bodies']);
      $mailvars['!name'] = $s['!name'];
      $mailvars['!manage_url'] = $s['!manage_url'];
      $subject = strtr(subscriptions_mail_template_preprocess($subject_template, $mailvars), $mailvars);
      $body = strtr(subscriptions_mail_template_preprocess($body_template, $mailvars), $mailvars);
      subscriptions_mail_mail_edit_variables($mailvars);
      _subscriptions_mail_send(SUBSCRIPTIONS_DIGEST_MAILKEY, $s['name'], $s['mail'], $subject, $body, $s['from'], $uid);
      ++$digest_count;
    }
    $user = $saved_user;
    $locale = locale_initialize();
    session_save_session(TRUE);
  }
  if ($single_count + $digest_count > 0) {
    $watchdog = 'watchdog';

    // keep potx from translating 'cron'
    $watchdog('cron', t("!module sent !single_count single and !digest_count digest notifications in !used_seconds of !available_seconds available seconds; !remaining_items queue items left.", array(
      '!module' => 'Subscriptions',
      '!single_count' => $single_count,
      '!digest_count' => $digest_count,
      '!used_seconds' => (int) (timer_read('page') / 1000 - $lost_seconds),
      '!available_seconds' => (int) $available_seconds . ($lost_seconds > 5 * $total_seconds / 100 ? " ({$total_seconds})" : ''),
      '!remaining_items' => db_result(db_query("SELECT COUNT(*) FROM {subscriptions_queue} WHERE last_sent + send_interval < %d", time())),
    )));
  }
}