You are here

publication_date.module in Publication Date 7.2

Add a field to nodes containing the publication date.

File

publication_date.module
View source
<?php

/**
 * @file
 * Add a field to nodes containing the publication date.
 */

// Publication dates are stored in the database as 32-bit integers and, as such,
// can only contain values between -2147483648 and 2147483647.
// @note: This is going to trigger the Year 2038 problem.
define('PUBLICATION_DATE_MAX', 2147483647);
define('PUBLICATION_DATE_MIN', -2147483648);
define('PUBLICATION_DATE_FORMAT', 'Y-m-d H:i:s');
define('PUBLICATION_DATE_FORMAT_WITH_TZ', 'Y-m-d H:i:s O');

/**
 * Implements hook_node_load().
 *
 * For each node we set four properties...
 *   - published_at: Equals the publication date in Epoc time, if one has been
 *     set, or NULL otherwise.
 *   - published_at_or_now: Equals published_at if a publication date has been
 *     set, or the current REQUEST_TIME if it hasn't.
 *   - published_at_or_changed: Equals published_at if a publication date has
 *     been set, or the node's changed timestamp if it hasn't.
 *   - published_at_or_created: Equals published_at if a publication date has
 *     been set, or the node's created timestamp if it hasn't.
 */
function publication_date_node_load($nodes, $types) {
  foreach ($nodes as $node) {

    // Get the publication date from the database and set node properties.
    if ($published_at = _publication_date_get_date($node->nid)) {
      $node->published_at = $published_at;
      $node->published_at_or_now = $published_at;
      $node->published_at_or_changed = $published_at;
      $node->published_at_or_created = $published_at;
    }
    else {
      $node->published_at = NULL;
      $node->published_at_or_now = REQUEST_TIME;
      $node->published_at_or_changed = $node->changed;
      $node->published_at_or_created = $node->created;
    }
  }
}

/**
 * Implements hook_node_insert().
 */
function publication_date_node_insert($node) {

  // Save the publication date.
  _publication_date_set_date($node, 'insert');
}

/**
 * Implements hook_node_update().
 */
function publication_date_node_update($node) {

  // Save the publication date.
  _publication_date_set_date($node, 'update');
}

/**
 * Implements hook_node_delete().
 */
function publication_date_node_delete($node) {

  // Delete the publication date for the deleted node.
  db_delete('publication_date')
    ->condition('nid', $node->nid)
    ->execute();
}

/**
 * Worker function to save the published date to the database.
 *
 * @param object $node
 *   The node object.
 * @param string $op
 *   The node operation being performed:
 *   - 'insert': A new node was created.
 *   - 'update': An existing node was updated.
 *
 * @see hook_node_insert()
 * @see hook_node_update()
 */
function _publication_date_set_date($node, $op = '') {

  // If a publication date has already been set then retain it.
  if (!empty($node->published_at)) {
    $published_at = $node->published_at;
  }
  elseif ($node->status == 1) {
    $published_at = REQUEST_TIME;
  }
  else {
    $published_at = NULL;
  }

  // Allow other modules to alter the publication date before it is saved.
  drupal_alter('publication_date', $published_at, $node, $op);

  // Update the node object.
  $node->published_at = $published_at;

  // Save the publication date to the database.
  db_merge('publication_date')
    ->key(array(
    'nid' => $node->nid,
  ))
    ->fields(array(
    'published_at' => $published_at,
  ))
    ->execute();
}

/**
 * Worker function to get a published date from the database.
 *
 * @param int $nid
 *   The node ID.
 *
 * @return mixed
 *   The publication date for the given node, or false if the node is not
 *   published.
 *
 * @see hook_node_load()
 */
function _publication_date_get_date($nid) {
  $published_at = db_query("SELECT published_at FROM {publication_date} WHERE nid = :nid", array(
    ':nid' => $nid,
  ))
    ->fetchField();
  return empty($published_at) ? FALSE : $published_at;
}

/**
 * Implements hook_views_api().
 */
function publication_date_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'publication_date') . '/includes',
  );
}

/**
 * Implements hook_form_BASE_ID_alter().
 *
 * Display the publication date on the node edit form.
 *
 * @note: This won't work where you have Display Suite/REL enabled.
 */
