Completed
Push — develop ( e9f396...2b8a13 )
by Nate
04:23
created

UsersAssociatedToOrganizationManager   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 264
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 36
lcom 1
cbo 10
dl 0
loc 264
ccs 0
cts 145
cp 0
rs 9.52
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A query() 0 18 3
A create() 0 6 1
B save() 0 52 9
A associateOne() 0 18 3
A associateMany() 0 14 3
A dissociateOne() 0 16 3
A dissociateMany() 0 14 3
A findKey() 0 18 4
B resolveUser() 0 22 6
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/organization/license
6
 * @link       https://www.flipboxfactory.com/software/organization/
7
 */
8
9
namespace flipbox\organizations\objects;
10
11
use craft\elements\User;
12
use craft\helpers\ArrayHelper;
13
use craft\helpers\Json;
14
use flipbox\craft\ember\helpers\QueryHelper;
15
use flipbox\organizations\elements\Organization;
16
use flipbox\organizations\Organizations;
17
use flipbox\organizations\queries\UserAssociationQuery;
18
use flipbox\organizations\records\UserAssociation;
19
use yii\db\QueryInterface;
20
21
/**
22
 * @author Flipbox Factory <[email protected]>
23
 * @since 1.0.0
24
 */
25
class UsersAssociatedToOrganizationManager
26
{
27
    use UserAssociationManagerTrait;
28
29
    /**
30
     * @var Organization
31
     */
32
    private $organization;
33
34
    /**
35
     * @param Organization $organization
36
     */
37
    public function __construct(Organization $organization)
38
    {
39
        $this->organization = $organization;
40
    }
41
42
    /**
43
     * @param array $criteria
44
     * @return UserAssociationQuery
45
     */
46
    public function query(array $criteria = []): UserAssociationQuery
47
    {
48
        /** @noinspection PhpUndefinedMethodInspection */
49
        $query = UserAssociation::find()
50
            ->setOrganizationId($this->organization->getId() ?: false)
0 ignored issues
show
Security Bug introduced by
It seems like $this->organization->getId() ?: false can also be of type false; however, flipbox\organizations\qu...it::setOrganizationId() does only seem to accept string|array<integer,str...nts\Organization>>|null, did you maybe forget to handle an error condition?
Loading history...
51
            ->orderBy([
52
                'userOrder' => SORT_ASC
53
            ]);
54
55
        if (!empty($criteria)) {
56
            QueryHelper::configure(
57
                $query,
58
                $criteria
59
            );
60
        }
61
62
        return $query;
63
    }
64
65
    /**
66
     * @param $object
67
     * @return UserAssociation
68
     */
69
    public function create($object): UserAssociation
70
    {
71
        return (new UserAssociation())
72
            ->setOrganization($this->organization)
73
            ->setUser($this->resolveUser($object));
74
    }
75
76
    /*******************************************
77
     * ASSOCIATE and/or DISASSOCIATE
78
     *******************************************/
79
80
    /**
81
     * @return bool
82
     * @throws \Throwable
83
     * @throws \yii\db\StaleObjectException
84
     */
85
    public function save(): bool
86
    {
87
        // No changes?
88
        if (!$this->isMutated()) {
89
            return true;
90
        }
91
92
        $success = true;
93
94
        $existingAssociations = $this->query()
95
            ->indexBy('userId')
96
            ->all();
97
98
        $associations = [];
99
        foreach ($this->findAll() as $newAssociation) {
100
            if (null === ($association = ArrayHelper::remove(
101
                $existingAssociations,
102
                $newAssociation->getUserId()
103
            ))) {
104
                $association = $newAssociation;
105
            }
106
107
            $association->userOrder = $newAssociation->userOrder;
108
            $association->organizationOrder = $newAssociation->organizationOrder;
109
110
            $associations[] = $association;
111
        }
112
113
        // Delete those removed
114
        foreach ($existingAssociations as $existingAssociation) {
115
            if (!$existingAssociation->delete()) {
116
                $success = false;
117
            }
118
        }
119
120
        $order = 1;
121
        foreach ($associations as $association) {
122
            $association->userOrder = $order++;
123
124
            if (!$association->save()) {
125
                $success = false;
126
            }
127
        }
128
129
        $this->associations = $associations;
130
131
        if (!$success) {
132
            $this->organization->addError('users', 'Unable to save user organizations.');
133
        }
134
135
        return $success;
136
    }
137
138
    /*******************************************
139
     * ASSOCIATE
140
     *******************************************/
141
142
    /**
143
     * @param $object
144
     * @param int|null $sortOrder
145
     * @return bool
146
     */
147
    public function associateOne($object, int $sortOrder = null): bool
148
    {
149
        $association = $this->findOrCreate($object);
150
151
        if (null !== $sortOrder) {
152
            $association->userOrder = $sortOrder;
153
        }
154
155
        if (!$association->save()) {
156
            $this->organization->addError('users', 'Unable to associate organization.');
157
158
            return false;
159
        }
160
161
        $this->reset();
162
163
        return true;
164
    }
165
166
    /**
167
     * @param QueryInterface|Organization[] $objects
168
     * @return bool
169
     * @throws \Throwable
170
     */
171
    public function associateMany($objects): bool
172
    {
173
        if ($objects instanceof QueryInterface) {
174
            $objects = $objects->all();
175
        }
176
177
        if (empty($objects)) {
178
            return true;
179
        }
180
181
        $this->addMany($objects);
182
183
        return $this->save();
184
    }
185
186
187
    /*******************************************
188
     * DISSOCIATE
189
     *******************************************/
190
191
    /**
192
     * @param $object
193
     * @return bool
194
     * @throws \Throwable
195
     * @throws \yii\db\StaleObjectException
196
     */
197
    public function dissociateOne($object): bool
198
    {
199
        if (null === ($association = $this->findOne($object))) {
200
            return true;
201
        }
202
203
        if (!$association->delete()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $association->delete() of type false|integer is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

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

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
204
            $this->organization->addError('users', 'Unable to dissociate organization.');
205
206
            return false;
207
        }
208
209
        $this->removeOne($association);
210
211
        return true;
212
    }
213
214
    /**
215
     * @param QueryInterface|Organization[] $objects
216
     * @return bool
217
     * @throws \Throwable
218
     */
219
    public function dissociateMany($objects): bool
220
    {
221
        if ($objects instanceof QueryInterface) {
222
            $objects = $objects->all();
223
        }
224
225
        if (empty($objects)) {
226
            return true;
227
        }
228
229
        $this->removeMany($objects);
230
231
        return $this->save();
232
    }
233
234
235
    /*******************************************
236
     * UTILS
237
     *******************************************/
238
239
    /**
240
     * @param UserAssociation|Organization|int|array|null $object
241
     * @return int|null
242
     */
243
    protected function findKey($object = null)
244
    {
245
        if (null === ($element = $this->resolveUser($object))) {
246
            Organizations::info(sprintf(
247
                "Unable to resolve user: %s",
248
                (string)Json::encode($object)
249
            ));
250
            return null;
251
        }
252
253
        foreach ($this->findAll() as $key => $association) {
254
            if ($association->getUserId() === $element->getId()) {
255
                return $key;
256
            }
257
        }
258
259
        return null;
260
    }
261
262
    /**
263
     * @param UserAssociation|User|int|array|null $user
264
     * @return User|null
265
     */
266
    protected function resolveUser($user = null)
267
    {
268
        if (null === $user) {
269
            return null;
270
        }
271
272
        if ($user instanceof UserAssociation) {
273
            return $user->getUser();
274
        }
275
276
        if ($user instanceof User) {
277
            return $user;
278
        }
279
280
        if (is_array($user) &&
281
            null !== ($id = ArrayHelper::getValue($user, 'id'))
282
        ) {
283
            $user = ['id' => $id];
284
        }
285
286
        return User::findOne($user);
287
    }
288
}
289