diff --git a/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php b/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php index 29fa9bc..c608b87 100644 --- a/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php +++ b/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Menu; use Drupal\Core\Access\AccessManagerInterface; +use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\Query\QueryFactory; use Drupal\Core\Session\AccountInterface; @@ -45,6 +46,13 @@ class DefaultMenuLinkTreeManipulators { protected $queryFactory; /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityManagerInterface + */ + protected $entityManager; + + /** * Constructs a \Drupal\Core\Menu\DefaultMenuLinkTreeManipulators object. * * @param \Drupal\Core\Access\AccessManagerInterface $access_manager @@ -53,11 +61,14 @@ class DefaultMenuLinkTreeManipulators { * The current user. * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory * The entity query factory. + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. */ - public function __construct(AccessManagerInterface $access_manager, AccountInterface $account, QueryFactory $query_factory) { + public function __construct(AccessManagerInterface $access_manager, AccountInterface $account, QueryFactory $query_factory, EntityManagerInterface $entity_manager) { $this->accessManager = $access_manager; $this->account = $account; $this->queryFactory = $query_factory; + $this->entityManager = $entity_manager; } /** @@ -139,6 +150,49 @@ public function checkNodeAccess(array $tree) { } /** + * Load all entities which are part of the menu tree using loadMultiple(). + * + * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree + * The menu link tree to manipulate. + */ + public function loadEntities(array &$tree) { + $entity_ids = []; + $this->collectEntityIds($tree, $entity_ids); + + foreach ($entity_ids as $entity_type => $ids) { + $this->entityManager->getStorage($entity_type)->loadMultiple(array_unique($ids)); + } + } + + /** + * Collect all entity IDs of all referenced entities. + * + * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree + * The menu link tree to manipulate. + * @param array $entity_ids + * The entity IDs keyed by entity type. + */ + protected function collectEntityIds(array &$tree, array &$entity_ids) { + foreach ($tree as $key => &$element) { + if (isset($element->access)) { + continue; + } + $route_name = $element->link->getRouteName(); + // Find a better way to extract the entity type. + if (strpos($route_name, 'entity.') === 0 && strpos($route_name, '.canonical') !== FALSE) { + $entity_type = substr($route_name, 7, -10); + $parameters = $element->link->getRouteParameters(); + if (isset($parameters[$entity_type])) { + $entity_ids[$entity_type][] = $parameters[$entity_type]; + } + } + if ($element->hasChildren) { + $this->collectNodeLinks($element->subtree, $entity_ids); + } + } + } + + /** * Collects the node links in the menu tree. * * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree diff --git a/core/lib/Drupal/Core/Menu/MenuParentFormSelector.php b/core/lib/Drupal/Core/Menu/MenuParentFormSelector.php index e5a1264..1aa812f 100644 --- a/core/lib/Drupal/Core/Menu/MenuParentFormSelector.php +++ b/core/lib/Drupal/Core/Menu/MenuParentFormSelector.php @@ -68,6 +68,7 @@ public function getParentSelectOptions($id = '', array $menus = NULL) { $tree = $this->menuLinkTree->load($menu_name, $parameters); $manipulators = array( array('callable' => 'menu.default_tree_manipulators:checkNodeAccess'), + array('callable' => 'menu.default_tree_manipulators:loadEntities'), array('callable' => 'menu.default_tree_manipulators:checkAccess'), array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'), ); diff --git a/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php b/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php index f05a6e3..05da9a6 100644 --- a/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php +++ b/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php @@ -142,19 +142,7 @@ public function getEntity() { if (empty($this->entity)) { $entity_type_id = $this->pluginDefinition['metadata']['entity_type_id']; $entity_id = $this->pluginDefinition['metadata']['entity_id']; - // Make sure the current ID is in the list, since each plugin empties - // the list after calling loadMultple(). Note that the list may include - // multiple IDs added earlier in each plugin's constructor. - static::$entityIdsToLoad[$entity_type_id][$entity_id] = $entity_id; - $entities = $this->entityManager->getStorage($entity_type_id)->loadMultiple(array_values(static::$entityIdsToLoad[$entity_type_id])); - $entity = isset($entities[$entity_id]) ? $entities[$entity_id] : NULL; - static::$entityIdsToLoad[$entity_type_id] = array(); - // Clone the entity object to avoid tampering with the static cache. - $this->entity = clone $entity; - if (!empty($this->pluginDefinition['metadata']['translateable'])) { - $the_entity = $this->entityManager->getTranslationFromContext($this->entity); - $this->entity = $the_entity; - } + $this->entity = $this->entityManager->getStorage($entity_type_id)->load($entity_id); } return $this->entity; } diff --git a/core/modules/menu_ui/src/MenuForm.php b/core/modules/menu_ui/src/MenuForm.php index 2415032..75ab6a2 100644 --- a/core/modules/menu_ui/src/MenuForm.php +++ b/core/modules/menu_ui/src/MenuForm.php @@ -224,6 +224,8 @@ protected function buildOverviewForm(array &$form, FormStateInterface $form_stat // We indicate that a menu administrator is running the menu access check. $this->getRequest()->attributes->set('_menu_admin', TRUE); $manipulators = array( + array('callable' => 'menu.default_tree_manipulators:checkNodeAccess'), + array('callable' => 'menu.default_tree_manipulators:loadEntities'), array('callable' => 'menu.default_tree_manipulators:checkAccess'), array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'), ); diff --git a/core/modules/system/src/Controller/SystemController.php b/core/modules/system/src/Controller/SystemController.php index 22bade6..073e872 100644 --- a/core/modules/system/src/Controller/SystemController.php +++ b/core/modules/system/src/Controller/SystemController.php @@ -124,6 +124,8 @@ public function overview($link_id) { $parameters->setRoot($link_id)->excludeRoot()->setTopLevelOnly()->onlyEnabledLinks(); $tree = $this->menuLinkTree->load(NULL, $parameters); $manipulators = array( + array('callable' => 'menu.default_tree_manipulators:checkNodeAccess'), + array('callable' => 'menu.default_tree_manipulators:loadEntities'), array('callable' => 'menu.default_tree_manipulators:checkAccess'), array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'), ); diff --git a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php index 16af329..17d3c29 100644 --- a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php @@ -146,6 +146,8 @@ public function build() { $tree = $this->menuTree->load($menu_name, $parameters); $manipulators = array( + array('callable' => 'menu.default_tree_manipulators:checkNodeAccess'), + array('callable' => 'menu.default_tree_manipulators:loadEntities'), array('callable' => 'menu.default_tree_manipulators:checkAccess'), array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'), ); diff --git a/core/modules/system/src/SystemManager.php b/core/modules/system/src/SystemManager.php index 145705f..4a0022f 100644 --- a/core/modules/system/src/SystemManager.php +++ b/core/modules/system/src/SystemManager.php @@ -205,6 +205,8 @@ public function getAdminBlock(MenuLinkInterface $instance) { $parameters->setRoot($link_id)->excludeRoot()->setTopLevelOnly()->onlyEnabledLinks(); $tree = $this->menuTree->load(NULL, $parameters); $manipulators = array( + array('callable' => 'menu.default_tree_manipulators:checkNodeAccess'), + array('callable' => 'menu.default_tree_manipulators:loadEntities'), array('callable' => 'menu.default_tree_manipulators:checkAccess'), array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'), ); diff --git a/core/modules/system/src/Tests/System/AdminTest.php b/core/modules/system/src/Tests/System/AdminTest.php index fee3cd9..8dc9aa0 100644 --- a/core/modules/system/src/Tests/System/AdminTest.php +++ b/core/modules/system/src/Tests/System/AdminTest.php @@ -131,6 +131,8 @@ protected function getTopLevelMenuLinks() { $parameters->setRoot('system.admin')->excludeRoot()->setTopLevelOnly()->onlyEnabledLinks(); $tree = $menu_tree->load(NULL, $parameters); $manipulators = array( + array('callable' => 'menu.default_tree_manipulators:checkNodeAccess'), + array('callable' => 'menu.default_tree_manipulators:loadEntities'), array('callable' => 'menu.default_tree_manipulators:checkAccess'), array('callable' => 'menu.default_tree_manipulators:flatten'), ); diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 7b75cc9..67fe902 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -1134,6 +1134,8 @@ function system_get_module_admin_tasks($module, array $info) { $parameters->setRoot('system.admin')->excludeRoot()->onlyEnabledLinks(); $tree = $menu_tree->load('system.admin', $parameters); $manipulators = array( + array('callable' => 'menu.default_tree_manipulators:checkNodeAccess'), + array('callable' => 'menu.default_tree_manipulators:loadEntities'), array('callable' => 'menu.default_tree_manipulators:checkAccess'), array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'), array('callable' => 'menu.default_tree_manipulators:flatten'), diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index 7b75e89..9087753 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -210,6 +210,8 @@ function toolbar_prerender_toolbar_administration_tray(array $element) { $parameters->setRoot('system.admin')->excludeRoot()->setTopLevelOnly()->onlyEnabledLinks(); $tree = $menu_tree->load(NULL, $parameters); $manipulators = array( + array('callable' => 'menu.default_tree_manipulators:checkNodeAccess'), + array('callable' => 'menu.default_tree_manipulators:loadEntities'), array('callable' => 'menu.default_tree_manipulators:checkAccess'), array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'), array('callable' => 'toolbar_menu_navigation_links'), @@ -266,6 +268,8 @@ function toolbar_get_rendered_subtrees() { $parameters->setRoot('system.admin')->excludeRoot()->setMaxDepth(3)->onlyEnabledLinks(); $tree = $menu_tree->load(NULL, $parameters); $manipulators = array( + array('callable' => 'menu.default_tree_manipulators:checkNodeAccess'), + array('callable' => 'menu.default_tree_manipulators:loadEntities'), array('callable' => 'menu.default_tree_manipulators:checkAccess'), array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'), array('callable' => 'toolbar_menu_navigation_links'),