Domains   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 254
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 9

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 27
lcom 2
cbo 9
dl 0
loc 254
ccs 0
cts 150
cp 0
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A displayName() 0 4 1
A getStatuses() 0 8 1
A hasContentColumn() 0 4 1
A getElementValidationRules() 0 23 3
A getSearchKeywords() 0 10 2
A getSettingsHtml() 0 10 1
A getInputHtml() 0 4 1
A inputHtml() 0 38 3
C afterElementSave() 0 70 14
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/domains/license
6
 * @link       https://www.flipboxfactory.com/software/domains/
7
 */
8
9
namespace flipbox\craft\domains\fields;
10
11
use Craft;
12
use craft\base\ElementInterface;
13
use craft\base\Field;
14
use craft\base\FieldInterface;
15
use craft\helpers\ArrayHelper;
16
use flipbox\craft\ember\validators\MinMaxValidator;
17
use flipbox\craft\domains\queries\DomainsQuery;
18
use flipbox\craft\domains\records\Domain;
19
use flipbox\craft\domains\validators\DomainsValidator;
20
use yii\base\Exception;
21
22
/**
23
 * @author Flipbox Factory <[email protected]>
24
 * @since 1.0.0
25
 */
26
class Domains extends Field implements FieldInterface
27
{
28
    use NormalizeValueTrait,
29
        ModifyElementsQueryTrait;
30
31
    /**
32
     * @var bool
33
     */
34
    public $unique = true;
35
36
    /**
37
     * @var int|null
38
     */
39
    public $min;
40
41
    /**
42
     * @var int|null
43
     */
44
    public $max;
45
46
    /**
47
     * @var string
48
     */
49
    public $defaultStatus = 'pending';
50
51
    /**
52
     * @inheritdoc
53
     */
54
    public static function displayName(): string
55
    {
56
        return Craft::t('domains', 'Domains');
57
    }
58
59
    /**
60
     * @return array
61
     */
62
    public static function getStatuses(): array
63
    {
64
        return [
65
            'enabled' => Craft::t('domains', 'Enabled'),
66
            'pending' => Craft::t('domains', 'Pending'),
67
            'disabled' => Craft::t('domains', 'Disabled')
68
        ];
69
    }
70
71
    /**
72
     * @inheritdoc
73
     */
74
    public static function hasContentColumn(): bool
75
    {
76
        return false;
77
    }
78
79
    /**
80
     * @inheritdoc
81
     */
82
    public function getElementValidationRules(): array
83
    {
84
        return [
85
            [
86
                DomainsValidator::class,
87
                'field' => $this
88
            ],
89
            [
90
                MinMaxValidator::class,
91
                'min' => $this->min ? (int)$this->min : null,
92
                'max' => $this->max ? (int)$this->max : null,
93
                'tooFew' => Craft::t(
94
                    'domains',
95
                    '{attribute} should contain at least {min, number} {min, plural, one{domain} other{domains}}.'
96
                ),
97
                'tooMany' => Craft::t(
98
                    'domains',
99
                    '{attribute} should contain at most {max, number} {max, plural, one{domain} other{domains}}.'
100
                ),
101
                'skipOnEmpty' => false
102
            ]
103
        ];
104
    }
105
106
    /**
107
     * @param DomainsQuery $value
108
     * @inheritdoc
109
     */
110
    public function getSearchKeywords($value, ElementInterface $element): string
111
    {
112
        $domains = [];
113
114
        foreach ($value->all() as $association) {
115
            array_push($domains, $association->domain);
116
        }
117
118
        return parent::getSearchKeywords($domains, $element);
119
    }
120
121
122
    /*******************************************
123
     * VIEWS
124
     *******************************************/
125
126
    /**
127
     * @inheritdoc
128
     * @throws \Twig_Error_Loader
129
     * @throws \yii\base\Exception
130
     */
131
    public function getSettingsHtml()
132
    {
133
134
        return Craft::$app->getView()->renderTemplate(
135
            'domains/_components/fieldtypes/Domains/settings',
136
            [
137
                'field' => $this
138
            ]
139
        );
140
    }
141
142
    /**
143
     * @inheritdoc
144
     * @param DomainsQuery $value
145
     * @throws \Twig_Error_Loader
146
     * @throws \yii\base\Exception
147
     */
148
    public function getInputHtml($value, ElementInterface $element = null): string
149
    {
150
        return $this->inputHtml($value, false);
151
    }
152
153
    /**
154
     * @param DomainsQuery $query
155
     * @param bool $static
156
     * @return string
157
     * @throws \Twig_Error_Loader
158
     * @throws \yii\base\Exception
159
     */
160
    protected function inputHtml(DomainsQuery $query, bool $static)
161
    {
162
        $columns = [
163
            'domain' => [
164
                'heading' => 'Domain',
165
                'handle' => 'domain',
166
                'type' => 'singleline'
167
            ],
168
            'status' => [
169
                'heading' => 'Status',
170
                'handle' => 'status',
171
                'class' => 'thin',
172
                'type' => 'select',
173
                'options' => $this->getStatuses()
174
            ]
175
        ];
176
177
        // Translate the column headings
178
        foreach ($columns as &$column) {
179
            $heading = (string)$column['heading'];
180
            if ($heading !== null) {
181
                $column['heading'] = Craft::t('site', $heading);
182
            }
183
        }
184
        unset($column);
185
186
        return Craft::$app->getView()->renderTemplate(
187
            'domains/_components/fieldtypes/Domains/input',
188
            [
189
                'id' => Craft::$app->getView()->formatInputId($this->handle),
190
                'name' => $this->handle,
191
                'cols' => $columns,
192
                'rows' => $query->all(),
193
                'static' => $static,
194
                'field' => $this
195
            ]
196
        );
197
    }
198
199
    /*******************************************
200
     * EVENTS
201
     *******************************************/
202
203
    /**
204
     * @param ElementInterface $element
205
     * @param bool $isNew
206
     * @return bool|void
207
     * @throws \Throwable
208
     */
209
    public function afterElementSave(ElementInterface $element, bool $isNew)
210
    {
211
        /** @var DomainsQuery $query */
212
        $query = $element->getFieldValue($this->handle);
213
214
        // Cached results
215
        if (null === ($records = $query->getCachedResult())) {
216
            parent::afterElementSave($element, $isNew);
217
            return;
218
        }
219
220
        $currentDomains = [];
221
        if ($isNew === false) {
222
            /** @var DomainsQuery $existingQuery */
223
            $existingQuery = Domain::find();
224
            $existingQuery->element = $query->element;
225
            $existingQuery->field = $query->field;
226
            $existingQuery->site = $query->site;
227
            $existingQuery->indexBy = 'domain';
228
229
            $currentDomains = $existingQuery->all();
230
        }
231
232
        $success = true;
233
        if (empty($records)) {
234
            foreach ($currentDomains as $currentDomain) {
235
                if (!$currentDomain->delete()) {
236
                    $success = false;
237
                }
238
            }
239
240
            if (!$success) {
241
                $this->addError('types', 'Unable to delete domain.');
242
                throw new Exception('Unable to delete domain.');
243
            }
244
245
            parent::afterElementSave($element, $isNew);
246
            return;
247
        }
248
249
        $newDomains = [];
250
        $order = 1;
251
252
        foreach ($records as $record) {
253
            if (null === ($domain = ArrayHelper::remove($currentDomains, $record->domain))) {
254
                $domain = $record;
255
            }
256
            $domain->sortOrder = $order++;
257
            $domain->status = $record->status;
258
            $newDomains[] = $domain;
259
        }
260
261
        // DeleteOrganization those removed
262
        foreach ($currentDomains as $currentDomain) {
263
            if (!$currentDomain->delete()) {
264
                $success = false;
265
            }
266
        }
267
268
        foreach ($newDomains as $domain) {
269
            if (!$domain->save()) {
270
                $success = false;
271
            }
272
        }
273
274
        if (!$success) {
275
            $this->addError('users', 'Unable to save domains.');
276
            throw new Exception('Unable to save domains.');
277
        }
278
    }
279
}
280