/**
  * Tests creating links with an expected tree structure.
  */
 public function testCreateLinksInMenu()
 {
     // This creates a tree with the following structure:
     // - 1
     // - 2
     //   - 3
     //     - 4
     // - 5
     //   - 7
     // - 6
     // - 8
     // With link 6 being the only external link.
     $links = array(1 => MenuLinkMock::create(array('id' => 'test.example1', 'route_name' => 'example1', 'title' => 'foo', 'parent' => '')), 2 => MenuLinkMock::create(array('id' => 'test.example2', 'route_name' => 'example2', 'title' => 'bar', 'parent' => 'test.example1', 'route_parameters' => array('foo' => 'bar'))), 3 => MenuLinkMock::create(array('id' => 'test.example3', 'route_name' => 'example3', 'title' => 'baz', 'parent' => 'test.example2', 'route_parameters' => array('baz' => 'qux'))), 4 => MenuLinkMock::create(array('id' => 'test.example4', 'route_name' => 'example4', 'title' => 'qux', 'parent' => 'test.example3')), 5 => MenuLinkMock::create(array('id' => 'test.example5', 'route_name' => 'example5', 'title' => 'foofoo', 'parent' => '')), 6 => MenuLinkMock::create(array('id' => 'test.example6', 'route_name' => '', 'url' => 'https://drupal.org/', 'title' => 'barbar', 'parent' => '')), 7 => MenuLinkMock::create(array('id' => 'test.example7', 'route_name' => 'example7', 'title' => 'bazbaz', 'parent' => '')), 8 => MenuLinkMock::create(array('id' => 'test.example8', 'route_name' => 'example8', 'title' => 'quxqux', 'parent' => '')));
     foreach ($links as $instance) {
         $this->menuLinkManager->addDefinition($instance->getPluginId(), $instance->getPluginDefinition());
     }
     $parameters = new MenuTreeParameters();
     $tree = $this->linkTree->load('mock', $parameters);
     $count = function (array $tree) {
         $sum = function ($carry, MenuLinkTreeElement $item) {
             return $carry + $item->count();
         };
         return array_reduce($tree, $sum);
     };
     $this->assertEqual($count($tree), 8);
     $parameters = new MenuTreeParameters();
     $parameters->setRoot('test.example2');
     $tree = $this->linkTree->load($instance->getMenuName(), $parameters);
     $top_link = reset($tree);
     $this->assertEqual(count($top_link->subtree), 1);
     $child = reset($top_link->subtree);
     $this->assertEqual($child->link->getPluginId(), $links[3]->getPluginId());
     $height = $this->linkTree->getSubtreeHeight('test.example2');
     $this->assertEqual($height, 3);
 }
 /**
  * Provides test data for all test methods.
  *
  * @return array
  *   Returns a list of test data of which each is an array containing the
  *   following elements:
  *     - request: A request object.
  *     - links: An array of menu links keyed by ID.
  *     - menu_name: The active menu name.
  *     - expected_link: The expected active link for the given menu.
  */
 public function provider()
 {
     $data = array();
     $mock_route = new Route('');
     $request = new Request();
     $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'baby_llama');
     $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $mock_route);
     $request->attributes->set('_raw_variables', new ParameterBag(array()));
     $link_1 = MenuLinkMock::create(array('id' => 'baby_llama_link_1', 'route_name' => 'baby_llama', 'title' => 'Baby llama', 'parent' => 'mama_llama_link'));
     $link_2 = MenuLinkMock::create(array('id' => 'baby_llama_link_2', 'route_name' => 'baby_llama', 'title' => 'Baby llama', 'parent' => 'papa_llama_link'));
     // @see \Drupal\Core\Menu\MenuLinkManagerInterface::getParentIds()
     $link_1_parent_ids = array('baby_llama_link_1', 'mama_llama_link', '');
     $empty_active_trail = array('');
     $link_1__active_trail_cache_key = 'menu_trail.baby_llama_link_1|mama_llama_link|';
     $empty_active_trail_cache_key = 'menu_trail.';
     // No active link is returned when zero links match the current route.
     $data[] = array($request, array(), $this->randomMachineName(), NULL, $empty_active_trail, $empty_active_trail_cache_key);
     // The first (and only) matching link is returned when one link matches the
     // current route.
     $data[] = array($request, array('baby_llama_link_1' => $link_1), $this->randomMachineName(), $link_1, $link_1_parent_ids, $link_1__active_trail_cache_key);
     // The first of multiple matching links is returned when multiple links
     // match the current route, where "first" is determined by sorting by key.
     $data[] = array($request, array('baby_llama_link_1' => $link_1, 'baby_llama_link_2' => $link_2), $this->randomMachineName(), $link_1, $link_1_parent_ids, $link_1__active_trail_cache_key);
     // No active link is returned in case of a 403.
     $request = new Request();
     $request->attributes->set('_exception_statuscode', 403);
     $data[] = array($request, FALSE, $this->randomMachineName(), NULL, $empty_active_trail, $empty_active_trail_cache_key);
     // No active link is returned when the route name is missing.
     $request = new Request();
     $data[] = array($request, FALSE, $this->randomMachineName(), NULL, $empty_active_trail, $empty_active_trail_cache_key);
     return $data;
 }
