Completed
Push — wip/steps ( 116a8d...b2c91c )
by Romain
02:25
created

StepMiddlewareService::getFormRawValues()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 10
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\Middleware\Item\Step\Service;
15
16
use Romm\Formz\Condition\Processor\ConditionProcessorFactory;
17
use Romm\Formz\Condition\Processor\DataObject\PhpConditionDataObject;
18
use Romm\Formz\Error\FormResult;
19
use Romm\Formz\Exceptions\InvalidArgumentTypeException;
20
use Romm\Formz\Form\Definition\Step\Step\Step;
21
use Romm\Formz\Form\Definition\Step\Step\StepDefinition;
22
use Romm\Formz\Form\FormObject\FormObject;
23
use Romm\Formz\Form\FormObject\FormObjectFactory;
24
use Romm\Formz\Form\FormObject\Service\Step\FormStepPersistence;
25
use Romm\Formz\Middleware\Request\Redirect;
26
use Romm\Formz\Service\Traits\SelfInstantiateTrait;
27
use Romm\Formz\Validation\Form\DataObject\FormValidatorDataObject;
28
use Romm\Formz\Validation\Form\FormValidatorExecutor;
29
use TYPO3\CMS\Core\SingletonInterface;
30
use TYPO3\CMS\Core\Utility\GeneralUtility;
31
use TYPO3\CMS\Extbase\Mvc\Web\Request;
32
33
/**
34
 * This service allows extended form steps manipulation.
35
 */
