You are here

content_lock_timeout.module in Content locking (anti-concurrent editing) 6

Allowed time-based automatic unlocking of nodes locked for editing with content_lock.

File

modules/content_lock_timeout/content_lock_timeout.module
View source
<?php

/**
 * @file
 * Allowed time-based automatic unlocking of nodes locked for editing with content_lock.
 */

/**
 * Implement hook_form_FORM_ID_alter() to append settings to
 * content_lock's settings page.
 */
function content_lock_timeout_form_content_lock_admin_settings_alter(&$form, &$form_state) {
  $form['content_lock_timeout'] = array(
    '#type' => 'fieldset',
    '#title' => t('Lock Timeouts'),
    '#description' => t('Configure automatic stale lock breaking.'),
    '#collapsible' => TRUE,
  );
  $form['content_lock_timeout']['content_lock_timeout_minutes'] = array(
    '#type' => 'textfield',
    '#title' => t('Lock timeout'),
    '#description' => t('The maximum number of minutes that each lock may be kept. Set to zero to not break locks based on time.'),
    '#default_value' => variable_get('content_lock_timeout_minutes', 120),
  );
  $form['content_lock_timeout']['content_lock_timeout_on_edit'] = array(
    '#type' => 'checkbox',
    '#title' => t('Break stale locks on edit'),
    '#description' => t('By default, stale locks will be broken when cron is run. This option enables checking for stale locks when a user clicks a node\'s Edit link, enabling lower lock timeout values without having to run cron every few minutes.'),
    '#default_value' => variable_get('content_lock_timeout_on_edit', FALSE),
  );

  // Apply some form beautification
  $form['buttons']['#weight'] = 2;
  $form['#validate'][] = 'content_lock_timeout_admin_settings_validate';
}

/**
 * Validation handler for the altered content_lock_admin_settings form.
 */
function content_lock_timeout_admin_settings_validate($form, &$form_state) {
  if (!is_numeric($form_state['values']['content_lock_timeout_minutes']) || $form_state['values']['content_lock_timeout_minutes'] <= 0) {
    form_set_error('content_lock_timeout_minutes', t('You must set your content lock timeout value to a positive number.'));
  }
}

/**
 * Implementation of hook_cron().
 *
 * Breaks batches of stale locks whenever the cron hooks are
 * run. Inspired by original content_lock_cron() (leftover from the
 * checkout module).
 */
function content_lock_timeout_cron() {
  $timeout_minutes = variable_get('content_lock_timeout_minutes', 120);
  $last_valid_time = time() - 60 * $timeout_minutes;

  // We call content_lock_release() for each lock so that the
  // hook_content_lock_released may be invoked.
  $result = db_query('SELECT nid FROM {content_lock} WHERE timestamp < %d', $last_valid_time);
  $count = 0;
  while ($nid = db_result($result)) {
    content_lock_release($nid);
    $count++;
  }
  if ($count) {
    $period = format_interval($timeout_minutes * 60);
    watchdog('content_lock_timeout', 'Released @count stale node locks which lasted at least @period.', array(
      '@count' => $count,
      '@period' => $period,
    ));
  }
}

/**
 * Implemention of hook_form_alter().
 *
 * Break stale locks on edit. 
 *
 * Breaks an individual lock when a user attempts to edit a form. This
 * way, if the lock timeout is a low value such as 20 minutes and cron
 * only runs every few hours, a workflow of quick lock breaks can be
 * maintained.
 */
function content_lock_timeout_nodeapi(&$node, $op, $teaser, $page) {
  global $user;
  if (!variable_get('content_lock_timeout_on_edit', FALSE)) {
    return;
  }
  $timeout_minutes = variable_get('content_lock_timeout_minutes', 120);
  switch ($op) {
    case 'prepare':
      $last_valid_time = time() - 60 * $timeout_minutes;
      $lock = content_lock_fetch_lock($node->nid);
      if (is_object($lock) && $lock->uid != $user->uid && $lock->timestamp < $last_valid_time && user_access('check out documents') && $user->uid > 0) {
        content_lock_release($node->nid, $lock->uid);
        if (_content_lock_verbose()) {
          $username = theme('username', $lock);
          $date = format_date($lock->timestamp, 'medium');
          $stale_time = format_interval($last_valid_time - $lock->timestamp);
          drupal_set_message(t('Breaking existing lock by !name so that you may edit this node. (This lock was set on @date and was @stale_time stale.)', array(
            '!name' => $username,
            '@date' => $date,
            '@stale_time' => $stale_time,
          )));
        }
      }
      break;
  }
}

/**
 * Implementation of hook_content_lock_locked().
 *
 * Informs user that his lock will be considered stale.
 */
function content_lock_timeout_content_lock_locked($nid, $uid) {
  if (_content_lock_verbose()) {
    $on_edit = '';
    if (variable_get('content_lock_timeout_on_edit', FALSE)) {
      $on_edit = ' and up for grabs';
    }
    $time = format_interval(variable_get('content_lock_timeout_minutes', 120) * 60);
    drupal_set_message(t('Your lock will be considered stale' . $on_edit . ' in @time.', array(
      '@time' => $time,
    )));
  }
}

Functions

Namesort descending Description
content_lock_timeout_admin_settings_validate Validation handler for the altered content_lock_admin_settings form.
content_lock_timeout_content_lock_locked Implementation of hook_content_lock_locked().
content_lock_timeout_cron Implementation of hook_cron().
content_lock_timeout_form_content_lock_admin_settings_alter Implement hook_form_FORM_ID_alter() to append settings to content_lock's settings page.
content_lock_timeout_nodeapi Implemention of hook_form_alter().