Completed
Push — feature-EZP-25696 ( 52d929...5f47d3 )
by André
23:51
created

PermissionTest::getPermissionResolverMock()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 19
cc 2
eloc 12
nc 2
nop 1
rs 9.4285
1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
namespace eZ\Publish\Core\Repository\Tests\Service\Mock;
8
9
use eZ\Publish\API\Repository\Repository;
10
use eZ\Publish\Core\Repository\Permission\PermissionResolver;
11
use eZ\Publish\Core\Repository\Values\User\UserReference;
12
use eZ\Publish\Core\Base\Exceptions\NotFound\LimitationNotFoundException;
13
use eZ\Publish\Core\Repository\Tests\Service\Mock\Base as BaseServiceMockTest;
14
use eZ\Publish\SPI\Persistence\User\RoleAssignment;
15
use eZ\Publish\SPI\Persistence\User\Role;
16
use eZ\Publish\SPI\Persistence\User\Policy;
17
18
/**
19
 * Mock test case for PermissionResolver.
20
 */
21
class PermissionTest extends BaseServiceMockTest
22
{
23
    public function providerForTestHasAccessReturnsTrue()
24
    {
25
        return array(
26
            array(
27
                array(
28
                    25 => $this->createRole(
29
                        array(
30
                            array('dummy-module', 'dummy-function', 'dummy-limitation'),
31
                            array('dummy-module2', 'dummy-function2', 'dummy-limitation2'),
32
                        ),
33
                        25
34
                    ),
35
                    26 => $this->createRole(
36
                        array(
37
                            array('*', 'dummy-function', 'dummy-limitation'),
38
                        ),
39
                        26
40
                    ),
41
                ),
42
                array(
43
                    new RoleAssignment(
44
                        array(
45
                            'roleId' => 25,
46
                        )
47
                    ),
48
                    new RoleAssignment(
49
                        array(
50
                            'roleId' => 26,
51
                        )
52
                    ),
53
                ),
54
            ),
55
            array(
56
                array(
57
                    27 => $this->createRole(
58
                        array(
59
                            array('test-module', '*', 'dummy-limitation'),
60
                        ),
61
                        27
62
                    ),
63
                ),
64
                array(
65
                    new RoleAssignment(
66
                        array(
67
                            'roleId' => 27,
68
                        )
69
                    ),
70
                ),
71
            ),
72
            array(
73
                array(
74
                    28 => $this->createRole(
75
                        array(
76
                            array('test-module', 'test-function', '*'),
77
                        ),
78
                        28
79
                    ),
80
                ),
81
                array(
82
                    new RoleAssignment(
83
                        array(
84
                            'roleId' => 28,
85
                        )
86
                    ),
87
                ),
88
            ),
89
        );
90
    }
91
92
    /**
93
     * Test for the hasAccess() method.
94
     *
95
     * @dataProvider providerForTestHasAccessReturnsTrue
96
     */
97 View Code Duplication
    public function testHasAccessReturnsTrue(array $roles, array $roleAssignments)
98
    {
99
        /** @var $userHandlerMock \PHPUnit_Framework_MockObject_MockObject */
100
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
101
        $userReferenceMock = $this->getUserReferenceMock();
102
        $mockedService = $this->getPermissionResolverMock(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
103
104
        $userReferenceMock
105
            ->expects($this->once())
106
            ->method('getUserId')
107
            ->will($this->returnValue(10));
108
109
        $userHandlerMock
110
            ->expects($this->once())
111
            ->method('loadRoleAssignmentsByGroupId')
112
            ->with($this->equalTo(10), $this->equalTo(true))
113
            ->will($this->returnValue($roleAssignments));
114
115
        foreach ($roleAssignments as $at => $roleAssignment) {
116
            $userHandlerMock
117
                ->expects($this->at($at + 1))
118
                ->method('loadRole')
119
                ->with($roleAssignment->roleId)
120
                ->will($this->returnValue($roles[$roleAssignment->roleId]));
121
        }
122
123
        $result = $mockedService->hasAccess('test-module', 'test-function');
124
125
        self::assertEquals(true, $result);
126
    }
127
128
    public function providerForTestHasAccessReturnsFalse()
129
    {
130
        return array(
131
            array(array(), array()),
132
            array(
133
                array(
134
                    29 => $this->createRole(
135
                        array(
136
                            array('dummy-module', 'dummy-function', 'dummy-limitation'),
137
                        ),
138
                        29
139
                    ),
140
                ),
141
                array(
142
                    new RoleAssignment(
143
                        array(
144
                            'roleId' => 29,
145
                        )
146
                    ),
147
                ),
148
            ),
149
            array(
150
                array(
151
                    30 => $this->createRole(
152
                        array(
153
                            array('test-module', 'dummy-function', 'dummy-limitation'),
154
                        ),
155
                        30
156
                    ),
157
                ),
158
                array(
159
                    new RoleAssignment(
160
                        array(
161
                            'roleId' => 30,
162
                        )
163
                    ),
164
                ),
165
            ),
166
        );
167
    }
168
169
    /**
170
     * Test for the hasAccess() method.
171
     *
172
     * @dataProvider providerForTestHasAccessReturnsFalse
173
     */
174 View Code Duplication
    public function testHasAccessReturnsFalse(array $roles, array $roleAssignments)
175
    {
176
        /** @var $userHandlerMock \PHPUnit_Framework_MockObject_MockObject */
177
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
178
        $userReferenceMock = $this->getUserReferenceMock();
179
        $service = $this->getPermissionResolverMock(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
180
181
        $userReferenceMock
182
            ->expects($this->once())
183
            ->method('getUserId')
184
            ->will($this->returnValue(10));
185
186
        $userHandlerMock
187
            ->expects($this->once())
188
            ->method('loadRoleAssignmentsByGroupId')
189
            ->with($this->equalTo(10), $this->equalTo(true))
190
            ->will($this->returnValue($roleAssignments));
191
192
        foreach ($roleAssignments as $at => $roleAssignment) {
193
            $userHandlerMock
194
                ->expects($this->at($at + 1))
195
                ->method('loadRole')
196
                ->with($roleAssignment->roleId)
197
                ->will($this->returnValue($roles[$roleAssignment->roleId]));
198
        }
199
200
        $result = $service->hasAccess('test-module', 'test-function');
201
202
        self::assertEquals(false, $result);
203
    }
204
205
    /**
206
     * Test for the sudo() & hasAccess() method.
207
     */
208
    public function testHasAccessReturnsFalseButSudoSoTrue()
209
    {
210
        /** @var $userHandlerMock \PHPUnit_Framework_MockObject_MockObject */
211
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
212
        $service = $this->getPermissionResolverMock(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
213
        $repositoryMock = $this->getRepositoryMock();
214
        $repositoryMock
215
            ->expects($this->any())
216
            ->method('getPermissionResolver')
217
            ->will($this->returnValue($service));
218
219
        $userHandlerMock
220
            ->expects($this->never())
221
            ->method($this->anything());
222
223
        $result = $service->sudo(
224
            function (Repository $repo) {
225
                return $repo->hasAccess('test-module', 'test-function');
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repository\Repository::hasAccess() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::hasAccess() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
226
            },
227
            $repositoryMock
228
        );
229
230
        self::assertEquals(true, $result);
231
    }
232
233
    /**
234
     * @return array
235
     */
236 View Code Duplication
    public function providerForTestHasAccessReturnsPermissionSets()
237
    {
238
        return array(
239
            array(
240
                array(
241
                    31 => $this->createRole(
242
                        array(
243
                            array('test-module', 'test-function', 'test-limitation'),
244
                        ),
245
                        31
246
                    ),
247
                ),
248
                array(
249
                    new RoleAssignment(
250
                        array(
251
                            'roleId' => 31,
252
                        )
253
                    ),
254
                ),
255
            ),
256
            array(
257
                array(
258
                    31 => $this->createRole(
259
                        array(
260
                            array('test-module', 'test-function', 'test-limitation'),
261
                        ),
262
                        31
263
                    ),
264
                    32 => $this->createRole(
265
                        array(
266
                            array('test-module', 'test-function', 'test-limitation2'),
267
                        ),
268
                        32
269
                    ),
270
                ),
271
                array(
272
                    new RoleAssignment(
273
                        array(
274
                            'roleId' => 31,
275
                        )
276
                    ),
277
                    new RoleAssignment(
278
                        array(
279
                            'roleId' => 32,
280
                        )
281
                    ),
282
                ),
283
            ),
284
        );
285
    }
286
287
    /**
288
     * Test for the hasAccess() method.
289
     *
290
     * @dataProvider providerForTestHasAccessReturnsPermissionSets
291
     */
292
    public function testHasAccessReturnsPermissionSets(array $roles, array $roleAssignments)
293
    {
294
        /** @var $userHandlerMock \PHPUnit_Framework_MockObject_MockObject */
295
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
296
        $roleDomainMapper = $this->getRoleDomainMapperMock(['buildDomainPolicyObject']);
297
        $permissionResolverMock = $this->getPermissionResolverMock(['getCurrentUserReference']);
298
299
        $permissionResolverMock
300
            ->expects($this->once())
301
            ->method('getCurrentUserReference')
302
            ->will($this->returnValue(new UserReference(14)));
303
304
        $userHandlerMock
305
            ->expects($this->once())
306
            ->method('loadRoleAssignmentsByGroupId')
307
            ->with($this->isType('integer'), $this->equalTo(true))
308
            ->will($this->returnValue($roleAssignments));
309
310
        foreach ($roleAssignments as $at => $roleAssignment) {
311
            $userHandlerMock
312
                ->expects($this->at($at + 1))
313
                ->method('loadRole')
314
                ->with($roleAssignment->roleId)
315
                ->will($this->returnValue($roles[$roleAssignment->roleId]));
316
        }
317
318
        $permissionSets = array();
319
        $count = 0;
320
        /* @var $roleAssignments \eZ\Publish\SPI\Persistence\User\RoleAssignment[] */
321
        foreach ($roleAssignments as $i => $roleAssignment) {
322
            $permissionSet = array('limitation' => null);
323
            foreach ($roles[$roleAssignment->roleId]->policies as $k => $policy) {
324
                $policyName = 'policy-' . $i . '-' . $k;
325
                $return = $this->returnValue($policyName);
326
                $permissionSet['policies'][] = $policyName;
327
328
                $roleDomainMapper
329
                    ->expects($this->at($count++))
330
                    ->method('buildDomainPolicyObject')
331
                    ->with($policy)
332
                    ->will($return);
333
            }
334
335
            if (!empty($permissionSet['policies'])) {
336
                $permissionSets[] = $permissionSet;
337
            }
338
        }
339
340
        /* @var $repositoryMock \eZ\Publish\Core\Repository\Repository */
341
        self::assertEquals(
342
            $permissionSets,
343
            $permissionResolverMock->hasAccess('test-module', 'test-function')
344
        );
345
    }
346
347
    /**
348
     * @return array
349
     */
350 View Code Duplication
    public function providerForTestHasAccessReturnsException()
351
    {
352
        return array(
353
            array(
354
                array(
355
                    31 => $this->createRole(
356
                        array(
357
                            array('test-module', 'test-function', 'notfound'),
358
                        ),
359
                        31
360
                    ),
361
                ),
362
                array(
363
                    new RoleAssignment(
364
                        array(
365
                            'roleId' => 31,
366
                        )
367
                    ),
368
                ),
369
            ),
370
            array(
371
                array(
372
                    31 => $this->createRole(
373
                        array(
374
                            array('test-module', 'test-function', 'test-limitation'),
375
                        ),
376
                        31
377
                    ),
378
                    32 => $this->createRole(
379
                        array(
380
                            array('test-module', 'test-function', 'notfound'),
381
                        ),
382
                        32
383
                    ),
384
                ),
385
                array(
386
                    new RoleAssignment(
387
                        array(
388
                            'roleId' => 31,
389
                        )
390
                    ),
391
                    new RoleAssignment(
392
                        array(
393
                            'roleId' => 32,
394
                        )
395
                    ),
396
                ),
397
            ),
398
        );
399
    }
400
401
    /**
402
     * Test for the hasAccess() method.
403
     *
404
     * @dataProvider providerForTestHasAccessReturnsException
405
     * @expectedException \eZ\Publish\Core\Base\Exceptions\NotFound\LimitationNotFoundException
406
     */
407
    public function testHasAccessReturnsException(array $roles, array $roleAssignments)
408
    {
409
        /** @var $userHandlerMock \PHPUnit_Framework_MockObject_MockObject */
410
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
411
        $roleDomainMapper = $this->getRoleDomainMapperMock();
412
        $permissionResolverMock = $this->getPermissionResolverMock(['getCurrentUserReference']);
413
414
        $permissionResolverMock
415
            ->expects($this->once())
416
            ->method('getCurrentUserReference')
417
            ->will($this->returnValue(new UserReference(14)));
418
419
        $userHandlerMock
420
            ->expects($this->once())
421
            ->method('loadRoleAssignmentsByGroupId')
422
            ->with($this->isType('integer'), $this->equalTo(true))
423
            ->will($this->returnValue($roleAssignments));
424
425
        foreach ($roleAssignments as $at => $roleAssignment) {
426
            $userHandlerMock
427
                ->expects($this->at($at + 1))
428
                ->method('loadRole')
429
                ->with($roleAssignment->roleId)
430
                ->will($this->returnValue($roles[$roleAssignment->roleId]));
431
        }
432
433
        $count = 0;
434
        /* @var $roleAssignments \eZ\Publish\SPI\Persistence\User\RoleAssignment[] */
435
        foreach ($roleAssignments as $i => $roleAssignment) {
436
            $permissionSet = array('limitation' => null);
437
            foreach ($roles[$roleAssignment->roleId]->policies as $k => $policy) {
438
                $policyName = 'policy-' . $i . '-' . $k;
439
                if ($policy->limitations === 'notfound') {
440
                    $return = $this->throwException(new LimitationNotFoundException('notfound'));
441
                } else {
442
                    $return = $this->returnValue($policyName);
443
                    $permissionSet['policies'][] = $policyName;
444
                }
445
446
                $roleDomainMapper
447
                    ->expects($this->at($count++))
448
                    ->method('buildDomainPolicyObject')
449
                    ->with($policy)
450
                    ->will($return);
451
452
                if ($policy->limitations === 'notfound') {
453
                    break 2;// no more execution after exception
454
                }
455
            }
456
        }
457
458
        $permissionResolverMock->hasAccess('test-module', 'test-function');
459
    }
460
461 View Code Duplication
    public function providerForTestHasAccessReturnsPermissionSetsWithRoleLimitation()
462
    {
463
        return array(
464
            array(
465
                array(
466
                    32 => $this->createRole(
467
                        array(
468
                            array('test-module', 'test-function', 'test-limitation'),
469
                        ),
470
                        32
471
                    ),
472
                ),
473
                array(
474
                    new RoleAssignment(
475
                        array(
476
                            'roleId' => 32,
477
                            'limitationIdentifier' => 'test-role-limitation',
478
                            'values' => array('test-role-limitation-value'),
479
                        )
480
                    ),
481
                ),
482
            ),
483
            array(
484
                array(
485
                    33 => $this->createRole(array(array('*', '*', '*')), 33),
486
                ),
487
                array(
488
                    new RoleAssignment(
489
                        array(
490
                            'roleId' => 33,
491
                            'limitationIdentifier' => 'test-role-limitation',
492
                            'values' => array('test-role-limitation-value'),
493
                        )
494
                    ),
495
                ),
496
            ),
497
        );
498
    }
499
500
    /**
501
     * Test for the hasAccess() method.
502
     *
503
     * @dataProvider providerForTestHasAccessReturnsPermissionSetsWithRoleLimitation
504
     */
505
    public function testHasAccessReturnsPermissionSetsWithRoleLimitation(array $roles, array $roleAssignments)
506
    {
507
        /** @var $userHandlerMock \PHPUnit_Framework_MockObject_MockObject */
508
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
509
        $limitationTypeMock = $this->getMock('eZ\\Publish\\SPI\\Limitation\\Type');
510
        $limitationService = $this->getLimitationServiceMock();
511
        $roleDomainMapper = $this->getRoleDomainMapperMock();
512
        $permissionResolverMock = $this->getPermissionResolverMock(['getCurrentUserReference']);
513
514
        $permissionResolverMock
515
            ->expects($this->once())
516
            ->method('getCurrentUserReference')
517
            ->will($this->returnValue(new UserReference(14)));
518
519
        $userHandlerMock
520
            ->expects($this->once())
521
            ->method('loadRoleAssignmentsByGroupId')
522
            ->with($this->isType('integer'), $this->equalTo(true))
523
            ->will($this->returnValue($roleAssignments));
524
525
        foreach ($roleAssignments as $at => $roleAssignment) {
526
            $userHandlerMock
527
                ->expects($this->at($at + 1))
528
                ->method('loadRole')
529
                ->with($roleAssignment->roleId)
530
                ->will($this->returnValue($roles[$roleAssignment->roleId]));
531
        }
532
533
        $permissionSets = array();
534
        /** @var $roleAssignments \eZ\Publish\SPI\Persistence\User\RoleAssignment[] */
535
        foreach ($roleAssignments as $i => $roleAssignment) {
536
            $permissionSet = array();
537
            foreach ($roles[$roleAssignment->roleId]->policies as $k => $policy) {
538
                $policyName = "policy-{$i}-{$k}";
539
                $permissionSet['policies'][] = $policyName;
540
                $roleDomainMapper
541
                    ->expects($this->at($k))
542
                    ->method('buildDomainPolicyObject')
543
                    ->with($policy)
544
                    ->will($this->returnValue($policyName));
545
            }
546
547
            $permissionSet['limitation'] = "limitation-{$i}";
548
            $limitationTypeMock
549
                ->expects($this->at($i))
550
                ->method('buildValue')
551
                ->with($roleAssignment->values)
552
                ->will($this->returnValue($permissionSet['limitation']));
553
            $limitationService
554
                ->expects($this->any())
555
                ->method('getLimitationType')
556
                ->with($roleAssignment->limitationIdentifier)
557
                ->will($this->returnValue($limitationTypeMock));
558
559
            $permissionSets[] = $permissionSet;
560
        }
561
562
        self::assertEquals(
563
            $permissionSets,
564
            $permissionResolverMock->hasAccess('test-module', 'test-function')
565
        );
566
    }
567
568
    /**
569
     * Returns Role stub.
570
     *
571
     * @param array $policiesData
572
     * @param mixed $roleId
573
     *
574
     * @return \eZ\Publish\SPI\Persistence\User\Role
575
     */
576
    private function createRole(array $policiesData, $roleId = null)
577
    {
578
        $policies = array();
579
        foreach ($policiesData as $policyData) {
580
            $policies[] = new Policy(
581
                array(
582
                    'module' => $policyData[0],
583
                    'function' => $policyData[1],
584
                    'limitations' => $policyData[2],
585
                )
586
            );
587
        }
588
589
        return new Role(
590
            array(
591
                'id' => $roleId,
592
                'policies' => $policies,
593
            )
594
        );
595
    }
596
597
    public function providerForTestCanUserSimple()
598
    {
599
        return array(
600
            array(true, true),
601
            array(false, false),
602
            array(array(), false),
603
        );
604
    }
605
606
    /**
607
     * Test for the canUser() method.
608
     *
609
     * Tests execution paths with permission sets equaling to boolean value or empty array.
610
     *
611
     * @dataProvider providerForTestCanUserSimple
612
     */
613 View Code Duplication
    public function testCanUserSimple($permissionSets, $result)
614
    {
615
        $permissionResolverMock = $this->getPermissionResolverMock(['hasAccess']);
616
617
        $permissionResolverMock
618
            ->expects($this->once())
619
            ->method('hasAccess')
620
            ->with($this->equalTo('test-module'), $this->equalTo('test-function'))
621
            ->will($this->returnValue($permissionSets));
622
623
        /** @var $valueObject \eZ\Publish\API\Repository\Values\ValueObject */
624
        $valueObject = $this->getMockForAbstractClass('eZ\\Publish\\API\\Repository\\Values\\ValueObject');
625
626
        self::assertEquals(
627
            $result,
628
            $permissionResolverMock->canUser('test-module', 'test-function', $valueObject, [$valueObject])
629
        );
630
    }
631
632
    /**
633
     * Test for the canUser() method.
634
     *
635
     * Tests execution path with permission set defining no limitations.
636
     */
637
    public function testCanUserWithoutLimitations()
638
    {
639
        $permissionResolverMock = $this->getPermissionResolverMock(
640
            [
641
                'hasAccess',
642
                'getCurrentUserReference',
643
            ]
644
        );
645
646
        $policyMock = $this->getMock(
647
            'eZ\\Publish\\SPI\\Persistence\\User\\Policy',
648
            array('getLimitations'),
649
            array(),
650
            '',
651
            false
652
        );
653
        $policyMock
654
            ->expects($this->once())
655
            ->method('getLimitations')
656
            ->will($this->returnValue('*'));
657
        $permissionSets = array(
658
            array(
659
                'limitation' => null,
660
                'policies' => array($policyMock),
661
            ),
662
        );
663
        $permissionResolverMock
664
            ->expects($this->once())
665
            ->method('hasAccess')
666
            ->with($this->equalTo('test-module'), $this->equalTo('test-function'))
667
            ->will($this->returnValue($permissionSets));
668
669
        $permissionResolverMock
670
            ->expects($this->once())
671
            ->method('getCurrentUserReference')
672
            ->will($this->returnValue(new UserReference(14)));
673
674
        /** @var $valueObject \eZ\Publish\API\Repository\Values\ValueObject */
675
        $valueObject = $this->getMockForAbstractClass(
676
            'eZ\\Publish\\API\\Repository\\Values\\ValueObject'
677
        );
678
679
        self::assertTrue(
680
            $permissionResolverMock->canUser(
681
                'test-module',
682
                'test-function',
683
                $valueObject,
684
                [$valueObject]
685
            )
686
        );
687
    }
688
689
    /**
690
     * @return array
691
     */
692
    private function getPermissionSetsMock()
693
    {
694
        $roleLimitationMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\User\\Limitation');
695
        $roleLimitationMock
696
            ->expects($this->any())
697
            ->method('getIdentifier')
698
            ->will($this->returnValue('test-role-limitation-identifier'));
699
700
        $policyLimitationMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\User\\Limitation');
701
        $policyLimitationMock
702
            ->expects($this->any())
703
            ->method('getIdentifier')
704
            ->will($this->returnValue('test-policy-limitation-identifier'));
705
706
        $policyMock = $this->getMock(
707
            'eZ\\Publish\\SPI\\Persistence\\User\\Policy',
708
            array('getLimitations'),
709
            array(),
710
            '',
711
            false
712
        );
713
        $policyMock
714
            ->expects($this->any())
715
            ->method('getLimitations')
716
            ->will($this->returnValue(array($policyLimitationMock, $policyLimitationMock)));
717
718
        $permissionSet = array(
719
            'limitation' => clone $roleLimitationMock,
720
            'policies' => array($policyMock, $policyMock),
721
        );
722
        $permissionSets = array($permissionSet, $permissionSet);
723
724
        return $permissionSets;
725
    }
726
727
    /**
728
     * Provides evaluation results for two permission sets, each with a role limitation and two policies,
729
     * with two limitations per policy.
730
     *
731
     * @return array
732
     */
733
    public function providerForTestCanUserComplex()
734
    {
735
        return array(
736
            array(
737
                array(true, true),
738
                array(
739
                    array(
740
                        array(true, true),
741
                        array(true, true),
742
                    ),
743
                    array(
744
                        array(true, true),
745
                        array(true, true),
746
                    ),
747
                ),
748
                true,
749
            ),
750
            array(
751
                array(false, false),
752
                array(
753
                    array(
754
                        array(true, true),
755
                        array(true, true),
756
                    ),
757
                    array(
758
                        array(true, true),
759
                        array(true, true),
760
                    ),
761
                ),
762
                false,
763
            ),
764
            array(
765
                array(false, true),
766
                array(
767
                    array(
768
                        array(true, true),
769
                        array(true, true),
770
                    ),
771
                    array(
772
                        array(true, true),
773
                        array(true, true),
774
                    ),
775
                ),
776
                true,
777
            ),
778
            array(
779
                array(false, true),
780
                array(
781
                    array(
782
                        array(true, true),
783
                        array(true, true),
784
                    ),
785
                    array(
786
                        array(true, false),
787
                        array(true, true),
788
                    ),
789
                ),
790
                true,
791
            ),
792
            array(
793
                array(true, false),
794
                array(
795
                    array(
796
                        array(true, false),
797
                        array(false, true),
798
                    ),
799
                    array(
800
                        array(true, true),
801
                        array(true, true),
802
                    ),
803
                ),
804
                false,
805
            ),
806
        );
807
    }
808
809
    /**
810
     * Test for the canUser() method.
811
     *
812
     * Tests execution paths with permission sets containing limitations.
813
     *
814
     * @dataProvider providerForTestCanUserComplex
815
     */
816
    public function testCanUserComplex(array $roleLimitationEvaluations, array $policyLimitationEvaluations, $userCan)
817
    {
818
        /** @var $valueObject \eZ\Publish\API\Repository\Values\ValueObject */
819
        $valueObject = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\ValueObject');
820
        $limitationServiceMock = $this->getLimitationServiceMock();
821
        $permissionResolverMock = $this->getPermissionResolverMock(
822
            [
823
                'hasAccess',
824
                'getCurrentUserReference',
825
            ]
826
        );
827
828
        $permissionSets = $this->getPermissionSetsMock();
829
        $permissionResolverMock
830
            ->expects($this->once())
831
            ->method('hasAccess')
832
            ->with($this->equalTo('test-module'), $this->equalTo('test-function'))
833
            ->will($this->returnValue($permissionSets));
834
835
        $userRef = new UserReference(14);
836
        $permissionResolverMock
837
            ->expects($this->once())
838
            ->method('getCurrentUserReference')
839
            ->will($this->returnValue(new UserReference(14)));
840
841
        $invocation = 0;
842
        for ($i = 0; $i < count($permissionSets); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
843
            $limitation = $this->getMock('eZ\\Publish\\SPI\\Limitation\\Type');
844
            $limitation
845
                ->expects($this->once())
846
                ->method('evaluate')
847
                ->with($permissionSets[$i]['limitation'], $userRef, $valueObject, array($valueObject))
848
                ->will($this->returnValue($roleLimitationEvaluations[$i]));
849
            $limitationServiceMock
850
                ->expects($this->at($invocation++))
851
                ->method('getLimitationType')
852
                ->with('test-role-limitation-identifier')
853
                ->will($this->returnValue($limitation));
854
855
            if (!$roleLimitationEvaluations[$i]) {
856
                continue;
857
            }
858
859
            for ($j = 0; $j < count($permissionSets[$i]['policies']); ++$j) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
860
                /** @var $policy \eZ\Publish\API\Repository\Values\User\Policy */
861
                $policy = $permissionSets[$i]['policies'][$j];
862
                $limitations = $policy->getLimitations();
863
                for ($k = 0; $k < count($limitations); ++$k) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
864
                    $limitationsPass = true;
865
                    $limitation = $this->getMock('eZ\\Publish\\SPI\\Limitation\\Type');
866
                    $limitation
867
                        ->expects($this->once())
868
                        ->method('evaluate')
869
                        ->with($limitations[$k], $userRef, $valueObject, array($valueObject))
870
                        ->will($this->returnValue($policyLimitationEvaluations[$i][$j][$k]));
871
                    $limitationServiceMock
872
                        ->expects($this->at($invocation++))
873
                        ->method('getLimitationType')
874
                        ->with('test-policy-limitation-identifier')
875
                        ->will($this->returnValue($limitation));
876
877
                    if (!$policyLimitationEvaluations[$i][$j][$k]) {
878
                        $limitationsPass = false;
879
                        break;
880
                    }
881
                }
882
883
                /** @var $limitationsPass */
884
                if ($limitationsPass) {
0 ignored issues
show
Bug introduced by
The variable $limitationsPass does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
885
                    break 2;
886
                }
887
            }
888
        }
889
890
        self::assertEquals(
891
            $userCan,
892
            $permissionResolverMock->canUser(
893
                'test-module',
894
                'test-function',
895
                $valueObject,
896
                [$valueObject]
897
            )
898
        );
899
    }
900
901
    /**
902
     * Test for the setCurrentUserReference() and getCurrentUserReference() methods.
903
     */
904
    public function testSetAndGetCurrentUserReference()
905
    {
906
        $permissionResolverMock = $this->getPermissionResolverMock(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
907
        $userReferenceMock = $this->getUserReferenceMock();
908
909
        $userReferenceMock
910
            ->expects($this->once())
911
            ->method('getUserId')
912
            ->will($this->returnValue(42));
913
914
        $permissionResolverMock->setCurrentUserReference($userReferenceMock);
915
916
        self::assertSame(
917
            $userReferenceMock,
918
            $permissionResolverMock->getCurrentUserReference()
919
        );
920
    }
921
922
    /**
923
     * Test for the getCurrentUserReference() method.
924
     */
925
    public function testGetCurrentUserReferenceReturnsAnonymousUser()
926
    {
927
        $permissionResolverMock = $this->getPermissionResolverMock(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
928
        $userReferenceMock = $this->getUserReferenceMock();
929
930
        self::assertSame(
931
            $userReferenceMock,
932
            $permissionResolverMock->getCurrentUserReference()
933
        );
934
    }
935
936
    protected $permissionResolverMock;
937
938
    /**
939
     * @return \eZ\Publish\API\Repository\PermissionResolver|\PHPUnit_Framework_MockObject_MockObject
940
     */
941
    protected function getPermissionResolverMock($methods = [])
942
    {
943
        if ($this->permissionResolverMock === null) {
944
            $this->permissionResolverMock = $this
945
                ->getMockBuilder('eZ\\Publish\\Core\\Repository\\Permission\\PermissionResolver')
946
                ->setMethods($methods)
947
                ->setConstructorArgs(
948
                    [
949
                        $this->getRoleDomainMapperMock(),
950
                        $this->getLimitationServiceMock(),
951
                        $this->getPersistenceMock()->userHandler(),
952
                        $this->getUserReferenceMock(),
953
                    ]
954
                )
955
                ->getMock();
956
        }
957
958
        return $this->permissionResolverMock;
959
    }
960
961
    protected $userReferenceMock;
962
963
    protected function getUserReferenceMock()
964
    {
965
        if ($this->userReferenceMock === null) {
966
            $this->userReferenceMock = $this
967
                ->getMockBuilder('eZ\Publish\API\Repository\Values\User\UserReference')
968
                ->getMock();
969
        }
970
971
        return $this->userReferenceMock;
972
    }
973
974
    protected $repositoryMock;
975
976
    /**
977
     * @return \eZ\Publish\API\Repository\Repository|\PHPUnit_Framework_MockObject_MockObject
978
     */
979
    protected function getRepositoryMock($methods = [])
0 ignored issues
show
Unused Code introduced by
The parameter $methods is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
980
    {
981
        if ($this->repositoryMock === null) {
982
            $this->repositoryMock = $this
983
                ->getMockBuilder('eZ\\Publish\\Core\\Repository\\Repository')
984
                ->setMethods(['getPermissionResolver'])
985
                ->disableOriginalConstructor()
986
                ->getMock();
987
        }
988
989
        return $this->repositoryMock;
990
    }
991
992
    protected $roleDomainMapperMock;
993
994
    /**
995
     * @return \eZ\Publish\Core\Repository\Helper\RoleDomainMapper|\PHPUnit_Framework_MockObject_MockObject
996
     */
997
    protected function getRoleDomainMapperMock($methods = [])
998
    {
999
        if ($this->roleDomainMapperMock === null) {
1000
            $this->roleDomainMapperMock = $this
1001
                ->getMockBuilder('eZ\\Publish\\Core\\Repository\\Helper\\RoleDomainMapper')
1002
                ->setMethods($methods)
1003
                ->disableOriginalConstructor()
1004
                ->getMock();
1005
        }
1006
1007
        return $this->roleDomainMapperMock;
1008
    }
1009
1010
    protected $limitationServiceMock;
1011
1012
    /**
1013
     * @return \eZ\Publish\Core\Repository\Helper\LimitationService|\PHPUnit_Framework_MockObject_MockObject
1014
     */
1015 View Code Duplication
    protected function getLimitationServiceMock($methods = [])
1016
    {
1017
        if ($this->limitationServiceMock === null) {
1018
            $this->limitationServiceMock = $this
1019
                ->getMockBuilder('eZ\\Publish\\Core\\Repository\\Helper\\LimitationService')
1020
                ->setMethods($methods)
1021
                ->disableOriginalConstructor()
1022
                ->getMock();
1023
        }
1024
1025
        return $this->limitationServiceMock;
1026
    }
1027
}
1028