Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

php-casbin / yii-permission / 1264202595

23 Sep 2021 - 2:11 coverage: 92.903% (-1.3%) from 94.215%
1264202595

Pull #15

github

GitHub
Merge 73570c299 into 6d4976bc7
Pull Request #15: feat: Support Casbin UpdatableAdapter interface

30 of 34 new or added lines in 1 file covered. (88.24%)

144 of 155 relevant lines covered (92.9%)

31.96 hits per line

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

94.92
/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;
88×
34
    }
88×
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
    }
24×
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;
88×
55
        $rows = $ar->find()->all();
88×
56

57
        foreach ($rows as $row) {
88×
58
            $line = implode(', ', array_filter(array_slice($row->toArray(), 1), function ($val) {
59
                return '' != $val && !is_null($val);
88×
60
            }));
88×
61
            $this->loadPolicyLine(trim($line), $model);
88×
62
        }
63
    }
88×
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×
80
                $this->savePolicyLine($ptype, $rule);
2×
81
            }
82
        }
83
    }
8×
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
    }
16×
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) {
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
    }
16×
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
    }
16×
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
        }
167
    }
8×
168

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

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

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

193
        array_walk($removedRules, function (&$removedRule) {
194
            unset($removedRule->id);
16×
195
            $removedRule = $removedRule->toArray();
16×
196
            $removedRule = array_filter($removedRule, function ($value) {
197
                return !is_null($value) && $value !== '';
16×
198
            });
16×
199
            unset($removedRule['ptype']);
16×
200
        });
16×
201

202
        return $removedRules;
16×
203
    }
204

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

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

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

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

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

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

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

324
        return $oldRules;
8×
325
    }
326

327
    /**
328
     * Returns true if the loaded policy has been filtered.
329
     *
330
     * @return bool
331
     */
332
    public function isFiltered(): bool
333
    {
334
        return $this->filtered;
88×
335
    }
336

337
    /**
338
     * Sets filtered parameter.
339
     *
340
     * @param bool $filtered
341
     */
342
    public function setFiltered(bool $filtered): void
343
    {
344
        $this->filtered = $filtered;
8×
345
    }
8×
346
}
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2023 Coveralls, Inc