Esempio n. 3
0
 /**
  * Tests count().
  *
  * @covers ::count
  */
 public function testCount()
 {
     $link_1 = MenuLinkMock::create(array('id' => 'test_1'));
     $link_2 = MenuLinkMock::create(array('id' => 'test_2'));
     $child_item = new MenuLinkTreeElement($link_2, FALSE, 2, FALSE, array());
     $parent_item = new MenuLinkTreeElement($link_1, FALSE, 2, FALSE, array($child_item));
     $this->assertSame(1, $child_item->count());
     $this->assertSame(2, $parent_item->count());
 }
 /**
  * Creates a mock tree.
  *
  * This mocks a tree with the following structure:
  * - 1
  * - 2
  *   - 3
  *     - 4
  * - 5
  *   - 7
  * - 6
  * - 8
  *
  * With link 6 being the only external link.
  */
 protected function mockTree()
 {
     $this->links = array(1 => MenuLinkMock::create(array('id' => 'test.example1', 'route_name' => 'example1', 'title' => 'foo', 'parent' => '')), 2 => MenuLinkMock::create(array('id' => 'test.example2', 'route_name' => 'example2', 'title' => 'bar', 'parent' => 'test.example1', 'route_parameters' => array('foo' => 'bar'))), 3 => MenuLinkMock::create(array('id' => 'test.example3', 'route_name' => 'example3', 'title' => 'baz', 'parent' => 'test.example2', 'route_parameters' => array('baz' => 'qux'))), 4 => MenuLinkMock::create(array('id' => 'test.example4', 'route_name' => 'example4', 'title' => 'qux', 'parent' => 'test.example3')), 5 => MenuLinkMock::create(array('id' => 'test.example5', 'route_name' => 'example5', 'title' => 'foofoo', 'parent' => '')), 6 => MenuLinkMock::create(array('id' => 'test.example6', 'route_name' => '', 'url' => 'https://drupal.org/', 'title' => 'barbar', 'parent' => '')), 7 => MenuLinkMock::create(array('id' => 'test.example7', 'route_name' => 'example7', 'title' => 'bazbaz', 'parent' => '')), 8 => MenuLinkMock::create(array('id' => 'test.example8', 'route_name' => 'example8', 'title' => 'quxqux', 'parent' => '')));
     $this->originalTree = array();
     $this->originalTree[1] = new MenuLinkTreeElement($this->links[1], FALSE, 1, FALSE, array());
     $this->originalTree[2] = new MenuLinkTreeElement($this->links[2], TRUE, 1, FALSE, array(3 => new MenuLinkTreeElement($this->links[3], TRUE, 2, FALSE, array(4 => new MenuLinkTreeElement($this->links[4], FALSE, 3, FALSE, array())))));
     $this->originalTree[5] = new MenuLinkTreeElement($this->links[5], TRUE, 1, FALSE, array(7 => new MenuLinkTreeElement($this->links[7], FALSE, 2, FALSE, array())));
     $this->originalTree[6] = new MenuLinkTreeElement($this->links[6], FALSE, 1, FALSE, array());
     $this->originalTree[8] = new MenuLinkTreeElement($this->links[8], FALSE, 1, FALSE, array());
 }
