Completed
Push — cached_permision_criterion ( 018fb5...098e4d )
by André
19:04 queued 06:14
created

CachedPermissionService::getPermissionsCriterion()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 9
nc 4
nop 2
dl 0
loc 19
rs 8.8571
c 0
b 0
f 0
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\Permission;
8
9
use eZ\Publish\API\Repository\PermissionResolver;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, eZ\Publish\Core\Reposito...sion\PermissionResolver.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
10
use eZ\Publish\API\Repository\PermissionCriterionResolver;
11
use eZ\Publish\API\Repository\Values\User\UserReference;
12
use eZ\Publish\API\Repository\Values\ValueObject;
13
14
/**
15
 * Cache implementation of PermissionResolver and PermissionCriterionResolver interface.
16
 *
17
 * Implements both interfaces as the cached permission criterion lookup needs to be
18
 * expired when a different user is set as current users in the system.
19
 *
20
 * Cache is only done for content/read policy, as that is the one needed by search service.
21
 *
22
 * The logic here uses a cache TTL of a few seconds, as this is in-memory cache we are not
23
 * able to know if any other concurrent user might be changing permissions.
24
 */
25
class CachedPermissionService implements PermissionResolver, PermissionCriterionResolver
26
{
27
    /**
28
     * @var \eZ\Publish\API\Repository\PermissionResolver
29
     */
30
    private $permissionResolver;
31
32
    /**
33
     * @var \eZ\Publish\API\Repository\PermissionCriterionResolver
34
     */
35
    private $permissionCriterionResolver;
36
37
    /**
38
     * @var int
39
     */
40
    private $cacheTTL;
41
42
    /**
43
     * Cached value for current user's getCriterion() result.
44
     *
45
     * Value is null if not yet set or cleared.
46
     *
47
     * @var bool|\eZ\Publish\API\Repository\Values\Content\Query\Criterion
48
     */
49
    private $permissionCriterion;
50
51
    /**
52
     * Cache time stamp.
53
     *
54
     * @var int
55
     */
56
    private $permissionCriterionTimeStamp;
57
58
    public function __construct(
59
        PermissionResolver $permissionResolver,
60
        PermissionCriterionResolver $permissionCriterionResolver,
61
        $cacheTTL = 5
62
    ) {
63
        $this->permissionResolver = $permissionResolver;
64
        $this->permissionCriterionResolver = $permissionCriterionResolver;
65
        $this->cacheTTL = $cacheTTL;
66
    }
67
68
    public function getCurrentUserReference()
69
    {
70
        return $this->permissionResolver->getCurrentUserReference();
71
    }
72
73
    public function setCurrentUserReference(UserReference $userReference)
74
    {
75
        $this->permissionCriterion = null;
76
        return $this->permissionResolver->setCurrentUserReference($userReference);
77
    }
78
79
    public function hasAccess($module, $function, UserReference $userReference = null)
80
    {
81
        return $this->permissionResolver->hasAccess($module, $function, $userReference);
82
    }
83
84
    public function canUser($module, $function, ValueObject $object, array $targets = [])
85
    {
86
        return $this->permissionResolver->canUser($module, $function, $object, $targets);
87
    }
88
89
    public function getPermissionsCriterion($module = 'content', $function = 'read')
90
    {
91
        // We only cache content/read lookups as those are the once frequently done
92
        if ($module !== 'content' || $function !== 'read') {
93
            return $this->permissionCriterionResolver->getPermissionsCriterion($module, $function);
94
        }
95
96
        if ($this->permissionCriterion !== null) {
97
            // If we are still within the cache TTL, then return the cached value
98
            if ((time() - $this->permissionCriterionTimeStamp) < $this->cacheTTL) {
99
                return $this->permissionCriterion;
100
            }
101
        }
102
103
        $this->permissionCriterionTimeStamp = time();
104
        $this->permissionCriterion = $this->permissionCriterionResolver->getPermissionsCriterion($module, $function);
105
106
        return $this->permissionCriterion;
107
    }
108
}