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

php-casbin / yii-permission / 11556580650

28 Oct 2024 02:52PM UTC coverage: 91.045% (-1.9%) from 92.925%
11556580650

push

github

web-flow
BREAKING CHANGE: upgrade to PHP 8.0 and PHP-Casbin 4.0 (#20)

5 of 6 new or added lines in 1 file covered. (83.33%)

2 existing lines in 2 files now uncovered.

183 of 201 relevant lines covered (91.04%)

48.72 hits per line

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

91.45
/src/Adapter.php
1
<?php
2

3
namespace yii\permission;
4

5
use yii\permission\models\CasbinRule;
6
use Casbin\Model\Model;
7
use Casbin\Persist\Adapter as AdapterContract;
8
use Casbin\Persist\BatchAdapter as BatchAdapterContract;
9
use Casbin\Persist\FilteredAdapter as FilteredAdapterContract;
10
use Casbin\Persist\UpdatableAdapter as UpdatableAdapterContract;
11
use Casbin\Persist\AdapterHelper;
12
use Casbin\Persist\Adapters\Filter;
13
use Casbin\Exceptions\InvalidFilterTypeException;
14

15
/**
16
 * DatabaseAdapter.
17
 *
18
 * @author techlee@qq.com
19
 */
20
class Adapter implements AdapterContract, BatchAdapterContract, FilteredAdapterContract, UpdatableAdapterContract
21
{
22
    use AdapterHelper;
23

24
    protected $casbinRule;
25

26
    /**
27
     * @var bool
28
     */
29
    private $filtered = false;
30

31
    public function __construct(CasbinRule $casbinRule)
32
    {
33
        $this->casbinRule = $casbinRule;
152✔
34
    }
35

36
    public function savePolicyLine($ptype, array $rule)
37
    {
38
        $col['ptype'] = $ptype;
24✔
39
        foreach ($rule as $key => $value) {
24✔
40
            $col['v' . strval($key) . ''] = $value;
24✔
41
        }
42
        $ar = clone $this->casbinRule;
24✔
43
        $ar->setAttributes($col);
24✔
44
        $ar->save();
24✔
45
    }
46

47
    /**
48
     * loads all policy rules from the storage.
49
     *
50
     * @param Model $model
51
     */
52
    public function loadPolicy(Model $model): void
53
    {
54
        $ar = clone $this->casbinRule;
152✔
55
        $rows = $ar->find()->all();
152✔
56

57
        foreach ($rows as $row) {
152✔
58
            $line = implode(', ', array_filter(array_slice($row->toArray(), 1), function ($val) {
152✔
59
                return '' != $val && !is_null($val);
152✔
60
            }));
152✔
61
            $this->loadPolicyLine(trim($line), $model);
152✔
62
        }
63
    }
64

65
    /**
66
     * saves all policy rules to the storage.
67
     *
68
     * @param Model $model
69
     */
70
    public function savePolicy(Model $model): void
71
    {
72
        foreach ($model['p'] as $ptype => $ast) {
8✔
73
            foreach ($ast->policy as $rule) {
8✔
74
                $this->savePolicyLine($ptype, $rule);
8✔
75
            }
76
        }
77

78
        foreach ($model['g'] as $ptype => $ast) {
8✔
79
            foreach ($ast->policy as $rule) {
8✔
UNCOV
80
                $this->savePolicyLine($ptype, $rule);
×
81
            }
82
        }
83
    }
84

85
    /**
86
     * adds a policy rule to the storage.
87
     * This is part of the Auto-Save feature.
88
     *
89
     * @param string $sec
90
     * @param string $ptype
91
     * @param array  $rule
92
     */
93
    public function addPolicy(string $sec, string $ptype, array $rule): void
94
    {
95
        $this->savePolicyLine($ptype, $rule);
16✔
96
    }
97

98
    /**
99
     * Adds a policy rules to the storage.
100
     * This is part of the Auto-Save feature.
101
     *
102
     * @param string $sec
103
     * @param string $ptype
104
     * @param string[][] $rules
105
     */
106
    public function addPolicies(string $sec, string $ptype, array $rules): void
107
    {
108
        $rows = [];
16✔
109
        $columns = array_keys($rules[0]);
16✔
110
        array_walk($columns, function (&$item) {
16✔
111
            $item = 'v' . strval($item);
16✔
112
        });
16✔
113
        array_unshift($columns, 'ptype');
16✔
114

115
        foreach ($rules as $rule) {
16✔
116
            $temp['`ptype`'] = $ptype;
16✔
117
            foreach ($rule as $key => $value) {
16✔
118
                $temp['`v'. strval($key) . '`'] = $value;
16✔
119
            }
120
            $rows[] = $temp;
16✔
121
            $temp = [];
16✔
122
        }
123

124
        $command = $this->casbinRule->getDb()->createCommand();
16✔
125
        $tableName = $this->casbinRule->tableName();
16✔
126
        $command->batchInsert($tableName, $columns, $rows)->execute();
16✔
127
    }
128

129
    /**
130
     * This is part of the Auto-Save feature.
131
     *
132
     * @param string $sec
133
     * @param string $ptype
134
     * @param array  $rule
135
     */
136
    public function removePolicy(string $sec, string $ptype, array $rule): void
137
    {
138
        $where = [];
16✔
139
        $where['ptype'] = $ptype;
16✔
140

141
        foreach ($rule as $key => $value) {
16✔
142
            $where['v' . strval($key)] = $value;
16✔
143
        }
144

145
        $this->casbinRule->deleteAll($where);
16✔
146
    }
147

148
    /**
149
     * Removes policy rules from the storage.
150
     * This is part of the Auto-Save feature.
151
     *
152
     * @param string $sec
153
     * @param string $ptype
154
     * @param string[][] $rules
155
     */
156
    public function removePolicies(string $sec, string $ptype, array $rules): void
157
    {
158
        $transaction = $this->casbinRule->getDb()->beginTransaction();
8✔
159
        try {
160
            foreach ($rules as $rule) {
8✔
161
                $this->removePolicy($sec, $ptype, $rule);
8✔
162
            }
163
            $transaction->commit();
8✔
164
        } catch (\Exception $e) {
×
165
            $transaction->rollBack();
×
166
            throw $e;
×
167
        }
168
    }
169

170
    /**
171
     * @param string $sec
172
     * @param string $ptype
173
     * @param int $fieldIndex
174
     * @param string|null ...$fieldValues
175
     * @return array
176
     * @throws Throwable
177
     */
178
    public function _removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, ?string ...$fieldValues): array
179
    {
180
        $where = [];
16✔
181
        $where['ptype'] = $ptype;
16✔
182

183
        foreach (range(0, 5) as $value) {
16✔
184
            if ($fieldIndex <= $value && $value < $fieldIndex + count($fieldValues)) {
16✔
185
                if ('' != $fieldValues[$value - $fieldIndex]) {
16✔
186
                    $where['v' . strval($value)] = $fieldValues[$value - $fieldIndex];
16✔
187
                }
188
            }
189
        }
190

191
        $removedRules = $this->casbinRule->find()->where($where)->all();
16✔
192
        $this->casbinRule->deleteAll($where);
16✔
193

194
        array_walk($removedRules, function (&$removedRule) {
16✔
195
            unset($removedRule->id);
16✔
196
            unset($removedRule->ptype);
16✔
197
            $removedRule = $removedRule->toArray();
16✔
198
            $removedRule = $this->filterRule($removedRule);
16✔
199
        });
16✔
200

201
        return $removedRules;
16✔
202
    }
203

204
    /**
205
     * RemoveFilteredPolicy removes policy rules that match the filter from the storage.
206
     * This is part of the Auto-Save feature.
207
     *
208
     * @param string $sec
209
     * @param string $ptype
210
     * @param int    $fieldIndex
211
     * @param string ...$fieldValues
212
     */
213
    public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, string ...$fieldValues): void
