Completed
Pull Request — master (#25)
by
unknown
04:17
created

FormzLocalizationJavaScriptAssetHandler::handleRealTranslations()   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
 * 2016 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\Configuration\Form\Field\Field;
17
use Romm\Formz\Core\Core;
18
19
/**
20
 * This asset handler will manage the translations which will be sent to Formz
21
 * in JavaScript (`Formz.Localization`).
22
 *
23
 * The validation messages of the fields are handled in this class.
24
 */
25
class FormzLocalizationJavaScriptAssetHandler extends AbstractJavaScriptAssetHandler
26
{
27
28
    /**
29
     * Contains the full list of keys/translations.
30
     *
31
     * @var array
32
     */
33
    protected $translations = [];
34
35
    /**
36
     * Contains the list of keys which are bound to translations, for a field
37
     * validation. The value is an array of keys, because a validation rule may
38
     * have several messages.
39
     *
40
     * @var array
41
     */
42
    protected $translationKeysForFieldValidation = [];
43
44
    /**
45
     * Contains the list of fields validations which were already processed by
46
     * this asset handler.
47
     *
48
     * @var array
49
     */
50
    protected $injectedTranslationKeysForFieldValidation = [];
51
52
    /**
53
     * Will generate and return the JavaScript code which add all registered
54
     * translations to the JavaScript library.
55
     *
56
     * @return string
57
     */
58
    public function getJavaScriptCode()
59
    {
60
        $realTranslations = [];
61
        $translationsBinding = [];
62
63
        foreach ($this->translations as $key => $value) {
64
            $hash = sha1($value);
65
            $realTranslations[$hash] = $value;
66
            $translationsBinding[$key] = $hash;
67
        }
68
69
        $jsonRealTranslations = $this->handleRealTranslations(Core::get()->arrayToJavaScriptJson($realTranslations));
70
        $jsonTranslationsBinding = $this->handleTranslationsBinding(Core::get()->arrayToJavaScriptJson($translationsBinding));
71
72
        return <<<JS
73
Formz.Localization.addLocalization($jsonRealTranslations, $jsonTranslationsBinding);
74
JS;
75
    }
76
77
    /**
78
     * Returns the keys which are bound to translations, for a given field
79
     * validation rule.
80
     *
81
     * @param Field  $field
82
     * @param string $validationName
83
     * @return array
84
     */
85
    public function getTranslationKeysForFieldValidation(Field $field, $validationName)
86
    {
87
        $result = [];
88
89
        if (true === $field->hasValidation($validationName)) {
90
            $key = $field->getFieldName() . '-' . $validationName;
91
92
            $this->storeTranslationsForFieldValidation($field);
93
94
            $result = $this->translationKeysForFieldValidation[$key];
95
        }
96
97
        return $result;
98
    }
99
100
    /**
101
     * Will loop on each field of the given form, and get every translations for
102
     * the validation rules messages.
103
     *
104
     * @return $this
105
     */
106
    public function injectTranslationsForFormFieldsValidation()
107
    {
108
        $formConfiguration = $this->getFormObject()->getConfiguration();
109
110
        foreach ($formConfiguration->getFields() as $field) {
111
            $this->storeTranslationsForFieldValidation($field);
112
        }
113
114
        return $this;
115
    }
116
117
    /**
118
     * Will loop on each validation rule of the given field, and get the
119
     * translations of the rule messages.
120
     *
121
     * @param Field $field
122
     * @return $this
123
     */
124
    protected function storeTranslationsForFieldValidation(Field $field)
125
    {
126
        if (false === $this->translationsForFieldValidationWereInjected($field)) {
127
            $fieldName = $field->getFieldName();
128
129
            foreach ($field->getValidation() as $validationName => $validationConfiguration) {
0 ignored issues
show
Bug introduced by
The expression $field->getValidation() of type object<Romm\Formz\Config...Validation\Validation>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
130
                $dummyValidator = $this->getDummyValidator()
131
                    ->cloneValidator($validationConfiguration->getClassName());
132
133
                $messages = $dummyValidator->setExternalMessages($validationConfiguration->getMessages())
134
                    ->getMessages();
135
136
                foreach ($messages as $key => $message) {
137
                    $message = $dummyValidator->getMessage($key, ['{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}']);
138
139
                    $message = (is_string($message)) ? $message : '';
140
141
                    $localizationKey = $this->getIdentifierForFieldValidationName($field, $validationName, $key);
142
                    $this->addTranslation($localizationKey, $message);
143
                    $messages[$key] = $localizationKey;
144
                }
145
146
                $this->translationKeysForFieldValidation[$fieldName . '-' . $validationName] = $messages;
147
148
                $key = $this->getFormObject()->getClassName() . '-' . $field->getFieldName();
149
                $this->injectedTranslationKeysForFieldValidation[$key] = true;
150
            }
151
        }
152
153
        return $this;
154
    }
155
156
    /**
157
     * Adds a global translation value which will be added to the Formz
158
     * JavaScript localization service.
159
     *
160
     * @param string $key
161
     * @param string $value
162
     */
163
    protected function addTranslation($key, $value)
164
    {
165
        $this->translations[(string)$key] = (string)$value;
166
    }
167
168
    /**
169
     * Checks if the given field validation rules were already handled by this
170
     * asset handler.
171
     *
172
     * @param Field $field
173
     * @return bool
174
     */
175
    protected function translationsForFieldValidationWereInjected(Field $field)
176
    {
177
        $key = $this->getFormObject()->getClassName() . '-' . $field->getFieldName();
178
179
        return (true === isset($this->injectedTranslationKeysForFieldValidation[$key]));
180
    }
181
182
    /**
183
     * @param Field  $field
184
     * @param string $validationName
185
     * @param string $messageKey
186
     * @return string
187
     */
188
    protected function getIdentifierForFieldValidationName(Field $field, $validationName, $messageKey)
189
    {
190
        return str_replace(['\\', '_'], '', $this->getFormObject()->getClassName()) . '-' . $field->getFieldName() . '-' . $validationName . '-' . $messageKey;
191
    }
192
193
    /**
194
     * This function is here to help unit tests mocking.
195
     *
196
     * @param string $realTranslations
197
     * @return string
198
     */
199
    protected function handleRealTranslations($realTranslations)
200
    {
201
        return $realTranslations;
202
    }
203
204
    /**
205
     * This function is here to help unit tests mocking.
206
     *
207
     * @param string $translationsBinding
208
     * @return string
209
     */
210
    protected function handleTranslationsBinding($translationsBinding)
211
    {
212
        return $translationsBinding;
213
    }
214
}
215