Completed
Push — master ( 5d951f...f67c03 )
by Nate
13:58 queued 11:06
created

Organizations::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

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 1
eloc 5
nc 1
nop 0
crap 2
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
    public function init()
40
    {
41
        $settings = OrganizationPlugin::getInstance()->getSettings();
42
        $this->cacheDuration = $settings->organizationsCacheDuration;
43
        $this->cacheDependency = $settings->organizationsCacheDependency;
44
45
        parent::init();
46
    }
47
48
    /**
49
     * @inheritdoc
50
     */
51
    public static function elementClass(): string
52
    {
53
        return OrganizationElement::class;
54
    }
55
56
    /**
57
     * @param $identifier
58
     * @param int|null $siteId
59
     * @return array
60
     */
61
    protected function identifierCondition($identifier, int $siteId = null): array
62
    {
63
        $base = [
64
            'siteId' => SiteHelper::ensureSiteId($siteId),
65
            'status' => null
66
        ];
67
68
        if (is_array($identifier)) {
69
            return array_merge($base, $identifier);
70
        }
71
72
        if (!is_numeric($identifier) && is_string($identifier)) {
73
            $base['slug'] = $identifier;
74
        } else {
75
            $base['id'] = $identifier;
76
        }
77
78
        return $base;
79
    }
80
81
    /**
82
     * @param mixed $organization
83
     * @return OrganizationElement
84
     */
85
    public function resolve($organization)
86
    {
87
        if (is_array($organization) &&
88
            null !== ($id = ArrayHelper::getValue($organization, 'id'))
89
        ) {
90
            return $this->get($id);
91
        }
92
93
        if ($object = $this->find($organization)) {
94
            return $object;
95
        }
96
97
        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
    public function dissociate(
137
        UserQuery $query,
138
        OrganizationElement $organization
139
    ): bool {
140
        return $this->associations(
141
            $query,
142
            $organization,
143
            [
144
                OrganizationPlugin::getInstance()->getOrganizationUserAssociations(),
145
                'dissociate'
146
            ]
147
        );
148
    }
149
150
    /**
151
     * @param UserQuery $query
152
     * @param OrganizationElement $organization
153
     * @return bool
154
     * @throws \Exception
155
     */
156
    public function associate(
157
        UserQuery $query,
158
        OrganizationElement $organization
159
    ): bool {
160
        return $this->associations(
161
            $query,
162
            $organization,
163
            [
164
                OrganizationPlugin::getInstance()->getOrganizationUserAssociations(),
165
                'associate'
166
            ]
167
        );
168
    }
169
170
    /**
171
     * @param UserQuery $query
172
     * @param OrganizationElement $organization
173
     * @param callable $callable
174
     * @return bool
175
     */
176
    protected function associations(UserQuery $query, OrganizationElement $organization, callable $callable)
177
    {
178
        /** @var UserElement[] $models */
179
        if (null === ($models = $query->getCachedResult())) {
180
            return true;
181
        }
182
183
        $models = ArrayHelper::index($models, 'id');
184
185
        $success = true;
186
        $ids = [];
187
        $count = count($models);
188
        $i = 0;
189
        foreach ($this->toAssociations($models, $organization->getId()) as $association) {
190
            if (true === call_user_func_array($callable, [$association, ++$i === $count])) {
191
                ArrayHelper::remove($models, $association->userId);
192
                $ids[] = $association->userId;
193
                continue;
194
            }
195
196
            $success = false;
197
        }
198
199
        $query->id($ids);
200
201
        if ($success === false) {
202
            $query->setCachedResult($models);
203
        }
204
205
        return $success;
206
    }
207
208
    /**
209
     * @param UserElement[] $users
210
     * @param int $organizationId
211
     * @return UserAssociation[]
212
     */
213
    private function toAssociations(
214
        array $users,
215
        int $organizationId
216
    ) {
217
        $associations = [];
218
        $sortOrder = 1;
219
220
        $associationService = OrganizationPlugin::getInstance()->getOrganizationUserAssociations();
221
        $sortOrderAttribute = $associationService::SORT_ORDER_ATTRIBUTE;
222
223
        $existingAssociations = $associationService->findAllByCriteria([
224
            'where' => [
225
                $associationService::TARGET_ATTRIBUTE => ArrayHelper::getColumn($users, 'id'),
226
                $associationService::SOURCE_ATTRIBUTE => $organizationId,
227
            ],
228
            'indexBy' => $associationService::TARGET_ATTRIBUTE
229
        ]);
230
231
        foreach ($users as $user) {
232
            if (null === ($association = ArrayHelper::remove($existingAssociations, $user->getId()))) {
233
                $association = $associationService->create([
234
                    'userId' => (int)$user->getId(),
235
                    'organizationId' => (int)$organizationId
236
                ]);
237
            }
238
239
            $association->{$sortOrderAttribute} = $sortOrder++;
240
            $associations[] = $association;
241
        }
242
243
        return $associations;
244
    }
245
246
    /*******************************************
247
     * EXCEPTIONS
248
     *******************************************/
249
250
    /**
251
     * @throws RecordNotFoundException
252
     */
253
    protected function recordNotFoundException()
254
    {
255
        throw new RecordNotFoundException('Record does not exist.');
256
    }
257
}
258