From 68acec2717d4096e3d5160ff36a6994500ec549e Mon Sep 17 00:00:00 2001
From: jwilson3 <jwilson3@220177.no-reply.drupal.org>
Date: Wed, 26 Aug 2015 14:55:21 -0400
Subject: [PATCH] Issue #1408838 by jwilson3, Kristen Pol, miteshmap,
 gabriel.achille, DamienMcKenna, colan: Increase performance on node history
 page.

---
 workbench_moderation.module   | 30 +++++-------------------
 workbench_moderation.node.inc | 54 +++++++++++++++++++++++++++++++++----------
 2 files changed, 48 insertions(+), 36 deletions(-)

diff --git a/workbench_moderation.module b/workbench_moderation.module
index 5a2ff16..1a2f0a0 100644
--- a/workbench_moderation.module
+++ b/workbench_moderation.module
@@ -186,14 +186,15 @@ function workbench_moderation_menu_alter(&$items) {
   $items['node/%node/revisions']['page arguments'] = array(1);
 
   // Override the node revision view callback.
- $items['node/%node/revisions/%/view']['page callback'] = 'workbench_moderation_node_view_revision';
- $items['node/%node/revisions/%/view']['file path'] = drupal_get_path('module', 'workbench_moderation');
- $items['node/%node/revisions/%/view']['file'] = 'workbench_moderation.node.inc';
-
+  $items['node/%node/revisions/%/view']['page callback'] = 'workbench_moderation_node_view_revision';
+  $items['node/%node/revisions/%/view']['file path'] = drupal_get_path('module', 'workbench_moderation');
+  $items['node/%node/revisions/%/view']['file'] = 'workbench_moderation.node.inc';
 
   // For revert and delete operations, use our own access check.
   $items['node/%node/revisions/%/revert']['access callback'] = '_workbench_moderation_revision_access';
+  $items['node/%node/revisions/%/revert']['access arguments'] = array(1, 'update');
   $items['node/%node/revisions/%/delete']['access callback'] = '_workbench_moderation_revision_access';
+  $items['node/%node/revisions/%/delete']['access arguments'] = array(1, 'delete');
 
   // Provide a container administration menu item, if one doesn't already exist.
   if (!isset($items['admin/config/workbench'])) {
@@ -527,27 +528,8 @@ function _workbench_moderation_revision_access($node, $op) {
     }
   }
 
-  // Temporarily give the node an impossible revision.
-  // _node_revision_access() keeps access check results in a static variable
-  // indexed by revision only, not by op. Thus, subsequent checks on the same
-  // vid for different ops yield the same result, regardless of permissions.
-  // Setting a fake vid here allows us to store different static results per op.
-  $tmp = $node->vid;
-  switch ($op) {
-    case 'update':
-      $node->vid = -1;
-      break;
-    case 'delete':
-      $node->vid = -2;
-      break;
-  }
-
   // Check access.
-  $access = _node_revision_access($node, $op);
-
-  // Restore the original revision id.
-  $node->vid = $tmp;
-  return $access;
+  return _node_revision_access($node, $op);
 }
 
 /**
diff --git a/workbench_moderation.node.inc b/workbench_moderation.node.inc
index efe9c4a..a5f6862 100644
--- a/workbench_moderation.node.inc
+++ b/workbench_moderation.node.inc
@@ -83,14 +83,15 @@ function workbench_moderation_node_history_view($node) {
   drupal_set_title(t('History of %title', array('%title' => $node->title)), PASS_THROUGH);
 
   // Get all of the node revisions, each with its most recent moderation.
-  $query = db_select('node', 'n');
+  $query = db_select('node', 'n')->extend('PagerDefault');
   $query->leftJoin('node_revision', 'r', 'n.nid = r.nid');
   $query->leftJoin('users', 'u', 'r.uid = u.uid');
   $query->addField('n', 'vid', 'live_revision');
   $query->condition('n.nid', $node->nid)
     ->orderBy('r.vid', 'DESC')
     ->fields('r', array('nid', 'vid', 'title', 'log', 'uid', 'timestamp'))
-    ->fields('u', array('name'));
+    ->fields('u', array('name'))
+    ->limit(30);
 
   $revisions = $query->execute()
     ->fetchAllAssoc('vid');
@@ -129,14 +130,36 @@ function workbench_moderation_node_history_view($node) {
 
     // Revision operations.
     $revision_operations = array();
-    if (isset($node->workbench_moderation['published']) && $revision->vid == $node->workbench_moderation['published']->vid) {
-      $revision_operations['view'] = workbench_moderation_access_link(t('View'), "node/{$revision->nid}");
-    }
-    elseif ($revision->vid == $node->workbench_moderation['current']->vid) {
-      $revision_operations['view'] = workbench_moderation_access_link(t('View'), "node/{$revision->nid}/current-revision");
+
+    // Loading the node at the specific revision using node_load() is too slow
+    // when there are many revisions, thus we fake it by cloning the original
+    // node and changing the 'vid' and the 'my_revision' elements required for
+    // granting access to the revision operations (view, update/revert, delete).
+    $node_revision = clone $node;
+    $node_revision->vid = $revision->vid;
+    $node_revision->workbench_moderation['my_revision'] = $revision;
+
+    // View operation.
+    if (_workbench_moderation_revision_access($node_revision, 'view')) {
+      // Link to the node page if this is the published revision.
+      if (isset($node->workbench_moderation['published']) && $revision->vid == $node->workbench_moderation['published']->vid) {
+        $url = "node/{$revision->nid}";
+      }
+      // The special case "current-revision" link handles routing for the
+      // current unpublished revision.
+      elseif ($revision->vid == $node->workbench_moderation['current']->vid) {
+        $url = "node/{$revision->nid}/current-revision";
+      }
+      // Otherwise, link to the normal revision view page.
+      else {
+        $url = "node/{$revision->nid}/revisions/{$revision->vid}/view";
+      }
+      $revision_operations['view'] = l(t('View'), $url);
     }
-    else {
-      $revision_operations['view'] = workbench_moderation_access_link(t('View'), "node/{$revision->nid}/revisions/{$revision->vid}/view");
+
+    // Revert operation.
+    if (_workbench_moderation_revision_access($node_revision, 'update')) {
+      $revision_operations['revert'] = l(t('Revert'), "node/{$revision->nid}/revisions/{$revision->vid}/revert");
     }
 
     // Provide a courtesy edit operation if this is the current revision.
@@ -154,8 +177,10 @@ function workbench_moderation_node_history_view($node) {
       $revision_operations['edit'] = l($edit_operation_title, "node/{$revision->nid}/edit", array('query' => array('destination' => "node/{$revision->nid}/moderation")));
     }
 
-    $revision_operations['revert'] = workbench_moderation_access_link(t('Revert'), "node/{$revision->nid}/revisions/{$revision->vid}/revert");
-    $revision_operations['delete'] = workbench_moderation_access_link(t('Delete'), "node/{$revision->nid}/revisions/{$revision->vid}/delete");
+    // Delete operation.
+    if (_workbench_moderation_revision_access($node_revision, 'delete')) {
+      $revision_operations['delete'] = l(t('Delete'), "node/{$revision->nid}/revisions/{$revision->vid}/delete");
+    }
 
     $row['data']['revision'] = implode(' | ', array_filter($revision_operations));
 
@@ -236,7 +261,7 @@ function workbench_moderation_node_history_view($node) {
   $header = array(t('Revision'), t('Title'), t('Date'), t('Revision actions'), t('Moderation actions'));
 
   // Return properly styled output.
-  return array(
+  $build['pager_table'] = array(
     '#attached' => array(
       'css' => array(
         drupal_get_path('module', 'workbench_moderation') . '/css/workbench_moderation.css',
@@ -246,6 +271,11 @@ function workbench_moderation_node_history_view($node) {
     '#header' => $header,
     '#rows' => $rows,
   );
+
+  // Attach the pager theme.
+  $build['pager_pager'] = array('#theme' => 'pager');
+
+  return $build;
 }
 
 /**
-- 
2.1.4

