• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

php-casbin / php-casbin / 11444189732

21 Oct 2024 04:08PM UTC coverage: 94.006% (+0.2%) from 93.837%
11444189732

push

github

web-flow
Merge pull request #167 from php-casbin/4.x

BREAKING CHANGE: Upgrade the minimum PHP version to 8.0.

716 of 758 new or added lines in 23 files covered. (94.46%)

10 existing lines in 4 files now uncovered.

1976 of 2102 relevant lines covered (94.01%)

134.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.96
/src/CachedEnforcer.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Casbin;
6

7
use Casbin\Contracts\CacheableParam;
8
use Casbin\Exceptions\CasbinException;
9
use Casbin\Log\Log;
10
use Casbin\Log\Logger;
11
use Casbin\Model\Model;
12
use Casbin\Persist\Adapter;
13
use Psr\Cache\CacheItemPoolInterface;
14
use Symfony\Component\Cache\Adapter\ArrayAdapter;
15

16
/**
17
 * Class CachedEnforcer
18
 * Wraps Enforcer and provides decision cache.
19
 * It is implemented using Symfony's Cache component, which supports multiple cache adapters such as 
20
 * filesystem, Redis, or Memcached. By default, it uses the `FilesystemAdapter` for local file-based caching.
21
 *
22
 * @author techlee@qq.com
23
 * @author 1692898084@qq.com
24
 */
