UserTypeRelationship::sync()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 8
cp 0
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 2
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\relationships;
10
11
use craft\helpers\ArrayHelper;
12
use craft\helpers\Json;
13
use flipbox\craft\ember\helpers\QueryHelper;
14
use flipbox\organizations\Organizations;
15
use flipbox\organizations\queries\UserTypeAssociationQuery;
16
use flipbox\organizations\records\OrganizationType;
17
use flipbox\organizations\records\OrganizationTypeAssociation;
18
use flipbox\organizations\records\UserAssociation;
19
use flipbox\organizations\records\UserType;
20
use flipbox\organizations\records\UserTypeAssociation;
21
use Tightenco\Collect\Support\Collection;
22
23
/**
24
 * Manages User Types associated to Organization/User associations
25
 *
26
 * @author Flipbox Factory <[email protected]>
27
 * @since 2.0.0
28
 *
29
 * @property UserTypeAssociation[] $associations
30
 *
31
 * @method UserTypeAssociation findOrCreate($object)
32
 * @method UserTypeAssociation findOne($object = null)
33
 * @method UserTypeAssociation findOrFail($object)
34
 */
35
class UserTypeRelationship implements RelationshipInterface
36
{
37
    use RelationshipTrait {
38
        reset as parentReset;
39
        newRelations as parentSetCache;
40
        addToRelations as parentAddToCache;
41
        removeFromRelations as parentRemoveFromCache;
42
    }
43
44
    /**
45
     * @var UserAssociation
46
     */
47
    private $association;
48
49
    /**
50
     * @param UserAssociation $association
51
     */
52
    public function __construct(UserAssociation $association)
53
    {
54
        $this->association = $association;
55
    }
56
57
58
    /************************************************************
59
     * COLLECTION
60
     ************************************************************/
61
62
    /**
63
     * Get a collection of associated organizations
64
     *
65
     * @return Collection
66
     */
67
    public function getCollection(): Collection
68
    {
69
        return $this->getRelationships()
70
            ->pluck('type');
71
    }
72
73
    /**
74
     * @return Collection
75
     */
76
    protected function existingRelationships(): Collection
77
    {
78
        return $this->createRelations(
79
            $this->query()
80
                ->with('typeRecord')
81
                ->all()
82
        );
83
    }
84
85
    /************************************************************
86
     * QUERY
87
     ************************************************************/
88
89
    /**
90
     * @inheritDoc
91
     * @return UserTypeAssociationQuery
92
     */
93
    private function query(): UserTypeAssociationQuery
94
    {
95
        return UserTypeAssociation::find()
96
            ->setUserId($this->association->getId() ?: false)
97
            ->orderBy([
98
                'sortOrder' => SORT_ASC
99
            ])
100
            ->limit(null);
101
    }
102
103
    /**
104
     * @param UserTypeAssociation|UserType|int|string $type
105
     * @return UserTypeAssociation
106
     */
107
    protected function create($type): UserTypeAssociation
108
    {
109
        if ($type instanceof UserTypeAssociation) {
110
            return $type;
111
        }
112
113
        $association = (new UserTypeAssociation())
114
            ->setType($this->resolveObject($type));
115
116
        $association->userId = $this->association->id;
117
118
        return $association;
119
    }
120
121
    /**
122
     * Reset associations
123
     */
124
    public function reset(): RelationshipInterface
125
    {
126
        unset($this->association->typeRecords);
127
        return $this->parentReset();
128
    }
129
130
131
    /*******************************************
132
     * SAVE
133
     *******************************************/
134
135
    /**
136
     * @inheritDoc
137
     */
138
    protected function delta(): array
139
    {
140
        $existingAssociations = $this->query()
141
            ->indexBy('typeId')
142
            ->all();
143
144
        $associations = [];
145
        $order = 1;
146
147
        /** @var UserTypeAssociation $newAssociation */
148
        foreach ($this->getRelationships() as $newAssociation) {
149
            $association = ArrayHelper::remove(
150
                $existingAssociations,
151
                $newAssociation->getTypeId()
152
            );
153
154
            $newAssociation->sortOrder = $order++;
155
156
            /** @var UserTypeAssociation $association */
157
            $association = $association ?: $newAssociation;
158
159
            // Has anything changed?
160
            if (!$association->getIsNewRecord() && !$this->hasChanged($newAssociation, $association)) {
161
                continue;
162
            }
163
164
            $associations[] = $this->sync($association, $newAssociation);
165
        }
166
167
        return [$associations, $existingAssociations];
168
    }
169
170
    /**
171
     * @param UserTypeAssociation $new
172
     * @param UserTypeAssociation $existing
173
     * @return bool
174
     */
175
    private function hasChanged(UserTypeAssociation $new, UserTypeAssociation $existing): bool
176
    {
177
        return $new->sortOrder != $existing->sortOrder;
178
    }
179
180
    /**
181
     * @param UserTypeAssociation $from
182
     * @param UserTypeAssociation $to
183
     *
184
     * @return UserTypeAssociation
185
     */
186
    private function sync(
187
        UserTypeAssociation $to,
188
        UserTypeAssociation $from
189
    ): UserTypeAssociation {
190
        $to->sortOrder = $from->sortOrder;
191
192
        $to->ignoreSortOrder();
193
194
        return $to;
195
    }
196
197
    /*******************************************
198
     * COLLECTION UTILS
199
     *******************************************/
200
201
    /**
202
     * @inheritDoc
203
     */
204
    protected function insertCollection(Collection $collection, UserTypeAssociation $association)
205
    {
206
        if ($association->sortOrder > 0) {
207
            $collection->splice($association->sortOrder - 1, 0, [$association]);
208
            return;
209
        }
210
211
        $collection->push($association);
212
    }
213
214
    /**
215
     * @inheritDoc
216
     */
217
    protected function updateCollection(Collection $collection, UserAssociation $association)
218
    {
219
        if (null !== ($key = $this->findKey($association))) {
0 ignored issues
show
Documentation introduced by
$association is of type object<flipbox\organizat...ecords\UserAssociation>, but the function expects a object<flipbox\organizat...ype>|integer|array|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...
220
            $collection->offsetUnset($key);
221
        }
222
223
        $this->insertCollection($collection, $association);
0 ignored issues
show
Documentation introduced by
$association is of type object<flipbox\organizat...ecords\UserAssociation>, but the function expects a object<flipbox\organizat...ds\UserTypeAssociation>.

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...
224
    }
225
226
227
    /*******************************************
228
     * CACHE
229
     *******************************************/
230
231
    /**
232
     * @param array $associations
233
     * @return static
234
     */
235
    protected function newRelations(array $associations): self
236
    {
237
        $this->parentSetCache($associations);
238
        $this->syncToRelations();
239
240
        return $this;
241
    }
242
243
    /**
244
     * @param $association
245
     * @return static
246
     */
247
    protected function addToRelations($association): self
248
    {
249
        $this->parentAddToCache($association);
250
        $this->syncToRelations();
251
252
        return $this;
253
    }
254
255
    /**
256
     * @param int $key
257
     * @return static
258
     */
259
    protected function removeFromRelations(int $key): self
260
    {
261
        $this->parentRemoveFromCache($key);
262
        $this->syncToRelations();
263
264
        return $this;
265
    }
266
267
    /*******************************************
268
     * UTILS
269
     *******************************************/
270
271
    /**
272
     * @return $this
273
     */
274
    private function syncToRelations()
275
    {
276
        $this->association->populateRelation(
277
            'typeRecords',
278
            $this->getRelationships()->pluck('type')->all()
279
        );
280
        return $this;
281
    }
282
283
    /**
284
     * @param UserTypeAssociation|UserType|int|array|null $object
285
     * @return int|null
286
     */
287
    protected function findKey($object = null)
288
    {
289
        if ($object instanceof UserTypeAssociation) {
290
            return $this->findRelationshipKey($object->getTypeId());
291
        }
292
293
        if (null === ($type = $this->resolveObject($object))) {
294
            return null;
295
        }
296
297
        return $this->findRelationshipKey($type->id);
298
    }
299
300
    /**
301
     * @param $identifier
302
     * @return int|string|null
303
     */
304
    private function findRelationshipKey($identifier)
305
    {
306
        if (null === $identifier) {
307
            return null;
308
        }
309
310
        /** @var UserTypeAssociation $association */
311
        foreach ($this->getRelationships()->all() as $key => $association) {
312
            if ($association->getTypeId() == $identifier) {
313
                return $key;
314
            }
315
        }
316
317
        return null;
318
    }
319
320
    /**
321
     * @param UserTypeAssociation|UserType|int|array|null $type
322
     * @return UserType|null
323
     */
324
    protected function resolveObjectInternal($type)
325
    {
326
        if ($type instanceof UserTypeAssociation) {
327
            return $type->getType();
328
        }
329
330
        if ($type instanceof UserType) {
331
            return $type;
332
        }
333
334
        return UserType::findOne($type);
335
    }
336
}
337