You are here

function _node_expire_cron in Node expire 6

Implementation of hook_cron().

1 call to _node_expire_cron()
node_expire_cron in ./node_expire.module
Implementation of hook_cron().

File

./node_expire.cron.inc, line 13
Cron functions. Its better to remove Cron's code from .module file because it wont be needed on every single page. It reduces the module footprint (memory consumption).

Code

function _node_expire_cron() {

  // Are email notifications enabled?
  if (variable_get('node-expire-enable-email', 1) == 1) {
    $updateids = array();
    $time = time();

    // Get a list of nodes that are past the expiration threshold and also
    // haven't been notified in the selected amount of time. For the qualifying
    // data, it gets the necessary information that a user might want to
    // include in the automatic email.
    $query = db_query("SELECT a.nid, a.expire, b.title, b.changed, c.name, c.mail\n      FROM {node_expire} a\n      LEFT JOIN {node} b ON a.nid = b.nid\n      LEFT JOIN {users} c ON b.uid = c.uid\n      WHERE a.expire <= %d AND a.expiremode != %d AND a.lastnotify <= %d AND b.status = 1\n      ORDER BY c.name ASC, b.title ASC", $time, NODE_EXPIRE_NONE, $time - variable_get('node-expire-renotify', 259200));
    while ($row = db_fetch_object($query)) {

      // Has this user received an out-of-date alert this run?
      if (!isset($newnotify[$row->name])) {
        $newnotify[$row->name] = array(
          'email' => $row->mail,
        );
      }

      // Has this node/book already been processed?
      $newnotify[$row->name][$row->nid] = array(
        'nid' => $row->nid,
        'title' => $row->title,
        'expire' => $row->expire,
        'changed' => $row->changed,
      );
    }

    // Now compile the messages. There are two lines to parse the data because
    // we want to do a bulk mailing method rather than emailing once per expired node.
    if (!empty($newnotify)) {

      // The subject and cc address are always the same so let's get them out of the way first.
      $subject = variable_get('node-expire-subject', '!site - Article Update Needed');
      $subject = str_replace('!site', variable_get('site_name', 'Drupal'), $subject);
      $cc = variable_get('node-expire-cc', '');

      // Go through the list of each user that will receive an alert.
      foreach ($newnotify as $user => $node) {

        // The e-mail address is stored in the array for easy access. We don't want to
        // count this as an expired node, so let's remove it from the data list.
        $to = $node['email'];
        unset($node['email']);

        // Make sure carriage returns are in UNIX format to prevent cross-OS problems.
        $body = str_replace("\r", "", variable_get('node-expire-body', "Hello !username,\r\n\r\nThe following article(s) are in " . "need for reviewing and updating. Please update these at your earliest convenience. If no changes are necessary, " . "simply open the editor and press 'Save'.\r\n\r\n!start_section!\r\nArticle: !section_article\r\nTime since " . "update: !section_timesinceupdate\r\nEdit Link: !section_editlink\r\n\r\n!stop_section!\r\n--  !site team"));

        // Replace allowed configurable variables
        $body = str_replace('!site', variable_get('site_name', 'Drupal'), $body);
        $body = str_replace('!username', $user, $body);

        // Grab just between !start_section! and !stop_section!
        $bodysec = drupal_substr($body, strpos($body, '!start_section!') + 15, strpos($body, '!stop_section!') - strpos($body, '!start_section!') - 15);

        // We usually have !start_section!, a carriage return, and then the
        // message for the sake of looking pretty during setup. Let's remove this
        // one instance. If an extra carriage return is requested, the user should
        // put it at the end of the loop as the default value is.
        $bodysec = preg_replace("/^\n/", "", $bodysec);
        $newbody = '';

        // Scan each message and process it according to the template.
        foreach ($node as $row) {
          $temp = $bodysec;
          $temp = str_replace('!section_article', $row['title'], $temp);
          $temp = str_replace('!section_timesinceupdate', format_interval(time() - $row['changed']) . ' ago', $temp);
          $temp = str_replace('!section_lastupdate', format_date($row['changed']), $temp);
          $temp = str_replace('!section_expirydate', format_date($row['expire']), $temp);
          $temp = str_replace('!section_nodelink', url('node/' . $row['nid'], array(
            'absolute' => TRUE,
          )), $temp);
          $temp = str_replace('!section_editlink', url('node/' . $row['nid'] . '/edit', array(
            'absolute' => TRUE,
          )), $temp);

          // Record this as sent so it's only notified once per the selected threshold.
          $updateids[] = $row['nid'];
          $updateids_sql[] = '%d';
          $newbody .= $temp;
        }

        // Ensure emails are treated as mailing list posts, not junk
        $headers['Precedence'] = "list";

        // Now let's take out the template from the settings, and replace it with the parsed data.
        $params = array(
          'body' => drupal_substr($body, 0, strpos($body, '!start_section!')) . $newbody . drupal_substr($body, strpos($body, '!stop_section!') + 15),
          'subject' => $subject,
          'headers' => $headers,
        );

        // This is just to prevent problems with "Anonymous" nodes.
        if ($to) {
          drupal_mail('node_expire', 'notice', $to, language_default(), $params);
        }

        // Send it to the requested carbon copy address, if any.
        if ($cc) {
          drupal_mail('node_expire', 'notice', $cc, language_default(), $params);
        }
      }
      array_unshift($updateids, $time);

      // Record which records were updated.
      db_query('UPDATE {node_expire} SET lastnotify = %d
        WHERE nid IN(' . implode(', ', $updateids_sql) . ')', $updateids);

      // Log the event
      watchdog('node_expire', format_plural(count($updateids), 'E-mail notice submitted for node !nodes', 'E-mail notice submitted for nodes !node'), array(
        '!node' => $updateids[0],
        '!nodes' => implode(', ', $updateids),
      ), WATCHDOG_NOTICE);
    }
  }

  // We run the code to unpublish expired documents after the email communications
  // are sent out because it only queries for published documents. This way,
  // people who want documents to instantly expire can still have email
  // notifications sent out about them too.
  if (variable_get('node-expire-unpublishtime', 0)) {

    // Find old documents.
    $query = db_query("SELECT n.nid FROM {node_expire} ne\n      INNER JOIN {node} n ON n.nid = ne.nid\n      WHERE n.status = 1 AND ne.expire <= '%s' AND ne.expiremode <> %d", time() - variable_get('node-expire-unpublishtime', 0), NODE_EXPIRE_NONE);
    while ($row = db_fetch_object($query)) {
      $unpublish[] = $row->nid;
    }

    // If any records are to be unpublished, unpublish them, and
    // log it through the watchdog service.
    if (!empty($unpublish)) {
      db_query('UPDATE {node} SET status = 0
        WHERE nid IN (' . implode(', ', $unpublish) . ')');
      $message = format_plural(count($unpublish), '@count node was automatically unpublished.', '@count nodes were automatically unpublished.');
      watchdog('node_expire', $message, WATCHDOG_NOTICE);
    }
  }
}