36
class StepMiddlewareService implements SingletonInterface
37
{
38
    use SelfInstantiateTrait;
39
40
    /**
41
     * @var FormObject
42
     */
43
    protected $formObject;
44
45
    /**
46
     * @var Request
47
     */
48
    protected $request;
49
50
    /**
51
     * @var StepMiddlewareValidationService
52
     */
53
    protected $validationService;
54
55
    /**
56
     * @var FormStepPersistence
57
     */
58
    protected $persistence;
59
60
    /**
61
     * @param FormObject $formObject
62
     * @param Request $request
63
     */
64
    public function reset(FormObject $formObject, Request $request)
65
    {
66
        $this->formObject = $formObject;
67
        $this->request = $request;
68
69
        $this->persistence = FormObjectFactory::get()->getStepService($formObject)->getStepPersistence();
70
71
        $this->validationService = GeneralUtility::makeInstance(StepMiddlewareValidationService::class, $this);
72
    }
73
74
    /**
75
     * @param Step $currentStep
76
     * @return StepDefinition|null
77
     */
78
    public function getNextStep(Step $currentStep)
79
    {
80
        /*
81
         * The form was submitted, and no error was found, we can safely
82
         * dispatch the request to the next step.
83
         */
84
        $currentStepDefinition = $this->getStepDefinition($currentStep);
85
86
        $this->validationService->markStepAsValidated($currentStepDefinition);
0 ignored issues
show
Bug introduced by
It seems like $currentStepDefinition defined by $this->getStepDefinition($currentStep) on line 84 can be null; however, Romm\Formz\Middleware\It...::markStepAsValidated() 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...
87
        // @todo tmp-delete?
88
//        // Saving submitted form data for further usage.
89
//        $this->markStepAsValidated($currentStepDefinition, $this->getFormRawValues());
90
        $this->addValidatedFields($this->formObject->getFormResult()->getValidatedFields());
91
92
        $nextStep = null;
93
94
        if ($currentStepDefinition->hasNextStep()) {
95
            $nextStep = $this->getNextStepDefinition($currentStepDefinition, true);
0 ignored issues
show
Bug introduced by
It seems like $currentStepDefinition defined by $this->getStepDefinition($currentStep) on line 84 can be null; however, Romm\Formz\Middleware\It...getNextStepDefinition() 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...
96
        }
97
98
        return $nextStep;
99
    }
100
101
    // @todo tmp-delete?
102
//    /**
103
//     * Saves the submitted values in the metadata, for the given step.
104
//     *
105
//     * @param Step $currentStep
106
//     */
107
//    public function saveStepFormValues(Step $currentStep)
108
//    {
109
//        $this->persistence->addStepFormValues($this->getStepDefinition($currentStep), $this->getFormRawValues());
110
//    }
111
//
112
//    /**
113
//     * Fetches the raw values sent in the request.
114
//     *
115
//     * @return array
116
//     * @throws InvalidArgumentTypeException
117
//     */
118
//    protected function getFormRawValues()
119
//    {
120
//        $formName = $this->getFormObject()->getName();
121
//        $formArray = null;
122
//
123
//        if ($this->request->hasArgument($formName)) {
124
//            /** @var array $formArray */
125
//            $formArray = $this->request->getArgument($formName);
126
//
127
//            if (false === is_array($formArray)) {
128
//                throw InvalidArgumentTypeException::formArgumentNotArray($this->getFormObject(), $formArray);
129
//            }
130
//        } else {
131
//            $formArray = [];
132
//        }
133
//
134
//        return $formArray;
135
//    }
136
//
137
//    /**
138
//     * @see \Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareValidationService::markStepAsValidated()
139
//     *
140
//     * @param StepDefinition $stepDefinition
141
//     * @param array          $formValues
142
//     */
143
//    public function markStepAsValidated(StepDefinition $stepDefinition, array $formValues)
144
//    {
145
//        $this->validationService->markStepAsValidated($stepDefinition, $formValues);
146
//    }
147
148
    /**
149
     * @see \Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareValidationService::addValidatedFields
150
     *
151
     * @param array $validatedFields
152
     */
153
    public function addValidatedFields(array $validatedFields)
154
    {
155
        $this->validationService->addValidatedFields($validatedFields);
156
    }
157
158
    /**
159
     * @see \Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareValidationService::stepDefinitionIsValid
160
     *
161
     * @param StepDefinition $stepDefinition
162
     * @return bool
163
     */
164
    public function stepIsValid(StepDefinition $stepDefinition)
165
    {
166
        return $this->validationService->stepDefinitionIsValid($stepDefinition);
167
    }
168
169
    /**
170
     * @see \Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareValidationService::getFirstInvalidStep
171
     *
172
     * @param Step $step
173
     * @return StepDefinition|null
174
     */
175
    public function getFirstInvalidStep(Step $step)
176
    {
177
        return $this->validationService->getFirstInvalidStep($step);
178
    }
179
180
    /**
181
     * @param StepDefinition $step
182
     * @param bool           $removeConditionalSteps
183
     * @return StepDefinition
184
     */
185
    public function getNextStepDefinition(StepDefinition $step, $removeConditionalSteps = false)
186
    {
187
        $nextStep = null;
188
189
        if ($step->hasDivergence()) {
190
            $divergenceSteps = $step->getDivergenceSteps();
191
192
            foreach ($divergenceSteps as $divergenceStep) {
193
                if (true === $this->getStepDefinitionConditionResult($divergenceStep)) {
194
                    $nextStep = $divergenceStep;
195
                    break;
196
                }
197
            }
198
        }
199
200
        if (null === $nextStep) {
201
            while ($step->hasNextStep()) {
202
                $step = $step->getNextStep();
203
204
                if ($step->hasActivation()) {
205
                    if (true === $this->getStepDefinitionConditionResult($step)) {
206
                        $nextStep = $step;
207
                        break;
208
                    } elseif (true === $removeConditionalSteps) {
209
                        $this->persistence->removeStep($step);
210
                    }
211
                } else {
212
                    $nextStep = $step;
213
                    break;
214
                }
215
            }
216
        }
217
218
        return $nextStep;
219
    }
220
221
    /**
222
     * @param StepDefinition $stepDefinition
223
     * @param Redirect       $redirect
224
     */
225
    public function moveForwardToStep(StepDefinition $stepDefinition, Redirect $redirect)
226
    {
227
        $this->persistence->setStepLevel($stepDefinition);
228
        $this->redirectToStep($stepDefinition->getStep(), $redirect);
229
    }
230
231
    /**
232
     * Redirects the current request to the given step.
233
     *
234
     * @param Step     $step
235
     * @param Redirect $redirect
236
     */
237
    public function redirectToStep(Step $step, Redirect $redirect)
238
    {
239
        $redirect->toPage($step->getPageUid())
240
            ->toExtension($step->getExtension())
241
            ->toController($step->getController())
242
            ->toAction($step->getAction())
243
            ->withArguments([
244
                'fz-hash' => [
245
                    $this->formObject->getName() => $this->formObject->getFormHash()
246
                ]
247
            ])
248
            ->dispatch();
249
    }
250
251
    /**
252
     * @param StepDefinition $stepDefinition
253
     * @return bool
254
     */
255
    public function getStepDefinitionConditionResult(StepDefinition $stepDefinition)
256
    {
257
        $conditionProcessor = ConditionProcessorFactory::getInstance()->get($this->getFormObject());
258
        $tree = $conditionProcessor->getActivationConditionTreeForStep($stepDefinition);
259
        $todo = new FormValidatorExecutor(new FormValidatorDataObject($this->getFormObject(), new FormResult())); // @todo
260
        $dataObject = new PhpConditionDataObject($this->getFormObject()->getForm(), $todo);
261
262
        return $tree->getPhpResult($dataObject);
263
    }
264
265
    /**
266
     * @param Step $step
267
     * @return StepDefinition|null
268
     */
269
    public function getStepDefinition(Step $step)
270
    {
271
        return $this->findStepDefinition($step, $this->getFirstStepDefinition());
272
    }
273
274
    /**
275
     * @param Step           $step
276
     * @param StepDefinition $stepDefinition
277
     * @return StepDefinition|null
278
     */
279
    protected function findStepDefinition(Step $step, StepDefinition $stepDefinition)
280
    {
281
        if ($stepDefinition->getStep() === $step) {
282
            return $stepDefinition;
283
        }
284
285
        if ($stepDefinition->hasNextStep()) {
286
            $result = $this->findStepDefinition($step, $stepDefinition->getNextStep());
287
288
            if ($result instanceof StepDefinition) {
289
                return $result;
290
            }
291
        }
292
293
        if ($stepDefinition->hasDivergence()) {
294
            foreach ($stepDefinition->getDivergenceSteps() as $divergenceStep) {
295
                $result = $this->findStepDefinition($step, $divergenceStep);
296
297
                if ($result instanceof StepDefinition) {
298
                    return $result;
299
                }
300
            }
301
        }
302
303
        return null;
304
    }
305
306
    /**
307
     * @return FormStepPersistence
308
     */
309
    public function getStepPersistence()
310
    {
311
        return $this->persistence;
312
    }
313
314
    /**
315
     * @return FormObject
316
     */
317
    public function getFormObject()
318
    {
319
        return $this->formObject;
320
    }
321
322
    /**
323
     * @return StepDefinition
324
     */
325
    public function getFirstStepDefinition()
326
    {
327
        return $this->formObject->getDefinition()->getSteps()->getFirstStepDefinition();
328
    }
329
}
330