Completed
Push — master ( f8cbc9...76d295 )
by vistart
03:56
created

UserOrganizationTrait::setUpOrganization()   C

Complexity

Conditions 11
Paths 18

Size

Total Lines 30
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 11.353

Importance

Changes 0
Metric Value
dl 0
loc 30
ccs 18
cts 21
cp 0.8571
rs 5.2653
c 0
b 0
f 0
cc 11
eloc 22
nc 18
nop 7
crap 11.353

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\organization\queries\MemberQuery;
16
use rhosocial\organization\queries\OrganizationQuery;
17
use Yii;
18
use yii\base\InvalidConfigException;
19
use yii\base\InvalidParamException;
20
21
/**
22
 * @property string $guidAttribute GUID Attribute.
23
 * @property-read Member[] $ofMembers
24
 * @property-read Organization[] $atOrganizations
25
 *
26
 * @version 1.0
27
 * @author vistart <[email protected]>
28
 */
29
trait UserOrganizationTrait
30
{
31
    public $organizationClass = Organization::class;
32
    public $memberClass = Member::class;
33
    private $noInitOrganization;
34
    private $noInitMember;
35
    public $lastSetUpOrganization;
36
    /**
37
     * @return Organization
38
     */
39
    protected function getNoInitOrganization()
40
    {
41
        if (!$this->noInitOrganization) {
42
            $class = $this->organizationClass;
43
            $this->noInitOrganization = $class::buildNoInitModel();
44
        }
45
        return $this->noInitOrganization;
46
    }
47
    /**
48
     * @return Member
49
     */
50 8
    protected function getNoInitMember()
51
    {
52 8
        if (!$this->noInitMember) {
53 8
            $class = $this->memberClass;
54 8
            $this->noInitMember = $class::buildNoInitModel();
55
        }
56 8
        return $this->noInitMember;
57
    }
58
59
    /**
60
     * 
61
     * @return MemberQuery
62
     */
63 8
    public function getOfMembers()
64
    {
65 8
        return $this->hasMany($this->memberClass, [$this->getNoInitMember()->memberAttribute => $this->guidAttribute])->inverseOf('memberUser');
0 ignored issues
show
Bug introduced by
It seems like hasMany() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
66
    }
67
68
    /**
69
     * 
70
     * @return OrganizationQuery
71
     */
72 8
    public function getAtOrganizations()
73
    {
74 8
        return $this->hasMany($this->organizationClass, [$this->guidAttribute => $this->getNoInitMember()->createdByAttribute])->via('ofMembers');
0 ignored issues
show
Bug introduced by
It seems like hasMany() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
75
    }
76
77
    /**
78
     * Set up organization.
79
     * @param string $name
80
     * @param Organization $parent
81
     * @param string $nickname
82
     * @param integer $gravatar_type
83
     * @param string $gravatar
84
     * @param string $timezone
85
     * @param string $description
86
     * @return boolean Whether indicate the setting-up succeeded or not.
87
     */
88 17
    public function setUpOrganization($name, $parent = null, $nickname = '', $gravatar_type = 0, $gravatar = '', $timezone = 'UTC', $description = '')
0 ignored issues
show
Unused Code introduced by
The parameter $nickname is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $gravatar_type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $gravatar is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $timezone is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $description is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
89
    {
90 17
        $transaction = Yii::$app->db->beginTransaction();
91
        try {
92 17
            $models = $this->createOrganization($name, $nickname = '', $gravatar_type = 0, $gravatar = '', $timezone = 'UTC', $description = '');
93 17
            if (!array_key_exists(0, $models) || !($models[0] instanceof Organization)) {
94 1
                throw new InvalidConfigException('Invalid Organization Model.');
95
            }
96 16
            $result = $models[0]->register($models['associatedModels']);
97 16
            if ($result instanceof \Exception) {
98
                throw $result;
99
            }
100 16
            if ($result !== true) {
101
                throw new \Exception('Failed to set up.');
102
            }
103 16
            if ($parent instanceof Organization && !$parent->getIsNewRecord()) {
104 3
                $setParentResult = ($models[0]->setParent($parent) && $models[0]->save());
0 ignored issues
show
Bug Best Practice introduced by
The expression $models[0]->setParent($parent) of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
105
            }
106 16
            if (isset($setParentResult) && $setParentResult === false) {
107
                throw new \Exception('Failed to set parent.');
108
            }
109 16
            $transaction->commit();
110 1
        } catch (\Exception $ex) {
111 1
            $transaction->rollBack();
112 1
            Yii::error($ex->getMessage(), __METHOD__);
113 1
            throw $ex;
114
        }
115 16
        $this->lastSetUpOrganization = $models[0];
116 16
        return true;
117
    }
118
119
    /**
120
     * Set up organization.
121
     * @param string $name
122
     * @param Organization $parent
123
     * @param string $nickname
124
     * @param integer $gravatar_type
125
     * @param string $gravatar
126
     * @param string $timezone
127
     * @param string $description
128
     * @return boolean Whether indicate the setting-up succeeded or not.
129
     */
130 2
    public function setUpDepartment($name, $parent = null, $nickname = '', $gravatar_type = 0, $gravatar = '', $timezone = 'UTC', $description = '')
0 ignored issues
show
Unused Code introduced by
The parameter $nickname is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $gravatar_type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $gravatar is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $timezone is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $description is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
131
    {
132 2
        if ($parent == null) {
133 1
            throw new InvalidConfigException('Invalid Parent Parameter.');
134
        }
135 1
        $transaction = Yii::$app->db->beginTransaction();
136
        try {
137 1
            $models = $this->createDepartment($name, $nickname = '', $gravatar_type = 0, $gravatar = '', $timezone = 'UTC', $description = '');
138 1
            if (!array_key_exists(0, $models) || !($models[0] instanceof Organization)) {
139
                throw new InvalidConfigException('Invalid Organization Model.');
140
            }
141 1
            $result = $models[0]->register($models['associatedModels']);
142 1
            if ($result instanceof \Exception) {
143
                throw $result;
144
            }
145 1
            if ($result !== true) {
146
                throw new \Exception('Failed to set up.');
147
            }
148 1
            if ($parent instanceof Organization && !$parent->getIsNewRecord()) {
149 1
                $setParentResult = ($models[0]->setParent($parent) && $models[0]->save());
0 ignored issues
show
Bug Best Practice introduced by
The expression $models[0]->setParent($parent) of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
150
            }
151 1
            if (isset($setParentResult) && $setParentResult === false) {
152
                throw new \Exception('Failed to set parent.');
153
            }
154 1
            $transaction->commit();
155
        } catch (\Exception $ex) {
156
            $transaction->rollBack();
157
            Yii::error($ex->getMessage(), __METHOD__);
158
            throw $ex;
159
        }
160 1
        $this->lastSetUpOrganization = $models[0];
161 1
        return true;
162
    }
163
164
    /**
165
     * Create organization.
166
     * @param string $name
167
     * @param string $nickname
168
     * @param string $gravatar_type
169
     * @param string $gravatar
170
     * @param string $timezone
171
     * @param string $description
172
     * @return Organization
173
     */
174 16
    public function createOrganization($name, $nickname = '', $gravatar_type = 0, $gravatar = '', $timezone = 'UTC', $description = '')
175
    {
176 16
        return $this->createBaseOrganization($name, $nickname, $gravatar_type, $gravatar, $timezone, $description);
177
    }
178
179
    /**
180
     * Create department.
181
     * @param string $name
182
     * @param string $nickname
183
     * @param string $gravatar_type
184
     * @param string $gravatar
185
     * @param string $timezone
186
     * @param string $description
187
     * @return Organization
188
     */
189 1
    public function createDepartment($name, $nickname = '', $gravatar_type = 0, $gravatar = '', $timezone = 'UTC', $description = '')
190
    {
191 1
        return $this->createBaseOrganization($name, $nickname, $gravatar_type, $gravatar, $timezone, $description, Organization::TYPE_DEPARTMENT);
192
    }
193
194
    /**
195
     * Create Base Organization.
196
     * @param string $name
197
     * @param string $nickname
198
     * @param integer $gravatar_type
199
     * @param string $gravatar
200
     * @param string $timezone
201
     * @param string $description
202
     * @param integer $type
203
     * @return array This array contains two elements, the first is `Organization` or `Department` depends on `$type`.
204
     * The other is `associatedModels` array, contains two elements `Profile`(profile) and `Creator`(creator).
205
     */
206 16
    protected function createBaseOrganization($name, $nickname = '', $gravatar_type = 0, $gravatar = '', $timezone = 'UTC', $description = '', $type = Organization::TYPE_ORGANIZATION)
207
    {
208 16
        $class = $this->organizationClass;
209 16
        $organization = new $class(['type' => $type]);
210
        /* @var $organization Organization */
211
        $profileConfig = [
212 16
            'name' => $name,
213 16
            'nickname' => $nickname,
214 16
            'gravatar_type' => $gravatar_type,
215 16
            'gravatar' => $gravatar,
216 16
            'timezone' => $timezone,
217 16
            'description' => $description,
218
        ];
219 16
        $profile = $organization->createProfile($profileConfig);
220 16
        $member = $organization->createMemberModelWithUser($this);
221 16
        return [0 => $organization, 'associatedModels' => ['profile' => $profile, 'creator'=> $member]];
222
    }
223
}
224