You are here

enforce_revlog.module in Enforce revision log message 8

Same filename and directory in other branches
  1. 6 enforce_revlog.module
  2. 7 enforce_revlog.module

Allows enforcing unpriviledged users to enter a log message every time a revisionable entity revision is created or reverted

File

enforce_revlog.module
View source
<?php

/**
 * @file
 * Allows enforcing unpriviledged users to enter a log message every time
 * a revisionable entity revision is created or reverted
 */

/**
 * Implements hook_menu().
 *
 * Administration page and JS callback
 */
function enforce_revlog_menu() {
  $items = array();
  $items['admin/config/user-interface/enforce_revlog'] = array(
    'title' => 'Enforce revlog',
    'description' => 'Enforce users to enter a log message for every revision.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'enforce_revlog_settings',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer site configuration',
    ),
  );
  return $items;
}

/**
 * Settings page
 */
function enforce_revlog_settings() {
  $form['info_msg'] = array(
    '#type' => 'markup',
    // not necessary (default value), added for exhaustivity
    '#value' => t('Do not forget to <a href="@setperms">set permissions</a> for roles that will be able to skip entering a log message', array(
      '@setperms' => url('admin/people/permissions', array(
        'fragment' => 'module-enforce_revlog',
      )),
    )),
    // use placeholder and url() as it's best practice for these translatable strings
    '#prefix' => '<p><em>',
    '#suffix' => '</em></p>',
  );
  $form['enforce_revlog_revision_revert'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enforce users to enter a log message when reverting a revision'),
    '#default_value' => variable_get('enforce_revlog_revision_revert', 0),
  );
  $form['types'] = array(
    '#type' => 'fieldset',
    '#title' => t('Enforce users to enter a log message for every revision of these content types'),
    '#description' => t('Each selected content type must have revisions enabled for this module to work'),
  );

  // Generate per content-type settings
  foreach (node_type_get_names() as $type => $name) {
    $form['types']['enforce_revlog_node_type_' . $type] = array(
      '#type' => 'checkbox',
      '#title' => $name,
      '#default_value' => variable_get('enforce_revlog_node_type_' . $type, 0),
    );
  }
  return system_settings_form($form);
}

/**
 * Implements hook_node_prepare().
 */
function enforce_revlog_node_prepare($node) {
  $node->enforce_revlog = FALSE;

  // We should enable enforce_revlog on add/edit form if:
  if (isset($node->nid) && (variable_get('enforce_revlog_node_type_' . $node->type, 0) && !user_access('skip revision log message'))) {
    $node->enforce_revlog = TRUE;
  }
}

/**
 * Implements hook_node_presave().
 */
function enforce_revlog_node_presave($node) {

  // Trigger only if we're reverting a revision
  // Determined thanks to a custom property in the node object
  if (!empty($node->enforce_revlog_revision_revert)) {

    // Adding the custom log message to the standard one
    $node->log = $node->enforce_revlog_log_message . ' (' . $node->log . ')';

    // Deleting custom object properties, there aren't needed anymore
    unset($node->enforce_revlog_log_message, $node->enforce_revlog_revision_revert);
  }
}

/**
 * Implements hook_help().
 */
function enforce_revlog_help($path, $arg) {
  switch ($path) {
    case 'admin/help#enforce_revlog':

      // Help page
      return '<p>' . t('Enforce users to enter a log message for every revision.') . '</p>';
    case 'admin/config/user-interface/enforce_revlog':

      // Settings page header
      return '<p>' . t('Settings for Enforce revlog module.') . '</p>';
  }
}

/**
 * Implements hook_form_alter().
 *
 * Trying to identify all node forms to enable log message textarea as required
 */