function publication_date_form_node_form_alter(&$form, &$form_state, $form_id) {
  $node = $form["#node"];

  // If this is an existing node then get the currently set publication date.
  $published_at = $form['nid'] == NULL || empty($node->published_at) ? NULL : $node->published_at;

  // Check if the user has permission to edit the publication date.
  $pubdate_access = user_access('set any published on date') || user_access('set ' . $node->type . ' published on date');

  // Use the popup date picker provided by the Date module, if it is enabled and
  // the user has access to edit the publication date.
  if ($pubdate_access && module_exists('date_popup') && variable_get('publication_date_popup_enable', 1)) {
    $form['options']['pubdate'] = array(
      '#type' => 'date_popup',
      '#title' => t('Published on'),
      '#description' => t('Leave blank to use the time of form submission.'),
      '#date_type' => DATE_UNIX,
      '#date_timezone' => date_default_timezone(),
      '#date_format' => PUBLICATION_DATE_FORMAT,
      '#date_increment' => 1,
      '#date_year_range' => '-' . variable_get('publication_date_popup_year_start', '6') . ':+' . variable_get('publication_date_popup_year_end', '1'),
      '#weight' => -1,
      '#access' => TRUE,
      // If there is an existing publication date, set it as the default value.
      // The date popup field requires a date format without the timezone.
      '#default_value' => empty($published_at) ? '' : format_date($published_at, 'custom', PUBLICATION_DATE_FORMAT),
    );
  }
  else {
    $form['options']['pubdate'] = array(
      '#type' => 'textfield',
      '#title' => t('Published on'),
      '#maxlength' => 25,
      '#description' => t('Format: %time. Leave blank to use the time of form submission.', array(
        '%time' => format_date(REQUEST_TIME, 'custom', PUBLICATION_DATE_FORMAT),
      )),
      '#weight' => -1,
      '#access' => $pubdate_access,
      // If there is an existing publication date, set it as the default value.
      '#default_value' => empty($published_at) ? '' : format_date($published_at, 'custom', PUBLICATION_DATE_FORMAT_WITH_TZ),
    );
  }

  // If the user can access pubdate, we need to make sure they also have access
  // to the options group.
  if ($pubdate_access && $form['options']['#access'] == FALSE) {
    $form['options']['#access'] = TRUE;

    // Check all fields in the options group and, if access has not been set,
    // set it to FALSE. We don't want to grant access to any extra fields.
    $children = element_children($form['options']);
    foreach ($children as $value) {
      if (!isset($form['options'][$value]['#access'])) {
        $form['options'][$value]['#access'] = FALSE;
      }
    }
  }

  // Add custom validation and submit handlers.
  $form['#validate'][] = 'publication_date_pubdate_validate';
  $form['#submit'][] = 'publication_date_pubdate_submit';
}

/**
 * Node edit form validation handler.
 *
 * Validate the published date input.
 */
function publication_date_pubdate_validate($form, &$form_state) {
  if (!empty($form_state['values']['pubdate']) && is_string($form_state['values']['pubdate'])) {
    $pubdate = strtotime($form_state['values']['pubdate']);
    if ($pubdate === FALSE) {
      form_set_error('pubdate', t('The value input for field <em>Published on</em> is invalid.'));
    }

    // The date must be within the range that can be stored as a 32-bit integer.
    if ($pubdate < PUBLICATION_DATE_MIN || $pubdate > PUBLICATION_DATE_MAX) {
      form_set_error('pubdate', t('Only dates between @min and @max are supported.', array(
        '@min' => format_date(PUBLICATION_DATE_MIN, 'custom', PUBLICATION_DATE_FORMAT),
        '@max' => format_date(PUBLICATION_DATE_MAX, 'custom', PUBLICATION_DATE_FORMAT),
      )));
    }
  }
}

/**
 * Node edit form submit handler.
 *
 * Convert the published date to Epoch time for other hook implementations to
 * deal with.
 */
function publication_date_pubdate_submit($form, &$form_state) {

  // Set $node->published_at to the publication date field value if it was set,
  // or NULL if it was not.
  $form_state['node']->published_at = empty($form_state['values']['pubdate']) ? NULL : strtotime($form_state['values']['pubdate']);
}

/**
 * Implements hook_permission().
 */
function publication_date_permission() {
  $permissions = array(
    'administer publication date' => array(
      'title' => t('Administer publication date'),
      'description' => t('Administer Publication date settings'),
    ),
    'set any published on date' => array(
      'title' => t('Modify any "Published On" date'),
      'description' => t('Change the "Published On" date for any content type.'),
    ),
  );

  // Generate permissions to modify Published On date for all node types.
  foreach (node_permissions_get_configured_types() as $type) {
    $permissions += publication_date_list_permissions($type);
  }
  return $permissions;
}

/**
 * Helper function to generate permission each content type.
 *
 * @param string $type
 *   The machine-readable name of the node type.
 *
 * @return array
 *   An array of permission names and description.
 */
function publication_date_list_permissions($type) {
  $name = node_type_get_name($type);
  $type = check_plain($type);
  $permissions = array(
    "set {$type} published on date" => array(
      'title' => t('Modify %type_name "Published On" date.', array(
        '%type_name' => $name,
      )),
      'description' => t('Change the "Published On" date for this content type.'),
    ),
  );
  return $permissions;
}

/**
 * Implements hook_entity_property_info_alter().
 */
function publication_date_entity_property_info_alter(&$info) {
  $properties =& $info['node']['properties'];
  $properties['published_at'] = array(
    'label' => t('Published at'),
    'description' => t('The publication date of the node.'),
    'type' => 'date',
    'getter callback' => '_publication_date_published_at_getter',
    'setter callback' => '_publication_date_published_at_setter',
    'setter permission' => 'set any published on date',
  );
  $properties['published_at_or_now'] = array(
    'label' => t('Published at or now'),
    'description' => t('The publication date of the node, or the current time if no publication date is set.'),
    'type' => 'date',
    'getter callback' => '_publication_date_published_at_or_now_getter',
  );
  $properties['published_at_or_changed'] = array(
    'label' => t('Published at or now'),
    'description' => t('The publication date of the node, or the time it was last changed if no publication date is set.'),
    'type' => 'date',
    'getter callback' => '_publication_date_published_at_or_changed_getter',
  );
  $properties['published_at_or_created'] = array(
    'label' => t('Published at or now'),
    'description' => t('The publication date of the node, or the time it was created if no publication date is set.'),
    'type' => 'date',
    'getter callback' => '_publication_date_published_at_or_created_getter',
  );
}

