6db02fe533321e076a2c8b612dd023af051c631a
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / Domain / Builder / ValidationBuilder.php
1 <?php
2 namespace TYPO3\CMS\Form\Domain\Builder;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\ArrayUtility;
18 use TYPO3\CMS\Form\Domain\Model\Configuration;
19 use TYPO3\CMS\Form\Domain\Validator\AbstractValidator;
20 use TYPO3\CMS\Form\Utility\FormUtility;
21
22 /**
23 * Parse and hole all the validation rules
24 */
25 class ValidationBuilder
26 {
27 /**
28 * @param Configuration $configuration
29 * @return ValidationBuilder
30 */
31 public static function create(Configuration $configuration)
32 {
33 /** @var ValidationBuilder $validationBuilder */
34 $validationBuilder = \TYPO3\CMS\Form\Utility\FormUtility::getObjectManager()->get(ValidationBuilder::class);
35 $validationBuilder->setConfiguration($configuration);
36 return $validationBuilder;
37 }
38
39 /**
40 * @var array|array[]
41 */
42 protected $rules = [];
43
44 /**
45 * @var string
46 */
47 protected $formPrefix = '';
48
49 /**
50 * @var \TYPO3\CMS\Extbase\Object\ObjectManager
51 */
52 protected $objectManager;
53
54 /**
55 * @var \TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository
56 */
57 protected $typoScriptRepository;
58
59 /**
60 * @var FormUtility
61 */
62 protected $formUtility;
63
64 /**
65 * @var Configuration
66 */
67 protected $configuration;
68
69 /**
70 * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager
71 * @return void
72 */
73 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager)
74 {
75 $this->objectManager = $objectManager;
76 }
77
78 /**
79 * @param \TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository $typoScriptRepository
80 * @return void
81 */
82 public function injectTypoScriptRepository(\TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository $typoScriptRepository)
83 {
84 $this->typoScriptRepository = $typoScriptRepository;
85 }
86
87 /**
88 * @param Configuration $configuration
89 */
90 public function setConfiguration(Configuration $configuration)
91 {
92 $this->configuration = $configuration;
93 }
94
95 /**
96 * @param FormUtility $formUtility
97 */
98 public function setFormUtility(FormUtility $formUtility)
99 {
100 $this->formUtility = $formUtility;
101 }
102
103 /**
104 * Build validation rules from typoscript.
105 * The old breakOnError property are no longer supported
106 *
107 * @param array $rawArgument
108 * @return void
109 */
110 public function buildRules(array $rawArgument = [])
111 {
112 $userConfiguredFormTyposcript = $this->configuration->getTypoScript();
113 $rulesTyposcript = isset($userConfiguredFormTyposcript['rules.']) ? $userConfiguredFormTyposcript['rules.'] : null;
114 $this->rules[$this->configuration->getPrefix()] = [];
115 if (is_array($rulesTyposcript)) {
116 $keys = ArrayUtility::filterAndSortByNumericKeys($rulesTyposcript);
117 foreach ($keys as $key) {
118 $ruleName = $rulesTyposcript[$key];
119 $validatorClassName = $this->typoScriptRepository->getRegisteredClassName($ruleName, 'registeredValidators');
120 if ($validatorClassName === null) {
121 throw new \RuntimeException('Class "' . $validatorClassName . '" not registered via typoscript.');
122 }
123 if (
124 (int)$key
125 && strpos($key, '.') === false
126 ) {
127 $ruleArguments = $rulesTyposcript[$key . '.'];
128 $fieldName = $this->formUtility->sanitizeNameAttribute($ruleArguments['element']);
129 // remove unsupported validator options
130 $validatorOptions = $ruleArguments;
131 $validatorOptions['errorMessage'] = [$ruleArguments['error.'], $ruleArguments['error']];
132 $keysToRemove = array_flip([
133 'breakOnError',
134 'message',
135 'message.',
136 'error',
137 'error.',
138 'showMessage',
139 ]);
140 $validatorOptions = array_diff_key($validatorOptions, $keysToRemove);
141
142 // Instantiate the validator to check if all required options are assigned
143 // and to use the validator message rendering function to pre-render the mandatory message
144 /** @var AbstractValidator $validator */
145 $validator = $this->objectManager->get($validatorClassName, $validatorOptions);
146
147 if ($validator instanceof AbstractValidator) {
148 $validator->setRawArgument($rawArgument);
149 $validator->setFormUtility($this->formUtility);
150
151 if ((int)$ruleArguments['showMessage'] === 1) {
152 $mandatoryMessage = $validator->renderMessage($ruleArguments['message.'], $ruleArguments['message']);
153 } else {
154 $mandatoryMessage = null;
155 }
156
157 $this->rules[$this->configuration->getPrefix()][$fieldName][] = [
158 'validator' => $validator,
159 'validatorName' => $validatorClassName,
160 'validatorOptions' => $validatorOptions,
161 'mandatoryMessage' => $mandatoryMessage
162 ];
163 } else {
164 throw new \RuntimeException('Class "' . $validatorClassName . '" could not be loaded.');
165 }
166 }
167 }
168 }
169 }
170
171 /**
172 * Set all validation rules
173 *
174 * @param array $rules
175 * @return void
176 */
177 public function setRules(array $rules)
178 {
179 $this->rules = $rules[$this->configuration->getPrefix()];
180 }
181
182 /**
183 * Get all validation rules
184 *
185 * @return array
186 */
187 public function getRules()
188 {
189 return $this->rules[$this->configuration->getPrefix()];
190 }
191
192 /**
193 * Set a validation rule
194 *
195 * @param string $key
196 * @param array $rule
197 * @return void
198 */
199 public function setRulesByElementName($key = '', array $rule = [])
200 {
201 $this->rules[$this->configuration->getPrefix()][$key] = $rule;
202 }
203
204 /**
205 * Get a validation rule by key
206 *
207 * @param string $key
208 * @return NULL|array
209 */
210 public function getRulesByElementName($key = '')
211 {
212 if (isset($this->rules[$this->configuration->getPrefix()][$key])) {
213 return $this->rules[$this->configuration->getPrefix()][$key];
214 }
215 return null;
216 }
217
218 /**
219 * Remove a validation rule by key
220 *
221 * @param string $key
222 * @return void
223 */
224 public function removeRule($key = '')
225 {
226 unset($this->rules[$this->configuration->getPrefix()][$key]);
227 }
228
229 /**
230 * Get all mandatory validation messages for a element
231 *
232 * @param string $key
233 * @return array
234 */
235 public function getMandatoryValidationMessagesByElementName($key = '')
236 {
237 $mandatoryMessages = [];
238 if ($this->getRulesByElementName($key)) {
239 $rules = $this->getRulesByElementName($key);
240 foreach ($rules as $rule) {
241 if ($rule['mandatoryMessage']) {
242 $mandatoryMessages[] = $rule['mandatoryMessage'];
243 }
244 }
245 }
246 return $mandatoryMessages;
247 }
248 }