diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index ec05c1a..97e3451 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -280,7 +280,7 @@ public function access($operation = 'view', AccountInterface $account = NULL) { } return \Drupal::entityManager() ->getAccessController($this->entityType) - ->access($this, $operation, Language::LANGCODE_DEFAULT, $account); + ->access($this, $operation, $this->language()->id, $account); } /** diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php index 62b5bfb..bbf97ff 100644 --- a/core/lib/Drupal/Core/Entity/EntityNG.php +++ b/core/lib/Drupal/Core/Entity/EntityNG.php @@ -420,7 +420,7 @@ public function access($operation = 'view', AccountInterface $account = NULL) { } return \Drupal::entityManager() ->getAccessController($this->entityType) - ->access($this, $operation, $this->activeLangcode, $account); + ->access($this, $operation, $this->language()->id, $account); } /** diff --git a/core/modules/forum/lib/Drupal/forum/ForumBreadcrumbBuilder.php b/core/modules/forum/lib/Drupal/forum/ForumBreadcrumbBuilder.php index c8d523c..fcf2921 100644 --- a/core/modules/forum/lib/Drupal/forum/ForumBreadcrumbBuilder.php +++ b/core/modules/forum/lib/Drupal/forum/ForumBreadcrumbBuilder.php @@ -54,15 +54,6 @@ public function build(array $attributes) { $item = $attributes['_drupal_menu_item']; switch ($item['path']) { - case 'node/%': - $node = $item['map'][1]; - // Load the object in case of missing wildcard loaders. - $node = is_object($node) ? $node : node_load($node); - if (_forum_node_check_node_type($node)) { - $breadcrumb = $this->forumPostBreadcrumb($node); - } - break; - case 'forum/%': $term = $item['map'][1]; // Load the object in case of missing wildcard loaders. @@ -71,6 +62,12 @@ public function build(array $attributes) { break; } } + elseif (isset($attributes['node'])) { + $node = $attributes['node']; + if (_forum_node_check_node_type($node)) { + $breadcrumb = $this->forumPostBreadcrumb($node); + } + } if (!empty($breadcrumb)) { return $breadcrumb; diff --git a/core/modules/node/lib/Drupal/node/Controller/NodeController.php b/core/modules/node/lib/Drupal/node/Controller/NodeController.php index 465975d..b2574cf 100644 --- a/core/modules/node/lib/Drupal/node/Controller/NodeController.php +++ b/core/modules/node/lib/Drupal/node/Controller/NodeController.php @@ -7,69 +7,16 @@ namespace Drupal\node\Controller; -use Drupal\Core\Controller\ControllerInterface; -use Drupal\Core\Entity\EntityRenderControllerInterface; -use Drupal\Core\Entity\EntityStorageControllerInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Controller\ControllerBase; use Drupal\node\NodeInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * View controller for nodes. */ -class NodeController implements ControllerInterface { +class NodeController extends ControllerBase { /** - * Stores the injected Module Handler. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * The node storage controller. - * - * @var \Drupal\Core\Entity\EntityStorageControllerInterface - */ - protected $storageController; - - /** - * The node render controller. - * - * @var \Drupal\Core\Entity\EntityRenderControllerInterface - */ - protected $renderController; - - /** - * Constructs a new NodeController. - * - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler. - * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller - * The node storage controller. - * @param \Drupal\Core\Entity\EntityRenderControllerInterface $render_controller - * The node render controller. - */ - public function __construct(ModuleHandlerInterface $module_handler, EntityStorageControllerInterface $storage_controller, EntityRenderControllerInterface $render_controller) { - $this->moduleHandler = $module_handler; - $this->storageController = $storage_controller; - $this->renderController = $render_controller; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - $entity_manager = $container->get('plugin.manager.entity'); - return new static( - $container->get('module_handler'), - $entity_manager->getStorageController('node'), - $entity_manager->getRenderController('node') - ); - } - - /** - * Generates an array which displays a node detail page. + * Display a specific revision of a single node. * * @param \Drupal\node\NodeInterface $node * The node being shown. @@ -80,19 +27,57 @@ public static function create(ContainerInterface $container) { * A $page element suitable for use by drupal_render(). */ public function nodeRevisionView(NodeInterface $node, $node_revision) { + // @todo Replace this once https://drupal.org/node/2032535 is in and we + // have a better way of dealing with titles. drupal_set_title(t('Revision of %title from %date', array('%title' => $node->label(), '%date' => format_date($node->revision_timestamp))), PASS_THROUGH); - $node = $this->storageController->loadRevision($node_revision); + $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->renderController->viewMultiple(array($node->id() => $node), 'full')); + $render_array = $this->entityManager()->getRenderController('node')->view($node, 'full'); // Update the history table, stating that this user viewed this node. - if ($this->moduleHandler->moduleExists('history')) { + if ($this->moduleHandler()->moduleExists('history')) { history_write($node->id()); } - return $nodes; + return $render_array; } + /** + * Displays a single node. + * + * @param \Drupal\Core\Entity\EntityInterface $node + * The node entity. + * + * @return + * A page array suitable for use by drupal_render(). + */ + public function nodeView(NodeInterface $node) { + // If there is a menu link to this node, the link becomes the last part + // of the active trail, and the link name becomes the page title. + // Thus, we must explicitly set the page title to be the node title. + // @todo Replace this once https://drupal.org/node/2032535 is in and we + // have a better way of dealing with titles. + drupal_set_title($node->label()); + + foreach ($node->uriRelationships() as $rel) { + $uri = $node->uri($rel); + // Set the node path as the canonical URL to prevent duplicate content. + drupal_add_html_head_link(array('rel' => $rel, 'href' => url($uri['path'], $uri['options'])), TRUE); + + if ($rel == 'canonical') { + // Set the non-aliased canonical path as a default shortlink. + drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE); + } + } + + $render_array = $this->entityManager()->getRenderController('node')->view($node, 'full'); + + // Update the history table, stating that this user viewed this node. + if ($this->moduleHandler()->moduleExists('history')) { + history_write($node->id()); + } + + return $render_array; + } } diff --git a/core/modules/node/lib/Drupal/node/NodeBreadcrumbBuilder.php b/core/modules/node/lib/Drupal/node/NodeBreadcrumbBuilder.php new file mode 100644 index 0000000..65cc3de --- /dev/null +++ b/core/modules/node/lib/Drupal/node/NodeBreadcrumbBuilder.php @@ -0,0 +1,55 @@ +translation = $translation; + } + + /** + * {@inheritdoc} + */ + public function build(array $attributes) { + $trail = array(); + $node = NULL; + + // @todo This only works for legacy routes. Once node/% has been converted + // to the new router this code will need to be updated. + if (isset($attributes['_drupal_menu_item'])) { + $trail = explode('/', $attributes['_drupal_menu_item']['href']); + $node = $attributes['_drupal_menu_item']['map'][1]; + } + // This is for the new routing system. + elseif (isset($attributes['node'])) { + $trail = explode('/', $attributes['_system_path']); + $node = $attributes['node']; + } + + // Show breadcrumbs for all subpages like /edit, /delete or any other. + if (count($trail) > 2 && $trail[0] == 'node' && is_numeric($trail[1])) { + $breadcrumb = array(); + $breadcrumb[] = l($this->translation->translate('Home'), NULL); + $breadcrumb[] = l($node->label(), 'node/' . $node->id()); + return $breadcrumb; + } + } +} diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 53fb45e..c322f22 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -607,46 +607,18 @@ function node_revision_delete($revision_id) { } /** - * Page callback: Generates an array which displays a node detail page. - * - * @param \Drupal\Core\Entity\EntityInterface $node - * A node entity. - * @param $message - * (optional) A flag which sets a page title relevant to the revision being - * viewed. Default is FALSE. - * - * @return - * A $page element suitable for use by drupal_render(). - * - * @see node_menu() - */ -function node_show(EntityInterface $node, $message = FALSE) { - if ($message) { - drupal_set_title(t('Revision of %title from %date', array('%title' => $node->label(), '%date' => format_date($node->getRevisionCreationTime()))), PASS_THROUGH); - } - - // For markup consistency with other pages, use node_view_multiple() rather than node_view(). - $nodes = array('nodes' => node_view_multiple(array($node->id() => $node), 'full')); - - // Update the history table, stating that this user viewed this node. - if (module_exists('history')) { - history_write($node->id()); - } - - return $nodes; -} - -/** * Checks whether the current page is the full page view of the passed-in node. * * @param \Drupal\Core\Entity\EntityInterface $node * A node entity. * + * @deprecated This function relies on global state, which is unreliable. + * * @return * The ID of the node if this is a full page view, otherwise FALSE. */ -function node_is_page(EntityInterface $node) { - $page_node = menu_get_object(); +function node_is_page(NodeInterface $node) { + $page_node = Drupal::service('request')->attributes->get('node'); return (!empty($page_node) ? $page_node->id() == $node->id() : FALSE); } @@ -1208,12 +1180,7 @@ function node_menu() { $items['node/%node'] = array( 'title callback' => 'node_page_title', 'title arguments' => array(1), - // The page callback also invokes drupal_set_title() in case - // the menu router's title is overridden by a menu link. - 'page callback' => 'node_page_view', - 'page arguments' => array(1), - 'access callback' => 'node_access', - 'access arguments' => array('view', 1), + 'route_name' => 'node_view', ); $items['node/%node/view'] = array( 'title' => 'View', @@ -1674,37 +1641,6 @@ function node_view_multiple($nodes, $view_mode = 'teaser', $langcode = NULL) { } /** - * Page callback: Displays a single node. - * - * @param \Drupal\Core\Entity\EntityInterface $node - * The node entity. - * - * @return - * A page array suitable for use by drupal_render(). - * - * @see node_menu() - */ -function node_page_view(EntityInterface $node) { - // If there is a menu link to this node, the link becomes the last part - // of the active trail, and the link name becomes the page title. - // Thus, we must explicitly set the page title to be the node title. - drupal_set_title($node->label()); - - foreach ($node->uriRelationships() as $rel) { - $uri = $node->uri($rel); - // Set the node path as the canonical URL to prevent duplicate content. - drupal_add_html_head_link(array('rel' => $rel, 'href' => url($uri['path'], $uri['options'])), TRUE); - - if ($rel == 'canonical') { - // Set the non-aliased canonical path as a default shortlink. - drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE); - } - } - - return node_show($node); -} - -/** * Implements hook_update_index(). */ function node_update_index() { diff --git a/core/modules/node/node.routing.yml b/core/modules/node/node.routing.yml index 0e72b55..905b0dd 100644 --- a/core/modules/node/node.routing.yml +++ b/core/modules/node/node.routing.yml @@ -30,6 +30,16 @@ node_revision_view: node: \d+ node_revision: \d+ +node_view: + pattern: /node/{node} + defaults: + _content: '\Drupal\node\Controller\NodeController::nodeView' + requirements: + _permission: 'access content' + options: + defaults: + node: \d+ + node_revision_revert_confirm: pattern: '/node/{node}/revisions/{node_revision}/revert' defaults: diff --git a/core/modules/node/node.services.yml b/core/modules/node/node.services.yml index ab49617..0dac681 100644 --- a/core/modules/node/node.services.yml +++ b/core/modules/node/node.services.yml @@ -7,3 +7,8 @@ services: arguments: ['@plugin.manager.entity', '@database'] tags: - { name: access_check } + node.breadcrumb: + class: Drupal\node\NodeBreadcrumbBuilder + arguments: ['@string_translation'] + tags: + - { name: breadcrumb_builder, priority: 10 } diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php index dd4cee8..59813aa 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php @@ -175,9 +175,6 @@ function testBreadCrumbs() { $this->assertBreadcrumb("node/$nid1", $trail); // Also verify that the node does not appear elsewhere (e.g., menu trees). $this->assertNoLink($node1->title); - // The node itself should not be contained in the breadcrumb on the default - // local task, since there is no difference between both pages. - $this->assertBreadcrumb("node/$nid1/view", $trail); // Also verify that the node does not appear elsewhere (e.g., menu trees). $this->assertNoLink($node1->title); @@ -221,9 +218,6 @@ function testBreadCrumbs() { "node/$nid2" => $node2->menu['link_title'], ); $this->assertBreadcrumb("node/$nid2", $trail, $node2->title, $tree); - // The node itself should not be contained in the breadcrumb on the - // default local task, since there is no difference between both pages. - $this->assertBreadcrumb("node/$nid2/view", $trail, $node2->title, $tree); $trail += array( "node/$nid2" => $node2->menu['link_title'], ); @@ -245,9 +239,6 @@ function testBreadCrumbs() { $nid3 = $node3->id(); $this->assertBreadcrumb("node/$nid3", $trail, $node3->title, $tree, FALSE); - // The node itself should not be contained in the breadcrumb on the - // default local task, since there is no difference between both pages. - $this->assertBreadcrumb("node/$nid3/view", $trail, $node3->title, $tree, FALSE); $trail += array( "node/$nid3" => $node3->menu['link_title'], );