Esempio n. 5
0
 /**
  * {@inheritdoc}
  */
 protected function setUp()
 {
     parent::setUp();
     $this->installSchema('system', 'sequences');
     $this->installEntitySchema('user');
     $this->installSchema('system', array('router'));
     $this->installEntitySchema('menu_link_content');
     $account = User::create(['name' => $this->randomMachineName(), 'status' => 1]);
     $account->save();
     $this->container->get('current_user')->setAccount($account);
     $this->menuLinkManager = $this->container->get('plugin.manager.menu.link');
     $this->linkTree = $this->container->get('menu.link_tree');
     $this->blockManager = $this->container->get('plugin.manager.block');
     $routes = new RouteCollection();
     $requirements = array('_access' => 'TRUE');
     $options = array('_access_checks' => array('access_check.default'));
     $routes->add('example1', new Route('/example1', array(), $requirements, $options));
     $routes->add('example2', new Route('/example2', array(), $requirements, $options));
     $routes->add('example3', new Route('/example3', array(), $requirements, $options));
     $routes->add('example4', new Route('/example4', array(), $requirements, $options));
     $routes->add('example5', new Route('/example5', array(), $requirements, $options));
     $routes->add('example6', new Route('/example6', array(), $requirements, $options));
     $routes->add('example7', new Route('/example7', array(), $requirements, $options));
     $routes->add('example8', new Route('/example8', array(), $requirements, $options));
     $mock_route_provider = new MockRouteProvider($routes);
     $this->container->set('router.route_provider', $mock_route_provider);
     // Add a new custom menu.
     $menu_name = 'mock';
     $label = $this->randomMachineName(16);
     $this->menu = entity_create('menu', array('id' => $menu_name, 'label' => $label, 'description' => 'Description text'));
     $this->menu->save();
     // This creates a tree with the following structure:
     // - 1
     // - 2
     //   - 3
     //     - 4
     // - 5
     //   - 7
     // - 6
     // - 8
     // With link 6 being the only external link.
     $links = array(1 => MenuLinkMock::create(array('id' => 'test.example1', 'route_name' => 'example1', 'title' => 'foo', 'parent' => '', 'weight' => 0)), 2 => MenuLinkMock::create(array('id' => 'test.example2', 'route_name' => 'example2', 'title' => 'bar', 'parent' => '', 'route_parameters' => array('foo' => 'bar'), 'weight' => 1)), 3 => MenuLinkMock::create(array('id' => 'test.example3', 'route_name' => 'example3', 'title' => 'baz', 'parent' => 'test.example2', 'weight' => 2)), 4 => MenuLinkMock::create(array('id' => 'test.example4', 'route_name' => 'example4', 'title' => 'qux', 'parent' => 'test.example3', 'weight' => 3)), 5 => MenuLinkMock::create(array('id' => 'test.example5', 'route_name' => 'example5', 'title' => 'foofoo', 'parent' => '', 'expanded' => TRUE, 'weight' => 4)), 6 => MenuLinkMock::create(array('id' => 'test.example6', 'route_name' => '', 'url' => 'https://drupal.org/', 'title' => 'barbar', 'parent' => '', 'weight' => 5)), 7 => MenuLinkMock::create(array('id' => 'test.example7', 'route_name' => 'example7', 'title' => 'bazbaz', 'parent' => 'test.example5', 'weight' => 6)), 8 => MenuLinkMock::create(array('id' => 'test.example8', 'route_name' => 'example8', 'title' => 'quxqux', 'parent' => '', 'weight' => 7)));
     foreach ($links as $instance) {
         $this->menuLinkManager->addDefinition($instance->getPluginId(), $instance->getPluginDefinition());
     }
 }
