Completed
Push — unit-test-services ( f70ec7...99caba )
by Romain
02:28
created

DataAttributesAssetHandler::getFieldsMessagesDataAttributes()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.2
c 0
b 0
f 0
cc 4
eloc 11
nc 3
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\AssetHandler\Html;
15
16
use Romm\Formz\AssetHandler\AbstractAssetHandler;
17
use Romm\Formz\Error\FormResult;
18
use Romm\Formz\Error\FormzMessageInterface;
19
use Romm\Formz\Service\StringService;
20
use TYPO3\CMS\Extbase\Error\Result;
21
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
22
23
/**
24
 * This asset handler generates several data attributes which will be added to
25
 * the form element in the Fluid template. Most of these data attributes are
26
 * directly bound to fields and their properties.
27
 *
28
 * Example of data attributes:
29
 *  - Fields values: when a field changes, its new value will be indicated in
30
 *    the form with the attribute: `fz-value-{field name}="value"`.
31
 *  - Fields validation: when a field is considered as valid (it passed all its
32
 *    validation rules), the form gets the attribute: `fz-valid-{field name}`.
33
 *  - Fields errors: when a field validation fails with an error, the form gets
34
 *    the attribute: `fz-error-{field name}-{name of the error}`.
35
 *  - Fields warnings and notices: same as errors.
36
 */
