Completed
Push — develop ( bcbf28...a87a8b )
by Nate
03:33
created

OrganizationRelationship::elementQuery()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 0
cts 7
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 1
nop 0
crap 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\relationships;
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\OrganizationQuery;
18
use flipbox\organizations\queries\UserAssociationQuery;
19
use flipbox\organizations\records\UserAssociation;
20
use Tightenco\Collect\Support\Collection;
21
22
/**
23
 * Manages Organizations associated to Users
24
 *
25
 * @author Flipbox Factory <[email protected]>
26
 * @since 2.0.0
27
 * *
28
 * @method UserAssociation findOrCreate($object)
29
 * @method UserAssociation findOne($object = null)
30
 * @method UserAssociation findOrFail($object)
31
 */
32
class OrganizationRelationship implements RelationshipInterface
33
{
34
    use RelationshipTrait;
35
36
    /**
37
     * @var User
38
     */
39
    private $user;
40
41
    /**
42
     * @param User $user
43
     */
44
    public function __construct(User $user)
45
    {
46
        $this->user = $user;
47
    }
48
49
50
    /************************************************************
51
     * COLLECTION
52
     ************************************************************/
53
54
    /**
55
     * @inheritDoc
56
     * @return Organization[]|Collection
57
     */
58
    public function getCollection(): Collection
59
    {
60
        if (null === $this->relations) {
61
            return new Collection(
62
                $this->elementQuery()
63
                    ->all()
64
            );
65
        }
66
67
        return $this->getRelationships()
68
            ->sortBy('organizationOrder')
69
            ->pluck('organization');
70
    }
71
72
    /**
73
     * @inheritDoc
74
     * @return Collection
75
     */
76
    protected function existingRelationships(): Collection
77
    {
78
        $relationships = $this->associationQuery()
79
            ->with('types')
80
            ->all();
81
82
        // 'eager' load where we'll pre-populate all of the associations
83
        $elements = $this->elementQuery()
84
            ->id(array_keys($relationships))
85
            ->indexBy('id')
86
            ->all();
87
88
        return $this->createRelations($relationships)
89
            ->transform(function (UserAssociation $association) use ($elements) {
90
                if (isset($elements[$association->getOrganizationId()])) {
91
                    $association->setOrganization($elements[$association->getOrganizationId()]);
92
                }
93
94
                $association->setUser($this->user);
95
96
                return $association;
97
            });
98
    }
99
100
    /************************************************************
101
     * QUERY
102
     ************************************************************/
103
104
    /**
105
     * @return OrganizationQuery
106
     */
107
    protected function elementQuery(): OrganizationQuery
108
    {
109
        return Organization::find()
110
            ->userId($this->user->getId() ?: false)
0 ignored issues
show
Security Bug introduced by
It seems like $this->user->getId() ?: false can also be of type false; however, flipbox\craft\ember\quer...ttributeTrait::userId() does only seem to accept string|array<integer,str...ft\elements\User>>|null, did you maybe forget to handle an error condition?
Loading history...
111
            ->anyStatus()
112
            ->limit(null);
113
    }
114
115
    /**
116
     * @return UserAssociationQuery
117
     */
118
    protected function associationQuery(): UserAssociationQuery
119
    {
120
        return UserAssociation::find()
121
            ->setUserId($this->user->getId() ?: false)
0 ignored issues
show
Security Bug introduced by
It seems like $this->user->getId() ?: false can also be of type false; however, flipbox\craft\ember\quer...ibuteTrait::setUserId() does only seem to accept string|array<integer,str...ft\elements\User>>|null, did you maybe forget to handle an error condition?
Loading history...
122
            ->orderBy([
123
                'organizationOrder' => SORT_ASC
124
            ])
125
            ->limit(null);
126
    }
127
128
129
    /************************************************************
130
     * CREATE
131
     ************************************************************/
132
133
    /**
134
     * @param $object
135
     * @return UserAssociation
136
     */
137
    protected function create($object): UserAssociation
138
    {
139
        if ($object instanceof UserAssociation) {
140
            return $object;
141
        }
142
143
        return (new UserAssociation())
144
            ->setOrganization($this->resolveObject($object))
145
            ->setUser($this->user);
146
    }
147
148
149
    /*******************************************
150
     * DELTA
151
     *******************************************/
152
153
    /**
154
     * @inheritDoc
155
     */
156
    protected function delta(): array
157
    {
158
        $existingAssociations = $this->associationQuery()
159
            ->indexBy('organizationId')
160
            ->all();
161
162
        $associations = [];
163
        $order = 1;
164
165
        /** @var UserAssociation $newAssociation */
166
        foreach ($this->getRelationships() as $newAssociation) {
167
            if (null === ($association = ArrayHelper::remove(
168
                $existingAssociations,
169
                $newAssociation->getOrganizationId()
170
            ))) {
171
                $association = $newAssociation;
172
            } elseif ($newAssociation->getTypes()->isMutated()) {
173
                /** @var UserAssociation $association */
174
                $association->getTypes()->clear()->add(
175
                    $newAssociation->getTypes()->getCollection()
176
                );
177
            }
178
179
            $association->userOrder = $newAssociation->userOrder;
180
            $association->organizationOrder = $order++;
181
            $association->state = $newAssociation->state;
182
183
            $association->ignoreSortOrder();
184
185
            $associations[] = $association;
186
        }
187
188
        return [$associations, $existingAssociations];
189
    }
190
191
    /*******************************************
192
     * COLLECTION
193
     *******************************************/
194
195
    /**
196
     * Position the relationship based on the sort order
197
     *
198
     * @inheritDoc
199
     */
200
    protected function insertCollection(Collection $collection, UserAssociation $association)
201
    {
202
        if ($association->organizationOrder > 0) {
203
            $collection->splice($association->organizationOrder - 1, 0, [$association]);
204
            return;
205
        }
206
207
        $collection->push($association);
208
    }
209
210
    /**
211
     * Reposition the relationship based on the sort order
212
     *
213
     * @inheritDoc
214
     */
215
    protected function updateCollection(Collection $collection, UserAssociation $association)
216
    {
217
        if ($key = $this->findKey($association)) {
218
            $collection->offsetUnset($key);
219
        }
220
221
        $this->insertCollection($collection, $association);
222
    }
223
224
225
    /*******************************************
226
     * UTILS
227
     *******************************************/
228
229
    /**
230
     * @param UserAssociation|Organization|int|array|null $object
231
     * @return int|null
232
     */
233
    protected function findKey($object = null)
234
    {
235
        if ($object instanceof UserAssociation) {
236
            return $this->findRelationshipKey($object->getOrganizationId());
237
        }
238
239
        if (null === ($element = $this->resolveObject($object))) {
240
            return null;
241
        }
242
243
        return $this->findRelationshipKey($element->getId());
244
    }
245
246
    /**
247
     * @param $identifier
248
     * @return int|string|null
249
     */
250
    protected function findRelationshipKey($identifier)
251
    {
252
        /** @var UserAssociation $association */
253
        foreach ($this->getRelationships()->all() as $key => $association) {
254
            if ($association->getOrganizationId() == $identifier) {
255
                return $key;
256
            }
257
        }
258
259
        return null;
260
    }
261
262
    /**
263
     * @param UserAssociation|Organization|int|array $organization
264
     * @return Organization|null
265
     */
266
    protected function resolveObjectInternal($organization)
267
    {
268
        if ($organization instanceof UserAssociation) {
269
            return $organization->getOrganization();
270
        }
271
272
        if ($organization instanceof Organization) {
273
            return $organization;
274
        }
275
276
        return Organization::findOne($organization);
277
    }
278
}
279