214
    {
215
        $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
8✔
216
    }
217

218
    /**
219
     * Loads only policy rules that match the filter.
220
     *
221
     * @param Model $model
222
     * @param mixed $filter
223
     */
224
    public function loadFilteredPolicy(Model $model, $filter): void
225
    {
226
        $entity = clone $this->casbinRule;
8✔
227
        $entity = $entity->find();
8✔
228

229
        if (is_string($filter)) {
8✔
230
            $entity->where($filter);
8✔
231
        } elseif ($filter instanceof Filter) {
8✔
232
            foreach ($filter->p as $k => $v) {
8✔
233
                $where[$v] = $filter->g[$k];
8✔
234
                $entity->where([$v => $filter->g[$k]]);
8✔
235
            }
236
        } elseif ($filter instanceof \Closure) {
8✔
237
            $filter($entity);
8✔
238
        } else {
239
            throw new InvalidFilterTypeException('invalid filter type');
8✔
240
        }
241

242
        $rows = $entity->all();
8✔
243
        foreach ($rows as $row) {
8✔
244
            unset($row->id);
8✔
245
            $row = $row->toArray();
8✔
246
            $line = implode(', ', array_filter($row, function ($val) {
8✔
247
                return '' != $val && !is_null($val);
8✔
248
            }));
8✔
249
            $this->loadPolicyLine(trim($line), $model);
8✔
250
        }
251
        $this->setFiltered(true);
8✔
252
    }
