class PermissionHandlerTest
Tests the permission handler.
@group user
@coversDefaultClass \Drupal\user\PermissionHandler
      
    
@runTestsInSeparateProcesses
Hierarchy
- class \Drupal\Tests\UnitTestCase uses \Drupal\Tests\Traits\PhpUnitWarnings, \Drupal\Tests\PhpUnitCompatibilityTrait, \Prophecy\PhpUnit\ProphecyTrait, \Symfony\Bridge\PhpUnit\ExpectDeprecationTrait, \Drupal\Tests\RandomGeneratorTrait extends \PHPUnit\Framework\TestCase- class \Drupal\Tests\user\Unit\PermissionHandlerTest extends \Drupal\Tests\UnitTestCase
 
Expanded class hierarchy of PermissionHandlerTest
File
- 
              core/modules/ user/ tests/ src/ Unit/ PermissionHandlerTest.php, line 26 
Namespace
Drupal\Tests\user\UnitView source
class PermissionHandlerTest extends UnitTestCase {
  
  /**
   * The tested permission handler.
   *
   * @var \Drupal\user\PermissionHandler
   */
  protected $permissionHandler;
  
  /**
   * The mocked module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $moduleHandler;
  
  /**
   * The mocked string translation.
   *
   * @var \Drupal\Tests\user\Unit\TestTranslationManager
   */
  protected $stringTranslation;
  
  /**
   * The mocked callable resolver.
   *
   * @var \Drupal\Core\Utility\CallableResolver|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $callableResolver;
  
  /**
   * {@inheritdoc}
   */
  protected function setUp() : void {
    parent::setUp();
    $this->stringTranslation = new TestTranslationManager();
    $this->callableResolver = $this->createMock('Drupal\\Core\\Utility\\CallableResolver');
  }
  
  /**
   * Provides an extension object for a given module with a human name.
   *
   * @param string $module
   *   The module machine name.
   * @param string $name
   *   The module human name.
   *
   * @return \Drupal\Core\Extension\Extension
   *   The extension object.
   */
  protected function mockModuleExtension($module, $name) {
    $extension = new Extension('vfs:/', $module, "modules/{$module}");
    $extension->info['name'] = $name;
    return $extension;
  }
  
