Completed
Push — develop ( 7ef839...356f72 )
by Nate
05:47
created

Organizations::dissociateUsers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

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