Passed
Push — master ( 07f514...4a086f )
by vistart
04:06
created

actionRevokeSetUpOrganization()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 0
cts 9
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 10
nc 2
nop 1
crap 6
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\console\controllers;
14
15
use rhosocial\user\User;
16
use rhosocial\organization\Organization;
17
use rhosocial\organization\rbac\permissions\SetUpOrganization;
18
use Yii;
19
use yii\console\Controller;
20
use yii\console\Exception;
21
22
/**
23
 * Organization commands.
24
 *
25
 * @version 1.0
26
 * @author vistart <[email protected]>
27
 */
28
class OrganizationController extends Controller
29
{
30
    public $userClass;
31
    public $organizationClass;
32
    public $defaultAction = 'show';  
33
34
    /**
35
     * Check user class.
36
     * @return User
37
     * @throws Exception throw if User is not an instance inherited from `\rhosocial\user\User`.
38
     */
39
    protected function checkUserClass()
40
    {
41
        $userClass = $this->userClass;
42
        if (!class_exists($userClass)) {
43
            throw new Exception('User Class Invalid.');
44
        }
45
        if (!((new $userClass()) instanceof User)) {
46
            throw new Exception('User Class(' . $userClass . ') does not inherited from `\rhosocial\user\User`.');
47
        }
48
        return $userClass;
49
    }
50
51
    /**
52
     * Get user from database.
53
     * @param User|string|integer $user User ID.
54
     * @return User
55
     */
56
    protected function getUser($user)
57
    {
58
        $userClass = $this->checkUserClass();
59
        if (is_numeric($user)) {
60
            $user = $userClass::find()->id($user)->one();
61
        } elseif (is_string($user) && strlen($user)) {
62
            $user = $userClass::find()->guid($user)->one();
63
        }
64
        if (!$user || $user->getIsNewRecord()) {
0 ignored issues
show
Bug introduced by
It seems like $user is not always an object, but can also be of type array|string. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
65
            throw new Exception('User Not Registered.');
66
        }
67
        return $user;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $user; (yii\db\ActiveRecord|array|string) is incompatible with the return type documented by rhosocial\organization\c...tionController::getUser of type rhosocial\user\User.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
68
    }
69
70
    /**
71
     * Check organization class.
72
     * @return Organization
73
     * @throws Exception throw if Organization is not an instance inherited from `\rhosocial\organization\Organization`.
74
     */
75
    protected function checkOrganizationClass()
76
    {
77
        $organizationClass = $this->organizationClass;
78
        if (!class_exists($organizationClass)) {
79
            throw new Exception('Organization Class Invalid.');
80
        }
81
        if (!((new $organizationClass()) instanceof Organization)) {
82
            throw new Exception('Organization Class(' . $organizationClass . ') does not inherited from `\rhosocial\organization\Organization`.');
83
        }
84
        return $organizationClass;
85
    }
86
87
    /**
88
     * Get organization.
89
     * @param Organization|string|integer $organization
90
     * @return Organization
91
     */
92
    protected function getOrganization($organization)
93
    {
94
        $organizationClass = $this->checkOrganizationClass();
95
        if (is_numeric($organization)) {
96
            $organization = $organizationClass::find()->id($organization)->one();
97
        } elseif (is_string($organization) && strlen($organization)) {
98
            $organization = $organizationClass::find()->guid($organization)->one();
99
        }
100
        if (!$organization || $organization->getIsNewRecord()) {
0 ignored issues
show
Bug introduced by
It seems like $organization is not always an object, but can also be of type array|string. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
101
            throw new Exception('Organization Not Set Up.');
102
        }
103
        return $organization;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $organization; (yii\db\ActiveRecord|array|string) is incompatible with the return type documented by rhosocial\organization\c...roller::getOrganization of type rhosocial\organization\Organization.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
104
    }
105
106
    /**
107
     * Assign SetUpOrganization permission.
108
     * @param User|string|integer $user
109
     * @return boolean
110
     */
111
    public function actionAssignSetUpOrganization($user)
112
    {
113
        $user = $this->getUser($user);
114
        $permission = new SetUpOrganization();
115
        try {
116
            $assignment = Yii::$app->authManager->assign($permission->name, $user);
117
        } catch (\yii\db\IntegrityException $ex) {
118
            echo "Failed to assign `" . $permission->name . "`.\n";
119
            echo "Maybe the permission has been assigned.\n";
120
            return false;
121
        }
122
        if ($assignment) {
123
            echo "`$permission->name`" . " assigned to User (" . $user->getID() . ") successfully.\n";
124
        } else {
125
            echo "Failed to assign `" . $permission->name . "`.\n";
126
        }
127
        return true;
128
    }
129
130
    /**
131
     * Revoke SetUpOrganization permission.
132
     * @param User|string|integer $user
133
     * @return boolean
134
     */
135
    public function actionRevokeSetUpOrganization($user)
136
    {
137
        $user = $this->getUser($user);
138
        $permission = new SetUpOrganization();
139
        $assignment = Yii::$app->authManager->revoke($permission->name, $user);
140
        if ($assignment) {
141
            echo "`$permission->name`" . " revoked from User (" . $user->getID() . ").\n";
142
        } else {
143
            echo "Failed to revoke `" . $permission->name . "`.\n";
144
            echo "Maybe the role has not been assigned yet.\n";
145
        }
146
        return true;
147
    }
148
149
    /**
150
     * Show Organization Information.
151
     * @param Organization|string|integer $organization Organization's or department's ID.
152
     */
153
    public function actionShow($organization)
154
    {
155
        $organization = $this->getOrganization($organization);
156
        echo $organization->getID() . "\n";
157
    }
158
159
    /**
160
     * Set up organization.
161
     * @param User|string|integer $user Organization creator.
162
     * @param string $name
163
     */
164
    public function actionSetUpOrganization($user, $name)
165
    {
166
        $user = $this->getUser($user);
167
        try {
168
            $result = $user->setUpOrganization($name);
169
            if ($result !== true) {
170
                throw new Exception('Failed to set up.');
171
            }
172
        } catch (\Exception $ex) {
173
            throw new Exception($ex->getMessage());
174
        }
175
        echo "Organization Set Up:\n";
176
        return $this->actionShow($user->lastSetUpOrganization);
177
    }
178
179
    /**
180
     * Set up department.
181
     * @param User|string|integer $user Department creator.
182
     * @param string $name
183
     * @param Organization|string|integer $parent
184
     */
185
    public function actionSetUpDepartment($user, $name, $parent)
186
    {
187
        $user = $this->getUser($user);
188
        $parent = $this->getOrganization($parent);
189
        try {
190
            $result = $user->setUpDepartment($name, $parent);
191
            if ($result !== true) {
192
                throw new Exception('Failed to set up.');
193
            }
194
        } catch (\Exception $ex) {
195
            throw new Exception($ex->getMessage());
196
        }
197
        echo "Department Set Up:\n";
198
        return $this->actionShow($user->lastSetUpOrganization);
199
    }
200
201
    /**
202
     * Revoke organization.
203
     * @param Organization|string|integer $organization
204
     * @throws Exception
205
     */
206
    public function actionRevokeOrganization($organization)
207
    {
208
        $organization = $this->getOrganization($organization);
209
        $creator = $organization->creator;
210
        if (!$creator->revokeOrganization($organization)) {
211
            throw new Exception('Failed to revoke: ' . $organization->getID);
0 ignored issues
show
Documentation introduced by
The property getID does not exist on object<rhosocial\organization\Organization>. 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...
212
        }
213
        echo "Organization ({$organization->getID()}) revoked.\n";
214
    }
215
216
    /**
217
     * Add administrator.
218
     * @param Organization|string|integer $organization
219
     * @param User|string|integer $user
220
     */
221
    public function actionAddAdministrator($organization, $user)
222
    {
223
        $organization = $this->getOrganization($organization);
224
        $user = $this->getUser($user);
225
        if (!$organization->addAdministrator($user)) {
226
            throw new Exception('Failed to add administrator.');
227
        }
228
        echo "User ({$user->getID()}) assigned administrator.\n";
229
    }
230
231
    /**
232
     * Remove administrator
233
     * @param Organization|string|integer $organization
234
     * @param User|string|integer $user
235
     * @param boolean $keepMember
236
     */
237
    public function actionRemoveAdministrator($organization, $user, $keepMember = "yes")
238
    {
239
        $keepMember = strtolower($keepMember) == "yes";
240
        $organization = $this->getOrganization($organization);
241
        $user = $this->getUser($user);
242
        $id = $user->getID();
243
        if (!$organization->removeAdministrator($user, $keepMember)) {
244
            throw new Exception('Failed to remove administrator.');
245
        }
246
        echo "Administrator ($id) removed.\n";
247
        echo ($keepMember) ? ("But he is still a member of it.\n") : ("At the same time, he was also removed from the organization.\n");
248
    }
249
250
    /**
251
     * Add member.
252
     * @param Organization|string|intger $organization
253
     * @param User|string|integer $user
254
     */
255
    public function actionAddMember($organization, $user)
256
    {
257
        $organization = $this->getOrganization($organization);
258
        $user = $this->getUser($user);
259
        $id = $user->getID();
260
        if (!$organization->addMember($user)) {
261
            throw new Exception('Failed to add member.');
262
        }
263
        echo "User ($id) added to Organization ({$organization->getID()}).\n";
264
    }
265
266
    /**
267
     * Remove member.
268
     * @param Organization|string|intger $organization
269
     * @param User|string|integer $user
270
     */
271
    public function actionRemoveMember($organization, $user)
272
    {
273
        $organization = $this->getOrganization($organization);
274
        $user = $this->getUser($user);
275
        $id = $user->getID();
276
        if (!$organization->removeMember($user)) {
277
            throw new Exception('Failed to remove member.');
278
        }
279
        echo "Member ($id) removed.\n";
280
    }
281
}
282