Completed
Push — feature/middleware-tmp-bis ( c68a6a...6aafad )
by Romain
02:19
created

AbstractFormValidator::isDummy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/*
3
 * 2017 Romain CANON <[email protected]>
4
 *
5
 * This file is part of the TYPO3 FormZ project.
6
 * It is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License, either
8
 * version 3 of the License, or any later version.
9
 *
10
 * For the full copyright and license information, see:
11
 * http://www.gnu.org/licenses/gpl-3.0.html
12
 */
13
14
namespace Romm\Formz\Validation\Validator\Form;
15
16
use Romm\Formz\Core\Core;
17
use Romm\Formz\Error\FormResult;
18
use Romm\Formz\Exceptions\InvalidArgumentTypeException;
19
use Romm\Formz\Form\Definition\Field\Field;
20
use Romm\Formz\Form\FormInterface;
21
use Romm\Formz\Form\FormObject\FormObject;
22
use Romm\Formz\Form\FormObject\FormObjectFactory;
23
use Romm\Formz\Form\FormObject\FormObjectProxy;
24
use Romm\Formz\Service\FormService;
25
use Romm\Formz\Validation\Validator\Form\DataObject\FormValidatorDataObject;
26
use TYPO3\CMS\Core\Utility\GeneralUtility;
27
use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator as ExtbaseAbstractValidator;
28
29
/**
30
 * This is the abstract form validator, which must be inherited by any custom
31
 * form validator in order to work properly.
32
 *
33
 * Please note that a default form validator already exists if you need a form
34
 * which does not require any particular action: `DefaultFormValidator`.
35
 *
36
 * A form validator should be called to validate any form instance (which is a
37
 * child of `AbstractForm`). Usually, this is used in controller actions to
38
 * validate a form sent by the user. Example:
39
 *
40
 * /**
41
 *  * Action called when the Example form is submitted.
42
 *  *
43
 *  * @param $exForm
44
 *  * @validate $exForm Romm.Formz:Form\DefaultFormValidator
45
 *  * /
46
 *  public function submitFormAction(ExampleForm $exForm) { ... }
47
 *
48
 *******************************************************************************
49
 *
50
 * You may use you own custom form validator in order to be able to use the
51
 * following features:
52
 *
53
 * - Pre-validation custom process:
54
 *   By extending the method `beforeValidationProcess()`, you are able to handle
55
 *   anything you want just before the form validation begins to loop on every
56
 *   field. This can be used for instance to (de)activate the validation of
57
 *   certain fields under very specific circumstances.
58
 *
59
 * - In real time custom process:
60
 *   After each field went trough a validation process, a magic method is called
61
 *   to allow very low level custom process. The magic method name looks like:
62
 *   "{lowerCamelCaseFieldName}Validated". For instance, when the "email" field
63
 *   just went trough the validation process, the method `emailValidated()` is
64
 *   called.
65
 *
66
 * - Post-validation custom process:
67
 *   After the validation was done on every field of the form, this method is
68
 *   called to allow you high level process. For instance, let's assume your
69
 *   form is used to calculate a price estimation depending on information
70
 *   submitted in the form; when the form went trough the validation process and
71
 *   got no error, you can run the price estimation, and if any error occurs you
72
 *   are still able to add an error to `$this->result` (in a controller you do
73
 *   not have access to it anymore).
74
 */
