comparison core/modules/user/tests/src/Unit/PermissionHandlerTest.php @ 0:4c8ae668cc8c

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