/**
 * Publication date getter for hook_entity_property_info_alter()
 *
 * @param object $entity
 *   The entity object.
 *
 * @return int
 *   The publication date as a timestamp get from the entity.
 */
function _publication_date_published_at_getter($entity) {
  return $entity->published_at;
}

/**
 * Publication date setter for hook_entity_property_info_alter()
 *
 * @param object $entity
 *   The entity object.
 * @param string $name
 *   The name of the published_at field.
 * @param string $value
 *   The timestamp to set as this entity's publication date.
 */
function _publication_date_published_at_setter(&$entity, $name, $value = NULL) {

  // If a valid timestamp is provided then set it as the publication date.
  if ($value !== NULL && is_int($value)) {
    $entity->published_at = $value;
    $entity->published_at_or_now = $value;
    $entity->published_at_or_changed = $value;
    $entity->published_at_or_created = $value;
  }
  elseif ($value === NULL && $entity->status) {
    $entity->published_at = REQUEST_TIME;
    $entity->published_at_or_now = REQUEST_TIME;
    $entity->published_at_or_changed = REQUEST_TIME;
    $entity->published_at_or_created = REQUEST_TIME;
  }
  elseif ($value === NULL) {
    $entity->published_at = NULL;
    $entity->published_at_or_now = REQUEST_TIME;
    $entity->published_at_or_changed = $entity->changed;
    $entity->published_at_or_created = $entity->created;
  }
}

/**
 * Publication date or now getter for hook_entity_property_info_alter()
 *
 * @param object $entity
 *   The entity object.
 *
 * @return int
 *   The publication date (or REQUEST_TIME) as a timestamp get from the entity.
 */
function _publication_date_published_at_or_now_getter($entity) {
  return $entity->published_at_or_now;
}

/**
 * Publication date or changed getter for hook_entity_property_info_alter()
 *
 * @param object $entity
 *   The entity object.
 *
 * @return int
 *   The publication date (or changed date) as a timestamp get from the entity.
 */
function _publication_date_published_at_or_changed_getter($entity) {
  return $entity->published_at_or_changed;
}

/**
 * Publication date or changed getter for hook_entity_property_info_alter()
 *
 * @param object $entity
 *   The entity object.
 *
 * @return int
 *   The publication date (or created date) as a timestamp get from the entity.
 */
function _publication_date_published_at_or_created_getter($entity) {
  return $entity->published_at_or_created;
}

/**
 * Implements hook_clone_node_alter().
 *
 * Reset the publication date when a node is cloned using the Node Clone module.
 *
 * @see clone.api.php
 */
function publication_date_clone_node_alter(&$node, $context) {
  $node->published_at = NULL;
  $node->published_at_or_now = REQUEST_TIME;
  $node->published_at_or_changed = REQUEST_TIME;
  $node->published_at_or_created = REQUEST_TIME;
}

/**
 * Implements hook_menu().
 */
function publication_date_menu() {
  $items['admin/config/content/publication-date'] = array(
    'title' => 'Publication date',
    'description' => 'Configure publication date settings when using the date popup module.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'publication_date_admin_form',
    ),
    'access arguments' => array(
      'administer publication date',
    ),
    'file' => 'includes/publication_date.admin.inc',
  );
  return $items;
}

Functions

Namesort descending Description
publication_date_clone_node_alter Implements hook_clone_node_alter().
publication_date_entity_property_info_alter Implements hook_entity_property_info_alter().
publication_date_form_node_form_alter Implements hook_form_BASE_ID_alter().
publication_date_list_permissions Helper function to generate permission each content type.
publication_date_menu Implements hook_menu().
publication_date_node_delete Implements hook_node_delete().
publication_date_node_insert Implements hook_node_insert().
publication_date_node_load Implements hook_node_load().
publication_date_node_update Implements hook_node_update().
publication_date_permission Implements hook_permission().
publication_date_pubdate_submit Node edit form submit handler.
publication_date_pubdate_validate Node edit form validation handler.
publication_date_views_api Implements hook_views_api().
_publication_date_get_date Worker function to get a published date from the database.
_publication_date_published_at_getter Publication date getter for hook_entity_property_info_alter()
_publication_date_published_at_or_changed_getter Publication date or changed getter for hook_entity_property_info_alter()
_publication_date_published_at_or_created_getter Publication date or changed getter for hook_entity_property_info_alter()
_publication_date_published_at_or_now_getter Publication date or now getter for hook_entity_property_info_alter()
_publication_date_published_at_setter Publication date setter for hook_entity_property_info_alter()
_publication_date_set_date Worker function to save the published date to the database.

Constants