CacheStrategy::loadAll()   D
last analyzed

Complexity

Conditions 9
Paths 8

Size

Total Lines 33
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 9

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 33
ccs 22
cts 22
cp 1
rs 4.909
cc 9
eloc 23
nc 8
nop 3
crap 9
1
<?php
2
declare(strict_types=1);
3
/**
4
 * Caridea
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
 * use this file except in compliance with the License. You may obtain a copy of
8
 * the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
 * License for the specific language governing permissions and limitations under
16
 * the License.
17
 *
18
 * @copyright 2015-2018 LibreWorks contributors
19
 * @license   Apache-2.0
20
 */
21
namespace Caridea\Acl;
22
23
/**
24
 * Caches ACLs based on Target and Subjects.
25
 *
26
 * @copyright 2015-2018 LibreWorks contributors
27
 * @license   Apache-2.0
28
 */
29
class CacheStrategy implements MultiStrategy
30
{
31
    /**
32
     * @var array<string,\Caridea\Acl\Acl> contains the ACLs indexed by Target and Subjects string
33
     */
34
    protected $cache = [];
35
    /**
36
     * @var \Caridea\Acl\Strategy The actual loading strategy
37
     */
38
    protected $delegate;
39
40
    /**
41
     * Creates a new CacheStrategy.
42
     *
43
     * @param \Caridea\Acl\Strategy $delegate The actual loading strategy to use
44
     */
45 6
    public function __construct(Strategy $delegate)
46
    {
47 6
        $this->delegate = $delegate;
48 6
    }
49
50
    /**
51
     * Loads the ACL for a Target.
52
     *
53
     * @param \Caridea\Acl\Target $target The `Target` whose ACL will be loaded
54
     * @param \Caridea\Acl\Subject[] $subjects An array of `Subject`s
55
     * @param \Caridea\Acl\Service $service The ACL service (to load parent ACLs)
56
     * @return \Caridea\Acl\Acl The loaded ACL
57
     * @throws \Caridea\Acl\Exception\Unloadable If the resource provided is invalid
58
     * @throws \InvalidArgumentException If the `subjects` argument contains invalid values
59
     */
60 3
    public function load(Target $target, array $subjects, Service $service): Acl
61
    {
62 3
        $key = $this->buildKey($target, $subjects);
63 2
        if (!isset($this->cache[$key])) {
64 2
            $acl = $this->delegate->load($target, $subjects, $service);
65 2
            $this->cache[$key] = $acl;
66
        }
67 2
        return $this->cache[$key];
68
    }
69
70
    /**
71
     * Loads the ACLs for several Targets.
72
     *
73
     * @since 2.1.0
74
     * @param \Caridea\Acl\Target[] $targets The `Target` whose ACL will be loaded
75
     * @param \Caridea\Acl\Subject[] $subjects An array of `Subject`s
76
     * @param \Caridea\Acl\Service $service The ACL service (to load parent ACLs)
77
     * @return array<string,\Caridea\Acl\Acl> The loaded ACLs
78
     * @throws \Caridea\Acl\Exception\Unloadable If the target provided is invalid
79
     * @throws \InvalidArgumentException If the `subjects` argument contains invalid values
80
     */
81 4
    public function loadAll(array $targets, array $subjects, Service $service): array
82
    {
83 4
        $acls = [];
84 4
        if ($this->delegate instanceof MultiStrategy) {
85 2
            $oids = array_merge($targets);
86 2
            foreach ($targets as $i => $target) {
87 2
                if (!($target instanceof Target)) {
88 1
                    throw new \InvalidArgumentException("Only instances of Target are permitted in the targets argument");
89
                }
90 1
                $key = $this->buildKey($target, $subjects);
91 1
                if (isset($this->cache[$key])) {
92 1
                    $acls[(string)$target] = $this->cache[$key];
93 1
                    unset($oids[$i]);
94
                }
95
            }
96 1
            if (!empty($oids)) {
97 1
                $a = $this->delegate->loadAll($oids, $subjects, $service);
98 1
                foreach ($a as $acl) {
99 1
                    $key = $this->buildKey($acl->getTarget(), $subjects);
100 1
                    $this->cache[$key] = $acl;
101 1
                    $acls[(string)$acl->getTarget()] = $acl;
102
                }
103
            }
104
        } else {
105 2
            foreach ($targets as $target) {
106 2
                if (!($target instanceof Target)) {
107 1
                    throw new \InvalidArgumentException("Only instances of Target are permitted in the targets argument");
108
                }
109 1
                $acls[(string) $target] = $this->load($target, $subjects, $service);
110
            }
111
        }
112 2
        return $acls;
113
    }
114
115
    /**
116
     * Generates the key to use for caching the ACL.
117
     *
118
     * @param \Caridea\Acl\Target $target The `Target` whose ACL will be loaded
119
     * @param array $subjects An array of `Subject`s
120
     * @return string The cache key
121
     * @throws \InvalidArgumentException If the `subjects` argument contains invalid values
122
     */
123 4
    protected function buildKey(Target $target, array $subjects): string
124
    {
125 4
        $key = (string) $target;
126 4
        foreach ($subjects as $subject) {
127 4
            if (!($subject instanceof Subject)) {
128 1
                throw new \InvalidArgumentException("Only instances of Subject are permitted in the subjects argument");
129
            }
130 3
            $key .= ";{$subject}";
131
        }
132 3
        return $key;
133
    }
134
}
135