Completed
Push — feature/middleware ( f1ca06...1ed36f )
by Romain
02:16
created

applyBehavioursOnSubmittedForm()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 24
rs 8.6845
cc 4
eloc 12
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\Service\ViewHelper\Form;
15
16
use Romm\Formz\AssetHandler\Html\DataAttributesAssetHandler;
17
use Romm\Formz\Behaviours\BehavioursManager;
18
use Romm\Formz\Core\Core;
19
use Romm\Formz\Error\FormResult;
20
use Romm\Formz\Exceptions\DuplicateEntryException;
21
use Romm\Formz\Form\FormObject\FormObject;
22
use Romm\Formz\Validation\Validator\Form\AbstractFormValidator;
23
use Romm\Formz\Validation\Validator\Form\DefaultFormValidator;
24
use TYPO3\CMS\Core\SingletonInterface;
25
use TYPO3\CMS\Core\Utility\GeneralUtility;
26
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
27
use TYPO3\CMS\Extbase\Error\Result;
28
use TYPO3\CMS\Extbase\Mvc\Web\Request;
29
use TYPO3\CMS\Fluid\Core\ViewHelper\ViewHelperVariableContainer;
30
use TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper;
31
32
/**
33
 * This class contains methods that help view helpers to manipulate data and
34
 * know more things concerning the current form state.
35
 *
36
 * It is mainly configured inside the `FormViewHelper`, and used in other
37
 * view helpers.
38
 */
