Completed
Push — master ( 9ed145...8e4a93 )
by vistart
04:04
created

Member::getOrganization()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
/**
4
 *  _   __ __ _____ _____ ___  ____  _____
5
 * | | / // // ___//_  _//   ||  __||_   _|
6
 * | |/ // /(__  )  / / / /| || |     | |
7
 * |___//_//____/  /_/ /_/ |_||_|     |_|
8
 * @link https://vistart.me/
9
 * @copyright Copyright (c) 2016 - 2017 vistart
10
 * @license https://vistart.me/license/
11
 */
12
13
namespace rhosocial\organization;
14
15
use rhosocial\base\models\models\BaseBlameableModel;
16
use rhosocial\user\rbac\Item;
17
use rhosocial\user\rbac\Role;
18
use rhosocial\user\User;
19
use rhosocial\organization\rbac\roles\DepartmentAdmin;
20
use rhosocial\organization\rbac\roles\DepartmentCreator;
21
use rhosocial\organization\rbac\roles\OrganizationAdmin;
22
use rhosocial\organization\rbac\roles\OrganizationCreator;
23
use rhosocial\organization\queries\OrganizationQuery;
24
use rhosocial\organization\queries\MemberQuery;
25
use Yii;
26
use yii\base\InvalidParamException;
27
use yii\base\InvalidValueException;
28
use yii\db\IntegrityException;
29
30
/**
31
 * Organization member.
32
 *
33
 * @property string $organization_guid
34
 * @property string $user_guid store guid of user who represents this member.
35
 * @property string $nickname
36
 * @property string $role
37
 * @property string $position
38
 * @property string $description
39
 * 
40
 * @property string $department_guid
41
 * @property string $member_guid
42
 * @property Organization $organization
43
 * @property User $memberUser
44
 *
45
 * @version 1.0
46
 * @author vistart <[email protected]>
47
 */
