Completed
Push — middleware-wip ( 7e7b3d...2c3646 )
by Romain
02:25
created

AbstractFormValidator::setResult()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
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\Configuration\Form\Field\Field;
17
use Romm\Formz\Core\Core;
18
use Romm\Formz\Error\FormResult;
19
use Romm\Formz\Exceptions\InvalidArgumentTypeException;
20
use Romm\Formz\Form\FormInterface;
21
use Romm\Formz\Service\FormService;
22
use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator as ExtbaseAbstractValidator;
23
24
/**
25
 * This is the abstract form validator, which must be inherited by any custom
26
 * form validator in order to work properly.
27
 *
28
 * Please note that a default form validator already exists if you need a form
29
 * which does not require any particular action: `DefaultFormValidator`.
30
 *
31
 * A form validator should be called to validate any form instance (which is a
32
 * child of `AbstractForm`). Usually, this is used in controller actions to
33
 * validate a form sent by the user. Example:
34
 *
35
 * /**
36
 *  * Action called when the Example form is submitted.
37
 *  *
38
 *  * @param $exForm
39
 *  * @validate $exForm Romm.Formz:Form\DefaultFormValidator
40
 *  * /
41
 *  public function submitFormAction(ExampleForm $exForm) { ... }
42
 *
43
 *******************************************************************************
44
 *
45
 * You may use you own custom form validator in order to be able to use the
46
 * following features:
47
 *
48
 * - Pre-validation custom process:
49
 *   By extending the method `beforeValidationProcess()`, you are able to handle
50
 *   anything you want just before the form validation begins to loop on every
51
 *   field. This can be used for instance to (de)activate the validation of
52
 *   certain fields under very specific circumstances.
53
 *
54
 * - In real time custom process:
55
 *   After each field went trough a validation process, a magic method is called
56
 *   to allow very low level custom process. The magic method name looks like:
57
 *   "{lowerCamelCaseFieldName}Validated". For instance, when the "email" field
58
 *   just went trough the validation process, the method `emailValidated()` is
59
 *   called.
60
 *
61
 * - Post-validation custom process:
62
 *   After the validation was done on every field of the form, this method is
63
 *   called to allow you high level process. For instance, let's assume your
64
 *   form is used to calculate a price estimation depending on information
65
 *   submitted in the form; when the form went trough the validation process and
66
 *   got no error, you can run the price estimation, and if any error occurs you
67
 *   are still able to add an error to `$this->result` (in a controller you do
68
 *   not have access to it anymore).
69
 */
70
abstract class AbstractFormValidator extends ExtbaseAbstractValidator implements FormValidatorInterface
71
{
72
    /**
73
     * @inheritdoc
74
     */
75
    protected $supportedOptions = [
76
        'name' => ['', 'Name of the form.', 'string', true]
77
    ];
78
79
    /**
80
     * @var FormResult
81
     */
82
    protected $result;
83
84
    /**
85
     * @var FormInterface
86
     */
87
    protected $form;
88
89
    /**
90
     * @var FormValidatorExecutor
91
     */
92
    private $formValidatorExecutor;
93
94
    /**
95
     * Initializes all class variables.
96
     *
97
     * @param FormInterface $form
98
     * @throws InvalidArgumentTypeException
99
     */
100
    private function initializeValidator($form)
101
    {
102
        if (false === $form instanceof FormInterface) {
103
            throw InvalidArgumentTypeException::validatingWrongFormType(get_class($form));
104
        }
105
106
        $this->form = $form;
107
        $this->formValidatorExecutor = $this->getFormValidatorExecutor($form);
108
109
        if (null === $this->result) {
110
            $this->result = new FormResult;
111
        }
112
    }
113
114
    /**
115
     * Checks the given form instance, and launches the validation if it is a
116
     * correct form.
117
     *
118
     * @param FormInterface $form The form instance to be validated.
119
     * @return FormResult
120
     */
121
    final public function validate($form)
122
    {
123
        $this->initializeValidator($form);
124
125
        $formObject = $this->formValidatorExecutor->getFormObject();
126
        $formObject->markFormAsSubmitted();
127
        $formObject->setForm($form);
128
129
        $this->validateGhost($form, false);
130
131
        $formObject->setFormResult($this->result);
132
133
        return $this->result;
134
    }
135
136
    /**
137
     * Validates the form, but wont save form data in the form object.
138
     *
139
     * @param FormInterface $form
140
     * @param bool          $initialize
141
     * @return FormResult
142
     * @internal
143
     */
144
    public function validateGhost($form, $initialize = true)
145
    {
146
        if ($initialize) {
147
            $this->initializeValidator($form);
148
        }
149
150
        $this->isValid($form);
151
152
        return $this->result;
153
    }
154
155
    /**
156
     * Runs the whole validation workflow.
157
     *
158
     * @param FormInterface $form
159
     */
160
    final public function isValid($form)
161
    {
162
        $this->formValidatorExecutor->applyBehaviours();
163
        $this->formValidatorExecutor->checkFieldsActivation();
164
165
        $this->beforeValidationProcess();
166
167
        $this->formValidatorExecutor->validateFields(function (Field $field) {
168
            $this->callAfterFieldValidationMethod($field);
169
        });
170
171
        $this->afterValidationProcess();
172
173
        if ($this->result->hasErrors()) {
174
            // Storing the form for possible third party further usage.
175
            FormService::addFormWithErrors($form);
176
        }
177
    }
178
179
    /**
180
     * Override this function in your child class to handle some pre-validation
181
     * process.
182
     */
183
    protected function beforeValidationProcess()
184
    {
185
    }
186
187
    /**
188
     * Override this function in your child class to handle some post-validation
189
     * process.
190
     */
191
    protected function afterValidationProcess()
192
    {
193
    }
194
195
    /**
196
     * After each field has been validated, a matching method can be called if
197
     * it exists in the child class.
198
     *
199
     * The syntax is `{lowerCamelCaseFieldName}Validated()`.
200
     *
201
     * Example: for field `firstName` - `firstNameValidated()`.
202
     *
203
     * @param Field $field
204
     */
205
    private function callAfterFieldValidationMethod(Field $field)
206
    {
207
        $functionName = lcfirst($field->getFieldName() . 'Validated');
208
209
        if (method_exists($this, $functionName)) {
210
            call_user_func([$this, $functionName]);
211
        }
212
    }
213
214
    /**
215
     * @param FormInterface $form
216
     * @return FormValidatorExecutor
217
     */
218
    protected function getFormValidatorExecutor(FormInterface $form)
219
    {
220
        /** @var FormValidatorExecutor $formValidatorExecutor */
221
        $formValidatorExecutor = Core::instantiate(FormValidatorExecutor::class, $form, $this->options['name'], $this->result);
222
223
        return $formValidatorExecutor;
224
    }
225
226
    /**
227
     * @param FormResult $result
228
     */
229
    public function setResult(FormResult $result)
230
    {
231
        $this->result = $result;
232
    }
233
}
234