39
class FormViewHelperService implements SingletonInterface
40
{
41
    /**
42
     * @var bool
43
     */
44
    protected $formContext = false;
45
46
    /**
47
     * @var FormObject
48
     */
49
    protected $formObject;
50
51
    /**
52
     * @var Request
53
     */
54
    protected $request;
55
56
    /**
57
     * @var Result
58
     */
59
    protected $result;
60
61
    /**
62
     * Reset every state that can be used by this service.
63
     */
64
    public function resetState()
65
    {
66
        $this->formContext = false;
67
        $this->formObject = null;
68
        $this->request = null;
69
    }
70
71
    /**
72
     * Will activate the form context, changing the result returned by the
73
     * function `formContextExists()`.
74
     *
75
     * @return FormViewHelperService
76
     * @throws DuplicateEntryException
77
     */
78
    public function activateFormContext()
79
    {
80
        if (true === $this->formContext) {
81
            throw DuplicateEntryException::duplicatedFormContext();
82
        }
83
84
        $this->formContext = true;
85
        $this->result = new Result;
86
87
        return $this;
88
    }
89
90
    /**
91
     * Returns `true` if the `FormViewHelper` context exists.
92
     *
93
     * @return bool
94
     */
95
    public function formContextExists()
96
    {
97
        return $this->formContext;
98
    }
99
100
    /**
101
     * Will loop on the submitted form fields and apply behaviours if their
102
     * configuration contains.
103
     */
104
    public function applyBehavioursOnSubmittedForm()
105
    {
106
        if ($this->formObject->formWasSubmitted()) {
107
            $request = $this->request->getOriginalRequest();
108
            $formName = $this->formObject->getName();
109
110
            if ($request
111
                && $request->hasArgument($formName)
112
            ) {
113
                /** @var BehavioursManager $behavioursManager */
114
                $behavioursManager = GeneralUtility::makeInstance(BehavioursManager::class);
115
116
                /** @var array $originalForm */
117
                $originalForm = $request->getArgument($formName);
118
119
                $formProperties = $behavioursManager->applyBehaviourOnPropertiesArray(
120
                    $originalForm,
121
                    $this->formObject->getDefinition()
122
                );
123
124
                $request->setArgument($formName, $formProperties);
125
            }
126
        }
127
    }
128
129
    /**
130
     * Takes care of injecting data for the form.
131
     *
132
     * If the form was generated using a content object, information about it
133
     * are injected, to be retrieved later to be able for instance to fetch the
134
     * object settings (TypoScript, FlexForm, ...).
135
     */
136
    public function injectFormRequestData()
137
    {
138
        if (false === $this->formObject->hasForm()) {
139
            return;
140
        }
141
142
        /** @var ConfigurationManager $configurationManager */
143
        $configurationManager = Core::instantiate(ConfigurationManager::class);
144
145
        $contentObject = $configurationManager->getContentObject();
146
147
        if (null !== $contentObject) {
148
            $requestData = $this->formObject->getRequestData();
149
150
            $requestData->setContentObjectTable($contentObject->getCurrentTable());
151
            $requestData->setContentObjectUid($contentObject->data['uid']);
152
        }
153
    }
154
155
    /**
156
     * Fetches all data attributes that are bound to the form: fields values,
157
     * validation result and others.
158
     *
159
     * @param DataAttributesAssetHandler $dataAttributesAssetHandler
160
     * @return array
161
     */
162
    public function getDataAttributes(DataAttributesAssetHandler $dataAttributesAssetHandler)
163
    {
164
        $dataAttributes = [];
165
166
        if ($this->formObject->hasForm()) {
167
            /*
168
             * Getting the data attributes for the form values. It is needed to
169
             * have a validation result because a field can be deactivated (in
170
             * that case, the data attribute for this field is removed).
171
             */
172
            if (false === $this->formObject->formWasValidated()) {
173
                $formResult = $this->getFormValidationResult();
174
            } else {
175
                $formResult = $this->formObject->getFormResult();
176
            }
177
178
            $dataAttributes += $dataAttributesAssetHandler->getFieldsValuesDataAttributes($formResult);
179
        }
180
181
        if (true === $this->formObject->formWasSubmitted()) {
182
            $dataAttributes += $dataAttributesAssetHandler->getFieldSubmissionDoneDataAttribute();
183
        }
184
185
        if (true === $this->formObject->formWasValidated()) {
186
            $dataAttributes += $dataAttributesAssetHandler->getFieldsValidDataAttributes();
187
            $dataAttributes += $dataAttributesAssetHandler->getFieldsMessagesDataAttributes();
188
        }
189
190
        return $dataAttributes;
191
    }
192
193
    /**
194
     * Returns the list of fields that have been added below the form view
195
     * helper.
196
     *
197
     * @param ViewHelperVariableContainer $variableContainer
198
     * @return array
199
     */
200
    public function getCurrentFormFieldNames(ViewHelperVariableContainer $variableContainer)
201
    {
202
        $formFieldNames = $variableContainer->get(FormViewHelper::class, 'formFieldNames');
203
        $cleanFormFieldNames = [];
204
205
        foreach ($formFieldNames as $fieldName) {
206
            $explode = explode('[', $fieldName);
207
208
            if (count($explode) >= 3) {
209
                $formName = rtrim($explode[1], ']');
210
                $fieldName = rtrim($explode[2], ']');
211
212
                if ($formName === $this->formObject->getName()
213
                    && $fieldName !== '__identity'
214
                ) {
215
                    $cleanFormFieldNames[$fieldName] = $fieldName;
216
                }
217
            }
218
        }
219
220
        return $cleanFormFieldNames;
221
    }
222
223
    /**
224
     * @return FormObject
225
     */
226
    public function getFormObject()
227
    {
228
        return $this->formObject;
229
    }
230
231
    /**
232
     * @param FormObject $formObject
233
     */
234
    public function setFormObject(FormObject $formObject)
235
    {
236
        $this->formObject = $formObject;
237
    }
238
239
    /**
240
     * @param Request $request
241
     */
242
    public function setRequest(Request $request)
243
    {
244
        $this->request = $request;
245
    }
246
247
    /**
248
     * @return Result
249
     */
250
    public function getResult()
251
    {
252
        return $this->result;
253
    }
254
255
    /**
256
     * @return FormResult
257
     */
258
    protected function getFormValidationResult()
259
    {
260
        $formValidator = $this->getFormValidator($this->formObject->getName());
261
262
        return $formValidator->validate($this->formObject->getForm());
263
    }
264
265
    /**
266
     * @param string $formName
267
     * @return AbstractFormValidator
268
     */
269
    protected function getFormValidator($formName)
270
    {
271
        /** @var AbstractFormValidator $validator */
272
        $validator = Core::instantiate(
273
            DefaultFormValidator::class,
274
            [
275
                'name'  => $formName,
276
                'dummy' => true
277
            ]
278
        );
279
280
        return $validator;
281
    }
282
}
283