48
class Member extends BaseBlameableModel
49
{
50
    public $createdByAttribute = 'organization_guid';
51
    public $updatedByAttribute = false;
52
    public $hostClass = Organization::class;
53
54
    public $memberAttribute = 'user_guid';
55
    public $memberUserClass = User::class;
56
    public $contentAttribute = 'nickname';
57
    private $noInitMemberUser;
58
    /**
59
     * @return User
60
     */
61 36
    protected function getNoInitMemberUser()
62
    {
63 36
        if (!$this->noInitMemberUser) {
64 36
            $class = $this->memberUserClass;
65 36
            $this->noInitMemberUser = $class::buildNoInitModel();
66
        }
67 36
        return $this->noInitMemberUser;
68
    }
69
70
    /**
71
     * @inheritdoc
72
     */
73 37
    public function init()
74
    {
75 37
        if (!is_string($this->queryClass)) {
76 37
            $this->queryClass = MemberQuery::class;
77
        }
78 37
        if ($this->skipInit) {
79 37
            return;
80
        }
81 36
        parent::init();
82 36
    }
83
84
    public $descriptionAttribute = 'description';
85
86 36
    public function getMemberUserRules()
87
    {
88
        return [
89 36
            [$this->memberAttribute, 'required'],
90 36
            [$this->memberAttribute, 'string', 'max' => 36],
91
        ];
92
    }
93
94 36
    public function getMemberRoleRules()
95
    {
96
        return [
97 36
            ['role', 'string', 'max' => 255],
98
        ];
99
    }
100
101 36
    public function getMemberPositionRules()
102
    {
103
        return [
104 36
            ['position', 'default', 'value' => ''],
105
            ['position', 'string', 'max' => 255],
106
        ];
107
    }
108
109
    /**
110
     * Set member user.
111
     * @param User|string|integer $user
112
     */
113 36
    public function setMemberUser($user)
114
    {
115 36
        $class = $this->memberUserClass;
116 36
        if (is_numeric($user)) {
117
            $user = $class::find()->id($user)->one();
118
        }
119 36
        if ($user instanceof $class) {
120 36
            $user = $user->getGUID();
121
        }
122 36
        $this->{$this->memberAttribute} = $user;
123 36
    }
124
125 36
    public function getMemberUser()
126
    {
127 36
        return $this->hasOne($this->memberUserClass, [$this->getNoInitMemberUser()->guidAttribute => $this->memberAttribute]);
128
    }
129
130
    /**
131
     * Get Organization Query.
132
     * Alias of `getHost` method.
133
     * @return OrganizationQuery
134
     */
135 28
    public function getOrganization()
136
    {
137 28
        return $this->getHost();
138
    }
139
140
    /**
141
     * Set Organization.
142
     * @param BaseOrganization $organization
143
     * @return boolean
144
     */
145 36
    public function setOrganization($organization)
146
    {
147 36
        return $this->setHost($organization);
148
    }
149
150
    /**
151
     * Assign role.
152
     * The setting role operation will not take effect immediately. You should
153
     * wrap this method and the subsequent save operations together into a
154
     * transaction, in order to ensure data cosistency.
155
     * @param Role $role
156
     * @return boolean
157
     */
158 36
    public function assignRole($role)
159
    {
160 36
        $user = $this->memberUser;
161 36
        if (!$user) {
162
            throw new InvalidValueException('Invalid User');
163
        }
164 36
        if ($role instanceof Item) {
165 7
            $role = $role->name;
166
        }
167 36
        $assignment = Yii::$app->authManager->getAssignment($role, $user);
168 36
        if (!$assignment) {
169 36
            $assignment = Yii::$app->authManager->assign($role, $user->getGUID());
0 ignored issues
show
Unused Code introduced by
$assignment is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
170
        }
171 36
        return $this->setRole($role);
0 ignored issues
show
Documentation introduced by
$role is of type string, but the function expects a object<rhosocial\user\rbac\Role>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
172
    }
173
174
    /**
175
     * Assign administrator.
176
     * @return boolean
177
     * @throws \Exception
178
     * @throws IntegrityException
179
     */
180 7
    public function assignAdministrator()
181
    {
182 7
        $host = $this->organization;
183
        /* @var $host Organization */
184 7
        $role = null;
185 7
        if ($host->type == Organization::TYPE_ORGANIZATION) {
186 7
            $role = new OrganizationAdmin();
187 1
        } elseif ($host->type == Organization::TYPE_DEPARTMENT) {
188 1
            $role = new DepartmentAdmin();
189
        }
190 7
        $transaction = Yii::$app->db->beginTransaction();
191
        try {
192 7
            $this->assignRole($role);
0 ignored issues
show
Bug introduced by
It seems like $role defined by null on line 184 can also be of type null; however, rhosocial\organization\Member::assignRole() does only seem to accept object<rhosocial\user\rbac\Role>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
193 7
            if (!$this->save()) {
194
                throw new IntegrityException("Failed to assign administrator.");
195
            }
196 7
            $transaction->commit();
197
        } catch (\Exception $ex) {
198
            $transaction->rollBack();
199
            Yii::error($ex->getMessage(), __METHOD__);
200
            throw $ex;
201
        }
202 7
        return true;
203
    }
204
205
    /**
206
     * Set role.
207
     * @param Role $role
208
     * @return boolean
209
     */
210 36
    public function setRole($role = null)
211
    {
212 36
        if (empty($role)) {
213 17
            $role = '';
214
        }
215 36
        if ($role instanceof Item) {
216
            $role = $role->name;
217
        }
218 36
        $this->role = $role;
219 36
        return true;
220
    }
221
222
    /**
223
     * Revoke role.
224
     * @param Role $role
225
     * @throws InvalidParamException
226
     * @throws IntegrityException
227
     * @throws \Exception
228
     * @return boolean
229
     */
230 17
    public function revokeRole($role)
231
    {
232 17
        $user = $this->memberUser;
233 17
        if (!$user) {
234
            throw new InvalidValueException('Invalid User');
235
        }
236 17
        if ($role instanceof Item) {
237 1
            $role = $role->name;
238
        }
239 17
        $transaction = Yii::$app->db->beginTransaction();
240
        try {
241 17
            $assignment = Yii::$app->authManager->getAssignment($role, $user);
242 17
            if ($assignment) {
243 17
                $count = (int)($user->getOfMembers()->role($role)->count());
244 17
                if ($count <= 1) {
245 15
                    Yii::$app->authManager->revoke($role, $user);
246
                }
247
            }
248 17
            $this->setRole();
249 17
            if (!$this->save()) {
250
                throw new IntegrityException('Save failed.');
251
            }
252 17
            $transaction->commit();
253
        } catch (\Exception $ex) {
254
            $transaction->rollBack();
255
            Yii::error($ex->getMessage(), __METHOD__);
256
            throw $ex;
257
        }
258 17
        return true;
259
    }
260
261
    /**
262
     * Revoke administrator.
263
     * @return boolean
264
     * @throws IntegrityException
265
     * @throws \Exception
266
     */
267 1
    public function revokeAdministrator()
268
    {
269 1
        $host = $this->organization;
270
        /* @var $host Organization */
271 1
        $role = null;
272 1
        if ($host->type == Organization::TYPE_ORGANIZATION) {
273 1
            $role = new OrganizationAdmin();
274 1
        } elseif ($host->type == Organization::TYPE_DEPARTMENT) {
275 1
            $role = new DepartmentAdmin();
276
        }
277 1
        $transaction = Yii::$app->db->beginTransaction();
278
        try {
279 1
            $this->revokeRole($role);
0 ignored issues
show
Bug introduced by
It seems like $role defined by null on line 271 can also be of type null; however, rhosocial\organization\Member::revokeRole() does only seem to accept object<rhosocial\user\rbac\Role>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
280 1
            if (!$this->save()) {
281
                throw new IntegrityException("Failed to revoke administrator.");
282
            }
283 1
            $transaction->commit();
284
        } catch (\Exception $ex) {
285
            $transaction->rollBack();
286
            Yii::error($ex->getMessage(), __METHOD__);
287
            throw $ex;
288
        }
289 1
        return true;
290
    }
291
292 36
    public function rules()
293
    {
294 36
        return array_merge($this->getMemberUserRules(), $this->getMemberRoleRules(), $this->getMemberPositionRules(), parent::rules());
295
    }
296
297
    /**
298
     * @inheritdoc
299
     */
300 37
    public static function tableName()
301
    {
302 37
        return '{{%organization_member}}';
303
    }
304
305
    /**
306
     * Find.
307
     * Friendly to IDE.
308
     * @return MemberQuery
309
     */
310 37
    public static function find()
311
    {
312 37
        return parent::find();
313
    }
314
315
    /**
316
     * @inheritdoc
317
     */
318 1
    public function attributeLabels()
319
    {
320
        return [
321 1
            'guid' => Yii::t('user', 'GUID'),
322 1
            'id' => Yii::t('user', 'ID'),
323 1
            'organization_guid' => Yii::t('organization', 'Organization GUID'),
324 1
            'user_guid' => Yii::t('organization', 'User GUID'),
325 1
            'nickname' => Yii::t('user', 'Nickname'),
326 1
            'role' => Yii::t('organization', 'Role'),
327 1
            'position' => Yii::t('organization', 'Member Position'),
328 1
            'description' => Yii::t('organization', 'Description'),
329 1
            'ip' => Yii::t('user', 'IP Address'),
330 1
            'ip_type' => Yii::t('user', 'IP Address Type'),
331 1
            'created_at' => Yii::t('user', 'Creation Time'),
332 1
            'updated_at' => Yii::t('user', 'Last Updated Time'),
333
        ];
334
    }
335
336 6
    public function isDepartmentAdministrator()
337
    {
338 6
        return $this->role == (new DepartmentAdmin)->name;
339
    }
340
    
341 17
    public function isDepartmentCreator()
342
    {
343 17
        return $this->role == (new DepartmentCreator)->name;
344
    }
345
346 6
    public function isOrganizationAdministrator()
347
    {
348 6
        return $this->role == (new OrganizationAdmin)->name;
349
    }
350
    
351 17
    public function isOrganizationCreator()
352
    {
353 17
        return $this->role == (new OrganizationCreator)->name;
354
    }
355
356
    /**
357
     * Check whether current member is administrator.
358
     * @return boolean
359
     */
360 6
    public function isAdministrator()
361
    {
362 6
        return $this->isDepartmentAdministrator() || $this->isOrganizationAdministrator();
363
    }
364
365
    /**
366
     * Check whether current member is creator.
367
     * @return boolean
368
     */
369 17
    public function isCreator()
370
    {
371 17
        return $this->isDepartmentCreator() || $this->isOrganizationCreator();
372
    }
373
374
    /**
375
     * We think it a `member` if `role` property is empty.
376
     * @return boolean
377
     */
378 2
    public function isOnlyMember()
379
    {
380 2
        return empty($this->role);
381
    }
382
}
383