Passed
Push — master ( 57b5b6...1bd009 )
by
unknown
47:04 queued 32:28
created

validatePropertyCollectionPropertyValue()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 40
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 40
rs 9.4222
c 0
b 0
f 0
cc 5
nc 5
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
namespace TYPO3\CMS\Form\Domain\Configuration\FormDefinition\Validators;
19
20
use TYPO3\CMS\Core\Utility\ArrayUtility;
21
use TYPO3\CMS\Form\Domain\Configuration\Exception\PropertyException;
22
23
/**
24
 * @internal
25
 */
26
class CreatablePropertyCollectionElementPropertiesValidator extends CollectionBasedValidator
27
{
28
29
    /**
30
     * Checks if the property collection element property is defined
31
     * within the form editor setup or if the property is defined within
32
     * the "predefinedDefaults" in the form editor setup
33
     * and the property value matches the predefined value
34
     * or if there is a valid hmac hash for the value.
35
     * If the property collection element property is defined within the form editor setup
36
     * and there is no valid hmac hash for the value
37
     * and is the form property collection element property configured to only allow a limited set of values,
38
     * check the current (submitted) value against the allowed set of values (defined within the form setup).
39
     *
40
     * @param string $key
41
     * @param mixed $value
42
     */
43
    public function __invoke(string $key, $value)
44
    {
45
        $dto = $this->validationDto->withPropertyPath($key);
46
47
        if ($this->getConfigurationService()->isPropertyCollectionPropertyDefinedInFormEditorSetup($dto)) {
48
            if ($this->getConfigurationService()->propertyCollectionPropertyHasLimitedAllowedValuesDefinedWithinFormEditorSetup($dto)) {
49
                $this->validatePropertyCollectionPropertyValue($value, $dto);
50
            }
51
        } elseif (
52
            $this->getConfigurationService()->isPropertyCollectionPropertyDefinedInPredefinedDefaultsInFormEditorSetup($dto)
53
            && !ArrayUtility::isValidPath($this->currentElement, $this->buildHmacDataPath($dto->getPropertyPath()), '.')
54
        ) {
55
            $this->validatePropertyCollectionElementPredefinedDefaultValue($value, $dto);
56
        } else {
57
            $this->validatePropertyCollectionElementPropertyValueByHmacData(
58
                $this->currentElement,
59
                $value,
60
                $this->sessionToken,
61
                $dto
62
            );
63
        }
64
    }
65
66
    /**
67
     * Throws an exception if the value from a property collection property
68
     * does not match the default value from the form editor setup.
69
     *
70
     * @param mixed $value
71
     * @param ValidationDto $dto
72
     * @throws PropertyException
73
     */
74
    protected function validatePropertyCollectionElementPredefinedDefaultValue(
75
        $value,
76
        ValidationDto $dto
77
    ): void {
78
        // If the property collection element is newly created, we have to compare the $value (form definition) with $predefinedDefaultValue (form setup)
79
        // to check the integrity (at this time we don't have a hmac on the value to check the integrity)
80
        $predefinedDefaultValue = $this->getConfigurationService()->getPropertyCollectionPredefinedDefaultValueFromFormEditorSetup($dto);
81
        if ($value !== $predefinedDefaultValue) {
82
            $throwException = true;
83
84
            if (is_string($predefinedDefaultValue)) {
85
                // Last chance:
86
                // Get all translations (from all backend languages) for the untranslated! $predefinedDefaultValue and
87
                // compare the (already translated) $value (from the form definition) against the possible
88
                // translations from $predefinedDefaultValue.
89
                $untranslatedPredefinedDefaultValue = $this->getConfigurationService()->getPropertyCollectionPredefinedDefaultValueFromFormEditorSetup($dto, false);
90
                $translations = $this->getConfigurationService()->getAllBackendTranslationsForTranslationKey(
91
                    $untranslatedPredefinedDefaultValue,
92
                    $dto->getPrototypeName()
93
                );
94
95
                if (in_array($value, $translations, true)) {
96
                    $throwException = false;
97
                }
98
            }
99
100
            if ($throwException) {
101
                $message = 'The value "%s" of property "%s" (form element "%s" / "%s.%s") is not equal to the default value "%s" #1528591502';
102
                throw new PropertyException(
103
                    sprintf(
104
                        $message,
105
                        $value,
106
                        $dto->getPropertyPath(),
107
                        $dto->getFormElementIdentifier(),
108
                        $dto->getPropertyCollectionName(),
109
                        $dto->getPropertyCollectionElementIdentifier(),
110
                        $predefinedDefaultValue
111
                    ),
112
                    1528591502
113
                );
114
            }
115
        }
116
    }
117
118
    /**
119
     * Throws an exception if the value from a property collection property
120
     * does not match the allowed set of values (defined within the form setup).
121
     *
122
     * @param mixed $value
123
     * @param ValidationDto $dto
124
     * @throws PropertyException
125
     */
126
    protected function validatePropertyCollectionPropertyValue(
127
        $value,
128
        ValidationDto $dto
129
    ): void {
130
        $allowedValues = $this->getConfigurationService()->getAllowedValuesForPropertyCollectionPropertyFromFormEditorSetup($dto);
131
132
        if (!in_array($value, $allowedValues, true)) {
133
            $untranslatedAllowedValues = $this->getConfigurationService()->getAllowedValuesForPropertyCollectionPropertyFromFormEditorSetup($dto, false);
134
            // Compare the $value against the untranslated set of allowed values
135
            if (in_array($value, $untranslatedAllowedValues, true)) {
136
                // All good, $value is within the untranslated set of allowed values
137
                return;
138
            }
139
            // Get all translations (from all backend languages) for the untranslated! $allowedValues and
140
            // compare the (already translated) $value (from the form definition) against all possible
141
            // translations for $untranslatedAllowedValues.
142
            $allPossibleAllowedValuesTranslations = $this->getConfigurationService()->getAllBackendTranslationsForTranslationKeys(
143
                $untranslatedAllowedValues,
144
                $dto->getPrototypeName()
145
            );
146
147
            foreach ($allPossibleAllowedValuesTranslations as $translations) {
148
                if (in_array($value, $translations, true)) {
149
                    // All good, $value is within the set of translated allowed values
150
                    return;
151
                }
152
            }
153
154
            // Last chance:
155
            // If $value is not configured within the form setup as an allowed value
156
            // but was written within the form definition by hand (and therefore contains a hmac),
157
            // check if $value is manipulated.
158
            // If $value has no hmac or if the hmac exists but is not valid,
159
            // then $this->validatePropertyCollectionElementPropertyValueByHmacData() will
160
            // throw an exception.
161
            $this->validatePropertyCollectionElementPropertyValueByHmacData(
162
                $this->currentElement,
163
                $value,
164
                $this->sessionToken,
165
                $dto
166
            );
167
        }
168
    }
169
}
170