annotate core/modules/user/tests/src/Unit/PermissionHandlerTest.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /**
Chris@0 4 * @file
Chris@0 5 * Contains \Drupal\Tests\user\Unit\PermissionHandlerTest.
Chris@0 6 */
Chris@0 7
Chris@0 8 namespace Drupal\Tests\user\Unit;
Chris@0 9
Chris@0 10 use Drupal\Core\Extension\Extension;
Chris@0 11 use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
Chris@0 12 use Drupal\Core\StringTranslation\TranslatableMarkup;
Chris@0 13 use Drupal\Core\StringTranslation\TranslationInterface;
Chris@0 14 use Drupal\Tests\UnitTestCase;
Chris@0 15 use Drupal\user\PermissionHandler;
Chris@0 16 use org\bovigo\vfs\vfsStream;
Chris@0 17 use org\bovigo\vfs\vfsStreamDirectory;
Chris@0 18 use org\bovigo\vfs\vfsStreamWrapper;
Chris@0 19
Chris@0 20 /**
Chris@0 21 * Tests the permission handler.
Chris@0 22 *
Chris@0 23 * @group user
Chris@0 24 *
Chris@0 25 * @coversDefaultClass \Drupal\user\PermissionHandler
Chris@0 26 */
Chris@0 27 class PermissionHandlerTest extends UnitTestCase {
Chris@0 28
Chris@0 29 /**
Chris@0 30 * The tested permission handler.
Chris@0 31 *
Chris@0 32 * @var \Drupal\Tests\user\Unit\TestPermissionHandler|\Drupal\user\PermissionHandler
Chris@0 33 */
Chris@0 34 protected $permissionHandler;
Chris@0 35
Chris@0 36 /**
Chris@0 37 * The mocked module handler.
Chris@0 38 *
Chris@0 39 * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
Chris@0 40 */
Chris@0 41 protected $moduleHandler;
Chris@0 42
Chris@0 43 /**
Chris@0 44 * The mocked string translation.
Chris@0 45 *
Chris@0 46 * @var \Drupal\Tests\user\Unit\TestTranslationManager
Chris@0 47 */
Chris@0 48 protected $stringTranslation;
Chris@0 49
Chris@0 50 /**
Chris@0 51 * The mocked controller resolver.
Chris@0 52 *
Chris@0 53 * @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
Chris@0 54 */
Chris@0 55 protected $controllerResolver;
Chris@0 56
Chris@0 57 /**
Chris@0 58 * {@inheritdoc}
Chris@0 59 */
Chris@0 60 protected function setUp() {
Chris@0 61 parent::setUp();
Chris@0 62
Chris@0 63 $this->stringTranslation = new TestTranslationManager();
Chris@0 64 $this->controllerResolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface');
Chris@0 65 }
Chris@0 66
Chris@0 67 /**
Chris@0 68 * Provides an extension object for a given module with a human name.
Chris@0 69 *
Chris@0 70 * @param string $module
Chris@0 71 * The module machine name.
Chris@0 72 * @param string $name
Chris@0 73 * The module human name.
Chris@0 74 *
Chris@0 75 * @return \Drupal\Core\Extension\Extension
Chris@0 76 * The extension object.
Chris@0 77 */
Chris@0 78 protected function mockModuleExtension($module, $name) {
Chris@0 79 $extension = new Extension($this->root, $module, "modules/$module");
Chris@0 80 $extension->info['name'] = $name;
Chris@0 81 return $extension;
Chris@0 82 }
Chris@0 83
Chris@0 84 /**
Chris@0 85 * Tests permissions provided by YML files.
Chris@0 86 *
Chris@0 87 * @covers ::__construct
Chris@0 88 * @covers ::getPermissions
Chris@0 89 * @covers ::buildPermissionsYaml
Chris@0 90 * @covers ::moduleProvidesPermissions
Chris@0 91 */
Chris@0 92 public function testBuildPermissionsYaml() {
Chris@0 93 vfsStreamWrapper::register();
Chris@0 94 $root = new vfsStreamDirectory('modules');
Chris@0 95 vfsStreamWrapper::setRoot($root);
Chris@0 96
Chris@0 97 $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
Chris@0 98 $this->moduleHandler->expects($this->once())
Chris@0 99 ->method('getModuleDirectories')
Chris@0 100 ->willReturn([
Chris@0 101 'module_a' => vfsStream::url('modules/module_a'),
Chris@0 102 'module_b' => vfsStream::url('modules/module_b'),
Chris@0 103 'module_c' => vfsStream::url('modules/module_c'),
Chris@0 104 ]);
Chris@0 105
Chris@0 106 $url = vfsStream::url('modules');
Chris@0 107 mkdir($url . '/module_a');
Chris@0 108 file_put_contents($url . '/module_a/module_a.permissions.yml', "access_module_a: single_description");
Chris@0 109 mkdir($url . '/module_b');
Chris@0 110 file_put_contents($url . '/module_b/module_b.permissions.yml', <<<EOF
Chris@0 111 'access module b':
Chris@0 112 title: 'Access B'
Chris@0 113 description: 'bla bla'
Chris@0 114 'access module a via module b':
Chris@0 115 title: 'Access A via B'
Chris@0 116 provider: 'module_a'
Chris@0 117 EOF
Chris@0 118 );
Chris@0 119 mkdir($url . '/module_c');
Chris@0 120 file_put_contents($url . '/module_c/module_c.permissions.yml', <<<EOF
Chris@0 121 'access_module_c':
Chris@0 122 title: 'Access C'
Chris@0 123 description: 'bla bla'
Chris@0 124 'restrict access': TRUE
Chris@0 125 EOF
Chris@0 126 );
Chris@0 127 $modules = ['module_a', 'module_b', 'module_c'];
Chris@0 128 $extensions = [
Chris@0 129 'module_a' => $this->mockModuleExtension('module_a', 'Module a'),
Chris@0 130 'module_b' => $this->mockModuleExtension('module_b', 'Module b'),
Chris@0 131 'module_c' => $this->mockModuleExtension('module_c', 'Module c'),
Chris@0 132 ];
Chris@0 133 $this->moduleHandler->expects($this->any())
Chris@0 134 ->method('getImplementations')
Chris@0 135 ->with('permission')
Chris@0 136 ->willReturn([]);
Chris@0 137
Chris@0 138 $this->moduleHandler->expects($this->any())
Chris@0 139 ->method('getModuleList')
Chris@0 140 ->willReturn(array_flip($modules));
Chris@0 141
Chris@0 142 $this->controllerResolver->expects($this->never())
Chris@0 143 ->method('getControllerFromDefinition');
Chris@0 144
Chris@0 145 $this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
Chris@0 146
Chris@0 147 // Setup system_rebuild_module_data().
Chris@0 148 $this->permissionHandler->setSystemRebuildModuleData($extensions);
Chris@0 149
Chris@0 150 $actual_permissions = $this->permissionHandler->getPermissions();
Chris@0 151 $this->assertPermissions($actual_permissions);
Chris@0 152
Chris@0 153 $this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_a'));
Chris@0 154 $this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_b'));
Chris@0 155 $this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_c'));
Chris@0 156 $this->assertFalse($this->permissionHandler->moduleProvidesPermissions('module_d'));
Chris@0 157 }
Chris@0 158
Chris@0 159 /**
Chris@0 160 * Tests permissions sort inside a module.
Chris@0 161 *
Chris@0 162 * @covers ::__construct
Chris@0 163 * @covers ::getPermissions
Chris@0 164 * @covers ::buildPermissionsYaml
Chris@0 165 * @covers ::sortPermissions
Chris@0 166 */
Chris@0 167 public function testBuildPermissionsSortPerModule() {
Chris@0 168 vfsStreamWrapper::register();
Chris@0 169 $root = new vfsStreamDirectory('modules');
Chris@0 170 vfsStreamWrapper::setRoot($root);
Chris@0 171
Chris@0 172 $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
Chris@0 173 $this->moduleHandler->expects($this->once())
Chris@0 174 ->method('getModuleDirectories')
Chris@0 175 ->willReturn([
Chris@0 176 'module_a' => vfsStream::url('modules/module_a'),
Chris@0 177 'module_b' => vfsStream::url('modules/module_b'),
Chris@0 178 'module_c' => vfsStream::url('modules/module_c'),
Chris@0 179 ]);
Chris@0 180 $this->moduleHandler->expects($this->exactly(3))
Chris@0 181 ->method('getName')
Chris@0 182 ->will($this->returnValueMap([
Chris@0 183 ['module_a', 'Module a'],
Chris@0 184 ['module_b', 'Module b'],
Chris@0 185 ['module_c', 'A Module'],
Chris@0 186 ]));
Chris@0 187
Chris@0 188 $url = vfsStream::url('modules');
Chris@0 189 mkdir($url . '/module_a');
Chris@0 190 file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
Chris@0 191 access_module_a2: single_description2
Chris@0 192 access_module_a1: single_description1
Chris@0 193 EOF
Chris@0 194 );
Chris@0 195 mkdir($url . '/module_b');
Chris@0 196 file_put_contents($url . '/module_b/module_b.permissions.yml',
Chris@0 197 "access_module_a3: single_description"
Chris@0 198 );
Chris@0 199 mkdir($url . '/module_c');
Chris@0 200 file_put_contents($url . '/module_c/module_c.permissions.yml',
Chris@0 201 "access_module_a4: single_description"
Chris@0 202 );
Chris@0 203
Chris@0 204 $modules = ['module_a', 'module_b', 'module_c'];
Chris@0 205 $this->moduleHandler->expects($this->once())
Chris@0 206 ->method('getModuleList')
Chris@0 207 ->willReturn(array_flip($modules));
Chris@0 208
Chris@0 209 $permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
Chris@0 210 $actual_permissions = $permissionHandler->getPermissions();
Chris@0 211 $this->assertEquals(['access_module_a4', 'access_module_a1', 'access_module_a2', 'access_module_a3'],
Chris@0 212 array_keys($actual_permissions));
Chris@0 213 }
Chris@0 214
Chris@0 215 /**
Chris@0 216 * Tests dynamic callback permissions provided by YML files.
Chris@0 217 *
Chris@0 218 * @covers ::__construct
Chris@0 219 * @covers ::getPermissions
Chris@0 220 * @covers ::buildPermissionsYaml
Chris@0 221 */
Chris@0 222 public function testBuildPermissionsYamlCallback() {
Chris@0 223 vfsStreamWrapper::register();
Chris@0 224 $root = new vfsStreamDirectory('modules');
Chris@0 225 vfsStreamWrapper::setRoot($root);
Chris@0 226
Chris@0 227 $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
Chris@0 228 $this->moduleHandler->expects($this->once())
Chris@0 229 ->method('getModuleDirectories')
Chris@0 230 ->willReturn([
Chris@0 231 'module_a' => vfsStream::url('modules/module_a'),
Chris@0 232 'module_b' => vfsStream::url('modules/module_b'),
Chris@0 233 'module_c' => vfsStream::url('modules/module_c'),
Chris@0 234 ]);
Chris@0 235
Chris@0 236 $url = vfsStream::url('modules');
Chris@0 237 mkdir($url . '/module_a');
Chris@0 238 file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
Chris@0 239 permission_callbacks:
Chris@0 240 - 'Drupal\\user\\Tests\\TestPermissionCallbacks::singleDescription'
Chris@0 241 EOF
Chris@0 242 );
Chris@0 243 mkdir($url . '/module_b');
Chris@0 244 file_put_contents($url . '/module_b/module_b.permissions.yml', <<<EOF
Chris@0 245 permission_callbacks:
Chris@0 246 - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription'
Chris@0 247 - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleProvider'
Chris@0 248 EOF
Chris@0 249 );
Chris@0 250 mkdir($url . '/module_c');
Chris@0 251 file_put_contents($url . '/module_c/module_c.permissions.yml', <<<EOF
Chris@0 252 permission_callbacks:
Chris@0 253 - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess'
Chris@0 254 EOF
Chris@0 255 );
Chris@0 256
Chris@0 257 $modules = ['module_a', 'module_b', 'module_c'];
Chris@0 258 $extensions = [
Chris@0 259 'module_a' => $this->mockModuleExtension('module_a', 'Module a'),
Chris@0 260 'module_b' => $this->mockModuleExtension('module_b', 'Module b'),
Chris@0 261 'module_c' => $this->mockModuleExtension('module_c', 'Module c'),
Chris@0 262 ];
Chris@0 263
Chris@0 264 $this->moduleHandler->expects($this->any())
Chris@0 265 ->method('getImplementations')
Chris@0 266 ->with('permission')
Chris@0 267 ->willReturn([]);
Chris@0 268
Chris@0 269 $this->moduleHandler->expects($this->any())
Chris@0 270 ->method('getModuleList')
Chris@0 271 ->willReturn(array_flip($modules));
Chris@0 272
Chris@0 273 $this->controllerResolver->expects($this->at(0))
Chris@0 274 ->method('getControllerFromDefinition')
Chris@0 275 ->with('Drupal\\user\\Tests\\TestPermissionCallbacks::singleDescription')
Chris@0 276 ->willReturn([new TestPermissionCallbacks(), 'singleDescription']);
Chris@0 277 $this->controllerResolver->expects($this->at(1))
Chris@0 278 ->method('getControllerFromDefinition')
Chris@0 279 ->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription')
Chris@0 280 ->willReturn([new TestPermissionCallbacks(), 'titleDescription']);
Chris@0 281 $this->controllerResolver->expects($this->at(2))
Chris@0 282 ->method('getControllerFromDefinition')
Chris@0 283 ->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleProvider')
Chris@0 284 ->willReturn([new TestPermissionCallbacks(), 'titleProvider']);
Chris@0 285 $this->controllerResolver->expects($this->at(3))
Chris@0 286 ->method('getControllerFromDefinition')
Chris@0 287 ->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess')
Chris@0 288 ->willReturn([new TestPermissionCallbacks(), 'titleDescriptionRestrictAccess']);
Chris@0 289
Chris@0 290 $this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
Chris@0 291
Chris@0 292 // Setup system_rebuild_module_data().
Chris@0 293 $this->permissionHandler->setSystemRebuildModuleData($extensions);
Chris@0 294
Chris@0 295 $actual_permissions = $this->permissionHandler->getPermissions();
Chris@0 296 $this->assertPermissions($actual_permissions);
Chris@0 297 }
Chris@0 298
Chris@0 299 /**
Chris@0 300 * Tests a YAML file containing both static permissions and a callback.
Chris@0 301 */
Chris@0 302 public function testPermissionsYamlStaticAndCallback() {
Chris@0 303 vfsStreamWrapper::register();
Chris@0 304 $root = new vfsStreamDirectory('modules');
Chris@0 305 vfsStreamWrapper::setRoot($root);
Chris@0 306
Chris@0 307 $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
Chris@0 308 $this->moduleHandler->expects($this->once())
Chris@0 309 ->method('getModuleDirectories')
Chris@0 310 ->willReturn([
Chris@0 311 'module_a' => vfsStream::url('modules/module_a'),
Chris@0 312 ]);
Chris@0 313
Chris@0 314 $url = vfsStream::url('modules');
Chris@0 315 mkdir($url . '/module_a');
Chris@0 316 file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
Chris@0 317 'access module a':
Chris@0 318 title: 'Access A'
Chris@0 319 description: 'bla bla'
Chris@0 320 permission_callbacks:
Chris@0 321 - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription'
Chris@0 322 EOF
Chris@0 323 );
Chris@0 324
Chris@0 325 $modules = ['module_a'];
Chris@0 326 $extensions = [
Chris@0 327 'module_a' => $this->mockModuleExtension('module_a', 'Module a'),
Chris@0 328 ];
Chris@0 329
Chris@0 330 $this->moduleHandler->expects($this->any())
Chris@0 331 ->method('getImplementations')
Chris@0 332 ->with('permission')
Chris@0 333 ->willReturn([]);
Chris@0 334
Chris@0 335 $this->moduleHandler->expects($this->any())
Chris@0 336 ->method('getModuleList')
Chris@0 337 ->willReturn(array_flip($modules));
Chris@0 338
Chris@0 339 $this->controllerResolver->expects($this->once())
Chris@0 340 ->method('getControllerFromDefinition')
Chris@0 341 ->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription')
Chris@0 342 ->willReturn([new TestPermissionCallbacks(), 'titleDescription']);
Chris@0 343
Chris@0 344 $this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
Chris@0 345
Chris@0 346 // Setup system_rebuild_module_data().
Chris@0 347 $this->permissionHandler->setSystemRebuildModuleData($extensions);
Chris@0 348
Chris@0 349 $actual_permissions = $this->permissionHandler->getPermissions();
Chris@0 350
Chris@0 351 $this->assertCount(2, $actual_permissions);
Chris@0 352 $this->assertEquals($actual_permissions['access module a']['title'], 'Access A');
Chris@0 353 $this->assertEquals($actual_permissions['access module a']['provider'], 'module_a');
Chris@0 354 $this->assertEquals($actual_permissions['access module a']['description'], 'bla bla');
Chris@0 355 $this->assertEquals($actual_permissions['access module b']['title'], 'Access B');
Chris@0 356 $this->assertEquals($actual_permissions['access module b']['provider'], 'module_a');
Chris@0 357 $this->assertEquals($actual_permissions['access module b']['description'], 'bla bla');
Chris@0 358 }
Chris@0 359
Chris@0 360 /**
Chris@0 361 * Checks that the permissions are like expected.
Chris@0 362 *
Chris@0 363 * @param array $actual_permissions
Chris@0 364 * The actual permissions
Chris@0 365 */
Chris@0 366 protected function assertPermissions(array $actual_permissions) {
Chris@0 367 $this->assertCount(4, $actual_permissions);
Chris@0 368 $this->assertEquals($actual_permissions['access_module_a']['title'], 'single_description');
Chris@0 369 $this->assertEquals($actual_permissions['access_module_a']['provider'], 'module_a');
Chris@0 370 $this->assertEquals($actual_permissions['access module b']['title'], 'Access B');
Chris@0 371 $this->assertEquals($actual_permissions['access module b']['provider'], 'module_b');
Chris@0 372 $this->assertEquals($actual_permissions['access_module_c']['title'], 'Access C');
Chris@0 373 $this->assertEquals($actual_permissions['access_module_c']['provider'], 'module_c');
Chris@0 374 $this->assertEquals($actual_permissions['access_module_c']['restrict access'], TRUE);
Chris@0 375 $this->assertEquals($actual_permissions['access module a via module b']['provider'], 'module_a');
Chris@0 376 }
Chris@0 377
Chris@0 378 }
Chris@0 379
Chris@0 380 class TestPermissionHandler extends PermissionHandler {
Chris@0 381
Chris@0 382 /**
Chris@0 383 * Test module data.
Chris@0 384 *
Chris@0 385 * @var array
Chris@0 386 */
Chris@0 387 protected $systemModuleData;
Chris@0 388
Chris@0 389 protected function systemRebuildModuleData() {
Chris@0 390 return $this->systemModuleData;
Chris@0 391 }
Chris@0 392
Chris@0 393 public function setSystemRebuildModuleData(array $extensions) {
Chris@0 394 $this->systemModuleData = $extensions;
Chris@0 395 }
Chris@0 396
Chris@0 397 }
Chris@0 398
Chris@0 399 class TestPermissionCallbacks {
Chris@0 400
Chris@0 401 public function singleDescription() {
Chris@0 402 return [
Chris@17 403 'access_module_a' => 'single_description',
Chris@0 404 ];
Chris@0 405 }
Chris@0 406
Chris@0 407 public function titleDescription() {
Chris@0 408 return [
Chris@0 409 'access module b' => [
Chris@0 410 'title' => 'Access B',
Chris@0 411 'description' => 'bla bla',
Chris@0 412 ],
Chris@0 413 ];
Chris@0 414 }
Chris@0 415
Chris@0 416 public function titleDescriptionRestrictAccess() {
Chris@0 417 return [
Chris@0 418 'access_module_c' => [
Chris@0 419 'title' => 'Access C',
Chris@0 420 'description' => 'bla bla',
Chris@0 421 'restrict access' => TRUE,
Chris@0 422 ],
Chris@0 423 ];
Chris@0 424 }
Chris@0 425
Chris@0 426 public function titleProvider() {
Chris@0 427 return [
Chris@0 428 'access module a via module b' => [
Chris@0 429 'title' => 'Access A via B',
Chris@0 430 'provider' => 'module_a',
Chris@0 431 ],
Chris@0 432 ];
Chris@0 433 }
Chris@0 434
Chris@0 435 }
Chris@0 436
Chris@0 437 /**
Chris@0 438 * Implements a translation manager in tests.
Chris@0 439 */
Chris@0 440 class TestTranslationManager implements TranslationInterface {
Chris@0 441
Chris@0 442 /**
Chris@0 443 * {@inheritdoc}
Chris@0 444 */
Chris@0 445 public function translate($string, array $args = [], array $options = []) {
Chris@0 446 return new TranslatableMarkup($string, $args, $options, $this);
Chris@0 447 }
Chris@0 448
Chris@0 449 /**
Chris@0 450 * {@inheritdoc}
Chris@0 451 */
Chris@0 452 public function translateString(TranslatableMarkup $translated_string) {
Chris@0 453 return $translated_string->getUntranslatedString();
Chris@0 454 }
Chris@0 455
Chris@0 456 /**
Chris@0 457 * {@inheritdoc}
Chris@0 458 */
Chris@0 459 public function formatPlural($count, $singular, $plural, array $args = [], array $options = []) {
Chris@0 460 return new PluralTranslatableMarkup($count, $singular, $plural, $args, $options, $this);
Chris@0 461 }
Chris@0 462
Chris@0 463 }