When you update a node with "New revisions in moderation" checked, but without "Create new revision", the title in the node table isn't updated.

Comments

jconkey’s picture

Has anyone found a solution to this problem? Do you have a patch? Thanks

jconkey’s picture

I think the bug is in revision_moderation_workflow_ng.inc in the last function:

/**
 * Implementation of a worklfow-ng action: publishes a revision.
 */
function revision_moderation_workflow_ng_publish($node) {
  db_query("UPDATE {node} SET vid = %d WHERE nid = %d", $node->vid, $node->nid);
}

To have the title updated also, the function should call revision_moderation_publish (in revision_moderation.module), which properly updates the title field:

/**
 * Implementation of a worklfow-ng action: publishes a revision.
 */
function revision_moderation_workflow_ng_publish($node) {
  revision_moderation_publish($node->nid, $node->vid);
}

I found this when I copied revision_moderation_workflow_ng_publish() to make a function that publishes the latest revision in moderation:

/**
 * Implementation of a workflow-ng action: publishes the latest revision.
 * Fails silently if there is no revision in moderation.
 */
function revision_moderation_workflow_ng_publish_latest_revision($node) {
  // Get the most recent revision for this node.
  $revisions = revision_moderation_get_node_pending_revisions($node->nid);
  if (!empty($revisions)) {
    reset($revisions);
    $newest_vid = key($revisions);
    revision_moderation_publish($node->nid, $newest_vid);
  }
}
add1sun’s picture

Status: Active » Fixed

Yep, core RM doesn't have this problem so this is a Workflow-NG issue. Updated the WNG inc file to use the proper RM function. Committed to 5 dev.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

junro’s picture

Version: 5.x-1.x-dev » 6.x-1.0-alpha2
Status: Closed (fixed) » Active

I've got exactly the same issue with the 6.x-1.0-alpha2 version.

What changes I should do? Into revision_moderation.module file I suppose.

Thanks :)

junro’s picture

Still nobody on this problem?

junro’s picture

Here the file:

// $Id: revision_moderation.module,v 1.39.2.12 2009/12/17 06:18:07 brauerranch Exp $

/**
 * @file
 * Allows moderation of node revisions while existing revisions stay visible.
 */

// Actions module support.
include_once drupal_get_path('module', 'revision_moderation') .'/revision_moderation_actions.inc';

/**
 * Implementation of hook_menu().
 */
