You are here

auto_expire.module in Auto Expire 5

Same filename and directory in other branches
  1. 7 auto_expire.module

File

auto_expire.module
View source
<?php

require_once 'auto_expire.inc';

// hook_perm
function auto_expire_perm() {
  return array(
    ADMINISTER_AUTO_EXPIRE,
    EXTEND_AUTO_EXPIRE_OWN,
    EXTEND_AUTO_EXPIRE_ALL,
  );
}

// hook_help
function auto_expire_help($section) {
  switch ($section) {
    case 'admin/help#auto_expire':
    case 'admin/modules#description':
      return t('Expires nodes automatically.');
      break;
  }
}

// hook_menu
function auto_expire_menu($may_cache) {
  $items = array();
  if ($may_cache) {
  }
  else {
    $items[] = array(
      'path' => 'admin/settings/auto_expire',
      'title' => t('Auto Expire'),
      'description' => t('Set node types that auto expire.'),
      'callback' => 'drupal_get_form',
      'callback arguments' => '_auto_expire_admin_settings',
      'access' => user_access(ADMINISTER_AUTO_EXPIRE),
      'type' => MENU_NORMAL_ITEM,
    );
    if (arg(0) == 'node' && is_numeric(arg(1))) {
      $node = node_load(arg(1));
      if (_auto_expire_is_expiring_node($node)) {
        $items[] = array(
          'path' => 'node/' . $node->nid . '/expiry',
          'title' => t('Extend'),
          'description' => t('See and extend the expiry period.'),
          'callback' => 'drupal_get_form',
          'callback arguments' => array(
            '_auto_expire_expiry',
            $node->nid,
          ),
          'access' => _auto_expire_can_user_extend($node),
          'type' => MENU_LOCAL_TASK,
          'weight' => 10,
        );
      }
    }
  }
  return $items;
}
function _auto_expire_is_expiring_node($node) {
  return variable_get(AUTO_EXPIRE_NODE_TYPE . $node->type . '_e', 0);
}
function _auto_expire_can_user_extend($node) {
  global $user;
  return user_access(EXTEND_AUTO_EXPIRE_ALL) || user_access(EXTEND_AUTO_EXPIRE_OWN) && $user->uid > 0 && $node->uid == $user->uid;
}
function _auto_expire_expiry($nid) {
  $node = node_load($nid);
  drupal_set_title(check_plain($node->title));
  $expire = _auto_expire_get_expire($node->nid);
  $code = AUTO_EXPIRE_NODE_TYPE . $node->type;
  $warn = variable_get($code . '_w', AUTO_EXPIRE_WARN);
  $form['nid'] = array(
    '#type' => 'value',
    '#value' => $nid,
  );
  $form['expireson'] = array(
    '#value' => '<p>' . t('!title will expire on !date<br />that is in !interval.', array(
      '!title' => $node->title,
      '!date' => format_date($expire),
      '!interval' => format_interval($expire - time()),
    )) . '</p>',
  );
  if (time() > $expire - $warn * 24 * 60 * 60) {
    $days = variable_get($code . '_d', AUTO_EXPIRE_DAYS);
    $form['extendby'] = array(
      '#value' => '<p>' . format_plural($days, 'You can extend it with 1 day.', 'You can extend it with @count days.') . '</p>',
    );
    $form['extend'] = array(
      '#type' => 'submit',
      '#value' => t('Extend'),
    );
  }
  else {
    $form['extendwhen'] = array(
      '#value' => '<p>' . format_plural($warn, 'You will be able to extend this 24 hours before the expiry time.', 'You will be able to extend this @count days before the expiry time.') . ' ' . t('You will receive an email notification at that time.') . '</p>',
    );
  }
  return $form;
}
function _auto_expire_expiry_submit($form_id, $form_values) {
  $op = $form_values['op'];
  $node = node_load($form_values['nid']);
  switch ($op) {
    case t('Extend'):
      $days = variable_get(AUTO_EXPIRE_NODE_TYPE . $node->type . '_d', AUTO_EXPIRE_DAYS);
      db_query('UPDATE {auto_expire} SET expire = %d, extended = extended + 1, warned = 0 WHERE nid = %d', time() + $days * 24 * 60 * 60, $node->nid);
      db_query('UPDATE {node} SET status = 1 WHERE nid = %d', $node->nid);
      watchdog('auto_expire', "Extended node {$node->nid} by {$days} days", WATCHDOG_NOTICE);
      drupal_set_message(t('Extended for !days more days', array(
        '!days' => $days,
      )));
      break;
  }
  return "node/{$node->nid}/expiry";
}
function _auto_expire_admin_settings() {
  $form = array();
  foreach (node_get_types() as $type => $name) {
    $code = AUTO_EXPIRE_NODE_TYPE . $type;
    $form['nodetypes'][$type] = array(
      '#type' => 'fieldset',
      '#title' => $name->name,
      '#collapsible' => TRUE,
      '#collapsed' => !variable_get($code . '_e', 0),
    );
    $form['nodetypes'][$type][$code . '_e'] = array(
      '#type' => 'checkbox',
      '#title' => t('Expire'),
      '#return_value' => 1,
      '#default_value' => variable_get($code . '_e', 0),
    );
    $form['nodetypes'][$type][$code . '_d'] = array(
      '#type' => 'textfield',
      '#title' => t('Days'),
      '#field_suffix' => t('days'),
      '#return_value' => 1,
      '#default_value' => variable_get($code . '_d', AUTO_EXPIRE_DAYS),
      '#description' => t('Number of days after an item was created when it will be automatically expired.'),
    );
    $form['nodetypes'][$type][$code . '_w'] = array(
      '#type' => 'textfield',
      '#title' => t('Warn'),
      '#field_suffix' => t('days'),
      '#return_value' => 1,
      '#default_value' => variable_get($code . '_w', AUTO_EXPIRE_WARN),
      '#description' => t('Number of days before the items expiration when a warning message is sent to the user. Set to 0 (zero) for no warnings.'),
    );
    $form['nodetypes'][$type][$code . '_p'] = array(
      '#type' => 'textfield',
      '#title' => t('Purge'),
      '#field_suffix' => t('days'),
      '#return_value' => 1,
      '#default_value' => variable_get($code . '_p', AUTO_EXPIRE_PURGE),
      '#description' => t('Number of days after an item has expired when it will be purged from the database. Set to 0 (zero) for no purge.'),
    );
  }
  $form['email']['warn'] = array(
    '#type' => 'fieldset',
    '#title' => t('Expiration Warning Notification Email'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#description' => t("Template of email sent when content is about to expire. You can use the following variables:!type - content type, !title - title of content, !url - URL of content, !days - number of days before it expired, !site - site name, !siteurl - site URL"),
  );
  $form['email']['warn'][AUTO_EXPIRE_EMAIL . 'warn_subject'] = array(
    '#type' => 'textfield',
    '#title' => t('Email Subject'),
    '#description' => t('Leave empty to disable Expiration Warning Notifications.'),
    '#return_value' => 1,
    '#default_value' => variable_get(AUTO_EXPIRE_EMAIL . 'warn_subject', t('!type about to expire')),
  );
  $form['email']['warn'][AUTO_EXPIRE_EMAIL . 'warn_body'] = array(
    '#type' => 'textarea',
    '#title' => t('Email Body'),
    '#return_value' => 1,
    '#default_value' => variable_get(AUTO_EXPIRE_EMAIL . 'warn_body', t("Your !type listing '!title' will expire in !days days.\n\nPlease visit !site if you want to renew:\n!url")),
  );
  $form['email']['expired'] = array(
    '#type' => 'fieldset',
    '#title' => t('Expired Notification Email'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#description' => t("Template of email sent right after the content has expired. You can use the following variables:!type - content type, !title - title of content, !site - site name, !siteurl - site URL"),
  );
  $form['email']['expired'][AUTO_EXPIRE_EMAIL . 'expired_subject'] = array(
    '#type' => 'textfield',
    '#title' => t('Email Subject'),
    '#description' => t('Leave empty to disable Expired Notifications.'),
    '#return_value' => 1,
    '#default_value' => variable_get(AUTO_EXPIRE_EMAIL . 'expired_subject', t('!type has expired')),
  );
  $form['email']['expired'][AUTO_EXPIRE_EMAIL . 'expired_body'] = array(
    '#type' => 'textarea',
    '#title' => t('Email Body'),
    '#return_value' => 1,
    '#default_value' => variable_get(AUTO_EXPIRE_EMAIL . 'expired_body', t("Your !type listing '!title' has expired.\n\nPlease visit !site to add new content:\n!siteurl")),
  );
  $form['email']['cc'][AUTO_EXPIRE_EMAIL . 'bcc'] = array(
    '#type' => 'textfield',
    '#title' => t('BCC Address'),
    '#description' => t('An e-mail address to blind carbon copy notifications.'),
    '#return_value' => 1,
    '#default_value' => variable_get(AUTO_EXPIRE_EMAIL . 'bcc', ''),
  );
  return system_settings_form($form);
}

// hook_cron
function auto_expire_cron() {
  foreach (node_get_types() as $type => $name) {
    $code = AUTO_EXPIRE_NODE_TYPE . $type;
    if (variable_get($code . '_e', 0)) {
      $days = variable_get($code . '_d', AUTO_EXPIRE_DAYS);
      $warn = variable_get($code . '_w', AUTO_EXPIRE_WARN);
      $purge = variable_get($code . '_p', AUTO_EXPIRE_PURGE);

      // Send out expiration warnings
      if ($warn > 0) {
        $subject = variable_get(AUTO_EXPIRE_EMAIL . 'warn_subject', '');
        $body = variable_get(AUTO_EXPIRE_EMAIL . 'warn_body', '');
        switch ($GLOBALS['db_type']) {
          case 'mysql':
          case 'mysqli':
            $result = db_query('SELECT n.nid, n.title FROM {auto_expire} e, {node} n WHERE n.nid = e.nid AND n.status = 1 AND e.warned = 0 AND (FROM_UNIXTIME(e.expire) - INTERVAL %d DAY) <= NOW()', $warn);
            break;
          case 'pgsql':
            $result = db_query('SELECT n.nid, n.title FROM {auto_expire} e, {node} n WHERE n.nid = e.nid AND n.status = 1 AND e.warned = 0 AND ((e.expire::ABSTIME::TIMESTAMP) - INTERVAL \'%d DAYS\') <= NOW()', $warn);
            break;
        }
        while ($node = db_fetch_object($result)) {
          _auto_expire_notify_warning($node->nid, $node->title, $name->name, $days, $subject, $body);
          db_query('UPDATE {auto_expire} SET warned = 1 WHERE nid = %d', $node->nid);
          watchdog('auto_expire', 'Auto expire warning for node ' . $node->nid, WATCHDOG_NOTICE);
        }
      }

      // Expire
      $subject = variable_get(AUTO_EXPIRE_EMAIL . 'expired_subject', '');
      $body = variable_get(AUTO_EXPIRE_EMAIL . 'expired_body', '');
      switch ($GLOBALS['db_type']) {
        case 'mysql':
        case 'mysqli':
          $result = db_query('SELECT n.nid, n.title FROM {auto_expire} e, {node} n WHERE n.nid = e.nid AND n.status = 1 AND FROM_UNIXTIME(e.expire) <= NOW()');
          break;
        case 'pgsql':
          $result = db_query('SELECT n.nid, n.title FROM {auto_expire} e, {node} n WHERE n.nid = e.nid AND n.status = 1 AND (e.expire::ABSTIME::TIMESTAMP) <= NOW()');
          break;
      }
      while ($node = db_fetch_object($result)) {
        db_query('UPDATE {node} SET status = 0 WHERE nid = %d', $node->nid);
        _auto_expire_notify_expired($node->nid, $node->title, $name->name, $subject, $body);
        watchdog('auto_expire', 'Unpublishing node ' . $node->nid, WATCHDOG_NOTICE);
      }

      // Purge
      if ($purge > 0) {
        switch ($GLOBALS['db_type']) {
          case 'mysql':
          case 'mysqli':
            $result = db_query('SELECT e.nid FROM {auto_expire} e, {node} n WHERE n.nid = e.nid AND n.status = 0 AND (FROM_UNIXTIME(e.expire) + INTERVAL %d DAY) <= NOW()', $purge);
            break;
          case 'pgsql':
            $result = db_query('SELECT e.nid FROM {auto_expire} e, {node} n WHERE n.nid = e.nid AND n.status = 0 AND ((e.expire::ABSTIME::TIMESTAMP) + INTERVAL \'%d DAYS\') <= NOW()', $purge);
            break;
        }
        $cntPurged = 0;
        while ($nid = db_result($result)) {
          $node = node_load($nid);

          /* copied from node_delete - to bypass node_access - cache_clear_all moved outside the loop */
          db_query('DELETE FROM {node} WHERE nid = %d', $nid);
          db_query('DELETE FROM {node_revisions} WHERE nid = %d', $nid);

          // Call the node-specific callback (if any):
          node_invoke($node, 'delete');
          node_invoke_nodeapi($node, 'delete');

          // Remove this node from the search index if needed.
          if (function_exists('search_wipe')) {
            search_wipe($nid, 'node');
          }

          /* end of copy */
          watchdog('auto_expire', "Auto expire purged node: {$nid}", WATCHDOG_NOTICE);
          $cntPurged++;
        }
        if ($cntPurged > 0) {

          // Clear the cache so an anonymous poster can see the node being deleted.
          cache_clear_all();
          watchdog('auto_expire', "Auto expire purged {$cntPurged} node(s).", WATCHDOG_NOTICE);
        }
      }
    }
  }
}

// hook_nodeapi
function auto_expire_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  $code = AUTO_EXPIRE_NODE_TYPE . $node->type;
  if (variable_get($code . '_e', 0)) {
    switch ($op) {
      case 'insert':
        $days = variable_get($code . '_d', 0);
        db_query('INSERT INTO {auto_expire} (nid, expire) VALUES (%d, %d)', $node->nid, $node->created + $days * 24 * 60 * 60);
        drupal_set_message(t('This %type will autoexpire in %days days.', array(
          '%type' => node_get_types('name', $node),
          '%days' => $days,
        )));
        break;
      case 'delete':
        db_query('DELETE FROM {auto_expire} WHERE nid = %d', $node->nid);
        break;
    }
  }
}

// hook_node_type
function auto_expire_node_type($op, $info) {
  switch ($op) {
    case 'delete':
      $code = AUTO_EXPIRE_NODE_TYPE . $info->type;
      variable_del($code . '_e');
      variable_del($code . '_d');
      variable_del($code . '_w');
      variable_del($code . '_p');
      break;
    case 'update':
      if (!empty($info->old_type) && $info->old_type != $info->type) {
        $code_old = AUTO_EXPIRE_NODE_TYPE . $info->old_type;
        $code_new = AUTO_EXPIRE_NODE_TYPE . $info->type;
        $expire = variable_get($code_old . '_e', 0);
        $days = variable_get($code_old . '_d', AUTO_EXPIRE_DAYS);
        $warn = variable_get($code_old . '_w', AUTO_EXPIRE_WARN);
        $purge = variable_get($code_old . '_p', AUTO_EXPIRE_PURGE);
        variable_set($code_new . '_e', $expire);
        variable_set($code_new . '_d', $days);
        variable_set($code_new . '_w', $warn);
        variable_set($code_new . '_p', $purge);
        variable_del($code_old . '_e');
        variable_del($code_old . '_d');
        variable_del($code_old . '_w');
        variable_del($code_old . '_p');
      }
      break;
  }
}
function _auto_expire_notify_warning($nid, $title, $type, $days, $subject, $body) {
  $args = array(
    '!type' => $type,
    '!title' => $title,
    '!url' => url('node/' . $nid, NULL, NULL, TRUE),
    '!days' => $days,
    '!site' => variable_get('site_name', ''),
    '!siteurl' => url('<front>', NULL, NULL, TRUE),
  );
  _auto_expire_notify($nid, 'auto_expire_warning', $subject, $body, $args);
}
function _auto_expire_notify_expired($nid, $title, $type, $subject, $body) {
  $args = array(
    '!type' => $type,
    '!title' => $title,
    '!site' => variable_get('site_name', ''),
    '!siteurl' => url('<front>', NULL, NULL, TRUE),
  );
  _auto_expire_notify($nid, 'auto_expire_expired', $subject, $body, $args);
}
function _auto_expire_notify($nid, $mailkey, $subject, $body, $args) {
  if (!empty($subject)) {
    $result = db_query('SELECT u.mail FROM {users} u, {node} n WHERE n.nid = %d AND n.uid = u.uid AND u.status=1 AND u.uid>0', $nid);
    if ($result) {
      $userEmail = db_result($result);
      if ($userEmail) {
        $subject = t($subject, $args);
        $body = t($body, $args);
        $bcc = trim(variable_get(AUTO_EXPIRE_EMAIL . 'bcc', ''));
        if ($bcc == '') {
          $sent = drupal_mail($mailkey, $userEmail, $subject, $body);
        }
        else {
          $headers['Bcc'] = $bcc;
          $sent = drupal_mail($mailkey, $userEmail, $subject, $body, NULL, $headers);
        }
        if (!$sent) {
          watchdog('auto_expire', 'Could not send notification email to: ' . $userEmail, WATCHDOG_ERROR);
        }
      }
    }
  }
}
function _auto_expire_get_expire($nid) {
  return db_result(db_query('SELECT expire FROM {auto_expire} WHERE nid = %d', $nid));
}

/*Views integration, implementation of hook_views_tables*/
function auto_expire_views_tables() {
  $tables['auto_expire'] = array(
    'name' => 'auto_expire',
    'join' => array(
      'left' => array(
        'table' => 'node',
        'field' => 'nid',
      ),
      'right' => array(
        'field' => 'nid',
      ),
    ),
    'fields' => array(
      'expire' => array(
        'name' => t('Auto Expire: Expiration Date'),
        'sortable' => TRUE,
        'handler' => views_handler_field_dates(),
        'help' => t('Date the node will expire'),
        'option' => 'integer',
      ),
      'warned' => array(
        'name' => t('Auto Expire: Warning Sent?'),
        'help' => t('Has the warning already been sent?'),
        'field' => 'warned',
        'option' => 'integer',
      ),
    ),
    'filters' => array(
      'expire' => array(
        'field' => 'expire',
        'name' => t('Auto Expire: Expiration Date'),
        'help' => t('Date the node will expire. This filter allows nodes to be filtered by their expiration date. The "Value" can either be a date in the format: CCYY-MM-DD HH:MM:SS or the word "now" to use the current time. You may enter a positive or negative number in the "Option" field that will represent the amount of seconds that will be added or substracted to the time; this is most useful when combined with "now". If you have the jscalendar module from jstools installed, you can use a popup date picker here.'),
        'operator' => 'views_handler_operator_gtlt',
        'value' => views_handler_filter_date_value_form(),
        'option' => 'string',
        'handler' => 'views_handler_filter_timestamp',
      ),
      'warned' => array(
        'name' => t('Auto Expire: Warning Sent?'),
        'help' => t('Has the warning already been sent?'),
        'field' => 'warned',
        'operator' => 'views_handler_operator_eqneq',
      ),
    ),
    'sorts' => array(
      'expire' => array(
        'name' => t('Auto Expire: Date'),
        'help' => t('Sort by date'),
        'handler' => 'views_handler_sort_date',
        'option' => views_handler_sort_date_options(),
      ),
    ),
  );
  return $tables;
}