253

254
    /**
255
     * Updates a policy rule from storage.
256
     * This is part of the Auto-Save feature.
257
     *
258
     * @param string $sec
259
     * @param string $ptype
260
     * @param string[] $oldRule
261
     * @param string[] $newPolicy
262
     */
263
    public function updatePolicy(string $sec, string $ptype, array $oldRule, array $newPolicy): void
264
    {
265
        $entity = clone $this->casbinRule;
16✔
266

267
        $condition['ptype'] = $ptype;
16✔
268
        foreach ($oldRule as $k => $v) {
16✔
269
            $condition['v' . $k] = $v;
16✔
270
        }
271
        $item = $entity->findOne($condition);
16✔
272
        foreach ($newPolicy as $k => $v) {
16✔
273
            $key = 'v' . $k;
16✔
274
            $item->$key = $v;
16✔
275
        }
276
        $item->update();
16✔
277
    }
278

279
    /**
280
     * UpdatePolicies updates some policy rules to storage, like db, redis.
281
     *
282
     * @param string $sec
283
     * @param string $ptype
284
     * @param string[][] $oldRules
285
     * @param string[][] $newRules
286
     * @return void
287
     */
288
    public function updatePolicies(string $sec, string $ptype, array $oldRules, array $newRules): void
289
    {
290
        $transaction = $this->casbinRule->getDb()->beginTransaction();
8✔
291
        try {
292
            foreach ($oldRules as $i => $oldRule) {
8✔
293
                $this->updatePolicy($sec, $ptype, $oldRule, $newRules[$i]);
8✔
294
            }
295
            $transaction->commit();
8✔
296
        } catch (\Exception $e) {
×
297
            $transaction->rollBack();
×
298
            throw $e;
×
299
        }
300
    }
301

302
    /**
303
     * UpdateFilteredPolicies deletes old rules and adds new rules.
304
     *
305
     * @param string $sec
306
     * @param string $ptype
307
     * @param array $newPolicies
308
     * @param integer $fieldIndex
309
     * @param string ...$fieldValues
310
     * @return array
311
     */
312
    public function updateFilteredPolicies(string $sec, string $ptype, array $newRules, int $fieldIndex, ?string ...$fieldValues): array
313
    {
314
        $oldRules = [];
8✔
315
        $transaction = $this->casbinRule->getDb()->beginTransaction();
8✔
316
        try {
317
            $oldRules = $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
8✔
318
            $this->addPolicies($sec, $ptype, $newRules);
8✔
319
            $transaction->commit();
8✔
320
        } catch (\Exception $e) {
×
321
            $transaction->rollBack();
×
322
            throw $e;
×
323
        }
324

325
        return $oldRules;
8✔
326
    }
327

328
    /**
329
     * Filter the rule.
330
     *
331
     * @param array $rule
332
     * @return array
333
     */
334
    public function filterRule(array $rule): array
335
    {
336
        $rule = array_values($rule);
16✔
337

338
        $i = count($rule) - 1;
16✔
339
        for (; $i >= 0; $i--) {
16✔
340
            if ($rule[$i] != "" && !is_null($rule[$i])) {
16✔
341
                break;
16✔
342
            }
343
        }
344

345
        return array_slice($rule, 0, $i + 1);
16✔
346
    }
347

348
    /**
349
     * Returns true if the loaded policy has been filtered.
350
     *
351
     * @return bool
352
     */
353
    public function isFiltered(): bool
354
    {
355
        return $this->filtered;
152✔
356
    }
357

358
    /**
359
     * Sets filtered parameter.
360
     *
361
     * @param bool $filtered
362
     */
363
    public function setFiltered(bool $filtered): void
364
    {
365
        $this->filtered = $filtered;
8✔
366
    }
367
}
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