diff --git a/core/modules/node/lib/Drupal/node/Access/NodeAccessCheck.php b/core/modules/node/lib/Drupal/node/Access/NodeAccessCheck.php new file mode 100644 index 0000000..cfa4cb4 --- /dev/null +++ b/core/modules/node/lib/Drupal/node/Access/NodeAccessCheck.php @@ -0,0 +1,93 @@ +getRequirements()); + } + + /** + * This method is only called if applies() returned TRUE above. It may return: + * - TRUE: The user should be given access. + * - FALSE: The user should NOT be given access. + * - NULL: This checker has no input about whether or not access should be granted. + */ + public function access(Route $route, Request $request) { + $account = $GLOBALS['user']; + $op = $route->getRequirement('_node_revision_access'); + $node = $request->attributes->get('node'); + if(empty($node->type)) { + return NULL; + } + + $map = array( + 'view' => 'view all revisions', + 'update' => 'revert all revisions', + 'delete' => 'delete all revisions', + ); + + $type_map = array( + 'view' => "view $node->type revisions", + 'update' => "revert $node->type revisions", + 'delete' => "delete $node->type revisions", + ); + + if (!$node || !isset($map[$op]) || !isset($type_map[$op])) { + // If there was no node to check against, or the $op was not one of the + // supported ones, we return access denied. + return FALSE; + } + + if (!isset($account)) { + $account = $GLOBALS['user']; + } + + // If no language code was provided, default to the node revision's langcode. + if (empty($langcode)) { + $langcode = $node->langcode; + } + + // Statically cache access by revision ID, language code, user account ID, + // and operation. + $cid = $node->vid . ':' . $langcode . ':' . $account->uid . ':' . $op; + + if (!isset($access[$cid])) { + // Perform basic permission checks first. + if (!user_access($map[$op], $account) && !user_access($type_map[$op], $account) && !user_access('administer nodes', $account)) { + return $access[$cid] = FALSE; + } + + // There should be at least two revisions. If the vid of the given node + // and the vid of the default revision differ, then we already have two + // different revisions so there is no need for a separate database check. + // Also, if you try to revert to or delete the default revision, that's + // not good. + if ($node->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField() == 1 || $op == 'update' || $op == 'delete')) { + $access[$cid] = FALSE; + } + elseif (user_access('administer nodes', $account)) { + $access[$cid] = TRUE; + } + else { + // First check the access to the default revision and finally, if the + // node passed in is not the default revision then access to that, too. + $access[$cid] = node_access($op, node_load($node->nid), $account, $langcode) && ($node->isDefaultRevision() || node_access($op, $node, $account, $langcode)); + } + } + + return $access[$cid]; + } +} +?> diff --git a/core/modules/node/lib/Drupal/node/Controller/NodeController.php b/core/modules/node/lib/Drupal/node/Controller/NodeController.php new file mode 100644 index 0000000..bd6e097 --- /dev/null +++ b/core/modules/node/lib/Drupal/node/Controller/NodeController.php @@ -0,0 +1,58 @@ +get('plugin.manager.entity') + ); + } + + public function __construct(EntityManager $entity_manager) { + $this->entityManager = $entity_manager; + } + + public function nodeShow(EntityInterface $node, $node_revision) { + drupal_set_title(t('Revision of %title from %date', array('%title' => $node->label(), '%date' => format_date($node->revision_timestamp))), PASS_THROUGH); + + $node = $this->entityManager->getStorageController('node')->loadRevision($node_revision); + + // For markup consistency with other pages, use node_view_multiple() rather than node_view(). + $nodes = array('nodes' => $this->entityManager->getRenderController('node')->viewMultiple(array($node->nid => $node), 'full')); + + // Update the history table, stating that this user viewed this node. + if (\Drupal::moduleHandler()->moduleExists('history')) { + history_write($node->nid); + } + + return $nodes; + } +} diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 2cd835f..f8ba1e5 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -1742,10 +1742,7 @@ function node_menu() { ); $items['node/%node/revisions/%node_revision/view'] = array( 'title' => 'Revisions', - 'page callback' => 'node_show', - 'page arguments' => array(3, TRUE), - 'access callback' => '_node_revision_access', - 'access arguments' => array(3), + 'route_name' => 'node_show', ); $items['node/%node/revisions/%node_revision/revert'] = array( 'title' => 'Revert to earlier revision', diff --git a/core/modules/node/node.routing.yml b/core/modules/node/node.routing.yml new file mode 100644 index 0000000..d2087ff --- /dev/null +++ b/core/modules/node/node.routing.yml @@ -0,0 +1,10 @@ +node_show: + pattern: /node/{node}/revisions/{node_revision}/view + defaults: + _content: '\Drupal\node\Controller\NodeController::nodeShow' + requirements: + _node_revision_access: 'view' + options: + defaults: + node: \d+ + node_revision: \d+ \ No newline at end of file diff --git a/core/modules/node/node.services.yml b/core/modules/node/node.services.yml new file mode 100644 index 0000000..3b3b217 --- /dev/null +++ b/core/modules/node/node.services.yml @@ -0,0 +1,5 @@ +services: + access_check.revisions: + class: Drupal\node\Access\NodeAccessCheck + tags: + - { name: access_check }