Completed
Push — master ( 3f24f8...42984c )
by Andrey
01:17
created

Rbac::findOne()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Itstructure\RbacModule\models;
4
5
use Yii;
6
use yii\base\{Model, InvalidConfigException};
7
use yii\rbac\{Item, ManagerInterface};
8
use Itstructure\RbacModule\Module;
9
10
/**
11
 * Class Rbac
12
 * Model Rbac to work with roles and permissions.
13
 *
14
 * @property string $name
15
 * @property string $description
16
 * @property ManagerInterface $authManager
17
 *
18
 * @package Itstructure\RbacModule\models
19
 */
20
abstract class Rbac extends Model
21
{
22
    /**
23
     * Role name.
24
     *
25
     * @var string
26
     */
27
    public $name;
28
29
    /**
30
     * Role description.
31
     *
32
     * @var string
33
     */
34
    public $description;
35
36
    /**
37
     * Auth manager.
38
     *
39
     * @var ManagerInterface
40
     */
41
    private $authManager;
42
43
    /**
44
     * Create new item (Role or permission).
45
     *
46
     * @param string $name
47
     *
48
     * @return Item
49
     */
50
    abstract protected function createItem(string $name): Item;
51
52
    /**
53
     * Create child item.
54
     * Example: parent - role, child - permission.
55
     *
56
     * @param string $name
57
     *
58
     * @return Item
59
     */
60
    abstract protected function createChild(string $name): Item;
61
62
    /**
63
     * Get current child items.
64
     *
65
     * @return array
66
     */
67
    abstract protected function getCurrentChildren(): array ;
68
69
    /**
70
     * Get new child items.
71
     *
72
     * @return array
73
     */
74
    abstract protected function getNewChildren(): array ;
75
76
    /**
77
     * Returns old name in current object, which is set before new value.
78
     *
79
     * @return mixed
80
     */
81
    abstract protected function getOldName();
82
83
    /**
84
     * Returns item object: Role or Permission.
85
     *
86
     * @param string $key
87
     *
88
     * @return Item|null
89
     */
90
    abstract protected function getItem(string $key);
91
92
    /**
93
     * Set item (role or permission) for instance of Rbac.
94
     *
95
     * @param Rbac $instance
96
     * @param Item      $item
97
     *
98
     * @return Rbac
99
     */
100
    abstract protected function setItemForInstance(Rbac $instance, Item $item): Rbac;
101
102
    /**
103
     * Set children for instance of Rbac (for Role or Permission).
104
     *
105
     * @param Rbac $instance
106
     *
107
     * @return Rbac
108
     */
109
    abstract protected function setChildrenForInstance(Rbac $instance): Rbac;
110
111
    /**
112
     * Initialize.
113
     */
114 View Code Duplication
    public function init()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
115
    {
116
        if (null === $this->authManager) {
117
            $this->setAuthManager(Yii::$app->authManager);
118
        }
119
120
        if (null === $this->authManager) {
121
            throw new InvalidConfigException('The authManager is not defined.');
122
        }
123
    }
124
125
    /**
126
     * @inheritdoc
127
     */
128
    public function rules()
129
    {
130
        return [
131
            [
132
                [
133
                    'name',
134
                    'description',
135
                ],
136
                'required',
137
            ],
138
            [
139
                [
140
                    'name',
141
                ],
142
                'string',
143
                'min' => 3,
144
                'max' => 64,
145
            ],
146
            [
147
                'name',
148
                'match',
149
                'pattern' => '/^[a-z]\w*$/i',
150
                'message' => Module::t('rbac', 'Name must contain latin symbols and numeric without spaces.')
151
            ],
152
            [
153
                [
154
                    'description',
155
                ],
156
                'string',
157
            ],
158
            [
159
                [
160
                    'name',
161
                ],
162
                'checkNameForUnique',
163
            ],
164
        ];
165
    }
166
167
    /**
168
     * Set auth manager.
169
     *
170
     * @param ManagerInterface $authManager
171
     *
172
     * @return $this
173
     */
174
    public function setAuthManager(ManagerInterface $authManager)
175
    {
176
        $this->authManager = $authManager;
0 ignored issues
show
Documentation Bug introduced by
It seems like $authManager of type object<yii\rbac\ManagerInterface> is incompatible with the declared type object<ManagerInterface> of property $authManager.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
177
        return $this;
178
    }
179
180
    /**
181
     * Get auth manager.
182
     *
183
     * @return ManagerInterface
184
     */
185
    public function getAuthManager(): ManagerInterface
186
    {
187
        return $this->authManager;
188
    }
189
190
    /**
191
     * @param string $key
192
     *
193
     * @return static
194
     */
195
    public function findOne(string $key)
196
    {
197
        $item = $this->getItem($key);
198
199
        $instance = new static();
200
        $instance->name = $item->name;
201
        $instance->description = $item->description;
202
203
        return $this->setChildrenForInstance($this->setItemForInstance($instance, $item));
204
    }
205
206
    /**
207
     * Save item data.
208
     *
209
     * @return bool
210
     */
211
    public function save(): bool
212
    {
213
        if (!$this->validate()) {
214
            return false;
215
        }
216
217
        $item = $this->createItem($this->name);
218
        $item->description = $this->description;
219
220
        if ($this->checkForNewRecord()) {
221
            return $this->createData($item);
222
        } else {
223
            return $this->updateData($item);
224
        }
225
    }
226
227
    /**
228
     * Returns current model id.
229
     *
230
     * @return string
231
     */
232
    public function getId(): string
233
    {
234
        return $this->name;
235
    }
236
237
    /**
238
     * Delete current role.
239
     *
240
     * @return bool
241
     */
242
    public function delete(): bool
243
    {
244
        return $this->authManager->remove($this->createItem($this->name));
245
    }
246
247
    /**
248
     * Delete from general list children items, which can't be assigned to parent.
249
     *
250
     * @param array $chlidren
251
     *
252
     * @return array
253
     */
254
    public function filterChlidrenBeforeAdd(array $chlidren): array
255
    {
256
        if (null === $this->getOldName()) {
257
            return $chlidren;
258
        }
259
260
        foreach ($chlidren as $key => $value) {
261
262
            $parent = $this->createItem($this->getOldName());
263
264
            $child = $this->createChild($key);
265
266
            if (!$this->authManager->canAddChild($parent, $child)) {
267
                unset($chlidren[$key]);
268
            }
269
        }
270
271
        return $chlidren;
272
    }
273
274
    /**
275
     * Check name for unique.
276
     *
277
     * @param $attribute
278
     *
279
     * @return bool
280
     */
281
    public function checkNameForUnique($attribute): bool
282
    {
283
        $item = $this->getItem($this->name);
284
285
        if (null !== $item && $this->getOldName() !== $item->name) {
286
            $this->addError($attribute, Module::t('rbac', 'This name already exists.'));
287
            return false;
288
        }
289
290
        return true;
291
    }
292
293
    /**
294
     * Check if current model is new record.
295
     * Return true if there is a new record.
296
     *
297
     * @return bool
298
     */
299
    private function checkForNewRecord(): bool
300
    {
301
        return null === $this->getOldName();
302
    }
303
304
    /**
305
     * Function for creating record.
306
     *
307
     * @param Item $item
308
     *
309
     * @return bool
310
     */
311
    private function createData(Item $item): bool
312
    {
313
        if (!$this->authManager->add($item)) {
314
            return false;
315
        }
316
317
        $newChildren = $this->getNewChildren();
318
319
        if (count($newChildren) > 0) {
320
            $this->addChildren($newChildren);
321
        }
322
323
        return true;
324
    }
325
326
    /**
327
     * Function for updating record.
328
     *
329
     * @param Item $item
330
     *
331
     * @return bool
332
     */
333
    private function updateData(Item $item): bool
334
    {
335
        if (!$this->authManager->update($this->getOldName(), $item)) {
336
            return false;
337
        }
338
339
        $this->authManager->removeChildren($item);
340
341
        $newChildren = $this->getNewChildren();
342
343
        if (count($newChildren) > 0) {
344
            $this->addChildren($newChildren);
345
        }
346
347
        return true;
348
    }
349
350
    /**
351
     * Add childs items for parent item.
352
     *
353
     * @param array $childs
354
     */
355
    private function addChildren(array $childs): void
356
    {
357
        foreach ($childs as $child) {
358
359
            $this->authManager->addChild(
360
                $this->createItem($this->name),
361
                $this->createChild($child)
362
            );
363
        }
364
    }
365
}
366