function enforce_revlog_form_alter(&$form, &$form_state, $form_id) {
  if (strpos($form_id, 'node_form')) {

    // Get required state for revision message
    $required = isset($form_state['values']['revision']) ? (bool) $form_state['values']['revision'] : (bool) $form['revision_information']['revision']['#default_value'];

    // Only alter form if enforce_revlog is enabled
    if (!empty($form['#node']->enforce_revlog)) {

      // Mark the log message as required if creation of a new revision is enabled
      if (!empty($form['#node']->revision)) {
        $form['revision_information']['log']['#prefix'] = '<div id="enforce-revlog-wrapper">';
        $form['revision_information']['log']['#suffix'] = '</div>';
        $form['revision_information']['log']['#required'] = $required;
        $form['revision_information']['revision']['#ajax'] = array(
          'callback' => 'enforce_revlog_js',
          'wrapper' => 'enforce-revlog-wrapper',
        );
      }

      // Handle buttons before validation
      $form['#after_build'][] = 'enforce_revlog_after_build';
    }
  }
  elseif ($form_id == 'node_revision_revert_confirm') {

    // Add a log message textarea to the revision revert form - adapt the one from node.module
    $form['log'] = array(
      '#type' => 'textarea',
      '#title' => t('Log message'),
      '#default_value' => '',
      '#rows' => 2,
      '#description' => t('An explanation of your reasons for reverting the revision to help other authors understand your motivations.'),
      '#required' => variable_get('enforce_revlog_revision_revert', 0) && !user_access('skip revision log message'),
    );

    // Adding our own properties to the node object for future use
    $form['#node_revision']->enforce_revlog_revision_revert = 1;
    $form['#node_revision']->enforce_revlog_log_message = '';

    // Custom validation function
    $form['#validate'][] = 'enforce_revlog_revision_revert_validate';
  }
  elseif ($form_id == 'node_type_form') {

    // Adding enforce_revlog setting on the content type editing form.
    // Value will be automatically saved in the variable table.
    // Content type name changes are handled automatically too.
    $form['workflow']['enforce_revlog_node_type'] = array(
      '#type' => 'radios',
      '#title' => t('Enforce users to enter a log message for every revision'),
      '#description' => t('Revisions must be enabled for this module to work'),
      '#default_value' => variable_get('enforce_revlog_node_type_' . $form['#node_type']->type, 0),
      '#options' => array(
        t('Disabled'),
        t('Enabled'),
      ),
    );
  }
}

/**
 * After build callback
 */
function enforce_revlog_after_build($form, $form_state) {

  // Do not require a log message when previewing or deleting the node
  $excluded = array(
    $form['actions']['preview']['#value'],
  );
  if (isset($form['actions']['delete']['#value'])) {
    $excluded[] = $form['actions']['delete']['#value'];
  }
  if (!empty($form_state['input']['op']) && in_array($form_state['input']['op'], $excluded)) {
    $form['revision_information']['log']['#validated'] = TRUE;
  }
  return $form;
}

/**
 * Validation function for the revision revert form
 * Passing $form by reference to store changes to the object
 */
function enforce_revlog_revision_revert_validate(&$form, &$form_state) {

  // Storing the custom log message in the node object
  $form['#node_revision']->enforce_revlog_log_message = check_plain($form_state['values']['log']);
}

/**
 * AJAX callback to change the required state of the log message textarea.
 * Allows visual feedback by the user.
 * This function is only triggered when the right conditions are met.
 */
function enforce_revlog_js($form, $form_state) {
  $form['revision_information']['log']['#required'] = (bool) $form_state['values']['revision'];
  return $form['revision_information']['log'];
}

/**
 * Implements hook_node_type_delete().
 *
 * Deleting associated variable when content type is deleted
 * Avoiding issues with unused variables and hook_uninstall()
 * Update is handled automatically
 * @see enforce_revlog_uninstall()
 */
function enforce_revlog_node_type_delete($info) {
  variable_del('enforce_revlog_node_type_' . $info->type);
}

Functions

Namesort descending Description
enforce_revlog_after_build After build callback
enforce_revlog_form_alter Implements hook_form_alter().
enforce_revlog_help Implements hook_help().
enforce_revlog_js AJAX callback to change the required state of the log message textarea. Allows visual feedback by the user. This function is only triggered when the right conditions are met.
enforce_revlog_menu Implements hook_menu().
enforce_revlog_node_prepare Implements hook_node_prepare().
enforce_revlog_node_presave Implements hook_node_presave().
enforce_revlog_node_type_delete Implements hook_node_type_delete().
enforce_revlog_revision_revert_validate Validation function for the revision revert form Passing $form by reference to store changes to the object
enforce_revlog_settings Settings page