75
abstract class AbstractFormValidator extends ExtbaseAbstractValidator
76
{
77
    /**
78
     * @inheritdoc
79
     */
80
    protected $supportedOptions = [
81
        'name'  => ['', 'Name of the form.', 'string'],
82
        'dummy' => [false, 'Dummy mode?', 'bool']
83
    ];
84
85
    /**
86
     * @var FormResult
87
     */
88
    protected $result;
89
90
    /**
91
     * @var FormInterface
92
     */
93
    protected $form;
94
95
    /**
96
     * @var FormObject
97
     */
98
    protected $formObject;
99
100
    /**
101
     * @var FormValidatorExecutor
102
     */
103
    private $formValidatorExecutor;
104
105
    /**
106
     * @var FormValidatorDataObject
107
     */
108
    protected $dataObject;
109
110
    /**
111
     * Initializes all class variables.
112
     *
113
     * @param FormInterface $form
114
     * @throws InvalidArgumentTypeException
115
     */
116
    protected function initializeValidator($form)
117
    {
118
        if (false === $form instanceof FormInterface) {
119
            throw InvalidArgumentTypeException::validatingWrongFormType(get_class($form));
120
        }
121
122
        $this->form = $form;
123
        $this->formObject = $this->getFormObject();
124
        $this->result = $this->getFormResult();
125
        $this->formValidatorExecutor = $this->getFormValidatorExecutor();
126
127
        $this->getDataObject()->addFieldValidationCallback(function (Field $field) {
128
            $this->afterFieldValidation($field);
129
        });
130
    }
131
132
    /**
133
     * Checks the given form instance, and launches the validation if it is a
134
     * correct form.
135
     *
136
     * @param FormInterface $form The form instance to be validated.
137
     * @return FormResult
138
     */
139
    public function validate($form)
140
    {
141
        $this->initializeValidator($form);
142
143
        if (false === $this->isDummy()) {
144
            $proxy = $this->getProxy($form);
145
            $proxy->markFormAsValidated();
146
            $proxy->markFormAsSubmitted();
147
        }
148
149
        $this->isValid($form);
150
151
        return $this->result;
152
    }
153
154
    /**
155
     * Runs the whole validation workflow.
156
     *
157
     * @param FormInterface $form
158
     */
159
    final public function isValid($form)
160
    {
161
        $this->formValidatorExecutor->applyBehaviours();
162
        $this->formValidatorExecutor->checkFieldsActivation();
163
164
        $this->beforeValidationProcess();
165
166
        $this->formValidatorExecutor->validateFields();
167
168
        $this->afterValidationProcess();
169
170
        if ($this->result->hasErrors()) {
171
            // Storing the form for possible third party further usage.
172
            FormService::addFormWithErrors($form);
173
        }
174
    }
175
176
    /**
177
     * Override this function in your child class to handle some pre-validation
178
     * process.
179
     */
180
    protected function beforeValidationProcess()
181
    {
182
    }
183
184
    /**
185
     * Override this function in your child class to handle some post-validation
186
     * process.
187
     */
188
    protected function afterValidationProcess()
189
    {
190
    }
191
192
    /**
193
     * After each field has been validated, a matching method can be called if
194
     * it exists in the child class.
195
     *
196
     * The syntax is `{lowerCamelCaseFieldName}Validated()`.
197
     *
198
     * Example: for field `firstName` - `firstNameValidated()`.
199
     *
200
     * @param Field $field
201
     */
202
    protected function afterFieldValidation(Field $field)
203
    {
204
        $functionName = lcfirst($field->getName() . 'Validated');
205
206
        if (method_exists($this, $functionName)) {
207
            call_user_func([$this, $functionName]);
208
        }
209
    }
210
211
    /**
212
     * If the form validator is a dummy, a new instance of `FormResult` is
213
     * created and returned, preventing
214
     *
215
     * @return FormResult
216
     */
217
    protected function getFormResult()
218
    {
219
        /** @var FormResult $formResult */
220
        $formResult = $this->isDummy()
221
            ? GeneralUtility::makeInstance(FormResult::class)
222
            : $this->formObject->getFormResult();
223
224
        return $formResult;
225
    }
226
227
    /**
228
     * @return bool
229
     */
230
    protected function isDummy()
231
    {
232
        return true === $this->options['dummy'];
233
    }
234
235
    /**
236
     * @return FormValidatorExecutor
237
     */
238
    protected function getFormValidatorExecutor()
239
    {
240
        /** @var FormValidatorExecutor $formValidatorExecutor */
241
        $formValidatorExecutor = Core::instantiate(FormValidatorExecutor::class, $this->formObject, $this->getDataObject());
242
243
        return $formValidatorExecutor;
244
    }
245
246
    /**
247
     * @return FormObject
248
     */
249
    protected function getFormObject()
250
    {
251
        return FormObjectFactory::get()->registerAndGetFormInstance($this->form, $this->options['name']);
252
    }
253
254
    /**
255
     * @param FormInterface $form
256
     * @return FormObjectProxy
257
     */
258
    protected function getProxy(FormInterface $form)
259
    {
260
        return FormObjectFactory::get()->getProxy($form);
261
    }
262
263
    /**
264
     * @return FormValidatorDataObject
265
     */
266
    public function getDataObject()
267
    {
268
        if (null === $this->dataObject) {
269
            $this->dataObject = Core::instantiate(FormValidatorDataObject::class);
270
        }
271
272
        return $this->dataObject;
273
    }
274
}
275