function revision_moderation_menu() {
  $items = array();

  // Admin menu
  $items['admin/content/node/revisions'] = array(
    'title' => t('Pending revisions'),
    'page callback' => 'revision_moderation_pending_revisions_admin',
    'access arguments' => array('administer nodes'),
    'type' => MENU_LOCAL_TASK,
  );

  // Admin menu
  $items['admin/settings/revision_moderation'] = array(
    'title' => t('Revision moderation'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('revision_moderation_settings'),
    'description' => t('Configure revision publishing options.'),
    'access arguments' => array('administer nodes'),
  );

  // Callback to allow users to edit revisions.
  $items['node/%node/revisions/%/edit'] = array(
    'title' => t('Edit revision'),
    'load arguments' => array(3),
    'page callback' => 'revision_moderation_edit',
    'page arguments' => array(1),
    'access callback' => '_node_revision_access',
    'access arguments' => array(1, 'update'),
    'file' => 'node.pages.inc',
    'file path' => drupal_get_path('module', 'node'),
    'type' => MENU_CALLBACK,
  );

  // Callback to allow users to publish revisions directly.
  $items['node/%node/revisions/%/publish'] = array(
    'title' => t('Publish revision'),
    'load arguments' => array(3),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('revision_moderation_publish_confirm', 1),
    'access callback' => '_node_revision_access',
    'access arguments' => array(1, 'update'),
    'type' => MENU_CALLBACK,
  );

  return $items;
}

/**
 * Menu permission callback.
 */
function revision_moderation_admin_perm($nid) {
  $node = node_load($nid);
  $access = user_access('administer nodes') || (user_access('view revisions') && node_access('update', $node));
  return $access;
}

/**
 * Menu callback; admin settings page.
 */
function revision_moderation_settings() {
  $form['revision_moderation_exempt'] = array(
    '#type' => 'checkbox',
    '#title' => t('Exempt administrators from revision moderation'),
    '#default_value' => variable_get('revision_moderation_exempt', 1),
    '#description' => t('With this option enabled, users with the "administer nodes" privilege will bypass the moderation system, and their revisions will be published immediately.'),
  );

  return system_settings_form($form);
}

/**
 * Implementation of hook_form_alter().
 */
function revision_moderation_form_alter(&$form, $form_state, $form_id) {
  // On node edit forms, add in the "New revisions in moderation" option.
  if (isset($form['#id']) && $form['#id'] == 'node-form') {
    $default_value = in_array('revision_moderation', variable_get("node_options_{$form['type']['#value']}", array('status', 'promote')));
    if ($form['nid']['#value']) {
      $result = db_result(db_query('SELECT revision_moderation FROM {revision_moderation} WHERE nid = %d', $form['nid']['#value']));
      if ($result !== FALSE) {
        $default_value = $result;
      }
    }
    // Only show the checkbox if user has 'administer nodes' privileges.
    if (!empty($node->revision) || user_access('administer nodes')) {
      $form['revision_information']['revision_moderation'] = array(
        '#type' => 'checkbox',
        '#title' => t('New revisions in moderation'),
        '#default_value' => $default_value,
      );
    }
    else {
      $form['revision_moderation'] = array(
        '#type' => 'value',
        '#value' => $default_value,
      );
    }
  }
  // Also add option to node settings form
  elseif ($form_id == 'node_type_form') {
    $form['workflow']['node_options']['#options']['revision_moderation'] = t('New revisions in moderation');
  }
}

/**
 * Implementation of hook_nodeapi().
 */
function revision_moderation_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  $args = arg();
  switch ($op) {
    case 'insert':
      // Store revision moderation setting of this node.
      drupal_write_record('revision_moderation', $node);
      break;

    case 'update':
      // Update revision moderation setting of this node.
      drupal_write_record('revision_moderation', $node, 'nid');
      break;

    case 'delete':
      // Delete record from revision_moderation table when node is deleted.
      db_query('DELETE FROM {revision_moderation} WHERE nid = %d', $node->nid);
      break;

    case 'load':
      // Set a revision_moderation property which can be checked later.
      $node->revision_moderation = db_result(db_query('SELECT revision_moderation FROM {revision_moderation} WHERE nid = %d', $node->nid));
      break;

    case 'view':
      // Cannot use _node_revision_access() here, it's static cached with 1 op
      $access_update = user_access('revert revisions');
      $access_delete = user_access('delete revisions');
      // Display more descriptive message at the top of node revision views, including operations
      // that the current user has available to them.
      $current_vid = db_result(db_query('SELECT vid FROM {node} WHERE nid = %d', $node->nid));
      if ($node->vid != $current_vid) {
        $links = array(); // Array of links to show along with the message.
        if ($access_update) {
          // Add a link directly to the diff if we have Diff module installed.
          if (module_exists('diff')) {
           if ($node->vid > $current_vid) {
             $difflink = "node/$node->nid/revisions/view/$current_vid/$node->vid";
           }
           else {
             $difflink = "node/$node->nid/revisions/view/$node->vid/$current_vid";
           }
           $links[] = l(t('Compare revisions'), $difflink);
          }
          $links[] = l(t('Edit revision'), "node/$node->nid/revisions/$node->vid/edit");
          // If this revision is old, show an option to revert to it.
          // Otherwise, show an option to publish it.
          if ($node->vid < $current_vid) {
            $links[] = l(t('Revert to revision'), "node/$node->nid/revisions/$node->vid/revert");
          }
          else {
            $links[] = l(t('Publish revision'), "node/$node->nid/revisions/$node->vid/publish");
          }
        }
        if ($access_delete) {
          $links[] = l(t('Delete revision'), "node/$node->nid/revisions/$node->vid/delete");
        }
        // Get username for the revision rather than the original node.
        $revision_author = user_load($node->revision_uid);
        drupal_set_message(t('You are currently viewing a revision of this post created on @date by !author.', array('@date' => format_date($node->revision_timestamp, 'small'), '!author' => theme('username', $revision_author))) . theme('item_list', $links));
      }
      elseif ($node->revision_moderation == 1 && !$teaser) {
        // Notify admin if a node has pending revisions.
        if ($access_update && arg(2) != 'revisions' && revision_moderation_get_node_pending_revisions($node->nid)) {
          drupal_set_message(t('This post has one or more pending revisions: <a href="@list">view list of revisions</a>.', array('@list' => url("node/$node->nid/revisions"))));
        }
      }
      break;
  }

  // Only do this logic for non-admin users on nodes with revision moderation
  // turned on.
  // And not editing a chose revision
  if ($node->nid && $node->revision_moderation == 1 && arg(2) != 'revisions'
    && (!user_access('administer nodes') || !variable_get('revision_moderation_exempt', 1))) {
    switch ($op) {
      case 'prepare':
        // If user has a pending revision for this node, load the latest version of
        // it instead.
        if ($revisions = revision_moderation_get_node_pending_revisions($node->nid)) {
          global $user;
          foreach ($revisions as $revision) {
            if ($revision->uid == $user->uid) {
              drupal_set_message(t('Editing your latest revision, which is still pending moderation.'));
              $node = node_load($node->nid, $revision->vid);
              break;
            }
          }
        }
        break;

      case 'presave':
        $current_vid = db_result(db_query('SELECT vid FROM {node} WHERE nid = %d', $node->nid));
        $node->original_node = node_load($node->nid, $current_vid);
        break;

      case 'update':
        if (isset($node->original_node)) {
          // Update node table's vid to the original value.

          db_query("UPDATE {node} SET vid = %d, title = '%s', status = %d, moderate = %d WHERE nid = %d", $node->original_node->vid, $node->original_node->title, $node->original_node->status, $node->original_node->moderate, $node->nid);

          // If node doesn't exist in revision_moderation table, add it.
          $in_db = db_result(db_query("SELECT revision_moderation FROM {revision_moderation} WHERE nid = %d", $node->nid));
          if ($in_db === FALSE) {
            db_query("INSERT INTO {revision_moderation} (nid, revision_moderation) VALUES(%d, 1)", $node->nid);
          }

          drupal_set_message(t('Your changes have been submitted for moderation.'));
        }
        break;
    }
  }
  else if ($node->nid && $node->revision_moderation == 1 && end($args) == 'edit') {
    switch ($op) {
      case 'prepare':
		$revision_author = user_load($node->revision_uid);
  		drupal_set_message(t('You are currently editing a revision of this post created on @date by !author.', array('@date' => format_date($node->revision_timestamp, 'small'), '!author' => theme('username', $revision_author))));
        break;
      case 'presave':
        $current_vid = db_result(db_query('SELECT vid FROM {node} WHERE nid = %d', $node->nid));
        $node->original_node = node_load($node->nid, $current_vid);
        break;

      case 'update':
        if (isset($node->original_node)) {
          // Update node table's vid to the original value.

          db_query("UPDATE {node} SET vid = %d, title = '%s', status = %d, moderate = %d WHERE nid = %d", $node->original_node->vid, $node->original_node->title, $node->original_node->status, $node->original_node->moderate, $node->nid);
          drupal_set_message(t('Your changes have been submitted for moderation.'));
        }
        break;
    }
  }
 
}

