You are here

public function DefaultMenuLinkTreeManipulatorsTest::testCheckAccess in Drupal 8

Tests the checkAccess() tree manipulator.

@covers ::checkAccess @covers ::menuLinkCheckAccess

File

core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php, line 161

Class

DefaultMenuLinkTreeManipulatorsTest
Tests the default menu link tree manipulators.

Namespace

Drupal\Tests\Core\Menu

Code

public function testCheckAccess() {

  // Those menu links that are non-external will have their access checks
  // performed. 9 routes, but 1 is external, 2 already have their 'access'
  // property set, and 1 is a child if an inaccessible menu link, so only 5
  // calls will be made.
  $this->accessManager
    ->expects($this
    ->exactly(5))
    ->method('checkNamedRoute')
    ->will($this
    ->returnValueMap([
    [
      'example1',
      [],
      $this->currentUser,
      TRUE,
      AccessResult::forbidden(),
    ],
    [
      'example2',
      [
        'foo' => 'bar',
      ],
      $this->currentUser,
      TRUE,
      AccessResult::allowed()
        ->cachePerPermissions(),
    ],
    [
      'example3',
      [
        'baz' => 'qux',
      ],
      $this->currentUser,
      TRUE,
      AccessResult::neutral(),
    ],
    [
      'example5',
      [],
      $this->currentUser,
      TRUE,
      AccessResult::allowed(),
    ],
    [
      'user.logout',
      [],
      $this->currentUser,
      TRUE,
      AccessResult::allowed(),
    ],
  ]));
  $this
    ->mockTree();
  $this->originalTree[5]->subtree[7]->access = AccessResult::neutral();
  $this->originalTree[8]->access = AccessResult::allowed()
    ->cachePerUser();

  // Since \Drupal\Core\Menu\DefaultMenuLinkTreeManipulators::checkAccess()
  // allows access to any link if the user has the 'link to any page'
  // permission, *every* single access result is varied by permissions.
  $tree = $this->defaultMenuTreeManipulators
    ->checkAccess($this->originalTree);

  // Menu link 1: route without parameters, access forbidden, but at level 0,
  // hence kept.
  $element = $tree[1];
  $this
    ->assertEquals(AccessResult::forbidden()
    ->cachePerPermissions(), $element->access);
  $this
    ->assertInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);

  // Menu link 2: route with parameters, access granted.
  $element = $tree[2];
  $this
    ->assertEquals(AccessResult::allowed()
    ->cachePerPermissions(), $element->access);
  $this
    ->assertNotInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);

  // Menu link 3: route with parameters, AccessResult::neutral(), top-level
  // inaccessible link, hence kept for its cacheability metadata.
  // Note that the permissions cache context is added automatically, because
  // we always check the "link to any page" permission.
  $element = $tree[2]->subtree[3];
  $this
    ->assertEquals(AccessResult::neutral()
    ->cachePerPermissions(), $element->access);
  $this
    ->assertInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);

  // Menu link 4: child of menu link 3, which was AccessResult::neutral(),
  // hence menu link 3's subtree is removed, of which this menu link is one.
  $this
    ->assertArrayNotHasKey(4, $tree[2]->subtree[3]->subtree);

  // Menu link 5: no route name, treated as external, hence access granted.
  $element = $tree[5];
  $this
    ->assertEquals(AccessResult::allowed()
    ->cachePerPermissions(), $element->access);
  $this
    ->assertNotInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);

  // Menu link 6: external URL, hence access granted.
  $element = $tree[6];
  $this
    ->assertEquals(AccessResult::allowed()
    ->cachePerPermissions(), $element->access);
  $this
    ->assertNotInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);

  // Menu link 7: 'access' already set: AccessResult::neutral(), top-level
  // inaccessible link, hence kept for its cacheability metadata.
  // Note that unlike for menu link 3, the permission cache context is absent,
  // because ::checkAccess() doesn't perform access checking when 'access' is
  // already set.
  $element = $tree[5]->subtree[7];
  $this
    ->assertEquals(AccessResult::neutral(), $element->access);
  $this
    ->assertInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);

  // Menu link 8: 'access' already set, note that 'per permissions' caching
  // is not added.
  $element = $tree[8];
  $this
    ->assertEquals(AccessResult::allowed()
    ->cachePerUser(), $element->access);
  $this
    ->assertNotInstanceOf('\\Drupal\\Core\\Menu\\InaccessibleMenuLink', $element->link);
}