Completed
Pull Request — feature/version-2 (#72)
by
unknown
01:52
created

DataAttributesAssetHandler::formatValue()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 9
nc 4
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\AssetHandler\Html;
15
16
use DateTime;
17
use Romm\Formz\AssetHandler\AbstractAssetHandler;
18
use Romm\Formz\Error\FormResult;
19
use Romm\Formz\Error\FormzMessageInterface;
20
use Romm\Formz\Exceptions\InvalidArgumentTypeException;
21
use Romm\Formz\Service\MessageService;
22
use Romm\Formz\Service\StringService;
23
use Throwable;
24
use Traversable;
25
use TYPO3\CMS\Extbase\Error\Result;
26
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
27
28
/**
29
 * This asset handler generates several data attributes which will be added to
30
 * the form element in the Fluid template. Most of these data attributes are
31
 * directly bound to fields and their properties.
32
 *
33
 * Example of data attributes:
34
 *  - Fields values: when a field changes, its new value will be indicated in
35
 *    the form with the attribute: `fz-value-{field name}="value"`.
36
 *  - Fields validation: when a field is considered as valid (it passed all its
37
 *    validation rules), the form gets the attribute: `fz-valid-{field name}`.
38
 *  - Fields errors: when a field validation fails with an error, the form gets
39
 *    the attribute: `fz-error-{field name}-{name of the error}`.
40
 *  - Fields warnings and notices: same as errors.
41
 */
42
class DataAttributesAssetHandler extends AbstractAssetHandler
43
{
44
    /**
45
     * Handles the data attributes containing the values of the form fields.
46
     *
47
     * Example: `fz-value-color="blue"`
48
     *
49
     * @param FormResult $formResult
50
     * @return array
51
     */
52
    public function getFieldsValuesDataAttributes(FormResult $formResult)
53
    {
54
        $result = [];
55
        $formObject = $this->getFormObject();
56
        $formInstance = $formObject->getForm();
57
58
        foreach ($formObject->getDefinition()->getFields() as $field) {
59
            $fieldName = $field->getName();
60
61
            if (false === $formResult->fieldIsDeactivated($field)) {
62
                $value = ObjectAccess::getProperty($formInstance, $fieldName);
63
64
                try {
65
                    $value = $this->formatValue($value);
66
                } catch (Throwable $e) {
0 ignored issues
show
Bug introduced by
The class Throwable does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
67
                    throw InvalidArgumentTypeException::dataAttributeValueNotFormattable($formInstance, $fieldName, $value);
68
                }
69
70
                if (false === empty($value)) {
71
                    $result[self::getFieldDataValueKey($fieldName)] = $value;
72
                }
73
            }
74
        }
75
76
        return $result;
77
    }
78
79
    /**
80
     * @return array
81
     */
82
    public function getFieldSubmissionDoneDataAttribute()
83
    {
84
        return [self::getFieldSubmissionDone() => '1'];
85
    }
86
87
    /**
88
     * Handles the data attributes for the fields which are valid.
89
     *
90
     * Example: `fz-valid-email="1"`
91
     *
92
     * @return array
93
     */
94
    public function getFieldsValidDataAttributes()
95
    {
96
        $result = [];
97
        $formConfiguration = $this->getFormObject()->getDefinition();
98
        $formResult = $this->getFormObject()->getFormResult();
99
100
        foreach ($formConfiguration->getFields() as $field) {
101
            $fieldName = $field->getName();
102
103
            if (false === $formResult->fieldIsDeactivated($field)
104
                && false === $formResult->forProperty($fieldName)->hasErrors()
105
            ) {
106
                $result[self::getFieldDataValidKey($fieldName)] = '1';
107
            }
108
        }
109
110
        return $result;
111
    }
112
113
    /**
114
     * Handles the data attributes for the fields which got errors, warnings and
115
     * notices.
116
     *
117
     * Examples:
118
     * - `fz-error-email="1"`
119
     * - `fz-error-email-rule-default="1"`
120
     *
121
     * @return array
122
     */
123
    public function getFieldsMessagesDataAttributes()
124
    {
125
        $result = [];
126
        $formConfiguration = $this->getFormObject()->getDefinition();
127
        $formResult = $this->getFormObject()->getFormResult();
128
129
        foreach ($formResult->getSubResults() as $fieldName => $fieldResult) {
130
            if (true === $formConfiguration->hasField($fieldName)
131
                && false === $formResult->fieldIsDeactivated($formConfiguration->getField($fieldName))
132
            ) {
133
                $result += $this->getFieldErrorMessages($fieldName, $fieldResult);
134
                $result += $this->getFieldWarningMessages($fieldName, $fieldResult);
135
                $result += $this->getFieldNoticeMessages($fieldName, $fieldResult);
136
            }
137
        }
138
139
        return $result;
140
    }
141
142
    /**
143
     * @param string $fieldName
144
     * @param Result $fieldResult
145
     * @return array
146
     */
147
    protected function getFieldErrorMessages($fieldName, Result $fieldResult)
148
    {
149
        return (true === $fieldResult->hasErrors())
150
            ? $this->addFieldMessageDataAttribute($fieldName, $fieldResult->getErrors(), 'error')
0 ignored issues
show
Documentation introduced by
$fieldResult->getErrors() is of type array<integer,object<TYP...S\Extbase\Error\Error>>, but the function expects a array<integer,object<Rom...FormzMessageInterface>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
151
            : [];
152
    }
153
154
    /**
155
     * @param string $fieldName
156
     * @param Result $fieldResult
157
     * @return array
158
     */
159
    protected function getFieldWarningMessages($fieldName, Result $fieldResult)
160
    {
161
        return (true === $fieldResult->hasWarnings())
162
            ? $this->addFieldMessageDataAttribute($fieldName, $fieldResult->getWarnings(), 'warning')
0 ignored issues
show
Documentation introduced by
$fieldResult->getWarnings() is of type array<integer,object<TYP...Extbase\Error\Warning>>, but the function expects a array<integer,object<Rom...FormzMessageInterface>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
163
            : [];
164
    }
165
166
    /**
167
     * @param string $fieldName
168
     * @param Result $fieldResult
169
     * @return array
170
     */
171
    protected function getFieldNoticeMessages($fieldName, Result $fieldResult)
172
    {
173
        return (true === $fieldResult->hasNotices())
174
            ? $this->addFieldMessageDataAttribute($fieldName, $fieldResult->getNotices(), 'notice')
0 ignored issues
show
Documentation introduced by
$fieldResult->getNotices() is of type array<integer,object<TYP...\Extbase\Error\Notice>>, but the function expects a array<integer,object<Rom...FormzMessageInterface>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
175
            : [];
176
    }
177
178
    /**
179
     * @param string                  $fieldName
180
     * @param FormzMessageInterface[] $messages
181
     * @param string                  $type
182
     * @return array
183
     */
184
    protected function addFieldMessageDataAttribute($fieldName, array $messages, $type)
185
    {
186
        $result = [self::getFieldDataMessageKey($fieldName, $type) => '1'];
187
188
        foreach ($messages as $message) {
189
            $validationName = MessageService::get()->getMessageValidationName($message);
190
            $messageKey = MessageService::get()->getMessageKey($message);
191
192
            $result[self::getFieldDataValidationMessageKey($fieldName, $type, $validationName, $messageKey)] = '1';
193
        }
194
195
        return $result;
196
    }
197
198
    /**
199
     * Checks the type of a given data attribute and formats it if needed.
200
     *
201
     * @param mixed $value
202
     * @return array
203
     */
204
    protected function formatValue($value)
205
    {
206
        if (is_array($value) || $value instanceof Traversable) {
207
            $value = implode(',', $value);
208
        } elseif ($value instanceof DateTime) {
209
            $format = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
210
            $value = $value->format($format);
211
        } elseif (false === is_string($value)) {
212
            $value = (string)$value;
213
        }
214
215
        return $value;
216
    }
217
218
    /**
219
     * Formats the data value attribute key for a given field name.
220
     *
221
     * @param string $fieldName Name of the field.
222
     * @return string
223
     */
224
    public static function getFieldDataValueKey($fieldName)
225
    {
226
        return 'fz-value-' . StringService::get()->sanitizeString($fieldName);
227
    }
228
229
    /**
230
     * Formats the data valid attribute key for a given field name.
231
     *
232
     * @param string $fieldName Name of the field.
233
     * @return string
234
     */
235
    public static function getFieldDataValidKey($fieldName)
236
    {
237
        return 'fz-valid-' . StringService::get()->sanitizeString($fieldName);
238
    }
239
240
    /**
241
     * Formats the data message attribute key for a given field name.
242
     *
243
     * @param string $fieldName Name of the field.
244
     * @param string $type      Type of the message: `error`, `warning` or `notice`.
245
     * @return string
246
     */
247
    public static function getFieldDataMessageKey($fieldName, $type = 'error')
248
    {
249
        return 'fz-' . $type . '-' . StringService::get()->sanitizeString($fieldName);
250
    }
251
252
    /**
253
     * @return string
254
     */
255
    public static function getFieldSubmissionDone()
256
    {
257
        return 'fz-submission-done';
258
    }
259
260
    /**
261
     * Formats the data message attribute key for a given failed validation for
262
     * the given field name.
263
     *
264
     * @param string $fieldName
265
     * @param string $type Type of the message: `error`, `warning` or `notice`.
266
     * @param string $validationName
267
     * @param string $messageKey
268
     * @return string
269
     */
270
    public static function getFieldDataValidationMessageKey($fieldName, $type, $validationName, $messageKey)
271
    {
272
        $stringService = StringService::get();
273
274
        return vsprintf(
275
            'fz-%s-%s-%s-%s',
276
            [
277
                $type,
278
                $stringService->sanitizeString($fieldName),
279
                $stringService->sanitizeString($validationName),
280
                $stringService->sanitizeString($messageKey)
281
            ]
282
        );
283
    }
284
}
285