Completed
Push — middleware-wip ( 5cfd03...f2f782 )
by Romain
05:53
created

FieldsValidationJavaScriptAssetHandler::getValidationConfiguration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 3
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\AssetHandler\JavaScript;
15
16
use Romm\Formz\AssetHandler\AbstractAssetHandler;
17
use Romm\Formz\Form\Definition\Field\Field;
18
use Romm\Formz\Form\Definition\Field\Validation\Validator;
19
use Romm\Formz\Service\ArrayService;
20
use Romm\Formz\Service\ValidatorService;
21
use Romm\Formz\Validation\Validator\AbstractValidator;
22
use TYPO3\CMS\Core\Utility\GeneralUtility;
23
24
/**
25
 * This asset handler generates the JavaScript code which will initialize the
26
 * validation rules for every field of the form. Call the function
27
 * `getJavaScriptCode()`.
28
 *
29
 * It can also return the list of files which must be included in order to make
30
 * the form run correctly. Call the function `getJavaScriptValidationFiles()`.
31
 */
32
class FieldsValidationJavaScriptAssetHandler extends AbstractAssetHandler
33
{
34
    /**
35
     * @var array
36
     */
37
    protected $javaScriptValidationFiles;
38
39
    /**
40
     * Main function of this asset handler. See class description.
41
     *
42
     * @return string
43
     */
44
    public function getJavaScriptCode()
45
    {
46
        $fieldsJavaScriptCode = [];
47
        $formConfiguration = $this->getFormObject()->getDefinition();
48
49
        foreach ($formConfiguration->getFields() as $field) {
50
            $fieldsJavaScriptCode[] = $this->processField($field);
51
        }
52
53
        $formName = GeneralUtility::quoteJSvalue($this->getFormObject()->getName());
54
        $fieldsJavaScriptCode = implode(CRLF, $fieldsJavaScriptCode);
55
56
        return <<<JS
57
(function() {
58
    Fz.Form.get(
59
        $formName,
60
        function(form) {
61
            var field = null;
62
63
$fieldsJavaScriptCode
64
        }
65
    );
66
})();
67
JS;
68
    }
69
70
    /**
71
     * Will run the process for the given field.
72
     *
73
     * @param Field $field
74
     * @return string
75
     */
76
    protected function processField($field)
77
    {
78
        $javaScriptCode = [];
79
        $fieldName = $field->getName();
80
81
        foreach ($field->getValidators() as $validator) {
82
            $validatorClassName = $validator->getClassName();
83
84
            if (in_array(AbstractValidator::class, class_parents($validatorClassName))) {
85
                $javaScriptCode[] = (string)$this->getInlineJavaScriptValidatorCode($field, $validator);
86
            }
87
        }
88
89
        $javaScriptCode = implode(CRLF, $javaScriptCode);
90
        $javaScriptFieldName = GeneralUtility::quoteJSvalue($fieldName);
91
92
        return <<<JS
93
            /***************************
94
            * Field: "$fieldName"
95
            ****************************/
96
            field = form.getFieldByName($javaScriptFieldName);
97
98
            if (null !== field) {
99
$javaScriptCode
100
            }
101
102
JS;
103
    }
104
105
    /**
106
     * Generates the JavaScript code to add a validation rule to a field.
107
     *
108
     * @param Field     $field
109
     * @param Validator $validator      Contains the current validator configuration.
110
     * @return string
111
     */
112
    protected function getInlineJavaScriptValidatorCode(Field $field, Validator $validator)
113
    {
114
        $javaScriptValidatorName = GeneralUtility::quoteJSvalue($validator->getName());
115
        $validatorClassName = addslashes($validator->getClassName());
116
        $validatorConfigurationFinal = $this->getValidatorConfiguration($field, $validator);
117
        $validatorConfigurationFinal = $this->handleValidatorConfiguration($validatorConfigurationFinal);
118
119
        return <<<JS
120
                /*
121
                 * Validation rule "{$validator->getName()}"
122
                 */
123
                field.addValidation($javaScriptValidatorName, '$validatorClassName', $validatorConfigurationFinal);
124
125
JS;
126
    }
127
128
    /**
129
     * Wrapper for unit tests.
130
     *
131
     * @param string $jsonValidationConfiguration
132
     * @return string
133
     */
134
    protected function handleValidatorConfiguration($jsonValidationConfiguration)
135
    {
136
        return $jsonValidationConfiguration;
137
    }
138
139
    /**
140
     * Returns a JSON array containing the validator configuration needed by
141
     * JavaScript.
142
     *
143
     * @param Field     $field
144
     * @param Validator $validator
145
     * @return string
146
     */
147
    protected function getValidatorConfiguration(Field $field, Validator $validator)
148
    {
149
        $acceptsEmptyValues = ValidatorService::get()->validatorAcceptsEmptyValues($validator->getClassName());
150
151
        /** @var FormzLocalizationJavaScriptAssetHandler $formzLocalizationJavaScriptAssetHandler */
152
        $formzLocalizationJavaScriptAssetHandler = $this->assetHandlerFactory->getAssetHandler(FormzLocalizationJavaScriptAssetHandler::class);
153
154
        $messages = $formzLocalizationJavaScriptAssetHandler->getTranslationKeysForFieldValidator($field, $validator);
155
156
        return ArrayService::get()->arrayToJavaScriptJson([
157
            'options'            => $validator->getOptions(),
158
            'messages'           => $messages,
159
            'settings'           => $validator->toArray(),
160
            'acceptsEmptyValues' => $acceptsEmptyValues
161
        ]);
162
    }
163
164
    /**
165
     * @return array
166
     */
167
    public function getJavaScriptValidationFiles()
168
    {
169
        if (null === $this->javaScriptValidationFiles) {
170
            $this->javaScriptValidationFiles = [];
171
172
            $formConfiguration = $this->getFormObject()->getDefinition();
173
174
            foreach ($formConfiguration->getFields() as $field) {
175
                foreach ($field->getValidators() as $validator) {
176
                    $validatorClassName = $validator->getClassName();
177
178
                    if (in_array(AbstractValidator::class, class_parents($validatorClassName))) {
179
                        /** @var AbstractValidator $validatorClassName */
180
                        $this->javaScriptValidationFiles = array_merge($this->javaScriptValidationFiles, $validatorClassName::getJavaScriptValidationFiles());
181
                    }
182
                }
183
            }
184
185
            $this->javaScriptValidationFiles = array_unique($this->javaScriptValidationFiles);
186
        }
187
188
        return $this->javaScriptValidationFiles;
189
    }
190
}
191