publication_date.module in Publication Date 7.2
Same filename and directory in other branches
Add a field to nodes containing the publication date.
File
publication_date.moduleView 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;
}