Skip to content

Instantly share code, notes, and snippets.

@dawehner
Created April 24, 2014 19:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dawehner/11266535 to your computer and use it in GitHub Desktop.
Save dawehner/11266535 to your computer and use it in GitHub Desktop.
diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuTree.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuTree.php
index adbf85d..c52be9e 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/MenuTree.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuTree.php
@@ -428,7 +428,7 @@ public function buildTree($menu_name, array $parameters = array()) {
// Build the menu tree.
$tree = $this->doBuildTree($menu_name, $parameters);
// Check access for the current user to each item in the tree.
- $this->checkAccess($tree);
+ $this->doCheckAccess($tree);
return $tree;
}
@@ -513,13 +513,77 @@ protected function doBuildTree($menu_name, array $parameters = array()) {
* The menu tree you wish to operate on.
*/
protected function checkAccess(&$tree) {
+ $node_links = array();
+ $this->collectNodeLinks($tree, $node_links);
+ $this->doCheckNodeQueryAccess($tree, $node_links);
+ $this->doCheckAccess($tree);
+ }
+
+ /**
+ * Collects all node links in the tree.
+ *
+ *
+ * @param array $tree
+ * The menu tree you wish to operate on.
+ * @param array $node_links
+ * References to the links in the menu tree pointing to nodes.
+ */
+ protected function collectNodeLinks(&$tree, &$node_links) {
+ foreach ($tree as $key => $v) {
+ if ($tree[$key]['link']['route_name'] == 'node.view') {
+ $nid = $tree[$key]['link']['route_parameters']['node'];
+ if (is_numeric($nid)) {
+ $node_links[$nid][$tree[$key]['link']['mlid']] = & $tree[$key]['link'];
+ $tree[$key]['link']['access'] = FALSE;
+ }
+ }
+ if ($tree[$key]['below']) {
+ $this->collectNodeLinks($tree[$key]['below'], $node_links);
+ }
+ }
+ }
+
+ /**
+ * Performs a node access query to optimize the access checking later.
+ *
+ * The idea is to set access to TRUE, so _menu_link_translate no longer has to
+ * do it.
+ *
+ * @param array $node_links
+ * References to the links in the menu tree pointing to nodes.
+ */
+ protected function doCheckNodeQueryAccess(&$node_links = array()) {
+ if ($node_links) {
+ $nids = array_keys($node_links);
+ $select = $this->database->select('node', 'n');
+ $select->addField('n', 'nid');
+ $select->condition('n.status', 1);
+ $select->condition('n.nid', $nids, 'IN');
+ $select->addTag('node_access');
+ $nids = $select->execute()->fetchCol();
+ foreach ($nids as $nid) {
+ foreach ($node_links[$nid] as $mlid => $link) {
+ $node_links[$nid][$mlid]['access'] = TRUE;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Sorts the menu tree and recursively checks access for each item.
+ *
+ * @param array $tree
+ * The menu tree you wish to operate on.
+ */
+ protected function doCheckAccess(&$tree) {
$new_tree = array();
foreach ($tree as $key => $v) {
$item = &$tree[$key]['link'];
$this->menuLinkTranslate($item);
if ($item['access'] || ($item['in_active_trail'] && strpos($item['href'], '%') !== FALSE)) {
if ($tree[$key]['below']) {
- $this->checkAccess($tree[$key]['below']);
+ $this->doCheckAccess($tree[$key]['below']);
}
// The weights are made a uniform 5 digits by adding 50000 as an offset.
// After _menu_link_translate(), $item['title'] has the localized link
@@ -538,7 +602,8 @@ protected function checkAccess(&$tree) {
*/
public function buildTreeData(array $links, array $parents = array(), $depth = 1) {
$tree = $this->doBuildTreeData($links, $parents, $depth);
- $this->checkAccess($tree);
+
+ $this->CheckAccess($tree);
return $tree;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment