View source
<?php
namespace Drupal\Tests\Core\Menu;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\DependencyInjection\Container;
use Drupal\Core\Menu\DefaultMenuLinkTreeManipulators;
use Drupal\Core\Menu\MenuLinkTreeElement;
use Drupal\Tests\UnitTestCase;
class DefaultMenuLinkTreeManipulatorsTest extends UnitTestCase {
protected $accessManager;
protected $currentUser;
protected $queryFactory;
protected $defaultMenuTreeManipulators;
protected $originalTree = array();
protected $links = array();
protected function setUp() {
parent::setUp();
$this->accessManager = $this
->getMock('\\Drupal\\Core\\Access\\AccessManagerInterface');
$this->currentUser = $this
->getMock('Drupal\\Core\\Session\\AccountInterface');
$this->currentUser
->method('isAuthenticated')
->willReturn(TRUE);
$this->queryFactory = $this
->getMockBuilder('Drupal\\Core\\Entity\\Query\\QueryFactory')
->disableOriginalConstructor()
->getMock();
$this->defaultMenuTreeManipulators = new DefaultMenuLinkTreeManipulators($this->accessManager, $this->currentUser, $this->queryFactory);
$cache_contexts_manager = $this
->prophesize(CacheContextsManager::class);
$cache_contexts_manager
->assertValidTokens()
->willReturn(TRUE);
$cache_contexts_manager
->reveal();
$container = new Container();
$container
->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
}
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://www.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' => '',
)),
9 => DynamicMenuLinkMock::create(array(
'id' => 'test.example9',
'parent' => '',
))
->setCurrentUser($this->currentUser),
);
$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());
$this->originalTree[9] = new MenuLinkTreeElement($this->links[9], FALSE, 1, FALSE, array());
}
public function testGenerateIndexAndSort() {
$this
->mockTree();
$tree = $this->originalTree;
$tree = $this->defaultMenuTreeManipulators
->generateIndexAndSort($tree);
$this
->assertEquals($this->links[1]
->getPluginId(), $tree['50000 foo test.example1']->link
->getPluginId());
$this
->assertEquals($this->links[2]
->getPluginId(), $tree['50000 bar test.example2']->link
->getPluginId());
$this
->assertEquals($this->links[5]
->getPluginId(), $tree['50000 foofoo test.example5']->link
->getPluginId());
$this
->assertEquals($this->links[6]
->getPluginId(), $tree['50000 barbar test.example6']->link
->getPluginId());
$this
->assertEquals($this->links[8]
->getPluginId(), $tree['50000 quxqux test.example8']->link
->getPluginId());
$this
->assertEquals($this->links[4]
->getPluginId(), $tree['50000 bar test.example2']->subtree['50000 baz test.example3']->subtree['50000 qux test.example4']->link
->getPluginId());
$this
->assertEquals($this->links[7]
->getPluginId(), $tree['50000 foofoo test.example5']->subtree['50000 bazbaz test.example7']->link
->getPluginId());
}
public function testCheckAccess() {
$this->accessManager
->expects($this
->exactly(5))
->method('checkNamedRoute')
->will($this
->returnValueMap(array(
array(
'example1',
array(),
$this->currentUser,
TRUE,
AccessResult::forbidden(),
),
array(
'example2',
array(
'foo' => 'bar',
),
$this->currentUser,
TRUE,
AccessResult::allowed()
->cachePerPermissions(),
),
array(
'example3',
array(
'baz' => 'qux',
),
$this->currentUser,
TRUE,
AccessResult::neutral(),
),
array(
'example5',
array(),
$this->currentUser,
TRUE,
AccessResult::allowed(),
),
array(
'user.logout',
array(),
$this->currentUser,
TRUE,
AccessResult::allowed(),
),
)));
$this
->mockTree();
$this->originalTree[5]->subtree[7]->access = AccessResult::neutral();
$this->originalTree[8]->access = AccessResult::allowed()
->cachePerUser();
$tree = $this->defaultMenuTreeManipulators
->checkAccess($this->originalTree);
$element = $tree[1];
$this
->assertEquals(AccessResult::forbidden()
->cachePerPermissions(), $element->access);
$this
->assertInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);
$element = $tree[2];
$this
->assertEquals(AccessResult::allowed()
->cachePerPermissions(), $element->access);
$this
->assertNotInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);
$element = $tree[2]->subtree[3];
$this
->assertEquals(AccessResult::neutral()
->cachePerPermissions(), $element->access);
$this
->assertInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);
$this
->assertFalse(array_key_exists(4, $tree[2]->subtree[3]->subtree));
$element = $tree[5];
$this
->assertEquals(AccessResult::allowed()
->cachePerPermissions(), $element->access);
$this
->assertNotInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);
$element = $tree[6];
$this
->assertEquals(AccessResult::allowed()
->cachePerPermissions(), $element->access);
$this
->assertNotInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);
$element = $tree[5]->subtree[7];
$this
->assertEquals(AccessResult::neutral(), $element->access);
$this
->assertInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);
$element = $tree[8];
$this
->assertEquals(AccessResult::allowed()
->cachePerUser(), $element->access);
$this
->assertNotInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);
}
public function testCheckAccessWithLinkToAnyPagePermission() {
$this
->mockTree();
$this->currentUser
->expects($this
->exactly(9))
->method('hasPermission')
->with('link to any page')
->willReturn(TRUE);
$this
->mockTree();
$this->defaultMenuTreeManipulators
->checkAccess($this->originalTree);
$expected_access_result = AccessResult::allowed()
->cachePerPermissions();
$this
->assertEquals($expected_access_result, $this->originalTree[1]->access);
$this
->assertEquals($expected_access_result, $this->originalTree[2]->access);
$this
->assertEquals($expected_access_result, $this->originalTree[2]->subtree[3]->access);
$this
->assertEquals($expected_access_result, $this->originalTree[2]->subtree[3]->subtree[4]->access);
$this
->assertEquals($expected_access_result, $this->originalTree[5]->subtree[7]->access);
$this
->assertEquals($expected_access_result, $this->originalTree[6]->access);
$this
->assertEquals($expected_access_result, $this->originalTree[8]->access);
$this
->assertEquals($expected_access_result, $this->originalTree[9]->access);
}
public function testFlatten() {
$this
->mockTree();
$tree = $this->defaultMenuTreeManipulators
->flatten($this->originalTree);
$this
->assertEquals(array(
1,
2,
5,
6,
8,
9,
), array_keys($this->originalTree));
$this
->assertEquals(array(
1,
2,
5,
6,
8,
9,
3,
4,
7,
), array_keys($tree));
}
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);
$this
->assertEquals(AccessResult::neutral(), $tree[2]->subtree[3]->access);
$this
->assertEquals($node_access_result, $tree[2]->subtree[3]->subtree[4]->access);
$this
->assertNull($tree[5]->access);
$this
->assertNull($tree[5]->subtree[6]->access);
$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);
}
}
if (!defined('NODE_PUBLISHED')) {
define('NODE_PUBLISHED', 1);
}