Completed
Push — master ( 67ce08...91cbf1 )
by Nate
05:42
created

OrganizationTypes::handleOldFieldLayout()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 0
cts 10
cp 0
rs 9.2
c 0
b 0
f 0
cc 4
eloc 6
nc 2
nop 2
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\services;
10
11
use Craft;
12
use craft\helpers\ArrayHelper;
13
use craft\models\FieldLayout;
14
use flipbox\ember\helpers\ObjectHelper;
15
use flipbox\ember\services\traits\records\AccessorByString;
16
use flipbox\organizations\db\OrganizationTypeQuery;
17
use flipbox\organizations\elements\Organization as OrganizationElement;
18
use flipbox\organizations\Organizations as OrganizationPlugin;
19
use flipbox\organizations\records\OrganizationType;
20
use flipbox\organizations\records\OrganizationType as TypeRecord;
21
use flipbox\organizations\records\OrganizationTypeAssociation;
22
use yii\base\Component;
23
use yii\base\Exception;
24
25
/**
26
 * @author Flipbox Factory <[email protected]>
27
 * @since 1.0.0
28
 *
29
 * @method OrganizationTypeQuery getQuery($config = []): ActiveQuery
30
 * @method TypeRecord create(array $attributes = [], string $toScenario = null)
31
 * @method TypeRecord find($identifier, string $toScenario = null)
32
 * @method TypeRecord get($identifier, string $toScenario = null)
33
 * @method TypeRecord findByString($identifier, string $toScenario = null)
34
 * @method TypeRecord getByString($identifier, string $toScenario = null)
35
 * @method TypeRecord findByCondition($condition = [], string $toScenario = null)
36
 * @method TypeRecord getByCondition($condition = [], string $toScenario = null)
37
 * @method TypeRecord findByCriteria($criteria = [], string $toScenario = null)
38
 * @method TypeRecord getByCriteria($criteria = [], string $toScenario = null)
39
 * @method TypeRecord[] findAllByCondition($condition = [], string $toScenario = null)
40
 * @method TypeRecord[] getAllByCondition($condition = [], string $toScenario = null)
41
 * @method TypeRecord[] findAllByCriteria($criteria = [], string $toScenario = null)
42
 * @method TypeRecord[] getAllByCriteria($criteria = [], string $toScenario = null)
43
 */
