Completed
Push — master ( b7e6d7...fe783a )
by Nate
10:27 queued 08:34
created

Users::find()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 7
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
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\services;
10
11
use Craft;
12
use craft\elements\db\UserQuery;
13
use craft\elements\User as UserElement;
14
use craft\helpers\ArrayHelper;
15
use flipbox\ember\services\traits\elements\Accessor;
16
use flipbox\organizations\db\OrganizationQuery;
17
use flipbox\organizations\elements\Organization as OrganizationElement;
18
use flipbox\organizations\Organizations as OrganizationPlugin;
19
use flipbox\organizations\records\UserAssociation;
20
use yii\base\Component;
21
use yii\base\InvalidConfigException;
22
23
/**
24
 * @author Flipbox Factory <[email protected]>
25
 * @since 1.0.0
26
 *
27
 * @method UserElement parentFind($identifier)
28
 */
29
class Users extends Component
30
{
31
    use Accessor {
32
        find as parentFind;
33
    }
34
35
    /**
36
     * @inheritdoc
37
     */
38
    public static function elementClass(): string
39
    {
40
        return UserElement::class;
41
    }
42
43
    /**
44
     * @param $identifier
45
     * @return array
46
     */
47
    protected function identifierCondition($identifier): array
48
    {
49
        $base = [
50
            'status' => null
51
        ];
52
53
        if (is_array($identifier)) {
54
            return array_merge($base, $identifier);
55
        }
56
57
        if (!is_numeric($identifier) && is_string($identifier)) {
58
            $base['where'] = [
59
                'or',
60
                ['username' => $identifier],
61
                ['email' => $identifier]
62
            ];
63
        } else {
64
            $base['id'] = $identifier;
65
        }
66
67
        return $base;
68
    }
69
70
    /**
71
     * @param mixed $user
72
     * @return UserElement
73
     * @throws InvalidConfigException
74
     */
75
    public function resolve($user = 'CURRENT_USER')
76
    {
77
        if (is_array($user) &&
78
            null !== ($id = ArrayHelper::getValue($user, 'id'))
79
        ) {
80
            return Craft::$app->getUsers()->getUserById($id);
81
        }
82
83
        if ($object = $this->find($user)) {
84
            return $object;
85
        }
86
87
        return $this->create($user);
88
    }
89
90
    /*******************************************
91
     * FIND
92
     *******************************************/
93
94
    /**
95
     * @param mixed $identifier
96
     * @return UserElement|null
97
     */
98
    public function find($identifier = 'CURRENT_USER')
99
    {
100
        if ('CURRENT_USER' === $identifier) {
101
            return Craft::$app->getUser()->getIdentity();
102
        }
103
104
        return $this->parentFind($identifier);
105
    }
106
107
    /**
108
     * @param OrganizationQuery $query
109
     * @param UserElement $user
110
     * @return bool
111
     * @throws \Exception
112
     */
113
    public function saveAssociations(
114
        OrganizationQuery $query,
115
        UserElement $user
116
    ): bool {
117
        /** @var UserElement[] $models */
118
        if (null === ($models = $query->getCachedResult())) {
119
            return true;
120
        }
121
122
        $models = $query->all();
123
124
        $associationService = OrganizationPlugin::getInstance()->getUserAssociations();
125
126
        $query = $associationService->getQuery([
127
            $associationService::SOURCE_ATTRIBUTE => $user->getId() ?: false
128
        ]);
129
130
        $query->setCachedResult(
131
            $this->toAssociations($models, $user->getId())
132
        );
133
134
        return $associationService->save($query);
135
    }
136
137
    /**
138
     * @param OrganizationQuery $query
139
     * @param UserElement $user
140
     * @return bool
141
     * @throws \Exception
142
     */
143
    public function dissociate(
144
        OrganizationQuery $query,
145
        UserElement $user
146
    ): bool {
147
        return $this->associations(
148
            $query,
149
            $user,
150
            [
151
                OrganizationPlugin::getInstance()->getUserAssociations(),
152
                'dissociate'
153
            ]
154
        );
155
    }
156
157
    /**
158
     * @param OrganizationQuery $query
159
     * @param UserElement $user
160
     * @return bool
161
     * @throws \Exception
162
     */
163
    public function associate(
164
        OrganizationQuery $query,
165
        UserElement $user
166
    ): bool {
167
        return $this->associations(
168
            $query,
169
            $user,
170
            [
171
                OrganizationPlugin::getInstance()->getUserAssociations(),
172
                'associate'
173
            ]
174
        );
175
    }
176
177
    /**
178
     * @param OrganizationQuery $query
179
     * @param UserElement $user
180
     * @param callable $callable
181
     * @return bool
182
     */
183
    protected function associations(
184
        OrganizationQuery $query,
185
        UserElement $user,
186
        callable $callable
187
    ) {
188
        /** @var UserElement[] $models */
189
        if (null === ($models = $query->getCachedResult())) {
190
            return true;
191
        }
192
193
        $models = ArrayHelper::index($models, 'id');
194
195
        $success = true;
196
        $ids = [];
197
        $count = count($models);
198
        $i = 0;
199
        foreach ($this->toAssociations($models, $user->getId()) as $association) {
200
            if (true === call_user_func_array($callable, [$association, ++$i === $count])) {
201
                ArrayHelper::remove($models, $association->userId);
202
                $ids[] = $association->userId;
203
                continue;
204
            }
205
206
            $success = false;
207
        }
208
209
        $query->id($ids);
210
211
        if ($success === false) {
212
            $query->setCachedResult($models);
213
        }
214
215
        return $success;
216
    }
217
218
    /**
219
     * @param OrganizationElement[] $organizations
220
     * @param int $userId
221
     * @return UserAssociation[]
222
     */
223
    private function toAssociations(
224
        array $organizations,
225
        int $userId
226
    ) {
227
        $associations = [];
228
        $sortOrder = 1;
229
230
        $associationService = OrganizationPlugin::getInstance()->getUserAssociations();
231
        $sortOrderAttribute = $associationService::SORT_ORDER_ATTRIBUTE;
232
233
        $existingAssociations = $associationService->findAllByCriteria([
234
            'where' => [
235
                $associationService::SOURCE_ATTRIBUTE => ArrayHelper::getColumn($organizations, 'id'),
236
                $associationService::TARGET_ATTRIBUTE => $userId,
237
            ],
238
            'indexBy' => $associationService::SOURCE_ATTRIBUTE
239
        ]);
240
241
        foreach ($organizations as $organization) {
242
            if (null === ($association = ArrayHelper::remove($existingAssociations, $organization->getId()))) {
243
                $association = $associationService->create([
244
                    'userId' => (int) $userId,
245
                    'organizationId' => (int) $organization->getId()
246
                ]);
247
            }
248
249
            $association->{$sortOrderAttribute} = $sortOrder++;
250
            $associations[] = $association;
251
        }
252
253
        return $associations;
254
    }
255
}
256