25
class CachedEnforcer extends Enforcer
26
{
27
    /**
28
     * @var int|null
29
     */
30
    protected ?int $expireTime;
31

32
    /**
33
     * @var CacheItemPoolInterface
34
     */
35
    protected CacheItemPoolInterface $cache;
36

37
    /**
38
     * @var bool
39
     */
40
    protected bool $enableCache;
41

42
    /**
43
     * CachedEnforcer constructor.
44
     *
45
     * @param string|Model|null $model
46
     * @param string|Adapter|null $adapter
47
     * @param Logger|null $logger
48
     * @param bool|null $enableLog
49
     * 
50
     * @throws CasbinException
51
     */
52
    public function __construct(string|Model|null $model = null, string|Adapter|null $adapter = null, ?Logger $logger = null, ?bool $enableLog = null)
53
    {
54
        $this->enableCache = true;
12✔
55
        $this->cache = new ArrayAdapter();
12✔
56
        $this->expireTime = null;
12✔
57
        parent::__construct($model, $adapter, $logger, $enableLog);
12✔
58
    }
59

60
    /**
61
     * Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
62
     * If rvals is not string , ingore the cache.
63
     *
64
     * @param mixed ...$rvals
65
     *
66
     * @return bool
67
     *
68
     * @throws Exceptions\CasbinException
69
     */
70
    public function enforce(...$rvals): bool
71
    {
72
        if (!$this->enableCache) {
6✔
73
            return parent::enforce(...$rvals);
6✔
74
        }
75

76
        $key = $this->getKey(...$rvals);
6✔
77
        $res = $this->getCachedResult($key);
6✔
78
        if (!is_null($res)) {
6✔
79
            return $res;
6✔
80
        }
81

82
        $value = parent::enforce(...$rvals);
6✔
83
        $this->setCachedResult($key, $value);
6✔
84
        return $value;
6✔
85
    }
86

87
    /**
88
     * Determines whether to enable cache on Enforce(). When enableCache is enabled, cached result (true | false) will be returned for previous decisions.
89
     *
90
     * @param bool $enableCache
91
     * 
92
     * @return void
93
     */
94
    public function enableCache(bool $enableCache = true): void
95
    {
96
        $this->enableCache = $enableCache;
6✔
97
    }
98

99

100
    /**
101
     * Sets the cache adapter for the enforcer.
102
     * 
103
     *
104
     * @param CacheItemPoolInterface $cache
105
     * 
106
     * @return void
107
     */
108
    public function setCache(CacheItemPoolInterface $cache): void
109
    {
110
        $this->cache = $cache;
6✔
111
    }
112

113

114
    /**
115
     * Sets the expire time for the cache in seconds. If the value is null, the cache will never expire.
116
     *
117
     * @param int|null $expireTime
118
     * 
119
     * @return void
120
     */
121
    public function setExpireTime(int|null $expireTime): void
122
    {
123
        $this->expireTime = $expireTime;
6✔
124
    }
125

126
    /**
127
     * Invalidates the cache.
128
     */
129
    public function invalidateCache(): void
130
    {
131
        $this->cache->clear();
6✔
132
    }
133

134
    /**
135
     * Reloads the policy from file/database.
136
     */
137
    public function loadPolicy(): void
138
    {
139
        if ($this->enableCache) {
12✔
140
            $this->cache->clear();
12✔
141
        }
142

143
        parent::loadPolicy();
12✔
144
    }
145

146
    /**
147
     * Removes an authorization rule from the current policy.
148
     *
149
     * @param mixed ...$params
150
     *
151
     * @return bool
152
     */
153
    public function removePolicy(...$params): bool
154
    {
155
        if ($this->enableCache) {
6✔
156
            $key = $this->getKey(...$params);
6✔
157
            $this->cache->deleteItem($key);
6✔
158
        }
159

160
        return parent::removePolicy(...$params);
6✔
161
    }
162

163
    /**
164
     * Removes an authorization rules from the current policy.
165
     *
166
     * @param array $rules
167
     *
168
     * @return bool
169
     */
170
    public function removePolicies(array $rules): bool
171
    {
172
        if ($this->enableCache) {
6✔
173
            foreach ($rules as $rule) {
6✔
174
                $key = $this->getKey(...$rule);
6✔
175
                $this->cache->deleteItem($key);
6✔
176
            }
177
        }
178

179
        return parent::removePolicies($rules);
6✔
180
    }
181

182
    /**
183
     * Clears all policy.
184
     */
185
    public function clearPolicy(): void
186
    {
187
        if ($this->enableCache) {
6✔
188
            if (!$this->cache->clear()) {
6✔
NEW
189
                $this->logger->logError(new CasbinException('clear cache failed'));
×
190
            }
191
        }
192

193
        parent::clearPolicy();
6✔
194
    }
195

196
    /**
197
     * Gets the cached result from the cache by key.
198
     *
199
     * If the key does not exist in the cache, it returns null.
200
     *
201
     * @param string $key
202
     *
203
     * @return bool|null
204
     */
205
    public function getCachedResult(string $key): bool|null
206
    {
207
        $value = $this->cache->getItem($key)->get();
6✔
208
        return $value;
6✔
209
    }
210

211
    /**
212
     * Sets the cached result to the cache by key.
213
     *
214
     * @param string $key
215
     * @param bool $value
216
     *
217
     * @return void
218
     */
219
    public function setCachedResult(string $key, bool $value): void
220
    {
221
        $item = $this->cache->getItem($key);
6✔
222
        $item->set($value);
6✔
223
        $item->expiresAfter($this->expireTime);
6✔
224
        $this->cache->save($item);
6✔
225
    }
226

227
    /**
228
     * Gets the cache key by combining the input parameters.
229
     * 
230
     * @param mixed ...$rvals
231
     *
232
     * @return string
233
     */
234
    public function getCacheKey(...$rvals): string
235
    {
236
        $key = '';
12✔
237
        foreach ($rvals as $rval) {
12✔
238
            if (is_string($rval)) {
12✔
239
                $key .= $rval;
12✔
240
            } elseif ($rval instanceof CacheableParam) {
6✔
241
                $key .= $rval->getCacheKey();
6✔
242
            } else {
243
                return '';
6✔
244
            }
245
            $key .= '$$';
12✔
246
        }
247

248
        return $key;
12✔
249
    }
250

251
    /**
252
     * Gets the cache key by combining the input parameters.
253
     *
254
     * @param mixed ...$rvals
255
     *
256
     * @return string
257
     */
258
    private function getKey(...$rvals): string
259
    {
260
        return $this->getCacheKey(...$rvals);
6✔
261
    }
262
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc