Completed
Push — develop ( 0f5a88...a06987 )
by Nate
04:58
created

UserRelationship::delta()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 0
cts 25
cp 0
rs 9.424
c 0
b 0
f 0
cc 4
nc 4
nop 0
crap 20
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\db\UserQuery;
12
use craft\elements\User;
13
use craft\helpers\ArrayHelper;
14
use craft\helpers\Json;
15
use flipbox\craft\ember\helpers\QueryHelper;
16
use flipbox\organizations\elements\Organization;
17
use flipbox\organizations\Organizations;
18
use flipbox\organizations\queries\UserAssociationQuery;
19
use flipbox\organizations\records\UserAssociation;
20
use Tightenco\Collect\Support\Collection;
21
22
/**
23
 * Manages Users associated to Organizations
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 UserRelationship 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 a collection of associated users
56
     *
57
     * @return User[]|Collection
58
     */
59
    public function getCollection(): Collection
60
    {
61
        return $this->getRelationships()
62
            ->sortBy('userOrder')
63
            ->pluck('user');
64
    }
65
66
    /**
67
     * @return Collection
68
     */
69
    protected function existingRelationships(): Collection
70
    {
71
        $relationships = $this->query()
72
            ->with('types')
73
            ->all();
74
75
        // 'eager' load where we'll pre-populate all of the associations
76
        $elements = User::find()
77
            ->id(array_keys($relationships))
78
            ->anyStatus()
79
            ->limit(null)
80
            ->indexBy('id')
81
            ->all();
82
83
        return (new Collection($relationships))
84
            ->transform(function (UserAssociation $association, $key) use ($elements) {
85
                if (isset($elements[$key])) {
86
                    $association->setUser($elements[$key]);
87
                    $association->setOrganization($this->organization);
88
                }
89
                return $association;
90
            });
91
    }
92
93
    /************************************************************
94
     * QUERY
95
     ************************************************************/
96
97
    /**
98
     * @return UserAssociationQuery
99
     */
100
    protected function query(): UserAssociationQuery
101
    {
102
        /** @noinspection PhpUndefinedMethodInspection */
103
        return UserAssociation::find()
104
            ->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...
105
            ->orderBy([
106
                'userOrder' => SORT_ASC
107
            ])
108
            ->limit(null)
109
            ->indexBy('userId');
110
    }
111
112
    /**
113
     * @param $object
114
     * @return UserAssociation
115
     */
116
    protected function create($object): UserAssociation
117
    {
118
        return (new UserAssociation())
119
            ->setOrganization($this->organization)
120
            ->setUser($this->resolve($object));
121
    }
122
123
124
    /*******************************************
125
     * SAVE
126
     *******************************************/
127
128
    /**
129
     * @inheritDoc
130
     */
131
    protected function delta(): array
132
    {
133
        $existingAssociations = $this->query()
134
            ->indexBy('userId')
135
            ->all();
136
137
        $associations = [];
138
        $order = 1;
139
        /** @var UserAssociation $newAssociation */
140
        foreach ($this->getRelationships()->sortBy('userOrder') as $newAssociation) {
141
            if (null === ($association = ArrayHelper::remove(
142
                    $existingAssociations,
143
                    $newAssociation->getUserId()
144
                ))) {
145
                $association = $newAssociation;
146
            } elseif ($newAssociation->getTypes()->isMutated()) {
147
                /** @var UserAssociation $association */
148
                $association->getTypes()->clear()->add(
149
                    $newAssociation->getTypes()->getCollection()
150
                );
151
            }
152
153
            $association->userOrder = $order++;
154
            $association->organizationOrder = $newAssociation->organizationOrder;
155
            $association->state = $newAssociation->state;
156
157
            $associations[] = $association;
158
        }
159
160
        return [$associations, $existingAssociations];
161
    }
162
163
    /**
164
     * @inheritDoc
165
     */
166
    protected function handleAssociationError()
167
    {
168
        $this->organization->addError('users', 'Unable to save user organizations.');
169
    }
170
171
172
    /*******************************************
173
     * UTILS
174
     *******************************************/
175
176
    /**
177
     * @param UserAssociation|User|int|array|null $object
178
     * @return int|null
179
     */
180
    protected function findKey($object = null)
181
    {
182
        if (null === ($element = $this->resolve($object))) {
183
            Organizations::info(sprintf(
184
                "Unable to resolve user: %s",
185
                (string)Json::encode($object)
186
            ));
187
            return null;
188
        }
189
190
        /** @var UserAssociation $association */
191
        foreach ($this->getRelationships()->all() as $key => $association) {
192
            if (null !== $association->getUser() && $association->getUser()->email == $element->email) {
193
                return $key;
194
            }
195
        }
196
197
        return null;
198
    }
199
200
    /**
201
     * @param UserAssociation|User|int|array|null $user
202
     * @return User|null
203
     */
204
    protected function resolveObject($user)
205
    {
206
        if ($user instanceof UserAssociation) {
207
            return $user->getUser();
208
        }
209
210
        if ($user instanceof User) {
211
            return $user;
212
        }
213
214
        return User::findOne($user);
215
    }
216
}
217