DomainsValidator   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 7
dl 0
loc 138
ccs 0
cts 87
cp 0
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 8 2
A validateAttribute() 0 12 2
A validateElementAttribute() 0 14 2
A validateQuery() 0 14 4
A validateDomainModel() 0 21 4
A validateUniqueDomain() 0 32 3
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\validators;
10
11
use Craft;
12
use craft\base\Element;
13
use craft\base\ElementInterface;
14
use flipbox\craft\domains\queries\DomainsQuery;
15
use flipbox\craft\domains\fields\Domains;
16
use flipbox\craft\domains\records\Domain;
17
use yii\base\Exception;
18
use yii\base\Model;
19
use yii\validators\Validator;
20
21
/**
22
 * @author Flipbox Factory <[email protected]>
23
 * @since 1.0.0
24
 */
25
class DomainsValidator extends Validator
26
{
27
    /**
28
     * @var Domains
29
     */
30
    public $field;
31
32
    /**
33
     * @inheritdoc
34
     * @throws Exception
35
     */
36
    public function init()
37
    {
38
        parent::init();
39
40
        if (!$this->field instanceof Domains) {
41
            throw new Exception("Field must be an instance of 'Domains'.");
42
        }
43
    }
44
45
    /**
46
     * @param Model $model
47
     * @param string $attribute
48
     * @throws Exception
49
     */
50
    public function validateAttribute($model, $attribute)
51
    {
52
        if (!$model instanceof ElementInterface) {
53
            throw new Exception(sprintf(
54
                "Model must be an instance of '%s'.",
55
                (string)ElementInterface::class
56
            ));
57
        }
58
59
        /** @var ElementInterface $model */
60
        $this->validateElementAttribute($model, $attribute);
61
    }
62
63
    /**
64
     * @param ElementInterface $element
65
     * @param string $attribute
66
     * @throws Exception
67
     */
68
    protected function validateElementAttribute(ElementInterface $element, string $attribute)
69
    {
70
        /** @var Element $element */
71
        $value = $element->{$attribute};
72
73
        if (!$value instanceof DomainsQuery) {
74
            throw new Exception(sprintf(
75
                "Field value must be an instance of '%s'.",
76
                (string)DomainsQuery::class
77
            ));
78
        }
79
80
        $this->validateQuery($value, $element, $attribute);
81
    }
82
83
    /**
84
     * @param DomainsQuery $query
85
     * @param ElementInterface $element
86
     * @param string $attribute
87
     */
88
    protected function validateQuery(DomainsQuery $query, ElementInterface $element, string $attribute)
89
    {
90
        if (null !== ($cachedResult = $query->getCachedResult())) {
91
            $domains = [];
92
            foreach ($cachedResult as $model) {
93
                $this->validateDomainModel($model, $element, $attribute);
94
                $domains[$model->domain] = $model->domain;
95
            }
96
97
            if ($this->field->unique === true) {
98
                $this->validateUniqueDomain(array_keys($domains), $element, $attribute);
99
            }
100
        }
101
    }
102
103
    /**
104
     * @param Domain $domain
105
     * @param ElementInterface $element
106
     * @param string $attribute
107
     */
108
    protected function validateDomainModel(Domain $domain, ElementInterface $element, string $attribute)
109
    {
110
        /** @var Element $element */
111
        if (!$domain->validate(['domain', 'status'])) {
112
            if ($domain->hasErrors('domain')) {
113
                $this->addError(
114
                    $element,
115
                    $attribute,
116
                    $domain->getFirstError('domain')
117
                );
118
            }
119
120
            if ($domain->hasErrors('status')) {
121
                $this->addError(
122
                    $element,
123
                    $attribute,
124
                    $domain->getFirstError('status')
125
                );
126
            }
127
        }
128
    }
129
130
    protected function validateUniqueDomain(array $domains, ElementInterface $element, string $attribute)
131
    {
132
        /** @var Element $element */
133
        $domainQuery = Domain::find()
134
            ->select(['elementId', 'domain'])
135
            ->andWhere(['domain' => $domains]);
136
137
        // Ignore this element
138
        if (null !== ($existingElementId = $element->getId())) {
139
            $domainQuery->andWhere([
140
                '!=',
141
                'elementId',
142
                $existingElementId
143
            ]);
144
        }
145
146
        if (null !== ($domain = $domainQuery->one())) {
147
            /** @var Domain $domain */
148
            $this->addError(
149
                $element,
150
                $attribute,
151
                Craft::t(
152
                    'domains',
153
                    "Domain '{domain}' is already in use by element {elementId}.",
154
                    [
155
                        'domain' => $domain->domain,
156
                        'elementId' => $domain->elementId
157
                    ]
158
                )
159
            );
160
        }
161
    }
162
}
163