44
class OrganizationTypes extends Component
45
{
46
    use AccessorByString;
47
48
    /**
49
     * @inheritdoc
50
     */
51
    public static function recordClass(): string
52
    {
53
        return TypeRecord::class;
54
    }
55
56
    /**
57
     * @return string
58
     */
59
    protected function stringProperty(): string
60
    {
61
        return 'handle';
62
    }
63
64
    /*******************************************
65
     * RESOLVE
66
     *******************************************/
67
68
    /**
69
     * @param mixed $type
70
     * @return TypeRecord
71
     */
72
    public function resolve($type): TypeRecord
73
    {
74
        if ($type = $this->find($type)) {
75
            return $type;
76
        }
77
78
        $type = ArrayHelper::toArray($type, [], false);
79
80
        try {
81
            $object = $this->create($type);
82
        } catch (\Exception $e) {
83
            $object = new TypeRecord();
84
            ObjectHelper::populate(
85
                $object,
86
                $type
87
            );
88
        }
89
90
        return $object;
91
    }
92
93
94
    /**
95
     * @param TypeRecord|null $type
96
     * @return TypeRecord|null
97
     */
98
    public static function resolveFromRequest(TypeRecord $type = null)
99
    {
100
        if ($identifier = Craft::$app->getRequest()->getParam('type')) {
101
            return OrganizationPlugin::getInstance()->getOrganizationTypes()->get($identifier);
102
        }
103
104
        if ($type instanceof TypeRecord) {
105
            return $type;
106
        }
107
108
        return null;
109
    }
110
111
    /**
112
     * @param array $config
113
     * @return array
114
     */
115
    protected function prepareQueryConfig($config = [])
116
    {
117
        $config['with'] = ['siteSettingRecords'];
118
        return $config;
119
    }
120
121
    /*******************************************
122
     * BEFORE/AFTER SAVE
123
     *******************************************/
124
125
    /**
126
     * @param TypeRecord $type
127
     * @return bool
128
     * @throws Exception
129
     */
130
    public function beforeSave(TypeRecord $type): bool
131
    {
132
        $fieldLayout = $type->getFieldLayout();
133
134
        $this->handleOldFieldLayout($type, $fieldLayout);
135
136
        if ($fieldLayout === null || $fieldLayout->id == $this->getDefaultFieldLayoutId()) {
137
            return true;
138
        }
139
140
        if (!Craft::$app->getFields()->saveLayout($fieldLayout)) {
141
            return false;
142
        }
143
144
        return true;
145
    }
146
147
    /**
148
     * @param TypeRecord $type
149
     * @param FieldLayout|null $fieldLayout
150
     */
151
    private function handleOldFieldLayout(TypeRecord $type, FieldLayout $fieldLayout = null)
152
    {
153
        $oldFieldLayoutId = (int) $type->getOldAttribute('fieldLayoutId');
154
155
        if ($oldFieldLayoutId !== null &&
156
            $oldFieldLayoutId != $fieldLayout->id &&
157
            $oldFieldLayoutId != $this->getDefaultFieldLayoutId()
158
        ) {
159
            Craft::$app->getFields()->deleteLayoutById($oldFieldLayoutId);
160
        }
161
    }
162
163
    /**
164
     * @return int
165
     */
166
    private function getDefaultFieldLayoutId(): int
167
    {
168
        return (int) OrganizationPlugin::getInstance()->getSettings()->getFieldLayout()->id;
169
    }
170
171
    /**
172
     * @param TypeRecord $type
173
     * @throws Exception
174
     * @throws \Exception
175
     * @throws \Throwable
176
     * @throws \yii\db\StaleObjectException
177
     */
178
    public function afterSave(TypeRecord $type)
179
    {
180
        if (!OrganizationPlugin::getInstance()->getOrganizationTypeSettings()->saveByType($type)) {
181
            throw new Exception("Unable to save site settings");
182
        };
183
    }
184
185
    /**
186
     * @param OrganizationTypeQuery $query
187
     * @param OrganizationElement $organization
188
     * @return bool
189
     * @throws \Exception
190
     */
191
    public function saveAssociations(
192
        OrganizationTypeQuery $query,
193
        OrganizationElement $organization
194
    ): bool {
195
        if (null === ($models = $query->getCachedResult())) {
196
            return true;
197
        }
198
199
        $associationService = OrganizationPlugin::getInstance()->getOrganizationTypeAssociations();
200
201
        $query = $associationService->getQuery([
202
            $associationService::SOURCE_ATTRIBUTE => $organization->getId() ?: false
203
        ]);
204
205
        $query->setCachedResult(
206
            $this->toAssociations($models, $organization->getId())
207
        );
208
209
        return $associationService->save($query);
210
    }
211
212
    /**
213
     * @param OrganizationTypeQuery $query
214
     * @param OrganizationElement $organization
215
     * @return bool
216
     * @throws \Exception
217
     */
218
    public function dissociate(
219
        OrganizationTypeQuery $query,
220
        OrganizationElement $organization
221
    ): bool {
222
        return $this->associations(
223
            $query,
224
            $organization,
225
            [
226
                OrganizationPlugin::getInstance()->getOrganizationTypeAssociations(),
227
                'dissociate'
228
            ]
229
        );
230
    }
231
232
    /**
233
     * @param OrganizationTypeQuery $query
234
     * @param OrganizationElement $organization
235
     * @return bool
236
     * @throws \Exception
237
     */
238
    public function associate(
239
        OrganizationTypeQuery $query,
240
        OrganizationElement $organization
241
    ): bool {
242
        return $this->associations(
243
            $query,
244
            $organization,
245
            [
246
                OrganizationPlugin::getInstance()->getOrganizationTypeAssociations(),
247
                'associate'
248
            ]
249
        );
250
    }
251
252
    /**
253
     * @param OrganizationTypeQuery $query
254
     * @param OrganizationElement $organization
255
     * @param callable $callable
256
     * @return bool
257
     */
258
    protected function associations(OrganizationTypeQuery $query, OrganizationElement $organization, callable $callable)
259
    {
260
        if (null === ($models = $query->getCachedResult())) {
261
            return true;
262
        }
263
264
        $models = ArrayHelper::index($models, 'id');
265
266
        $success = true;
267
        $ids = [];
268
        $count = count($models);
269
        $i = 0;
270
        foreach ($this->toAssociations($models, $organization->getId()) as $association) {
271
            if (true === call_user_func_array($callable, [$association, ++$i === $count])) {
272
                ArrayHelper::remove($models, $association->typeId);
273
                $ids[] = $association->typeId;
274
                continue;
275
            }
276
277
            $success = false;
278
        }
279
280
        $query->organizationTypeId($ids);
281
282
        if ($success === false) {
283
            $query->setCachedResult($models);
284
        }
285
286
        return $success;
287
    }
288
289
    /**
290
     * @param OrganizationType[] $types
291
     * @param int $organizationId
292
     * @return OrganizationTypeAssociation[]
293
     */
294
    private function toAssociations(
295
        array $types,
296
        int $organizationId
297
    ) {
298
        $associations = [];
299
        $sortOrder = 1;
300
        foreach ($types as $type) {
301
            $associations[] = new OrganizationTypeAssociation([
302
                'organizationId' => $organizationId,
303
                'typeId' => $type->id,
304
                'sortOrder' => $sortOrder++
305
            ]);
306
        }
307
308
        return $associations;
309
    }
310
}
311