  /**
   * Tests permissions provided by YML files.
   *
   * @covers ::__construct
   * @covers ::getPermissions
   * @covers ::buildPermissionsYaml
   * @covers ::moduleProvidesPermissions
   */
  public function testBuildPermissionsYaml() : void {
    vfsStreamWrapper::register();
    $root = new vfsStreamDirectory('modules');
    vfsStreamWrapper::setRoot($root);
    $this->moduleHandler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
    $this->moduleHandler
      ->expects($this->once())
      ->method('getModuleDirectories')
      ->willReturn([
      'module_a' => vfsStream::url('modules/module_a'),
      'module_b' => vfsStream::url('modules/module_b'),
      'module_c' => vfsStream::url('modules/module_c'),
    ]);
    $url = vfsStream::url('modules');
    mkdir($url . '/module_a');
    file_put_contents($url . '/module_a/module_a.permissions.yml', "access_module_a: single_description");
    mkdir($url . '/module_b');
    file_put_contents($url . '/module_b/module_b.permissions.yml', <<<EOF
    'access module b':
      title: 'Access B'
      description: 'bla bla'
    'access module a via module b':
      title: 'Access A via B'
      provider: 'module_a'
    EOF);
    mkdir($url . '/module_c');
    file_put_contents($url . '/module_c/module_c.permissions.yml', <<<EOF
    'access_module_c':
      title: 'Access C'
      description: 'bla bla'
      'restrict access': TRUE
    EOF);
    $modules = [
      'module_a',
      'module_b',
      'module_c',
    ];
    $this->moduleHandler
      ->expects($this->any())
      ->method('getModuleList')
      ->willReturn(array_flip($modules));
    $this->callableResolver
      ->expects($this->never())
      ->method('getCallableFromDefinition');
    $module_extension_list = $this->createMock(ModuleExtensionList::class);
    $this->permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->callableResolver, $module_extension_list);
    $actual_permissions = $this->permissionHandler
      ->getPermissions();
    $this->assertPermissions($actual_permissions);
    $this->assertTrue($this->permissionHandler
      ->moduleProvidesPermissions('module_a'));
    $this->assertTrue($this->permissionHandler
      ->moduleProvidesPermissions('module_b'));
    $this->assertTrue($this->permissionHandler
      ->moduleProvidesPermissions('module_c'));
    $this->assertFalse($this->permissionHandler
      ->moduleProvidesPermissions('module_d'));
  }
  
  /**
   * Tests permissions sort inside a module.
   *
   * @covers ::__construct
   * @covers ::getPermissions
   * @covers ::buildPermissionsYaml
   * @covers ::sortPermissions
   */
  public function testBuildPermissionsSortPerModule() : void {
    vfsStreamWrapper::register();
    $root = new vfsStreamDirectory('modules');
    vfsStreamWrapper::setRoot($root);
    $this->moduleHandler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
    $this->moduleHandler
      ->expects($this->once())
      ->method('getModuleDirectories')
      ->willReturn([
      'module_a' => vfsStream::url('modules/module_a'),
      'module_b' => vfsStream::url('modules/module_b'),
      'module_c' => vfsStream::url('modules/module_c'),
    ]);
    $module_extension_list = $this->createMock(ModuleExtensionList::class);
    $module_extension_list->expects($this->exactly(3))
      ->method('getName')
      ->willReturnMap([
      [
        'module_a',
        'Module a',
      ],
      [
        'module_b',
        'Module b',
      ],
      [
        'module_c',
        'A Module',
      ],
    ]);
    $url = vfsStream::url('modules');
    mkdir($url . '/module_a');
    file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
    access_module_a2: single_description2
    access_module_a1: single_description1
    EOF);
    mkdir($url . '/module_b');
    file_put_contents($url . '/module_b/module_b.permissions.yml', "access_module_a3: single_description");
    mkdir($url . '/module_c');
    file_put_contents($url . '/module_c/module_c.permissions.yml', "access_module_a4: single_description");
    $modules = [
      'module_a',
      'module_b',
      'module_c',
    ];
    $this->moduleHandler
      ->expects($this->once())
      ->method('getModuleList')
      ->willReturn(array_flip($modules));
    $permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->callableResolver, $module_extension_list);
    $actual_permissions = $permissionHandler->getPermissions();
    $this->assertEquals([
      'access_module_a4',
      'access_module_a1',
      'access_module_a2',
      'access_module_a3',
    ], array_keys($actual_permissions));
  }
  
  /**
   * Tests dynamic callback permissions provided by YML files.
   *
   * @covers ::__construct
   * @covers ::getPermissions
   * @covers ::buildPermissionsYaml
   */
  public function testBuildPermissionsYamlCallback() : void {
    vfsStreamWrapper::register();
    $root = new vfsStreamDirectory('modules');
    vfsStreamWrapper::setRoot($root);
    $this->moduleHandler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
    $this->moduleHandler
      ->expects($this->once())
      ->method('getModuleDirectories')
      ->willReturn([
      'module_a' => vfsStream::url('modules/module_a'),
      'module_b' => vfsStream::url('modules/module_b'),
      'module_c' => vfsStream::url('modules/module_c'),
    ]);
    $url = vfsStream::url('modules');
    mkdir($url . '/module_a');
    file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
    permission_callbacks:
      - 'Drupal\\user\\Tests\\TestPermissionCallbacks::singleDescription'
    EOF);
    mkdir($url . '/module_b');
    file_put_contents($url . '/module_b/module_b.permissions.yml', <<<EOF
    permission_callbacks:
      - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription'
      - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleProvider'
    EOF);
    mkdir($url . '/module_c');
    file_put_contents($url . '/module_c/module_c.permissions.yml', <<<EOF
    permission_callbacks:
      - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess'
    EOF);
    $modules = [
      'module_a',
      'module_b',
      'module_c',
    ];
    $this->moduleHandler
      ->expects($this->any())
      ->method('getModuleList')
      ->willReturn(array_flip($modules));
    $this->callableResolver
      ->expects($this->exactly(4))
      ->method('getCallableFromDefinition')
      ->willReturnMap([
      [
        'Drupal\\user\\Tests\\TestPermissionCallbacks::singleDescription',
        [
          new TestPermissionCallbacks(),
          'singleDescription',
        ],
      ],
      [
        'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription',
        [
          new TestPermissionCallbacks(),
          'titleDescription',
        ],
      ],
      [
        'Drupal\\user\\Tests\\TestPermissionCallbacks::titleProvider',
        [
          new TestPermissionCallbacks(),
          'titleProvider',
        ],
      ],
      [
        'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess',
        [
          new TestPermissionCallbacks(),
          'titleDescriptionRestrictAccess',
        ],
      ],
    ]);
    $module_extension_list = $this->createMock(ModuleExtensionList::class);
    $this->permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->callableResolver, $module_extension_list);
    $actual_permissions = $this->permissionHandler
      ->getPermissions();
    $this->assertPermissions($actual_permissions);
  }
  
  /**
   * Tests a YAML file containing both static permissions and a callback.
   */
  public function testPermissionsYamlStaticAndCallback() : void {
    vfsStreamWrapper::register();
    $root = new vfsStreamDirectory('modules');
    vfsStreamWrapper::setRoot($root);
    $this->moduleHandler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
    $this->moduleHandler
      ->expects($this->once())
      ->method('getModuleDirectories')
      ->willReturn([
      'module_a' => vfsStream::url('modules/module_a'),
    ]);
    $url = vfsStream::url('modules');
    mkdir($url . '/module_a');
    file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
    'access module a':
      title: 'Access A'
      description: 'bla bla'
    permission_callbacks:
      - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription'
    EOF);
    $modules = [
      'module_a',
    ];
    $this->moduleHandler
      ->expects($this->any())
      ->method('getModuleList')
      ->willReturn(array_flip($modules));
    $this->callableResolver
      ->expects($this->once())
      ->method('getCallableFromDefinition')
      ->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription')
      ->willReturn([
      new TestPermissionCallbacks(),
      'titleDescription',
    ]);
    $module_extension_list = $this->createMock(ModuleExtensionList::class);
    $this->permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->callableResolver, $module_extension_list);
    $actual_permissions = $this->permissionHandler
      ->getPermissions();
    $this->assertCount(2, $actual_permissions);
    $this->assertEquals('Access A', $actual_permissions['access module a']['title']);
    $this->assertEquals('module_a', $actual_permissions['access module a']['provider']);
    $this->assertEquals('bla bla', $actual_permissions['access module a']['description']);
    $this->assertEquals('Access B', $actual_permissions['access module b']['title']);
    $this->assertEquals('module_a', $actual_permissions['access module b']['provider']);
    $this->assertEquals('bla bla', $actual_permissions['access module b']['description']);
  }
  
  /**
   * Checks that the permissions are like expected.
   *
   * @param array $actual_permissions
   *   The actual permissions
   *
   * @internal
   */
  protected function assertPermissions(array $actual_permissions) : void {
    $this->assertCount(4, $actual_permissions);
    $this->assertEquals('single_description', $actual_permissions['access_module_a']['title']);
    $this->assertEquals('module_a', $actual_permissions['access_module_a']['provider']);
    $this->assertEquals('Access B', $actual_permissions['access module b']['title']);
    $this->assertEquals('module_b', $actual_permissions['access module b']['provider']);
    $this->assertEquals('Access C', $actual_permissions['access_module_c']['title']);
    $this->assertEquals('module_c', $actual_permissions['access_module_c']['provider']);
    $this->assertTrue($actual_permissions['access_module_c']['restrict access']);
    $this->assertEquals('module_a', $actual_permissions['access module a via module b']['provider']);
  }
}Members
| Title Sort descending | Deprecated | Modifiers | Object type | Summary | Overriden Title | Overrides | 
|---|---|---|---|---|---|---|
| PermissionHandlerTest::$callableResolver | protected | property | The mocked callable resolver. | |||
| PermissionHandlerTest::$moduleHandler | protected | property | The mocked module handler. | |||
| PermissionHandlerTest::$permissionHandler | protected | property | The tested permission handler. | |||
| PermissionHandlerTest::$stringTranslation | protected | property | The mocked string translation. | |||
| PermissionHandlerTest::assertPermissions | protected | function | Checks that the permissions are like expected. | |||
| PermissionHandlerTest::mockModuleExtension | protected | function | Provides an extension object for a given module with a human name. | |||
| PermissionHandlerTest::setUp | protected | function | Overrides UnitTestCase::setUp | |||
| PermissionHandlerTest::testBuildPermissionsSortPerModule | public | function | Tests permissions sort inside a module. | |||
| PermissionHandlerTest::testBuildPermissionsYaml | public | function | Tests permissions provided by YML files. | |||
| PermissionHandlerTest::testBuildPermissionsYamlCallback | public | function | Tests dynamic callback permissions provided by YML files. | |||
| PermissionHandlerTest::testPermissionsYamlStaticAndCallback | public | function | Tests a YAML file containing both static permissions and a callback. | |||
| PhpUnitWarnings::$deprecationWarnings | private static | property | Deprecation warnings from PHPUnit to raise with @trigger_error(). | |||
| PhpUnitWarnings::addWarning | public | function | Converts PHPUnit deprecation warnings to E_USER_DEPRECATED. | |||
| RandomGeneratorTrait::getRandomGenerator | protected | function | Gets the random generator for the utility methods. | |||
| RandomGeneratorTrait::randomMachineName | protected | function | Generates a unique random string containing letters and numbers. | |||
| RandomGeneratorTrait::randomObject | public | function | Generates a random PHP object. | |||
| RandomGeneratorTrait::randomString | public | function | Generates a pseudo-random string of ASCII characters of codes 32 to 126. | |||
| RandomGeneratorTrait::randomStringValidate | Deprecated | public | function | Callback for random string validation. | ||
| UnitTestCase::$root | protected | property | The app root. | 1 | ||
| UnitTestCase::getClassResolverStub | protected | function | Returns a stub class resolver. | |||
| UnitTestCase::getConfigFactoryStub | public | function | Returns a stub config factory that behaves according to the passed array. | |||
| UnitTestCase::getConfigStorageStub | public | function | Returns a stub config storage that returns the supplied configuration. | |||
| UnitTestCase::getContainerWithCacheTagsInvalidator | protected | function | Sets up a container with a cache tags invalidator. | |||
| UnitTestCase::getStringTranslationStub | public | function | Returns a stub translation manager that just returns the passed string. | |||
| UnitTestCase::setUpBeforeClass | public static | function | ||||
| UnitTestCase::__get | public | function | 
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.
