OrganizationTypeRelationship   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 234
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 28
lcom 1
cbo 7
dl 0
loc 234
ccs 0
cts 115
cp 0
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A existingRelationships() 0 8 1
A query() 0 9 2
A __construct() 0 4 1
A getCollection() 0 5 1
A create() 0 10 2
A delta() 0 31 5
A hasChanged() 0 4 1
A sync() 0 10 1
A insertCollection() 0 9 2
A updateCollection() 0 8 2
A findKey() 0 12 3
A findRelationshipKey() 0 15 4
A resolveObjectInternal() 0 12 3
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\elements\Organization;
15
use flipbox\organizations\Organizations;
16
use flipbox\organizations\queries\OrganizationTypeAssociationQuery;
17
use flipbox\organizations\records\OrganizationType;
18
use flipbox\organizations\records\OrganizationTypeAssociation;
19
use flipbox\organizations\records\UserAssociation;
20
use Tightenco\Collect\Support\Collection;
21
22
/**
23
 * Manages Organization Types associated to Organizations
24
 *
25
 * @author Flipbox Factory <[email protected]>
26
 * @since 2.0.0
27
 *
28
 * @method OrganizationTypeAssociation findOrCreate($object)
29
 * @method OrganizationTypeAssociation findOne($object = null)
30
 * @method OrganizationTypeAssociation findOrFail($object)
31
 */
32
class OrganizationTypeRelationship implements RelationshipInterface
33
{
34
    use RelationshipTrait;
35
36
    /**
37
     * @var Organization
38
     */
39
    private $organization;
40
41
    /**
42
     * @param Organization $organization
43
     */
44
    public function __construct(Organization $organization)
45
    {
46
        $this->organization = $organization;
47
    }
48
49
50
    /************************************************************
51
     * COLLECTION
52
     ************************************************************/
53
54
    /**
55
     * Get an array of types associated to an organization
56
     *
57
     * @return OrganizationType[]|Collection
58
     */
59
    public function getCollection(): Collection
60
    {
61
        return $this->getRelationships()
62
            ->pluck('type');
63
    }
64
65
    /**
66
     * @return Collection
67
     */
68
    protected function existingRelationships(): Collection
69
    {
70
        return $this->createRelations(
71
            $this->query()
72
                ->with('typeRecord')
73
                ->all()
74
        );
75
    }
76
77
78
    /************************************************************
79
     * QUERY
80
     ************************************************************/
81
82
    /**
83
     * @return OrganizationTypeAssociationQuery
84
     */
85
    private function query(): OrganizationTypeAssociationQuery
86
    {
87
        return OrganizationTypeAssociation::find()
88
            ->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...
89
            ->orderBy([
90
                'sortOrder' => SORT_ASC
91
            ])
92
            ->limit(null);
93
    }
94
95
    /**
96
     * @param OrganizationTypeAssociation|OrganizationType|int|string $type
97
     * @return OrganizationTypeAssociation
98
     */
99
    protected function create($type): OrganizationTypeAssociation
100
    {
101
        if ($type instanceof OrganizationTypeAssociation) {
102
            return $type;
103
        }
104
105
        return (new OrganizationTypeAssociation())
106
            ->setOrganization($this->organization)
107
            ->setType($this->resolveObject($type));
108
    }
109
110
111
    /*******************************************
112
     * SAVE
113
     *******************************************/
114
115
    /**
116
     * @inheritDoc
117
     */
118
    protected function delta(): array
119
    {
120
        $existingAssociations = $this->query()
121
            ->indexBy('typeId')
122
            ->all();
123
124
        $associations = [];
125
        $order = 1;
126
127
        /** @var OrganizationTypeAssociation $newAssociation */
128
        foreach ($this->getRelationships() as $newAssociation) {
129
            $association = ArrayHelper::remove(
130
                $existingAssociations,
131
                $newAssociation->getTypeId()
132
            );
133
134
            $newAssociation->sortOrder = $order++;
135
136
            /** @var OrganizationTypeAssociation $association */
137
            $association = $association ?: $newAssociation;
138
139
            // Has anything changed?
140
            if (!$association->getIsNewRecord() && !$this->hasChanged($newAssociation, $association)) {
141
                continue;
142
            }
143
144
            $associations[] = $this->sync($association, $newAssociation);
145
        }
146
147
        return [$associations, $existingAssociations];
148
    }
149
150
    /**
151
     * @param OrganizationTypeAssociation $new
152
     * @param OrganizationTypeAssociation $existing
153
     * @return bool
154
     */
155
    private function hasChanged(OrganizationTypeAssociation $new, OrganizationTypeAssociation $existing): bool
156
    {
157
        return $new->sortOrder != $existing->sortOrder;
158
    }
159
160
    /**
161
     * @param OrganizationTypeAssociation $from
162
     * @param OrganizationTypeAssociation $to
163
     *
164
     * @return OrganizationTypeAssociation
165
     */
166
    private function sync(
167
        OrganizationTypeAssociation $to,
168
        OrganizationTypeAssociation $from
169
    ): OrganizationTypeAssociation {
170
        $to->sortOrder = $from->sortOrder;
171
172
        $to->ignoreSortOrder();
173
174
        return $to;
175
    }
176
177
178
    /*******************************************
179
     * COLLECTION UTILS
180
     *******************************************/
181
182
    /**
183
     * @inheritDoc
184
     */
185
    protected function insertCollection(Collection $collection, OrganizationTypeAssociation $association)
186
    {
187
        if ($association->sortOrder > 0) {
188
            $collection->splice($association->sortOrder - 1, 0, [$association]);
189
            return;
190
        }
191
192
        $collection->push($association);
193
    }
194
195
    /**
196
     * @inheritDoc
197
     */
198
    protected function updateCollection(Collection $collection, OrganizationTypeAssociation $association)
199
    {
200
        if (null !== ($key = $this->findKey($association))) {
201
            $collection->offsetUnset($key);
202
        }
203
204
        $this->insertCollection($collection, $association);
205
    }
206
207
208
    /*******************************************
209
     * UTILS
210
     *******************************************/
211
212
    /**
213
     * @param OrganizationTypeAssociation|OrganizationType|int|array|null $object
214
     * @return int|null
215
     */
216
    protected function findKey($object = null)
217
    {
218
        if ($object instanceof OrganizationTypeAssociation) {
219
            return $this->findRelationshipKey($object->getTypeId());
220
        }
221
222
        if (null === ($type = $this->resolveObject($object))) {
223
            return null;
224
        }
225
226
        return $this->findRelationshipKey($type->id);
227
    }
228
229
    /**
230
     * @param $identifier
231
     * @return int|string|null
232
     */
233
    protected function findRelationshipKey($identifier)
234
    {
235
        if (null === $identifier) {
236
            return null;
237
        }
238
239
        /** @var OrganizationTypeAssociation $association */
240
        foreach ($this->getRelationships()->all() as $key => $association) {
241
            if ($association->getTypeId() == $identifier) {
242
                return $key;
243
            }
244
        }
245
246
        return null;
247
    }
248
249
    /**
250
     * @param OrganizationTypeAssociation|OrganizationType|int|array $type
251
     * @return OrganizationType|null
252
     */
253
    protected function resolveObjectInternal($type)
254
    {
255
        if ($type instanceof OrganizationTypeAssociation) {
256
            return $type->getType();
257
        }
258
259
        if ($type instanceof OrganizationType) {
260
            return $type;
261
        }
262
263
        return OrganizationType::findOne($type);
264
    }
265
}
266