/**
 * Implementation of hook_block().
 */
function revision_moderation_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks[0]['info'] = t('Pending revisions');

    return $blocks;
  }
  elseif ($op == 'view') {
    $block = array();

    if (user_access('administer nodes')) {
      $output = '';
      $list = array();

      $nodes = revision_moderation_get_all_pending_revisions(10);
      if (count($nodes)) {
        foreach ($nodes as $node) {
          $list[] = l($node->title, "node/$node->nid/revisions/$node->vid/view");
        }
        $output .= theme('item_list', $list);
        $output .= '<p>'. l(t('View all pending revisions'), 'admin/content/node/revisions') .'</p>';
      }
      else {
        $output .= t('No pending revisions found.');
      }

      $block['subject'] = t('Pending revisions');
      $block['content'] = $output;
    }

    return $block;
  }
}

/**
 * Menu callback to display list of nodes with pending revisions.
 */
function revision_moderation_pending_revisions_admin() {
  return theme('revision_moderation_pending_revisions_admin');
}

/**
 * Implementation of hook_theme().
 */
function revision_moderation_theme() {
  return array(
    'revision_moderation_pending_revisions_admin' => array(
      'arguments' => array(),
    ),
  );
}

/**
 * Displays list of nodes with pending revisions.
 */
function theme_revision_moderation_pending_revisions_admin() {
  $nodes = revision_moderation_get_all_pending_revisions(50);
  if (count($nodes)) {
    $header = array(
      t('Title'),
      t('Type'),
      t('Updated by'),
      t('Last updated'),
    );
    $rows = array();
    foreach ($nodes as $node) {
      $rows[] = array(
        l($node->title, "node/$node->nid/revisions"),
        check_plain(node_get_types('name', $node)),
        theme('username', user_load(array('uid' => $node->uid))),
        format_date($node->timestamp),
      );
    }
    return theme('table', $header, $rows);
  }
  else {
    return '<p>'. t('No pending revisions found.') .'</p>';
  }
}

