/[drupal]/contributions/modules/node_expire/node_expire.module
ViewVC logotype

Diff of /contributions/modules/node_expire/node_expire.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.4, Sat May 12 10:14:29 2007 UTC revision 1.5, Mon Jan 26 23:56:49 2009 UTC
# Line 1  Line 1 
1  <?php  <?php
2  /* $Id: node_expire.module,v 1.2.2.3 2007/05/10 07:19:54 andyl56 Exp $ */  // $Id: $
3    
4  /**  /**
5   * @file   * @file
6   * Allows Alerts administrators of possibly outdated materials and optionally unpublishes them.   * Set a timer into your content, allowing you to perform customized actions.
7   **/   */
   
 /**  
  * Implementation of hook_perm().  
  **/  
 function node_expire_perm() {  
   return array('administer node_expire', 'edit expirations');  
 }  
   
 /**  
  * Implementation of hook_menu().  
  **/  
 function node_expire_menu($may_cache) {  
   $items = array();  
   
   if ($may_cache) {  
     $items[] = array(  
       'path'               => 'admin/settings/node_expire',  
       'title'              => t('Node Expire'),  
       'description'        => t('Configure Node Expire'),  
       'callback'           => 'drupal_get_form',  
       'callback arguments' => array('node_expire_settings_form'),  
       'access'             => user_access('administer node_expire'),  
     );  
   
     $items[] = array(  
       'path'               => 'admin/settings/node_expire/settings',  
       'title'              => t('Settings'),  
       'callback'           => 'drupal_get_form',  
       'callback arguments' => array('node_expire_settings_form'),  
       'access'             => user_access('administer node_expire'),  
       'type'               => MENU_DEFAULT_LOCAL_TASK,  
     );  
   
     $items[] = array(  
       'path'               => 'admin/settings/node_expire/defaults',  
       'title'              => t('Defaults'),  
       'callback'           => 'drupal_get_form',  
       'callback arguments' => array('node_expire_default_settings_form'),  
       'access'             => user_access('administer node_expire'),  
       'type'               => MENU_LOCAL_TASK,  
       'weight'             => 1,  
     );  
   
     // If pages are set to expire instantly, this page is of absolutely no use. Let's just hide it.  
     $items[] = array(  
       'path'               => 'admin/content/node/outdated',  
       'title'              => t('Outdated Documents'),  
       'callback'           => 'node_expire_outdated_nodes',  
       'access'             => variable_get('node-expire-unpublishtime', 0) != 1 && user_access('administer nodes'),  
       'type'               => MENU_LOCAL_TASK,  
       'weight'             => 10,  
     );  
   }  
8    
9    return $items;  DEFINE('NODE_EXPIRE_FORMAT',    'Y-m-d');
10  }  DEFINE('NODE_EXPIRE_FORMAT_JS', 'yy-mm-dd');
11    
12  /**  /**
13   * Implementation of hook_cron().   * Implementation of hook_cron().
14   **/   */
15  function node_expire_cron() {  function node_expire_cron() {
16    // Are email notifications enabled?    if ($query = db_query('SELECT n.nid FROM {node} n
17    if (variable_get('node-expire-enable-email', 1) == 1) {        JOIN {node_expire} ne ON n.nid = ne.nid
18      $updateids = array();        WHERE ne.expired = 0 AND ne.expire <= %d', time())) {
19        while ($node = db_fetch_object($query)) {
20      /**        $nids[] = $node->nid;
21       * Get a list of nodes that are past the expiration threshold and also haven't been notified in the selected        $node = node_load($node->nid);
22       * amount of time. For the qualifying data, it gets the necessary information that a user might want to        rules_invoke_event('node_expired', array('node' => &$node));
      * include in the automatic email.  
      **/  
     $query = db_query('SELECT a.nid, b.title, a.expire, b.changed, c.name, c.mail FROM {node_expire} a LEFT JOIN {node} b ON '.  
       'a.nid = b.nid LEFT JOIN {users} c ON b.uid = c.uid WHERE a.expire <= NOW() AND a.expiremode != "none" AND a.lastnotify <= %d '.  
       'AND b.status = 1 ORDER BY c.name ASC, b.title ASC', 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 (count($newnotify) > 0) {  
       // 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 $tech => $contents) {  
         /**  
          * 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      = $contents['email'];  
         unset($contents['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: !secion_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', $tech, $body);  
   
         // Grab just between !start_section! and !stop_section!  
         $bodysec = 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 ($contents 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(strtotime($row['expire'])),           $temp);  
           $temp = str_replace('!secion_editlink',         url('node/'.$row['nid'], null, null, true),       $temp);  
   
           // Record this as sent so it's only notified once per the selected threshold.  
           $updateids[] = $row['nid'];  
   
           $newbody .= $temp;  
         }  
   
         // Now let's take out the template from the settings, and replace it with the parsed data.  
         $body = substr($body, 0, strpos($body, '!start_section!')) . $newbody . substr($body, strpos($body, '!stop_section!')+15);  
   
         // This is just to prevent problems with "Anonymous" nodes.  
         if ($to) {  
           drupal_mail('notify-'.$tech, $to, $subject, $body);  
         }  
   
         // Send it to the author and the requested carbon copy address, if any.  
         if ($cc) {  
           drupal_mail('notify-'.$tech, $cc, $subject, $body);  
         }  
       }  
   
       // Record which records were updated.  
       db_query('UPDATE {node_expire} SET lastnotify = %d WHERE nid IN(%d)', time(), implode(', ', $updateids));  
   
       // Log the event  
       watchdog('node_expire', format_plural(count($updateids), 'E-mail notice submitted for node #'.$updateids[0],  
       'E-mail notice submitted for 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) != 0) {  
     // Find old documents.  
     $unpublishme = array();  
     $query = db_query('SELECT nid FROM {node_expire} WHERE DATEDIFF(NOW(), expire) >= %s AND expiremode != "none"', floor(variable_get('node-expire-unpublishtime', 0) / 86400));  
     while ($row = db_fetch_object($query)) {  
       $unpublishme[] = $row->nid;  
     }  
   
     // If any records are to be unpublished, unpublish them, and log it through the watchdog service.  
     if (count($unpublishme) > 0) {  
       db_query('UPDATE {node} SET status = 0 WHERE status = 1 AND nid IN (%s)', implode(', ', $unpublishme));  
   
       watchdog('node_expire', format_plural(count($unpublishme), '@count node was automatically unpublished.',  
         '@count nodes were automatically unpublished.'), WATCHDOG_NOTICE);  
23      }      }
24        node_expire_set_expired($nids, TRUE);
25    }    }
   
   return true;  
26  }  }
27    
28  /**  /**
29   * Configuration form for node_expire   * Implementation of hook_form_alter().
30   **/   *
31  function node_expire_settings_form() {   * Add expiration options to the node entry forms
32    // Publishing settings section   */
33    $form['general'] = array(  function node_expire_form_alter(&$form, &$form_state, $form_id) {
34      '#title'       => t('General Settings'),    if (isset($form['type'])
35      '#type'        => 'fieldset',        and $form['type']['#value'] .'_node_form' == $form_id
36      '#tree'        => FALSE,        and $ntypes = variable_get('node_expire_ntypes', array())
37      '#collapsible' => TRUE,        and !empty($ntypes[$form['type']['#value']])) {
38      '#collapsed'   => FALSE,  
39    );      // Check if the Node Expire feature is enabled for the node type
40        $node = isset($form['#node']) ? $form['#node'] : NULL;
41    $expireperiod    = drupal_map_assoc(array(0, 1, 86400, 172800, 259200, 345600, 432000, 518400, 604800,  
42      691200, 777600, 864000, 950400, 1036800, 1123200, 1209600), 'format_interval');      if (user_access('edit node expire')) {
43    $expireperiod[0] = 'Never';        if (is_numeric($node->expire)) {
44    $expireperiod[1] = 'Instantly';          $node->expire = format_date($node->expire, 'custom', NODE_EXPIRE_FORMAT);
45    $form['general']['unpublishtime'] = array(        }
46      '#title'         => t('Timeout for automatic unpublishing'),        $form['expire'] = array(
47      '#description'   => t('The duration of time when a node is expired for it to become automatically unpublished. Notice: '.          '#title'         => t('Expiration Date'),
48        'Unpublished documents won\'t trigger any expiration notices.'),          '#description'   => t('Time date to consider the node expired. Format: %time.',
49      '#type'          => 'select',            array('%time' => format_date(time(), 'custom', NODE_EXPIRE_FORMAT))),
50      '#options'       => $expireperiod,          '#type'          => 'textfield',
51      '#default_value' => variable_get('node-expire-unpublishtime', 0),          '#maxlength'     => 25,
52    );          '#default_value' => $node->expire,
53          );
   // Only allow inheritance for book pages.  
   if (module_exists('book')) {  
     $form['general']['book_inherit'] = array(  
       '#title'         => t('Book pages - Inheritance'),  
       '#description'   => t('Enable inheritance/propagation of expiration times amongst child books.'),  
       '#type'          => 'select',  
       '#options'       => array(1 => 'Yes', 0 => 'No'),  
       '#default_value' => variable_get('node-expire-book-props', 1),  
     );  
   }  
   
   // Notification settings section  
   $form['notify'] = array(  
     '#title'       => t('Notifications'),  
     '#type'        => 'fieldset',  
     '#tree'        => FALSE,  
     '#collapsible' => TRUE,  
     '#collapsed'   => variable_get('node-expire-enable-email', 1) == 0,  
   );  
   
   $form['notify']['enabled'] = array(  
     '#title'         => t('Enable email notifications'),  
     '#description'   => t('Whether or not to e-mail out about expired nodes.'),  
     '#type'          => 'select',  
     '#options'       => array(1 => 'Yes', 0 => 'No'),  
     '#default_value' => variable_get('node-expire-enable-email', 1),  
   );  
   
   $period = drupal_map_assoc(array(86400, 172800, 259200, 345600, 432000, 518400, 604800), 'format_interval');  
   $form['notify']['renotify'] = array(  
     '#title'         => t('Re-notify user every'),  
     '#description'   => t('The length of time before the user is renotified of old content.'),  
     '#type'          => 'select',  
     '#options'       => $period,  
     '#default_value' => variable_get('node-expire-renotify', 259200),  
   );  
   
   $form['notify']['cc'] = array(  
     '#title'         => t('Carbon Copy Address'),  
     '#description'   => t('An e-mail address to carbon copy on all notifications.'),  
     '#type'          => 'textfield',  
     '#size'          => 50,  
     '#default_value' => variable_get('node-expire-cc', ''),  
   );  
   
   // E-mail content settings  
   $form['emlcontent'] = array(  
     '#title'       => t('E-mail Content'),  
     '#type'        => 'fieldset',  
     '#tree'        => FALSE,  
     '#collapsible' => TRUE,  
     '#collapsed'   => variable_get('node-expire-enable-email', 1) == 0,  
   );  
   
   $form['emlcontent']['subject'] = array(  
     '#title'         => t('Subject'),  
     '#description'   => t('The subject of the automated alerts. Available variables are: !site'),  
     '#type'          => 'textfield',  
     '#size'          => 60,  
     '#maxlength'     => 180,  
     '#default_value' => variable_get('node-expire-subject', '!site - Article Update Needed'),  
   );  
   
   $form['emlcontent']['body'] = array(  
     '#title' => t('Body'),  
     '#description' => t('The body of the automated alerts. Available variables are: !username !start_section! !stop_section! '.  
       '!section_article !section_timesinceupdate !section_lastupdate !section_expirydate !secion_editlink'),  
     '#type'  => 'textarea',  
     '#rows'  => 11,  
     '#cols'  => 60,  
     '#default_value' => 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: !secion_editlink\r\n\r\n!stop_section!\r\n--  !site team"),  
     );  
   
   $form['submit'] = array(  
     '#type'  => 'submit',  
     '#value' => t('Save Changes'),  
   );  
   $form['reset'] = array(  
     '#type'  => 'submit',  
     '#value' => t('Reset to Default'),  
   );  
   
   return $form;  
 }  
   
 /**  
  * Implementation of hook_form_validate()  
  **/  
 function node_expire_settings_form_validate($form_id, $form_values) {  
   // Only validate the form if we're saving changes. We don't care about values if we're just resetting them anyway.  
   if ($form_values['op'] == t('Save Changes')) {  
     // Is the CC address valid?  
     if ($form_values['cc'] && !valid_email_address($form_values['cc'])) {  
       form_set_error('cc', t('The entered carbon copy address is invalid.'));  
     }  
   
     // Count instances of !start_section!  
     $matches = array();  
     preg_match_all('/!start_section!/', $form_values['body'], $matches);  
     if (count($matches[0]) > 1) {  
       form_set_error('body', t('The tag "!start_section!" can only be used once.'));  
     }  
   
     // Make sure instances of !start_section! match !stop_section!  
     $matches2 = array();  
     preg_match_all('/!stop_section!/', $form_values['body'], $matches2);  
     if (count($matches[0]) != count($matches2[0])) {  
       form_set_error('body', t('The tag "!stop_section!" is missing or doesn\'t match with "!start_section!".'));  
     }  
   }  
 }  
   
 /**  
  * Implementation of hook_form_submit()  
  **/  
 function node_expire_settings_form_submit($form_id, $form_values) {  
   // Do we want to reset to the defaults?  
   if ($form_values['op'] == t('Reset to Default')) {  
     variable_del('node-expire-body');  
     variable_del('node-expire-book-props');  
     variable_del('node-expire-cc');  
     variable_del('node-expire-enable-email');  
     variable_del('node-expire-renotify');  
     variable_del('node-expire-subject');  
     variable_del('node-expire-unpublishtime');  
   
     drupal_set_message(t('Settings reset back to defaults.'));  
   }  
   // We must be saving new settings then.  
   else {  
     // Only allow inheritance for book pages.  
     if (module_exists('book')) {  
       variable_del('node-expire-book-props');  
     }  
     else {  
       variable_set('node-expire-book-props', $form_values['book_inherit']);  
     }  
   
     // Blank body resets to default  
     if (!$form_values['body']) {  
       variable_del('node-expire-body');  
     }  
     else {  
       variable_set('node-expire-body', $form_values['body']);  
     }  
54    
55      // Blank subject resets to default        if (module_exists('jquery_ui')) {
56      if (!$form_values['subject']) {          jquery_ui_add('ui.datepicker');
57        variable_del('node-expire-subject');          drupal_add_js(drupal_get_path('module', 'node_expire') .'/node_expire.js');
58            drupal_add_js(array('dateFormat' => NODE_EXPIRE_FORMAT_JS), 'setting');
59          }
60      }      }
61      else {      else {
62        variable_set('node-expire-subject', $form_values['subject']);        $form['expire'] = array(
63      }          '#type'         => 'value',
64            '#value'        => $node->expire
     // All other settings can be saved as-is.  
     variable_set('node-expire-enable-email',    $form_values['enabled']);  
     variable_set('node-expire-cc',              $form_values['cc']);  
     variable_set('node-expire-renotify',        $form_values['renotify']);  
     variable_set('node-expire-unpublishtime', $form_values['unpublishtime']);  
   
     drupal_set_message(t('Saved new settings.'));  
   }  
 }  
   
 /**  
  * Configuration form for default expirations for node_expire  
  **/  
 function node_expire_default_settings_form() {  
   // Get current settings  
   $curdefaults = variable_get('node-expire-node-visibility', array());  
   
   $period = array(  
      '+1 month'  => '1 Month',  
      '+2 months' => '2 Months',  
      '+3 months' => '3 Months',  
      '+4 months' => '4 Months',  
      '+5 months' => '5 Months',  
      '+6 months' => '6 Months',  
      '+7 months' => '7 Months',  
      '+8 months' => '8 Months',  
      '+9 months' => '9 Months',  
     '+10 months' => '10 Months',  
     '+11 months' => '11 Months',  
     '+1 Year'    => '1 Year',  
   );  
   
   // Make the options available for each node type.  
   $types    = node_get_types();  
   foreach ($types as $node) {  
     // If we don't already have defaults for this node set, use our own.  
     if (!$curdefaults[$node->type]) {  
       $curdefaults[$node->type] = array(  
         'enabled'         => false,  
         'expiration_type' => 'none',  
         'expire_timefrom' => '+3 months',  
         'expire'          => '+3 months',  
         'isroot'          => false,  
65        );        );
66      }      }
67    
68      $form[$node->type] = array(      if (isset($node->expired)) {
69        '#type'        => 'fieldset',        $form['node_expire'] = array(
70        '#title'       => $node->name,          '#type'         => 'value',
71        '#tree'        => TRUE,          '#value'        => TRUE,
       '#collapsible' => TRUE,  
       '#collapsed'   => $curdefaults[$node->type]['enabled'] == false,  
       '#description' => $node->module == 'book' ? t('These defaults will only be used when no inheritance is available.') : '',  
     );  
   
     $form[$node->type]['enabled'] = array(  
       '#type'          => 'checkbox',  
       '#title'         => t('Enable expiration for this node type.'),  
       '#default_value' => $curdefaults[$node->type]['enabled'],  
     );  
   
     $form[$node->type]['expiration_type'] = array(  
       '#title'         => t('Expiration Type'),  
       '#description'   => t('What type of node expiration should this node have?'),  
       '#type'          => 'select',  
       '#options'       => array(  
         'none'         => t('Doesn\'t Expire'),  
         'date'         => t('Expire on Date'),  
         'onupdate'     => t('Expire After Last Update'),  
       ),  
       '#default_value' => $curdefaults[$node->type]['expiration_type'],  
     );  
   
     $form[$node->type]['expire_timefrom'] = array(  
       '#title'         => t('Expiration Time'),  
       '#description'   => t('Time after last update to consider the node expired.'),  
       '#type'          => 'select',  
       '#options'       => $period,  
       '#default_value' => $curdefaults[$node->type]['expire_timefrom'],  
     );  
   
     $form[$node->type]['expire'] = array(  
       '#title'         => t('Expiration Date'),  
       '#description'   => t('Time date to consider the node expired. Format: %time or PHP <a href="http://www.php.net/strtotime" '.  
         'target="_blank">strtotime format</a>. Note that if the default date entered is in the past at the node post time, and '.  
         'the end-user doesn\'t have access to edit it, expiration settings for that node will be removed.',  
         array('%time' => format_date(time(), 'large'))),  
       '#type'          => 'textfield',  
       '#default_value' => $curdefaults[$node->type]['expire'],  
     );  
   
     // As book pages is the only node type that allows inheritance, only show it there.  
     if ($node->module == 'book' && variable_get('node-expire-book-props', 1) == 1) {  
       $form[$node->type]['isroot'] = array(  
         '#title'         => t('Block Inheritance'),  
         '#description'   => t('Whether or not to block inheritance of the above settings from parent nodes.'),  
         '#type'          => 'checkbox',  
         '#default_value' => $curdefaults[$node->type]['isroot'],  
72        );        );
73      }      }
74    }    }
   
   $form['submit'] = array(  
     '#type'  => 'submit',  
     '#value' => t('Save Changes'),  
   );  
   $form['reset'] = array(  
     '#type'  => 'submit',  
     '#value' => t('Reset to Default'),  
   );  
   
   return $form;  
 }  
   
 /**  
  * Implementation of hook_form_validate()  
  **/  
 function node_expire_default_settings_form_validate($form_id, $form_values) {  
   // Only validate the form if we're saving changes. We don't care about values if we're just resetting them anyway.  
   if ($form_values['op'] == t('Save Changes')) {  
     // The only field we have to check is the expiration date  
     foreach ($form_values as $key => $val) {  
       if (is_array($val) && isset($val['expire']) && $val['expiration_type'] != 'onupdate') {  
         if (($thetime = strtotime($val['expire'])) === false) {  
           form_set_error($key.'][expire', t('The entered expiration date is invalid.'));  
         }  
         else if ($thetime <= time()) {  
           form_set_error($key.'][expire', t('The entered expiration date occurrs in the past.'));  
         }  
       }  
     }  
   }  
75  }  }
76    
77  /**  /**
78   * Implementation of hook_form_submit()   * Implementation of hook_form_alter().
79   **/   *
80  function node_expire_default_settings_form_submit($form_id, $form_values) {   * Enable/Disable expiration feature on node types
   // Do we want to reset to the defaults?  
   if ($form_values['op'] == t('Reset to Default')) {  
     variable_del('node-expire-node-visibility');  
   
     drupal_set_message(t('Settings reset back to defaults.'));  
   }  
   // We must be saving new settings then.  
   else {  
     // Generate the settings as we need them for our module  
     $node_visibility = array();  
   
     foreach ($form_values as $key => $val) {  
       if (is_array($val) && isset($val['enabled']) && $val['enabled'] == true) {  
         $node_visibility[$key] = array(  
           'enabled'         => true,  
           'expiration_type' => $val['expiration_type'],  
           'expire_timefrom' => $val['expire_timefrom'],  
           'expire'          => $val['expiration_type'] == 'onupdate' ? '' : $val['expire'],  
           'isroot'          => isset($val['isroot']) ? $val['isroot'] : false,  
         );  
       }  
     }  
   
     variable_set('node-expire-node-visibility', $node_visibility);  
   
     // Delete expirations from database if they don't longer pertain to this module  
     if (count($node_visibility) == 0) {  
       db_query("DELETE FROM {node_expire}");  
     }  
     else {  
       $allowed = array();  
       foreach (array_keys($node_visibility) as $val) {  
         $allowed[] = "'".$val."'";  
       }  
   
       $query  = db_query("SELECT a.nid FROM {node_expire} a LEFT JOIN {node} b on a.nid = b.nid WHERE b.type NOT IN (".implode(', ', $allowed).")");  
       $delete = array();  
       while ($row = db_fetch_object($query)) {  
         $delete[] = $row->nid;  
       }  
       if (count($delete) > 0) {  
         // Using the normal db_query method, drupal escapes the quotes necessary for the query.  
         // This data should be safe anyways since it's pulling from the validated node types.  
         db_query("DELETE FROM {node_expire} WHERE nid IN(".implode(', ', $delete).")");  
       }  
     }  
   
     drupal_set_message(t('Saved new settings.'));  
   }  
 }  
   
 /**  
  * List all currently expired nodes  
  **/  
 function node_expire_outdated_nodes() {  
   // Prepare for the content  
   $header = array(  
     array(  
       'data'  => t('Title'),  
       'field' => 'b.title',  
     ),  
     array(  
       'data'  => t('Last Updated'),  
       'field' => 'b.changed',  
       'width' => '150px',  
     ),  
     array(  
       'data'  => t('Expiration Date'),  
       'field' => 'a.expire',  
       'sort'  => 'desc',  
       'width' => '150px',  
     ),  
     array(  
       'data'  => t('Owner'),  
       'field' => 'c.name',  
     ),  
     array('data' => t('Operations'), 'colspan' => '2'),  
   );  
   
   // Figure out what documents are old  
   $query = db_query('SELECT a.nid, b.title, b.changed, a.expire, IF(c.name = "" OR ISNULL(c.name), "%s", c.name) as name FROM {node_expire} a LEFT JOIN {node} b ON a.nid = b.nid '.  
     'LEFT JOIN {users} c ON b.uid = c.uid WHERE a.expire <= NOW() AND a.expiremode != "none" AND b.status = 1'.tablesort_sql($header), variable_get('anonymous', 'Anonymous'));  
   $rows  = array();  
   while ($row = db_fetch_object($query)) {  
     $rows[] = array(  
       $row->title,  
       format_date($row->changed, 'small'),  
       $row->expire == '0000-00-00 00:00:00' ? 'Never' : format_date(strtotime($row->expire), 'small'),  
       $row->name,  
       array(  
         'data'  => l(t('view'), 'node/'. $row->nid),  
         'align' => 'center',  
         'width' => '50px',  
       ),  
       array(  
         'data'  => l(t('edit'), 'node/'. $row->nid . '/edit'),  
         'align' => 'center',  
         'width' => '50px',  
       ),  
     );  
   }  
   
   // No results? Everything must be current.  
   if (count($rows) == 0) {  
     $rows[] = array(array(  
       'data' => t('No nodes are expired!'),  
       'colspan' => '5',  
       'align' => 'center',  
     ));  
   }  
   
   return theme('table', $header, $rows);  
 }  
   
 /**  
  * Add expiration options to the node entry forms  
81   */   */
82  function node_expire_form_alter($form_id, &$form) {  function node_expire_form_node_type_form_alter(&$form, &$form_state) {
83    $node = $form['#node'];    if (user_access('administer node expire')) {
84        $ntypes = variable_get('node_expire_ntypes', array());
85    if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id && !isset($node->expire_disabled)) {      $ntype  = $form['#node_type']->type;
86      $form['expiration'] = array(      $form['workflow']['node_expire'] = array(
       '#title'       => t('Expiration'),  
       '#type'        => 'fieldset',  
       '#tree'        => FALSE,  
       '#collapsible' => TRUE,  
       '#collapsed'   => $node->expiration_type == 'none',  
     );  
   
     $form['expiration']['expiration_type'] = array(  
       '#title'         => t('Expiration Type'),  
       '#description'   => t('What type of node expiration should this node have?'),  
       '#type'          => 'select',  
       '#options'       => array(  
         'none'         => t('Doesn\'t Expire'),  
         'date'         => t('Expire on Date'),  
         'onupdate'     => t('Expire After Last Update'),  
       ),  
       '#default_value' => $node->expiration_type,  
     );  
   
     $period = array(  
        '+1 month'  => '1 Month',  
        '+2 months' => '2 Months',  
        '+3 months' => '3 Months',  
        '+4 months' => '4 Months',  
        '+5 months' => '5 Months',  
        '+6 months' => '6 Months',  
        '+7 months' => '7 Months',  
        '+8 months' => '8 Months',  
        '+9 months' => '9 Months',  
       '+10 months' => '10 Months',  
       '+11 months' => '11 Months',  
       '+1 Year'    => '1 Year',  
     );  
     $form['expiration']['expire_timefrom'] = array(  
       '#title'         => t('Expiration Time'),  
       '#description'   => t('Time after last update to consider the node expired.'),  
       '#type'          => 'select',  
       '#options'       => $period,  
       '#default_value' => $node->expire_timefrom,  
     );  
   
     $form['expiration']['expire'] = array(  
87        '#title'         => t('Expiration Date'),        '#title'         => t('Expiration Date'),
88        '#description'   => t('Time date to consider the node expired. Format: %time.', array('%time' => $node->expire)),        '#description'   => t('Time/date to consider the node expired. Format: PHP <a href="http://www.php.net/strtotime" target="_blank">strtotime format</a>. Leave it blank if this content type never expires.'),
89        '#type'          => 'textfield',        '#type'          => 'textfield',
90        '#maxlength'     => 25,        '#default_value' => empty($ntypes[$ntype]) ? '' : $ntypes[$ntype],
91        '#default_value' => $node->expire,        '#attributes'    => array('class' => 'jscalendar'),
92      );      );
93    
94      // As book pages is the only node type that allows inheritance, only show it there.      // Add special validate/submit functions
95      if ($form['type']['#value'] == 'book' && variable_get('node-expire-book-props', 1) == 1) {      module_load_include('ntype.inc', 'node_expire');
96        $form['expiration']['isroot'] = array(      $form['#validate'][]  = '_node_expire_form_node_type_form_alter_validate';
97          '#title'         => t('Block Inheritance'),      $form['#submit'][]    = '_node_expire_form_node_type_form_alter_submit';
         '#description'   => t('Whether or not to block inheritance of the above settings from parent nodes.'),  
         '#type'          => 'checkbox',  
         '#default_value' => $node->isroot,  
       );  
     }  
98    }    }
99  }  }
100    
101  /**  /**
102   * Prepare and parse the data from our node entry forms.   * Implementation of hook_nodeapi().
103   *   */
  * @todo Propegate to child nodes.  
  **/  
104  function node_expire_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {  function node_expire_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
105    switch ($op) {    // Only deal with node types that have the Node Expire feature enabled
106      case 'view':    $ntypes = variable_get('node_expire_ntypes', array());
107        $query = db_query('SELECT expire, expiremode FROM {node_expire} WHERE nid = %d', $node->nid);    if (!$ntypes = $ntypes[$node->type]) {
108        return;
       // Use the existing expiration data if present.  
       if (db_num_rows($query) > 0) {  
         $row                   = db_fetch_object($query);  
         $node->expire          = $row->expire ? format_date(strtotime($row->expire), 'large') : '';  
         $node->expiration_type = $row->expiremode;  
       }  
       // Otherwise use the defaults  
       else {  
         $node->expire          = '';  
         $node->expiration_type = 'none';  
       }  
       break;  
   
     case 'prepare':  
       // Is the expiration feature enabled for this node type?  
       $curdefaults = variable_get('node-expire-node-visibility', array());  
   
       if (!isset($curdefaults[$node->type]) || !user_access('edit expirations')) {  
         $node->expire_disabled = true;  
       }  
       else {  
         $curdefaults = $curdefaults[$node->type];  
         $query = db_query('SELECT expire, expiresec, expiremode, isroot FROM {node_expire} WHERE nid = %d', $node->nid);  
   
         // Use the existing expiration data if present.  
         if (db_num_rows($query) > 0) {  
           $row                   = db_fetch_object($query);  
           $node->expiration_type = $row->expiremode;  
           $node->isroot          = $row->isroot;  
   
           if ($node->expiration_type == 'none') {  
             $node->expire_timefrom = $curdefaults['expire_timefrom'];  
             $node->expire          = format_date(strtotime($curdefaults['expire_timefrom']), 'custom', 'Y-m-d H:i:s');  
           }  
           else {  
             $node->expire          = $row->expire;  
             $node->expire_timefrom = $row->expiresec;  
           }  
         }  
         // Otherwise use the defaults  
         else {  
           // If this is a new book page, and inheritance is enabled, lets inherit the data.  
           if ($node->type == 'book' && variable_get('node-expire-book-props', 1) && arg(4) > 0) {  
             $row = db_fetch_object(db_query('SELECT expire, expiresec, expiremode FROM {node_expire} WHERE nid = %d', arg(4)));  
   
             $node->expire          = $row->expire;  
             $node->expire_timefrom = $row->expiresec;  
             $node->expiration_type = $row->expiremode;  
             $node->isroot          = 0;  
           }  
           // All others, use the plain old defaults.  
           else {  
             $node->expire          = format_date(strtotime($curdefaults['expire_timefrom']), 'custom', 'Y-m-d H:i:s');  
             $node->expire_timefrom = $curdefaults['expire_timefrom'];  
             $node->isroot          = $curdefaults['isroot'];  
             $node->expiration_type = $curdefaults['expiration_type'];  
   
             if ($curdefaults['expiration_type'] == 'onupdate') {  
               $node->expire        = format_date(strtotime($curdefaults['expire_timefrom']), 'custom', 'Y-m-d H:i:s');  
             }  
             else {  
               $node->expire        = format_date(strtotime($curdefaults['expire']), 'custom', 'Y-m-d H:i:s');  
             }  
           }  
         }  
       }  
       break;  
   
     case 'validate':  
       // The only restriction we have is that the node can't expire in the past.  
       if ($node->expiration_type == 'date') {  
         if (strtotime($node->expire) <= 0) {  
           form_set_error('expire_date', t('You have to specify a valid date.'));  
         }  
         else if (strtotime($node->expire) <= time()) {  
           form_set_error('expire_date', t('You can\'t expire a node in the past!'));  
         }  
       }  
       break;  
   
     case 'insert':  
     case 'update':  
       // We only want to deal with the database if the expiration feature is available for this node type  
       $curdefaults = variable_get('node-expire-node-visibility', array());  
   
       if (isset($curdefaults[$node->type])) {  
         // Do we need to update the database?  
         $update = 1;  
   
         // We only care about the defaults for this node type  
         $curdefaults = $curdefaults[$node->type];  
   
         // Does this user have access to change any expiration settings?  
         if (!user_access('edit expirations')) {  
           // Does this node already have data for us to work with?  
           $query = db_query('SELECT expire, expiresec, expiremode, isroot FROM {node_expire} WHERE nid = %d', $node->nid);  
   
           if (db_num_rows($query) > 0) {  
             $row = db_fetch_object($query);  
   
             // Let's keep our current settings  
             $node->expire          = $row->expire;  
             $node->expire_timefrom = $row->expiresec;  
             $node->expiration_type = $row->expiremode;  
             $node->isroot          = $row->expiresec ? 1 : 0;  
   
             // If this node is an "on update" expiration, update the expiration time.  
             if ($node->expiration_type == 'onupdate') {  
               $node->expire = strtotime($node->expire_timefrom);  
             }  
             else {  
               $update = 0;  
             }  
           }  
           // There's no existing data so let's make new data. If this is a new book page, and inheritance is enabled, let's inherit the data.  
           else if ($node->type == 'book' && variable_get('node-expire-book-props', 1) && $node->parent > 0) {  
             $row = db_fetch_object(db_query('SELECT expire, expiresec, expiremode FROM {node_expire} WHERE nid = %d', $node->parent));  
   
             $node->expire          = $row->expire;  
             $node->expire_timefrom = $row->expiresec;  
             $node->expiration_type = $row->expiremode;  
             $node->isroot          = 0;  
   
             // If the parent node is set to base expiration off last update time, let's mark this node accordingly.  
             if ($node->expiration_type == 'onupdate') {  
               $node->expire = strtotime($node->expire_timefrom);  
             }  
           }  
           // We have nothing to work with so use the defaults.  
           else {  
             $node->expire          = strtotime($curdefaults['expire']);  
             $node->expire_timefrom = $curdefaults['expire_timefrom'];  
             $node->isroot          = $curdefaults['isroot'];  
             $node->expiration_type = $curdefaults['expiration_type'];  
   
             if ($node->expiration_type == 'onupdate') {  
               $node->expire = strtotime($node->expire_timefrom);  
             }  
   
             /**  
              * The user can't change these settings, and it would be set to expire already,  
              * so, let's just not expire the node at all.  
              */  
             if ($node->expire <= time()) {  
               $node->expiration_type = 'none';  
             }  
           }  
   
           // Get the information SQL ready - format_date screws up the time zones so we don't want it.  
           $node->expire = $node->expire ? date('Y-m-d H:i:s', $node->expire) : '';  
         }  
         // Onto people who do have access to change this data.  
         else {  
           // If this is a book page, and it's not marked as a root book, override the user's input with the parent's data.  
           if ($node->type == 'book' && variable_get('node-expire-book-props', 1) && $node->parent > 0) {  
             $row = db_fetch_object(db_query('SELECT expire, expiresec, expiremode FROM {node_expire} WHERE nid = %d', $node->parent));  
   
             $node->expire          = $row->expire;  
             $node->expire_timefrom = $row->expiresec;  
             $node->expiration_type = $row->expiremode;  
             $node->isroot          = 0;  
   
             // If the parent node is set to base expiration off last update time, let's mark this node accordingly.  
             if ($node->expiration_type == 'onupdate') {  
               $node->expire = strtotime($node->expire_timefrom);  
             }  
           }  
           // The only choice now is to go with what the user told us. Let's work with that.  
           else {  
             if ($node->expiration_type == 'date') {  
               $node->expire           = strtotime($node->expire);  
               $node->expire_timefrom  = '';  
             }  
             else if ($node->expiration_type == 'onupdate') {  
               $node->expire           = strtotime($node->expire_timefrom);  
             }  
             else {  
               $node->expiration_type  = 'none';  
               $node->expire           = 0;  
               $node->expire_timefrom  = 0;  
             }  
           }  
   
           // Get the information SQL ready - format_date screws up the time zones so we don't want it.  
           $node->expire = $node->expire ? date('Y-m-d H:i:s', $node->expire) : '';  
   
           /**  
            * Propagate the settings to the child nodes, only if enabled. Notice this is in the section for people with access to edit these settings.  
            * It's a waste of resources to perform the recursion task as nothing will be changed.  
            **/  
           if ($node->type == 'book' && variable_get('node-expire-book-props', 1)) {  
             _node_expire_propagate_new($node->nid, $node->expire, $node);  
           }  
         }  
   
         // To keep track of inheritances and other such things, every node records its expiration settings, not just ones set to expire.  
         if ($update) {  
           db_query('DELETE FROM {node_expire} WHERE nid = %d', $node->nid);  
           db_query('INSERT INTO {node_expire} (nid, expire, expiresec, expiremode, isroot) VALUES (%d, "%s", "%s", "%s", %d)', $node->nid, $node->expire, $node->expire_timefrom, $node->expiration_type, $node->isroot);  
         }  
       }  
       break;  
   
     case 'delete':  
       db_query('DELETE FROM {node_expire} WHERE nid = %d', $node->nid);  
       break;  
109    }    }
110    
111      module_load_include('nodeapi.inc', 'node_expire');
112      _node_expire_nodeapi($ntypes, $node, $op, $a3, $a4 );
113  }  }
114    
115  /**  /**
116   * Recursion for inheritance.   * Implementation of hook_perm().
117   **/   */
118  function _node_expire_propagate_new($nid, $changed, $node) {  function node_expire_perm() {
119    // Get a list of all the children    return array('administer node expire', 'edit node expire');
   $query = db_query('SELECT a.nid, c.changed FROM {book} a LEFT JOIN {node_expire} b ON a.nid = b.nid LEFT JOIN {node} c ON a.nid = c.nid WHERE a.parent = %d AND IFNULL( b.isroot, 0 ) = 0', $nid);  
   
   while ($row = db_fetch_object($query)) {  
     _node_expire_propagate_new($row->nid, $row->changed, $node);  
   }  
   
   // Update the expiration time according to last update of the node itself  
   if ($node->expiration_type == 'onupdate') {  
     $changed = date('Y-m-d H:i:s', strtotime($node->expire_timefrom, $changed));  
   }  
   // Otherwise just use the date sent to us by the form.  
   else {  
     $changed = $node->expire;  
   }  
   
   // To keep track of inheritances and other such things, every node records its expiration settings, not just ones set to expire.  
   db_query('DELETE FROM {node_expire} WHERE nid = %d', $nid);  
   db_query('INSERT INTO {node_expire} (nid, expire, expiresec, expiremode, isroot) VALUES (%d, "%s", "%s", "%s", 0)', $nid, $changed, $node->expire_timefrom, $node->expiration_type);  
   
   return true;  
120  }  }
121    
122  ?>  /**
123     * Implementation of hook_views_api().
124     */
125    function node_expire_views_api() {
126      return array(
127        'api' => 2,
128        'path' => drupal_get_path('module', 'node_expire'),
129      );
130    }

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5

  ViewVC Help
Powered by ViewVC 1.1.2