Completed
Push — bugfix/version-2/format-data-a... ( a80407 )
by Romain
01:52
created

FormViewHelperService   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 187
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 23
lcom 1
cbo 7
dl 0
loc 187
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A resetState() 0 5 1
A activateFormContext() 0 10 2
A formContextExists() 0 4 1
B applyBehavioursOnSubmittedForm() 0 24 4
B getDataAttributes() 0 32 5
B formatDataAttributes() 0 15 6
A getFormObject() 0 4 1
A setFormObject() 0 4 1
A getFormValidationResult() 0 6 1
A getFormValidator() 0 13 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\Service\ViewHelper\Form;
15
16
use DateTime;
17
use Romm\Formz\AssetHandler\Html\DataAttributesAssetHandler;
18
use Romm\Formz\Behaviours\BehavioursManager;
19
use Romm\Formz\Core\Core;
20
use Romm\Formz\Error\FormResult;
21
use Romm\Formz\Exceptions\DuplicateEntryException;
22
use Romm\Formz\Form\FormObject\FormObject;
23
use Romm\Formz\Validation\Validator\Form\DefaultFormValidator;
24
use Traversable;
25
use TYPO3\CMS\Core\SingletonInterface;
26
use TYPO3\CMS\Core\Utility\GeneralUtility;
27
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
28
29
/**
30
 * This class contains methods that help view helpers to manipulate data and
31
 * know more things concerning the current form state.
32
 *
33
 * It is mainly configured inside the `FormViewHelper`, and used in other
34
 * view helpers.
35
 */
36
class FormViewHelperService implements SingletonInterface
37
{
38
    /**
39
     * @var bool
40
     */
41
    protected $formContext = false;
42
43
    /**
44
     * @var FormObject
45
     */
46
    protected $formObject;
47
48
    /**
49
     * Reset every state that can be used by this service.
50
     */
51
    public function resetState()
52
    {
53
        $this->formContext = false;
54
        $this->formObject = null;
55
    }
56
57
    /**
58
     * Will activate the form context, changing the result returned by the
59
     * function `formContextExists()`.
60
     *
61
     * @return FormViewHelperService
62
     * @throws DuplicateEntryException
63
     */
64
    public function activateFormContext()
65
    {
66
        if (true === $this->formContext) {
67
            throw DuplicateEntryException::duplicatedFormContext();
68
        }
69
70
        $this->formContext = true;
71
72
        return $this;
73
    }
74
75
    /**
76
     * Returns `true` if the `FormViewHelper` context exists.
77
     *
78
     * @return bool
79
     */
80
    public function formContextExists()
81
    {
82
        return $this->formContext;
83
    }
84
85
    /**
86
     * Will loop on the submitted form fields and apply behaviours if their
87
     * configuration contains.
88
     *
89
     * @param ControllerContext $controllerContext
90
     */
91
    public function applyBehavioursOnSubmittedForm(ControllerContext $controllerContext)
92
    {
93
        if ($this->formObject->formWasSubmitted()) {
94
            $request = $controllerContext->getRequest()->getOriginalRequest();
95
            $formName = $this->formObject->getName();
96
97
            if ($request
98
                && $request->hasArgument($formName)
99
            ) {
100
                /** @var BehavioursManager $behavioursManager */
101
                $behavioursManager = GeneralUtility::makeInstance(BehavioursManager::class);
102
103
                /** @var array $originalForm */
104
                $originalForm = $request->getArgument($formName);
105
106
                $formProperties = $behavioursManager->applyBehaviourOnPropertiesArray(
107
                    $originalForm,
108
                    $this->formObject->getDefinition()
109
                );
110
111
                $request->setArgument($formName, $formProperties);
112
            }
113
        }
114
    }
115
116
    /**
117
     * Fetches all data attributes that are bound to the form: fields values,
118
     * validation result and others.
119
     *
120
     * @param DataAttributesAssetHandler $dataAttributesAssetHandler
121
     * @return array
122
     */
123
    public function getDataAttributes(DataAttributesAssetHandler $dataAttributesAssetHandler)
124
    {
125
        $dataAttributes = [];
126
127
        if ($this->formObject->hasForm()) {
128
            /*
129
             * Getting the data attributes for the form values. It is needed to
130
             * have a validation result because a field can be deactivated (in
131
             * that case, the data attribute for this field is removed).
132
             */
133
            if (false === $this->formObject->formWasValidated()) {
134
                $formResult = $this->getFormValidationResult();
135
            } else {
136
                $formResult = $this->formObject->getFormResult();
137
            }
138
139
            $dataAttributes += $dataAttributesAssetHandler->getFieldsValuesDataAttributes($formResult);
140
        }
141
142
        if (true === $this->formObject->formWasSubmitted()) {
143
            $dataAttributes += $dataAttributesAssetHandler->getFieldSubmissionDoneDataAttribute();
144
        }
145
146
        if (true === $this->formObject->formWasValidated()) {
147
            $dataAttributes += $dataAttributesAssetHandler->getFieldsValidDataAttributes();
148
            $dataAttributes += $dataAttributesAssetHandler->getFieldsMessagesDataAttributes();
149
        }
150
151
        $dataAttributes = $this->formatDataAttributes($dataAttributes);
152
153
        return $dataAttributes;
154
    }
155
156
    /**
157
     * Checks the type of every data attribute and formats it if needed.
158
     * @todo add unit test
159
     *
160
     * @param array $dataAttributes
161
     * @return array
162
     */
163
    protected function formatDataAttributes(array $dataAttributes)
164
    {
165
        foreach ($dataAttributes as $key => $value) {
166
            if (is_array($value) || $value instanceof Traversable) {
167
                $dataAttributes[$key] = implode(',', $value);
168
            } elseif ($value instanceof DateTime) {
169
                $format = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
170
                $dataAttributes[$key] = $value->format($format);
171
            } elseif (false === is_string($value)) {
172
                $dataAttributes[$key] = (string)$value;
173
            }
174
        }
175
176
        return $dataAttributes;
177
    }
178
179
    /**
180
     * @return FormObject
181
     */
182
    public function getFormObject()
183
    {
184
        return $this->formObject;
185
    }
186
187
    /**
188
     * @param FormObject $formObject
189
     */
190
    public function setFormObject(FormObject $formObject)
191
    {
192
        $this->formObject = $formObject;
193
    }
194
195
    /**
196
     * @return FormResult
197
     */
198
    protected function getFormValidationResult()
199
    {
200
        $formValidator = $this->getFormValidator($this->formObject->getName());
201
202
        return $formValidator->validate($this->formObject->getForm());
203
    }
204
205
    /**
206
     * @param string $formName
207
     * @return DefaultFormValidator
208
     */
209
    protected function getFormValidator($formName)
210
    {
211
        /** @var DefaultFormValidator $validation */
212
        $validation = Core::instantiate(
213
            DefaultFormValidator::class,
214
            [
215
                'name'  => $formName,
216
                'dummy' => true
217
            ]
218
        );
219
220
        return $validation;
221
    }
222
}
223