Passed
Push — master ( 947fd1...b2167b )
by Misbahul D
03:16
created

AuthItem::checkRule()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 17
rs 9.2
cc 4
eloc 12
nc 6
nop 0
1
<?php
2
3
namespace mdm\admin\models;
4
5
use Yii;
6
use yii\rbac\Item;
7
use yii\helpers\Json;
8
use yii\base\Model;
9
use mdm\admin\components\Helper;
10
11
/**
12
 * This is the model class for table "tbl_auth_item".
13
 *
14
 * @property string $name
15
 * @property integer $type
16
 * @property string $description
17
 * @property string $ruleName
18
 * @property string $data
19
 *
20
 * @property Item $item
21
 *
22
 * @author Misbahul D Munir <[email protected]>
23
 * @since 1.0
24
 */
25
class AuthItem extends Model
26
{
27
    public $name;
28
    public $type;
29
    public $description;
30
    public $ruleName;
31
    public $data;
32
    /**
33
     * @var Item
34
     */
35
    private $_item;
36
37
    /**
38
     * Initialize object
39
     * @param Item  $item
40
     * @param array $config
41
     */
42
    public function __construct($item = null, $config = [])
43
    {
44
        $this->_item = $item;
45
        if ($item !== null) {
46
            $this->name = $item->name;
47
            $this->type = $item->type;
48
            $this->description = $item->description;
49
            $this->ruleName = $item->ruleName;
50
            $this->data = $item->data === null ? null : Json::encode($item->data);
51
        }
52
        parent::__construct($config);
53
    }
54
55
    /**
56
     * @inheritdoc
57
     */
58
    public function rules()
59
    {
60
        return [
61
            [['ruleName'], 'checkRule'],
62
            [['name', 'type'], 'required'],
63
            [['name'], 'unique', 'when' => function() {
64
                return $this->isNewRecord || ($this->_item->name != $this->name);
0 ignored issues
show
Documentation introduced by
The property isNewRecord does not exist on object<mdm\admin\models\AuthItem>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
65
            }],
66
            [['type'], 'integer'],
67
            [['description', 'data', 'ruleName'], 'default'],
68
            [['name'], 'string', 'max' => 64]
69
        ];
70
    }
71
72
    /**
73
     * Check role is unique
74
     */
75
    public function unique()
76
    {
77
        $authManager = Yii::$app->authManager;
78
        $value = $this->name;
79
        if ($authManager->getRole($value) !== null || $authManager->getPermission($value) !== null) {
80
            $message = Yii::t('yii', '{attribute} "{value}" has already been taken.');
81
            $params = [
82
                'attribute' => $this->getAttributeLabel('name'),
83
                'value' => $value,
84
            ];
85
            $this->addError('name', Yii::$app->getI18n()->format($message, $params, Yii::$app->language));
86
        }
87
    }
88
89
    /**
90
     * Check for rule
91
     */
92
    public function checkRule()
93
    {
94
        $name = $this->ruleName;
95
        if (!Yii::$app->getAuthManager()->getRule($name)) {
96
            try {
97
                $rule = Yii::createObject($name);
98
                if ($rule instanceof \yii\rbac\Rule) {
99
                    $rule->name = $name;
100
                    Yii::$app->getAuthManager()->add($rule);
101
                } else {
102
                    $this->addError('ruleName', Yii::t('rbac-admin', 'Invalid rule {value}', ['value' => $name]));
103
                }
104
            } catch (\Exception $exc) {
105
                $this->addError('ruleName', Yii::t('rbac-admin', 'Rule {value} does not exists', ['value' => $name]));
106
            }
107
        }
108
    }
109
110
    /**
111
     * @inheritdoc
112
     */
113
    public function attributeLabels()
114
    {
115
        return [
116
            'name' => Yii::t('rbac-admin', 'Name'),
117
            'type' => Yii::t('rbac-admin', 'Type'),
118
            'description' => Yii::t('rbac-admin', 'Description'),
119
            'ruleName' => Yii::t('rbac-admin', 'Rule Name'),
120
            'data' => Yii::t('rbac-admin', 'Data'),
121
        ];
122
    }
123
124
    /**
125
     * Check if is new record.
126
     * @return boolean
127
     */
128
    public function getIsNewRecord()
129
    {
130
        return $this->_item === null;
131
    }
132
133
    /**
134
     * Find role
135
     * @param string $id
136
     * @return null|\self
137
     */
138
    public static function find($id)
139
    {
140
        $item = Yii::$app->authManager->getRole($id);
141
        if ($item !== null) {
142
            return new self($item);
143
        }
144
145
        return null;
146
    }
147
148
    /**
149
     * Save role to [[\yii\rbac\authManager]]
150
     * @return boolean
151
     */
152
    public function save()
153
    {
154
        if ($this->validate()) {
155
            $manager = Yii::$app->authManager;
156
            if ($this->_item === null) {
157
                if ($this->type == Item::TYPE_ROLE) {
158
                    $this->_item = $manager->createRole($this->name);
159
                } else {
160
                    $this->_item = $manager->createPermission($this->name);
161
                }
162
                $isNew = true;
163
            } else {
164
                $isNew = false;
165
                $oldName = $this->_item->name;
166
            }
167
            $this->_item->name = $this->name;
168
            $this->_item->description = $this->description;
169
            $this->_item->ruleName = $this->ruleName;
170
            $this->_item->data = $this->data === null || $this->data === '' ? null : Json::decode($this->data);
171
            if ($isNew) {
172
                $manager->add($this->_item);
173
            } else {
174
                $manager->update($oldName, $this->_item);
0 ignored issues
show
Bug introduced by
The variable $oldName does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
175
            }
176
            Helper::invalidate();
177
            return true;
178
        } else {
179
            return false;
180
        }
181
    }
182
183
    /**
184
     * Adds an item as a child of another item.
185
     * @param array $items
186
     * @return int
187
     */
188 View Code Duplication
    public function addChildren($items)
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...
189
    {
190
        $manager = Yii::$app->getAuthManager();
191
        $success = 0;
192
        if ($this->_item) {
193
            foreach ($items as $name) {
194
                $child = $manager->getPermission($name);
195
                if ($this->type == Item::TYPE_ROLE && $child === null) {
196
                    $child = $manager->getRole($name);
197
                }
198
                try {
199
                    $manager->addChild($this->_item, $child);
200
                    $success++;
201
                } catch (\Exception $exc) {
202
                    Yii::error($exc->getMessage(), __METHOD__);
203
                }
204
            }
205
        }
206
        if ($success > 0) {
207
            Helper::invalidate();
208
        }
209
        return $success;
210
    }
211
212
    /**
213
     * Remove an item as a child of another item.
214
     * @param array $items
215
     * @return int
216
     */
217 View Code Duplication
    public function removeChildren($items)
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...
218
    {
219
        $manager = Yii::$app->getAuthManager();
220
        $success = 0;
221
        if ($this->_item !== null) {
222
            foreach ($items as $name) {
223
                $child = $manager->getPermission($name);
224
                if ($this->type == Item::TYPE_ROLE && $child === null) {
225
                    $child = $manager->getRole($name);
226
                }
227
                try {
228
                    $manager->removeChild($this->_item, $child);
229
                    $success++;
230
                } catch (\Exception $exc) {
231
                    Yii::error($exc->getMessage(), __METHOD__);
232
                }
233
            }
234
        }
235
        if ($success > 0) {
236
            Helper::invalidate();
237
        }
238
        return $success;
239
    }
240
241
    /**
242
     * Get items
243
     * @return array
244
     */
245
    public function getItems()
246
    {
247
        $manager = Yii::$app->getAuthManager();
248
        $avaliable = [];
249
        if ($this->type == Item::TYPE_ROLE) {
250
            foreach (array_keys($manager->getRoles()) as $name) {
251
                $avaliable[$name] = 'role';
252
            }
253
        }
254 View Code Duplication
        foreach (array_keys($manager->getPermissions()) as $name) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
255
            $avaliable[$name] = $name[0] == '/' ? 'route' : 'permission';
256
        }
257
258
        $assigned = [];
259
        foreach ($manager->getChildren($this->_item->name) as $item) {
260
            $assigned[$item->name] = $item->type == 1 ? 'role' : ($item->name[0] == '/' ? 'route' : 'permission');
261
            unset($avaliable[$item->name]);
262
        }
263
        unset($avaliable[$this->name]);
264
        return[
265
            'avaliable' => $avaliable,
266
            'assigned' => $assigned
267
        ];
268
    }
269
270
    /**
271
     * Get item
272
     * @return Item
273
     */
274
    public function getItem()
275
    {
276
        return $this->_item;
277
    }
278
279
    /**
280
     * Get type name
281
     * @param  mixed $type
282
     * @return string|array
283
     */
284
    public static function getTypeName($type = null)
285
    {
286
        $result = [
287
            Item::TYPE_PERMISSION => 'Permission',
288
            Item::TYPE_ROLE => 'Role'
289
        ];
290
        if ($type === null) {
291
            return $result;
292
        }
293
294
        return $result[$type];
295
    }
296
}
297