Completed
Push — develop ( 44ffbd...b889cd )
by Nate
05:02 queued 01:07
created

DomainsValidator::validateDomainModel()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 0
cts 19
cp 0
rs 9.0534
c 0
b 0
f 0
cc 4
eloc 12
nc 5
nop 3
crap 20
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\domains\validators;
10
11
use Craft;
12
use craft\base\Element;
13
use craft\base\ElementInterface;
14
use flipbox\domains\db\DomainsQuery;
15
use flipbox\domains\fields\Domains;
16
use flipbox\domains\models\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
    /**
29
     * @var Domains
30
     */
31
    public $field;
32
33
    /**
34
     * @inheritdoc
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->getFieldValue($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 = (new DomainsQuery($this->field))
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 ($domain = $domainQuery->one()) {
147
            $this->addError(
148
                $element,
149
                $attribute,
150
                Craft::t(
151
                    'domains',
152
                    "Domain '{domain}' is already in use by element {elementId}.",
153
                    [
154
                        'domain' => $domain->domain,
155
                        'elementId' => $domain->getElementId()
0 ignored issues
show
Bug introduced by
The method getElementId cannot be called on $domain (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
156
                    ]
157
                )
158
            );
159
        }
160
    }
161
}
162