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

php-casbin / php-casbin / 15422853167

03 Jun 2025 04:34PM UTC coverage: 94.307% (-0.2%) from 94.485%
15422853167

push

github

leeqvip
refactor: Upgrade phpstan to level 8

52 of 63 new or added lines in 8 files covered. (82.54%)

2 existing lines in 1 file now uncovered.

1938 of 2055 relevant lines covered (94.31%)

231.19 hits per line

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

82.07
/src/InternalEnforcer.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Casbin;
6

7
use Casbin\Exceptions\NotImplementedException;
8
use Casbin\Model\Policy;
9
use Casbin\Persist\BatchAdapter;
10
use Casbin\Persist\UpdatableAdapter;
11
use Casbin\Persist\WatcherEx;
12
use Casbin\Persist\WatcherUpdatable;
13

14
/**
15
 * InternalEnforcer = CoreEnforcer + Internal API.
16
 *
17
 * @author techlee@qq.com
18
 */
19
class InternalEnforcer extends CoreEnforcer
20
{
21
    /**
22
     * @return bool
23
     */
24
    protected function shouldPersist(): bool
25
    {
26
        return !is_null($this->adapter) && $this->autoSave;
330✔
27
    }
28

29
    /**
30
     * @return bool
31
     */
32
    protected function shouldNotify(): bool
33
    {
34
        return !is_null($this->watcher) && $this->autoNotifyWatcher;
320✔
35
    }
36

37
    /**
38
     * Adds a rule to the current policy without notify.
39
     * 
40
     * @param string $sec
41
     * @param string $ptype
42
     * @param array $rule
43
     * 
44
     * @return bool
45
     */
46
    protected function addPolicyWithoutNotifyInternal(string $sec, string $ptype, array $rule): bool
47
    {
48
        if ($this->model->hasPolicy($sec, $ptype, $rule)) {
160✔
49
            return false;
10✔
50
        }
51

52
        if ($this->shouldPersist()) {
160✔
53
            try {
54
                $this->adapter?->addPolicy($sec, $ptype, $rule);
150✔
55
            } catch (NotImplementedException $e) {
150✔
56
            }
57
        }
58

59
        $this->model->addPolicy($sec, $ptype, $rule);
160✔
60

61
        if ($sec == "g") {
160✔
62
            $this->buildIncrementalRoleLinks(Policy::POLICY_ADD, $ptype, [$rule]);
70✔
63
        }
64

65
        return true;
160✔
66
    }
67

68
    /**
69
     * Adds rules to the current policy without notify.
70
     * If autoRemoveRepeat == true, existing rules are automatically filtered
71
     * Otherwise, false is returned directly.
72
     * 
73
     * @param string $sec
74
     * @param string $ptype
75
     * @param array $rules
76
     * @param bool $autoRemoveRepeat
77
     * 
78
     * @return bool
79
     */
80
    protected function addPoliciesWithoutNotifyInternal(string $sec, string $ptype, array $rules, bool $autoRemoveRepeat): bool
81
    {
82
        if (!$autoRemoveRepeat) {
100✔
83
            if ($this->model->hasPolicies($sec, $ptype, $rules)) {
100✔
84
                return false;
30✔
85
            }
86
        }
87

88
        if ($this->shouldPersist() && $this->adapter instanceof BatchAdapter) {
100✔
89
            try {
90
                $this->adapter->addPolicies($sec, $ptype, $rules);
100✔
91
            } catch (NotImplementedException $e) {
80✔
92
            }
93
        }
94

95
        $this->model->addPolicies($sec, $ptype, $rules);
100✔
96

97
        if ($sec == "g") {
100✔
98
            $this->buildIncrementalRoleLinks(Policy::POLICY_ADD, $ptype, $rules);
30✔
99
            $this->buildIncrementalConditionalRoleLinks(Policy::POLICY_ADD, $ptype, $rules);
30✔
100
        }
101

102
        return true;
100✔
103
    }
104

105
    /**
106
     * Updates a rule from the current policy without notify.
107
     * 
108
     * @param string $sec
109
     * @param string $ptype
110
     * @param array $oldRule
111
     * @param array $newRule
112
     * 
113
     * @return bool
114
     */
115
    protected function updatePolicyWithoutNotifyInternal(string $sec, string $ptype, array $oldRule, array $newRule): bool
116
    {
117
        if ($this->shouldPersist() && $this->adapter instanceof UpdatableAdapter) {
10✔
118
            try {
119
                $this->adapter->updatePolicy($sec, $ptype, $oldRule, $newRule);
10✔
120
            } catch (NotImplementedException $e) {
10✔
121
            }
122
        }
123

124
        $ruleUpdated = $this->model->updatePolicy($sec, $ptype, $oldRule, $newRule);
10✔
125
        if (!$ruleUpdated) {
10✔
126
            return false;
×
127
        }
128

129
        if ($sec == "g") {
10✔
130
            // remove the old rule
131
            $this->buildIncrementalRoleLinks(Policy::POLICY_REMOVE, $ptype, [$oldRule]);
×
132

133
            // add the new rule
134
            $this->buildIncrementalRoleLinks(Policy::POLICY_ADD, $ptype, [$newRule]);
×
135
        }
136

137
        return true;
10✔
138
    }
139

140
    /**
141
     * Updates rules from the current policy without notify.
142
     * 
143
     * @param string $sec
144
     * @param string $ptype
145
     * @param array $oldRules
146
     * @param array $newRules
147
     * 
148
     * @return bool
149
     */
150
    protected function updatePoliciesWithoutNotifyInternal(string $sec, string $ptype, array $oldRules, array $newRules): bool
151
    {
152
        if ($this->shouldPersist() && $this->adapter instanceof UpdatableAdapter) {
10✔
153
            try {
154
                $this->adapter->updatePolicies($sec, $ptype, $oldRules, $newRules);
10✔
155
            } catch (NotImplementedException $e) {
10✔
156
            }
157
        }
158

159
        $ruleUpdated = $this->model->updatePolicies($sec, $ptype, $oldRules, $newRules);
10✔
160
        if (!$ruleUpdated) {
10✔
161
            return false;
10✔
162
        }
163

164
        if ($sec == "g") {
10✔
165
            // remove the old rule
166
            $this->buildIncrementalRoleLinks(Policy::POLICY_REMOVE, $ptype, $oldRules);
×
167

168
            // add the new rule
169
            $this->buildIncrementalRoleLinks(Policy::POLICY_ADD, $ptype, $newRules);
×
170
        }
171

172
        return true;
10✔
173
    }
174

175
    /**
176
     * Removes a rule from the current policy without notify.
177
     * 
178
     * @param string $sec
179
     * @param string $ptype
180
     * @param array $rule
181
     * 
182
     * @return bool
183
     */
184
    protected function removePolicyWithoutNotifyInternal(string $sec, string $ptype, array $rule): bool
185
    {
186
        if ($this->shouldPersist()) {
100✔
187
            try {
188
                $this->adapter?->removePolicy($sec, $ptype, $rule);
100✔
189
            } catch (NotImplementedException $e) {
100✔
190
            }
191
        }
192

193
        $ruleRemoved = $this->model->removePolicy($sec, $ptype, $rule);
100✔
194
        if (!$ruleRemoved) {
100✔
195
            return false;
20✔
196
        }
197

198
        if ($sec == "g") {
100✔
199
            $this->buildIncrementalRoleLinks(Policy::POLICY_REMOVE, $ptype, [$rule]);
60✔
200
        }
201

202
        return true;
100✔
203
    }
204

205
    /**
206
     * Removes rules from the current policy without notify.
207
     * 
208
     * @param string $sec
209
     * @param string $ptype
210
     * @param array $rules
211
     * 
212
     * @return bool
213
     */
214
    protected function removePoliciesWithoutNotifyInternal(string $sec, string $ptype, array $rules): bool
215
    {
216
        if (!$this->model->hasPolicies($sec, $ptype, $rules)) {
60✔
217
            return false;
30✔
218
        }
219

220
        if ($this->shouldPersist() && $this->adapter instanceof BatchAdapter) {
60✔
221
            try {
222
                $this->adapter->removePolicies($sec, $ptype, $rules);
60✔
223
            } catch (NotImplementedException $e) {
60✔
224
            }
225
        }
226

227
        $ruleRemoved = $this->model->removePolicies($sec, $ptype, $rules);
60✔
228
        if (!$ruleRemoved) {
60✔
229
            return false;
×
230
        }
231

232
        if ($sec == "g") {
60✔
233
            $this->buildIncrementalRoleLinks(Policy::POLICY_REMOVE, $ptype, $rules);
40✔
234
        }
235

236
        return true;
60✔
237
    }
238

239
    /**
240
     * Removes rules based on field filters from the current policy without notify.
241
     * 
242
     * @param string $sec
243
     * @param string $ptype
244
     * @param int $fieldIndex
245
     * @param string ...$fieldValues
246
     * 
247
     * @return bool
248
     */
249
    protected function removeFilteredPolicyWithoutNotifyInternal(string $sec, string $ptype, int $fieldIndex, string ...$fieldValues): bool
250
    {
251
        if ($this->shouldPersist()) {
80✔
252
            try {
253
                $this->adapter?->removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
80✔
254
            } catch (NotImplementedException $e) {
80✔
255
            }
256
        }
257

258
        $ruleRemoved = $this->model->removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
80✔
259
        if (!$ruleRemoved) {
80✔
260
            return false;
×
261
        }
262

263
        if ($sec == "g") {
80✔
264
            $this->buildIncrementalRoleLinks(Policy::POLICY_REMOVE, $ptype, $ruleRemoved);
40✔
265
        }
266

267
        return true;
80✔
268
    }
269

270
    /**
271
     * Updates rules based on field filters from the current policy without notify.
272
     * 
273
     * @param string $sec
274
     * @param string $ptype
275
     * @param array $newRules
276
     * @param int $fieldIndex
277
     * @param string ...$fieldValues
278
     * 
279
     * @return array
280
     */
281
    protected function updateFilteredPoliciesWithoutNotifyInternal(string $sec, string $ptype, array $newRules, int $fieldIndex, string ...$fieldValues): array
282
    {
283
        $oldRules = [];
20✔
284
        if ($this->shouldPersist()) {
20✔
285
            try {
286
                if ($this->adapter instanceof UpdatableAdapter) {
20✔
287
                    $oldRules = $this->adapter->updateFilteredPolicies($sec, $ptype, $newRules, $fieldIndex, ...$fieldValues);
20✔
288
                }
289
            } catch (NotImplementedException $e) {
10✔
290
            }
291
        }
292

293
        $ruleChanged = $this->model->removePolicies($sec, $ptype, $oldRules);
20✔
294
        $this->model->addPolicies($sec, $ptype, $newRules);
20✔
295

296
        $ruleChanged = $ruleChanged && count($newRules) !== 0;
20✔
297
        if (!$ruleChanged) {
20✔
298
            return [];
10✔
299
        }
300

301
        if ($sec == "g") {
20✔
302
            // remove the old rules
303
            $this->buildIncrementalRoleLinks(Policy::POLICY_REMOVE, $ptype, $oldRules);
×
304
            // add the new rules
305
            $this->buildIncrementalRoleLinks(Policy::POLICY_ADD, $ptype, $newRules);
×
306
        }
307

308
        return $oldRules;
20✔
309
    }
310

311
    /**
312
     * Adds a rule to the current policy.
313
     *
314
     * @param string $sec
315
     * @param string $ptype
316
     * @param array $rule
317
     *
318
     * @return bool
319
     */
320
    protected function addPolicyInternal(string $sec, string $ptype, array $rule): bool
321
    {
322
        if (!$this->addPolicyWithoutNotifyInternal($sec, $ptype, $rule)) {
160✔
323
            return false;
10✔
324
        }
325

326
        if ($this->shouldNotify()) {
160✔
327
            if ($this->watcher instanceof WatcherEx) {
10✔
328
                $this->watcher->updateForAddPolicy($sec, $ptype, ...$rule);
×
329
            } else {
330
                $this->watcher?->update();
10✔
331
            }
332
        }
333

334
        return true;
160✔
335
    }
336

337
    /**
338
     * Adds rules to the current policy.
339
     *
340
     * @param string $sec
341
     * @param string $ptype
342
     * @param array $rules
343
     *
344
     * @return bool
345
     * @throws Exceptions\CasbinException
346
     */
347
    protected function addPoliciesInternal(string $sec, string $ptype, array $rules, bool $autoRemoveRepeat): bool
348
    {
349
        if (!$this->addPoliciesWithoutNotifyInternal($sec, $ptype, $rules, $autoRemoveRepeat)) {
90✔
350
            return false;
30✔
351
        }
352

353
        if ($this->shouldNotify()) {
90✔
NEW
354
            $this->watcher?->update();
×
355
        }
356

357
        return true;
90✔
358
    }
359

360
    /**
361
     * Updates a rule from the current policy.
362
     * 
363
     * @param string $sec
364
     * @param string $ptype
365
     * @param string[] $oldRule
366
     * @param string[] $newRule
367
     *
368
     * @return bool
369
     */
370
    protected function updatePolicyInternal(string $sec, string $ptype, array $oldRule, array $newRule): bool
371
    {
372
        if (!$this->updatePolicyWithoutNotifyInternal($sec, $ptype, $oldRule, $newRule)) {
10✔
373
            return false;
×
374
        }
375

376
        if ($this->shouldNotify()) {
10✔
377
            try {
378
                if ($this->watcher instanceof WatcherUpdatable) {
×
379
                    $this->watcher->updateForUpdatePolicy($oldRule, $newRule);
×
380
                } else {
NEW
381
                    $this->watcher?->update();
×
382
                }
383
            } catch (\Exception $e) {
×
384
                $this->logger->logError($e);
×
385

386
                return false;
×
387
            }
388
        }
389

390
        return true;
10✔
391
    }
392

393
    /**
394
     * Updates rules from the current policy.
395
     * 
396
     * @param string $sec
397
     * @param string $ptype
398
     * @param string[][] $oldRules
399
     * @param string[][] $newRules
400
     * 
401
     * @return bool
402
     */
403
    protected function updatePoliciesInternal(string $sec, string $ptype, array $oldRules, array $newRules): bool
404
    {
405
        if (!$this->updatePoliciesWithoutNotifyInternal($sec, $ptype, $oldRules, $newRules)) {
10✔
406
            return false;
10✔
407
        }
408

409
        if ($this->shouldNotify()) {
10✔
410
            try {
411
                if ($this->watcher instanceof WatcherUpdatable) {
10✔
412
                    $this->watcher->updateForUpdatePolicies($oldRules, $newRules);
10✔
413
                } else {
414
                    $this->watcher?->update();
10✔
415
                }
416
            } catch (\Exception $e) {
10✔
417
                $this->logger->logError($e);
10✔
418
                return false;
10✔
419
            }
420
        }
421

422
        return true;
10✔
423
    }
424

425
    /**
426
     * Removes a rule from the current policy.
427
     *
428
     * @param string $sec
429
     * @param string $ptype
430
     * @param array $rule
431
     *
432
     * @return bool
433
     */
434
    protected function removePolicyInternal(string $sec, string $ptype, array $rule): bool
435
    {
436
        if (!$this->removePolicyWithoutNotifyInternal($sec, $ptype, $rule)) {
100✔
437
            return false;
20✔
438
        }
439

440
        if ($this->shouldNotify()) {
100✔
441
            if ($this->watcher instanceof WatcherEx) {
×
442
                $this->watcher->updateForRemovePolicy($sec, $ptype, ...$rule);
×
443
            } else {
NEW
444
                $this->watcher?->update();
×
445
            }
446
        }
447

448
        return true;
100✔
449
    }
450

451
    /**
452
     * Removes a rules from the current policy.
453
     *
454
     * @param string $sec
455
     * @param string $ptype
456
     * @param array $rules
457
     *
458
     * @return bool
459
     */
460
    protected function removePoliciesInternal(string $sec, string $ptype, array $rules): bool
461
    {
462
        if (!$this->removePoliciesWithoutNotifyInternal($sec, $ptype, $rules)) {
60✔
463
            return false;
30✔
464
        }
465

466
        if ($this->shouldNotify()) {
60✔
467
            // error intentionally ignored
NEW
468
            $this->watcher?->update();
×
469
        }
470

471
        return true;
60✔
472
    }
473

474
    /**
475
     * Removes rules based on field filters from the current policy.
476
     *
477
     * @param string $sec
478
     * @param string $ptype
479
     * @param int $fieldIndex
480
     * @param string ...$fieldValues
481
     *
482
     * @return bool
483
     */
484
    protected function removeFilteredPolicyInternal(string $sec, string $ptype, int $fieldIndex, string ...$fieldValues): bool
485
    {
486
        if (!$this->removeFilteredPolicyWithoutNotifyInternal($sec, $ptype, $fieldIndex, ...$fieldValues)) {
80✔
487
            return false;
×
488
        }
489

490
        if ($this->shouldNotify()) {
80✔
491
            // error intentionally ignored
492
            if ($this->watcher instanceof WatcherEx) {
×
493
                $this->watcher->updateForRemoveFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
×
494
            } else {
NEW
495
                $this->watcher?->update();
×
496
            }
497
        }
498

499
        return true;
80✔
500
    }
501

502
    /**
503
     * Removes rules based on field filters from the current policy.
504
     * 
505
     * @param string $sec
506
     * @param string $ptype
507
     * @param array $newRules
508
     * @param int $fieldIndex
509
     * @param string ...$fieldValues
510
     * 
511
     * @return bool
512
     */
513
    protected function updateFilteredPoliciesInternal(string $sec, string $ptype, array $newRules, int $fieldIndex, string ...$fieldValues): bool
514
    {
515
        $oldRules = $this->updateFilteredPoliciesWithoutNotifyInternal($sec, $ptype, $newRules, $fieldIndex, ...$fieldValues);
20✔
516
        if (count($oldRules) === 0) {
20✔
517
            return false;
10✔
518
        }
519

520
        if ($this->shouldNotify()) {
20✔
521
            // error intentionally ignored
522
            if ($this->watcher instanceof WatcherUpdatable) {
10✔
523
                $this->watcher->updateForUpdatePolicies($oldRules, $newRules);
10✔
524
            } else {
525
                $this->watcher?->update();
10✔
526
            }
527
            return true;
10✔
528
        }
529

530
        return true;
10✔
531
    }
532
}
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