37
class DataAttributesAssetHandler extends AbstractAssetHandler
38
{
39
40
    /**
41
     * Handles the data attributes containing the values of the form fields.
42
     *
43
     * Example: `fz-value-color="blue"`
44
     *
45
     * @param FormResult $formResult
46
     * @return array
47
     */
48
    public function getFieldsValuesDataAttributes(FormResult $formResult)
49
    {
50
        $result = [];
51
        $formObject = $this->getFormObject();
52
        $formInstance = $formObject->getForm();
53
54
        foreach ($formObject->getConfiguration()->getFields() as $field) {
55
            $fieldName = $field->getFieldName();
56
57
            if (false === $formResult->fieldIsDeactivated($field)) {
58
                $value = ObjectAccess::getProperty($formInstance, $fieldName);
59
                $value = (is_array($value))
60
                    ? implode(' ', $value)
61
                    : $value;
62
63
                if (false === empty($value)) {
64
                    $result[self::getFieldDataValueKey($fieldName)] = $value;
65
                }
66
            }
67
        }
68
69
        return $result;
70
    }
71
72
    /**
73
     * Handles the data attributes for the fields which got errors, warnings and
74
     * notices.
75
     *
76
     * Examples:
77
     * - `fz-error-email="1"`
78
     * - `fz-error-email-rule-default="1"`
79
     *
80
     * @return array
81
     */
82
    public function getFieldsMessagesDataAttributes()
83
    {
84
        $result = [];
85
        $formConfiguration = $this->getFormObject()->getConfiguration();
86
        $formResult = $this->getFormObject()->getFormResult();
87
88
        foreach ($formResult->getSubResults() as $fieldName => $fieldResult) {
89
            if (true === $formConfiguration->hasField($fieldName)
90
                && false === $formResult->fieldIsDeactivated($formConfiguration->getField($fieldName))
0 ignored issues
show
Bug introduced by
It seems like $formConfiguration->getField($fieldName) can be null; however, fieldIsDeactivated() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
91
            ) {
92
                $result += $this->getFieldErrorMessages($fieldName, $fieldResult);
93
                $result += $this->getFieldWarningMessages($fieldName, $fieldResult);
94
                $result += $this->getFieldNoticeMessages($fieldName, $fieldResult);
95
            }
96
        }
97
98
        return $result;
99
    }
100
101
    /**
102
     * @param string $fieldName
103
     * @param Result $fieldResult
104
     * @return array
105
     */
106
    protected function getFieldErrorMessages($fieldName, Result $fieldResult)
107
    {
108
        return (true === $fieldResult->hasErrors())
109
            ? $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...
110
            : [];
111
    }
112
113
    /**
114
     * @param string $fieldName
115
     * @param Result $fieldResult
116
     * @return array
117
     */
118
    protected function getFieldWarningMessages($fieldName, Result $fieldResult)
119
    {
120
        return (true === $fieldResult->hasWarnings())
121
            ? $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...
122
            : [];
123
    }
124
125
    /**
126
     * @param string $fieldName
127
     * @param Result $fieldResult
128
     * @return array
129
     */
130
    protected function getFieldNoticeMessages($fieldName, Result $fieldResult)
131
    {
132
        return (true === $fieldResult->hasNotices())
133
            ? $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...
134
            : [];
135
    }
136
137
    /**
138
     * @param string                  $fieldName
139
     * @param FormzMessageInterface[] $messages
140
     * @param string                  $type
141
     * @return array
142
     */
143
    protected function addFieldMessageDataAttribute($fieldName, array $messages, $type)
144
    {
145
        $result = [self::getFieldDataMessageKey($fieldName, $type) => '1'];
146
147
        foreach ($messages as $message) {
148
            $validationName = $message->getValidationName();
149
            $messageKey = $message->getMessageKey();
150
151
            $result[self::getFieldDataValidationMessageKey($fieldName, $type, $validationName, $messageKey)] = '1';
152
        }
153
154
        return $result;
155
    }
156
157
    /**
158
     * Handles the data attributes for the fields which are valid.
159
     *
160
     * Example: `fz-valid-email="1"`
161
     *
162
     * @return array
163
     */
164
    public function getFieldsValidDataAttributes()
165
    {
166
        $result = [];
167
        $formConfiguration = $this->getFormObject()->getConfiguration();
168
        $formResult = $this->getFormObject()->getFormResult();
169
170
        foreach ($formConfiguration->getFields() as $field) {
171
            $fieldName = $field->getFieldName();
172
173
            if (false === $formResult->fieldIsDeactivated($field)
174
                && false === $formResult->forProperty($fieldName)->hasErrors()
175
            ) {
176
                $result[self::getFieldDataValidKey($fieldName)] = '1';
177
            }
178
        }
179
180
        return $result;
181
    }
182
183
    /**
184
     * Formats the data value attribute key for a given field name.
185
     *
186
     * @param string $fieldName Name of the field.
187
     * @return string
188
     */
189
    public static function getFieldDataValueKey($fieldName)
190
    {
191
        return 'fz-value-' . StringService::get()->sanitizeString($fieldName);
192
    }
193
194
    /**
195
     * Formats the data valid attribute key for a given field name.
196
     *
197
     * @param string $fieldName Name of the field.
198
     * @return string
199
     */
200
    public static function getFieldDataValidKey($fieldName)
201
    {
202
        return 'fz-valid-' . StringService::get()->sanitizeString($fieldName);
203
    }
204
205
    /**
206
     * Formats the data message attribute key for a given field name.
207
     *
208
     * @param string $fieldName Name of the field.
209
     * @param string $type      Type of the message: `error`, `warning` or `notice`.
210
     * @return string
211
     */
212
    public static function getFieldDataMessageKey($fieldName, $type = 'error')
213
    {
214
        return 'fz-' . $type . '-' . StringService::get()->sanitizeString($fieldName);
215
    }
216
217
    /**
218
     * @return string
219
     */
220
    public static function getFieldSubmissionDone()
221
    {
222
        return 'fz-submission-done';
223
    }
224
225
    /**
226
     * Formats the data message attribute key for a given failed validation for
227
     * the given field name.
228
     *
229
     * @param string $fieldName
230
     * @param string $type Type of the message: `error`, `warning` or `notice`.
231
     * @param string $validationName
232
     * @param string $messageKey
233
     * @return string
234
     */
235
    public static function getFieldDataValidationMessageKey($fieldName, $type, $validationName, $messageKey)
236
    {
237
        $stringService = StringService::get();
238
239
        return vsprintf(
240
            'fz-%s-%s-%s-%s',
241
            [
242
                $type,
243
                $stringService->sanitizeString($fieldName),
244
                $stringService->sanitizeString($validationName),
245
                $stringService->sanitizeString($messageKey)
246
            ]
247
        );
248
    }
249
}
250