Esempio n. 6
0
 /**
  * Provides the test cases to test for ::testBuildCacheability().
  *
  * As explained in the documentation for ::testBuildCacheability(), this
  * generates 1 + (3 * 2 * 3) = 19 test cases.
  *
  * @see testBuildCacheability
  */
 public function providerTestBuildCacheability()
 {
     $base_expected_build_empty = ['#cache' => ['contexts' => [], 'tags' => [], 'max-age' => Cache::PERMANENT]];
     $base_expected_build = ['#cache' => ['contexts' => [], 'tags' => ['config:system.menu.mock'], 'max-age' => Cache::PERMANENT], '#sorted' => TRUE, '#theme' => 'menu__mock', '#items' => []];
     $get_built_element = function (MenuLinkTreeElement $element, array $classes) {
         return ['attributes' => new Attribute(['class' => array_merge(['menu-item'], $classes)]), 'title' => $element->link->getTitle(), 'url' => new Url($element->link->getRouteName(), $element->link->getRouteParameters(), ['set_active_class' => TRUE]), 'below' => [], 'original_link' => $element->link];
     };
     // The three access scenarios described in this method's documentation.
     $access_scenarios = [[NULL, []], [AccessResult::allowed(), ['access:allowed']], [AccessResult::neutral(), ['access:neutral']]];
     // The two links scenarios described in this method's documentation.
     $cache_defaults = ['cache_max_age' => Cache::PERMANENT, 'cache_tags' => []];
     $links_scenarios = [[MenuLinkMock::create(['id' => 'test.example1', 'route_name' => 'example1', 'title' => 'Example 1']), MenuLinkMock::create(['id' => 'test.example2', 'route_name' => 'example1', 'title' => 'Example 2', 'metadata' => ['cache_contexts' => ['llama']] + $cache_defaults])], [MenuLinkMock::create(['id' => 'test.example1', 'route_name' => 'example1', 'title' => 'Example 1', 'metadata' => ['cache_contexts' => ['foo']] + $cache_defaults]), MenuLinkMock::create(['id' => 'test.example2', 'route_name' => 'example1', 'title' => 'Example 2', 'metadata' => ['cache_contexts' => ['bar']] + $cache_defaults])]];
     $data = [];
     // Empty tree.
     $data[] = ['description' => 'Empty tree.', 'tree' => [], 'expected_build' => $base_expected_build_empty];
     for ($i = 0; $i < count($access_scenarios); $i++) {
         list($access, $access_cache_contexts) = $access_scenarios[$i];
         if ($access !== NULL) {
             $access->addCacheContexts($access_cache_contexts);
         }
         for ($j = 0; $j < count($links_scenarios); $j++) {
             $links = $links_scenarios[$j];
             // Single-element tree.
             $tree = [new MenuLinkTreeElement($links[0], FALSE, 0, FALSE, [])];
             $tree[0]->access = $access;
             if ($access === NULL || $access->isAllowed()) {
                 $expected_build = $base_expected_build;
                 $expected_build['#items']['test.example1'] = $get_built_element($tree[0], []);
             } else {
                 $expected_build = $base_expected_build_empty;
             }
             $expected_build['#cache']['contexts'] = array_merge($expected_build['#cache']['contexts'], $access_cache_contexts, $links[0]->getCacheContexts());
             $data[] = ['description' => "Single-item tree; access={$i}; link={$j}.", 'tree' => $tree, 'expected_build' => $expected_build];
             // Single-level tree.
             $tree = [new MenuLinkTreeElement($links[0], FALSE, 0, FALSE, []), new MenuLinkTreeElement($links[1], FALSE, 0, FALSE, [])];
             $tree[0]->access = $access;
             $expected_build = $base_expected_build;
             if ($access === NULL || $access->isAllowed()) {
                 $expected_build['#items']['test.example1'] = $get_built_element($tree[0], []);
             }
             $expected_build['#items']['test.example2'] = $get_built_element($tree[1], []);
             $expected_build['#cache']['contexts'] = array_merge($expected_build['#cache']['contexts'], $access_cache_contexts, $links[0]->getCacheContexts(), $links[1]->getCacheContexts());
             $data[] = ['description' => "Single-level tree; access={$i}; link={$j}.", 'tree' => $tree, 'expected_build' => $expected_build];
             // Multi-level tree.
             $multi_level_root_a = MenuLinkMock::create(['id' => 'test.roota', 'route_name' => 'roota', 'title' => 'Root A']);
             $multi_level_root_b = MenuLinkMock::create(['id' => 'test.rootb', 'route_name' => 'rootb', 'title' => 'Root B']);
             $multi_level_parent_c = MenuLinkMock::create(['id' => 'test.parentc', 'route_name' => 'parentc', 'title' => 'Parent C']);
             $tree = [new MenuLinkTreeElement($multi_level_root_a, TRUE, 0, FALSE, [new MenuLinkTreeElement($multi_level_parent_c, TRUE, 0, FALSE, [new MenuLinkTreeElement($links[0], FALSE, 0, FALSE, [])])]), new MenuLinkTreeElement($multi_level_root_b, TRUE, 0, FALSE, [new MenuLinkTreeElement($links[1], FALSE, 1, FALSE, [])])];
             $tree[0]->subtree[0]->subtree[0]->access = $access;
             $expected_build = $base_expected_build;
             $expected_build['#items']['test.roota'] = $get_built_element($tree[0], ['menu-item--expanded']);
             $expected_build['#items']['test.roota']['below']['test.parentc'] = $get_built_element($tree[0]->subtree[0], ['menu-item--expanded']);
             if ($access === NULL || $access->isAllowed()) {
                 $expected_build['#items']['test.roota']['below']['test.parentc']['below']['test.example1'] = $get_built_element($tree[0]->subtree[0]->subtree[0], []);
             }
             $expected_build['#items']['test.rootb'] = $get_built_element($tree[1], ['menu-item--expanded']);
             $expected_build['#items']['test.rootb']['below']['test.example2'] = $get_built_element($tree[1]->subtree[0], []);
             $expected_build['#cache']['contexts'] = array_merge($expected_build['#cache']['contexts'], $access_cache_contexts, $links[0]->getCacheContexts(), $links[1]->getCacheContexts());
             $data[] = ['description' => "Multi-level tree; access={$i}; link={$j}.", 'tree' => $tree, 'expected_build' => $expected_build];
         }
     }
     return $data;
 }
 /**
  * Tests the optimized node access checking.
  *
  * @covers ::checkNodeAccess
  * @covers ::collectNodeLinks
  * @covers ::checkAccess
  */
 public function testCheckNodeAccess()
 {
     $links = array(1 => MenuLinkMock::create(array('id' => 'node.1', 'route_name' => 'entity.node.canonical', 'title' => 'foo', 'parent' => '', 'route_parameters' => array('node' => 1))), 2 => MenuLinkMock::create(array('id' => 'node.2', 'route_name' => 'entity.node.canonical', 'title' => 'bar', 'parent' => '', 'route_parameters' => array('node' => 2))), 3 => MenuLinkMock::create(array('id' => 'node.3', 'route_name' => 'entity.node.canonical', 'title' => 'baz', 'parent' => 'node.2', 'route_parameters' => array('node' => 3))), 4 => MenuLinkMock::create(array('id' => 'node.4', 'route_name' => 'entity.node.canonical', 'title' => 'qux', 'parent' => 'node.3', 'route_parameters' => array('node' => 4))), 5 => MenuLinkMock::create(array('id' => 'test.1', 'route_name' => 'test_route', 'title' => 'qux', 'parent' => '')), 6 => MenuLinkMock::create(array('id' => 'test.2', 'route_name' => 'test_route', 'title' => 'qux', 'parent' => 'test.1')));
     $tree = array();
     $tree[1] = new MenuLinkTreeElement($links[1], FALSE, 1, FALSE, array());
     $tree[2] = new MenuLinkTreeElement($links[2], TRUE, 1, FALSE, array(3 => new MenuLinkTreeElement($links[3], TRUE, 2, FALSE, array(4 => new MenuLinkTreeElement($links[4], FALSE, 3, FALSE, array())))));
     $tree[5] = new MenuLinkTreeElement($links[5], TRUE, 1, FALSE, array(6 => new MenuLinkTreeElement($links[6], FALSE, 2, FALSE, array())));
     $query = $this->getMock('Drupal\\Core\\Entity\\Query\\QueryInterface');
     $query->expects($this->at(0))->method('condition')->with('nid', array(1, 2, 3, 4));
     $query->expects($this->at(1))->method('condition')->with('status', NODE_PUBLISHED);
     $query->expects($this->once())->method('execute')->willReturn(array(1, 2, 4));
     $this->queryFactory->expects($this->once())->method('get')->with('node')->willReturn($query);
     $node_access_result = AccessResult::allowed()->cachePerPermissions()->addCacheContexts(['user.node_grants:view']);
     $tree = $this->defaultMenuTreeManipulators->checkNodeAccess($tree);
     $this->assertEquals($node_access_result, $tree[1]->access);
     $this->assertEquals($node_access_result, $tree[2]->access);
     // Ensure that access denied is set.
     $this->assertEquals(AccessResult::neutral(), $tree[2]->subtree[3]->access);
     $this->assertEquals($node_access_result, $tree[2]->subtree[3]->subtree[4]->access);
     // Ensure that other routes than entity.node.canonical are set as well.
     $this->assertNull($tree[5]->access);
     $this->assertNull($tree[5]->subtree[6]->access);
     // On top of the node access checking now run the ordinary route based
     // access checkers.
     // Ensure that the access manager is just called for the non-node routes.
     $this->accessManager->expects($this->at(0))->method('checkNamedRoute')->with('test_route', [], $this->currentUser, TRUE)->willReturn(AccessResult::allowed());
     $this->accessManager->expects($this->at(1))->method('checkNamedRoute')->with('test_route', [], $this->currentUser, TRUE)->willReturn(AccessResult::neutral());
     $tree = $this->defaultMenuTreeManipulators->checkAccess($tree);
     $this->assertEquals($node_access_result, $tree[1]->access);
     $this->assertEquals($node_access_result, $tree[2]->access);
     $this->assertEquals(AccessResult::neutral(), $tree[2]->subtree[3]->access);
     $this->assertEquals(AccessResult::allowed()->cachePerPermissions(), $tree[5]->access);
     $this->assertEquals(AccessResult::neutral()->cachePerPermissions(), $tree[5]->subtree[6]->access);
 }