/**
 * Retrieve list of all pending revisions.
 *
 * @param $limit
 *  The number of pending revisions to retrieve.
 */
function revision_moderation_get_all_pending_revisions($limit) {
  // Obtain a list of nodes with revisions higher than current published revision.
  $sql = "SELECT n.nid, r.vid, n.type, r.title, r.body, r.uid, r.timestamp FROM {node} n INNER JOIN {node_revisions} r ON n.nid = r.nid WHERE r.vid > n.vid ORDER BY r.vid DESC LIMIT %d";
  $result = db_query($sql, $limit);
  $revisions = array();
  while ($revision = db_fetch_object($result)) {
    $revisions[$revision->nid] = $revision;
  }

  return $revisions;
}

/**
 * Retrieve list of all pending revisions for a given node.
 *
 * @param $nid
 *  The node ID to retrieve.
 */
function revision_moderation_get_node_pending_revisions($nid) {
  // Obtain a list of revisions higher than current published revision for a given node.
  $sql = "SELECT n.nid, r.vid, r.uid FROM {node} n INNER JOIN {node_revisions} r ON n.nid = r.nid WHERE r.vid > n.vid AND n.nid = %d ORDER BY r.vid DESC";
  $result = db_query($sql, $nid);
  $revisions = array();
  while ($revision = db_fetch_object($result)) {
    $revisions[$revision->vid] = $revision;
  }

  return $revisions;
}

/**
 * Menu callback; edit revision.
 */
function revision_moderation_edit($node) {
  // Get username for the revision rather than the original node.
  //$revision_author = user_load($node->revision_uid);
  //drupal_set_message(t('You are currently editing a revision of this post created on @date by !author.', array('@date' => format_date($node->revision_timestamp, 'small'), '!author' => theme('username', $revision_author))));
  return drupal_get_form($node->type .'_node_form', $node);
}

/**
 * Returns a confirmation page for publishing a revision.
 *
 * @param $node
 *   The node object for which revision is to be published.
 */
function revision_moderation_publish_confirm($form_state, $node) {
  $form['node_id'] = array('#type' => 'value', '#value' => $node->nid);
  $form['title'] = array('#type' => 'value', '#value' => $node->title);
  $form['revision'] = array('#type' => 'value', '#value' => $node->vid);
  $form['type'] = array('#type' => 'value', '#value' => $node->type);

  return confirm_form($form, t('Are you sure you want to publish this revision for %title?', array('%title' => $node->title)), 'node/'. $node->nid .'/revisions/'. $node->vid, t('Publishing this revision will make it public for all users.'), t('Publish'), t('Cancel'));
}

/**
 * Submission handler for the publish confirm form.
 * Publishes a revision directly.
 */
function revision_moderation_publish_confirm_submit($form, &$form_state) {
  $nid = $form_state['values']['node_id'];
  $title = $form_state['values']['title'];
  $vid = $form_state['values']['revision'];
  $type = $form_state['values']['type'];

  db_query("UPDATE {node} SET vid = %d, title = '%s' WHERE nid = %d", $vid, $title, $nid);
  // Clear the cache so an anonymous poster can see the changes
  cache_clear_all();
  drupal_set_message('The selected revision has been published.');
  watchdog('content', '@type: published %title revision %revision', array('@type' => t($type), '%title' => $title, '%revision' => $vid), WATCHDOG_NOTICE, l(t('view'), "node/$nid/revisions/$vid/view"));
  $form_state['redirect'] = 'node/'. $nid;
}
junro’s picture

Nobody knows this module ?