Passed
Pull Request — 4 (#930)
by Steve
03:25
created

ElementalAreasValidator   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 42
c 1
b 0
f 0
dl 0
loc 78
rs 10
wmc 14

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getElementID() 0 10 3
B php() 0 40 8
A getElementalAreaFieldNames() 0 11 3
1
<?php
2
3
namespace DNADesign\Elemental\Validators;
4
5
use DNADesign\Elemental\Controllers\ElementalAreaController;
6
use DNADesign\Elemental\Forms\EditFormFactory;
7
use DNADesign\Elemental\Models\BaseElement;
8
use DNADesign\Elemental\Models\ElementalArea;
9
use SilverStripe\Core\Config\Config;
10
use SilverStripe\Forms\Validator;
11
use SilverStripe\ORM\DataObject;
12
13
class ElementalAreasValidator extends Validator
14
{
15
    /**
16
     * @param array $data
17
     */
18
    public function php($data)
19
    {
20
        $valid = true;
21
        $areaFieldNames = $this->getElementalAreaFieldNames($data['ClassName']);
22
        foreach ($areaFieldNames as $areaFieldName) {
23
            $elementsData = $data[$areaFieldName] ?? [];
24
            if (empty($elementsData)) {
25
                continue;
26
            }
27
            foreach (array_values($elementsData) as $elementData) {
28
                $elementID = $this->getElementID($elementData);
29
                if (!$elementID) {
30
                    continue;
31
                }
32
                $key = sprintf(EditFormFactory::FIELD_NAMESPACE_TEMPLATE, $elementID, 'ClassName');
33
                $className = $elementData[$key] ?? '';
34
                if (!$className) {
35
                    continue;
36
                }
37
                /** @var BaseElement $element */
38
                $element = DataObject::get_by_id($className, $elementID, false);
0 ignored issues
show
Bug introduced by
$elementID of type string is incompatible with the type boolean|integer expected by parameter $idOrCache of SilverStripe\ORM\DataObject::get_by_id(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

38
                $element = DataObject::get_by_id($className, /** @scrutinizer ignore-type */ $elementID, false);
Loading history...
39
                $formData = ElementalAreaController::removeNamespacesFromFields($elementData, $elementID);
0 ignored issues
show
Bug introduced by
$elementID of type string is incompatible with the type integer expected by parameter $elementID of DNADesign\Elemental\Cont...eNamespacesFromFields(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

39
                $formData = ElementalAreaController::removeNamespacesFromFields($elementData, /** @scrutinizer ignore-type */ $elementID);
Loading history...
40
                $element->updateFromFormData($formData);
41
                /** @var ValidationResult $validationResult */
42
                $validationResult = $element->validate();
43
                if ($validationResult->isValid()) {
44
                    continue;
45
                }
46
                foreach ($validationResult->getMessages() as $message) {
47
                    $this->validationError(
48
                        "PageElements_{$elementID}_{$message['fieldName']}",
49
                        $message['message'],
50
                        $message['messageType'],
51
                        $message['messageCast']
52
                    );
53
                }
54
                $valid = false;
55
            }
56
        }
57
        return $valid;
58
    }
59
60
    /**
61
     * @param string $parentClassName
62
     * @return array
63
     */
64
    private function getElementalAreaFieldNames(string $parentClassName): array
65
    {
66
        $fieldNames = [];
67
        $hasOnes = Config::inst()->get($parentClassName, 'has_one');
68
        foreach ($hasOnes as $fieldName => $className) {
69
            if ($className !== ElementalArea::class) {
70
                continue;
71
            }
72
            $fieldNames[] = $fieldName;
73
        }
74
        return $fieldNames;
75
    }
76
77
    /**
78
     * @param array $elementData
79
     * @return string
80
     */
81
    private function getElementID(array $elementData): string
82
    {
83
        foreach (array_keys($elementData) as $key) {
84
            $rx = str_replace(['%d', '%s'], ['([0-9]+)', '(.+)'], EditFormFactory::FIELD_NAMESPACE_TEMPLATE);
85
            if (!preg_match("#^{$rx}$#", $key, $match)) {
86
                continue;
87
            }
88
            return $match[1];
89
        }
90
        return '';
91
    }
92
}
93