Completed
Push — wip/steps ( 00e2d0...2b61f8 )
by Romain
14:33
created

StepMiddlewareService::getFirstInvalidStep()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
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\Middleware\Item\Step\Service;
15
16
use Romm\Formz\Condition\Processor\ConditionProcessorFactory;
17
use Romm\Formz\Condition\Processor\DataObject\PhpConditionDataObject;
18
use Romm\Formz\Form\Definition\Step\Step\Step;
19
use Romm\Formz\Form\Definition\Step\Step\StepDefinition;
20
use Romm\Formz\Form\FormObject\FormObject;
21
use Romm\Formz\Form\FormObject\FormObjectFactory;
22
use Romm\Formz\Form\FormObject\Service\Step\FormStepPersistence;
23
use Romm\Formz\Middleware\Request\Redirect;
24
use Romm\Formz\Service\Traits\SelfInstantiateTrait;
25
use Romm\Formz\Validation\Validator\Form\DataObject\FormValidatorDataObject;
26
use Romm\Formz\Validation\Validator\Form\FormValidatorExecutor;
27
use TYPO3\CMS\Core\SingletonInterface;
28
use TYPO3\CMS\Core\Utility\GeneralUtility;
29
30
/**
31
 * This service allows extended form steps manipulation.
32
 */
33
class StepMiddlewareService implements SingletonInterface
34
{
35
    use SelfInstantiateTrait;
36
37
    /**
38
     * @var FormObject
39
     */
40
    protected $formObject;
41
42
    /**
43
     * @var StepMiddlewareValidationService
44
     */
45
    protected $validationService;
46
47
    /**
48
     * @var FormStepPersistence
49
     */
50
    protected $persistence;
51
52
    /**
53
     * @param FormObject $formObject
54
     */
55
    public function reset(FormObject $formObject)
56
    {
57
        $this->formObject = $formObject;
58
59
        $proxy = FormObjectFactory::get()->getProxy($formObject->getForm());
60
        $this->persistence = $proxy->getStepPersistence();
61
62
        $this->validationService = GeneralUtility::makeInstance(StepMiddlewareValidationService::class, $this);
63
    }
64
65
    /**
66
     * @see \Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareValidationService::markStepAsValidated
67
     *
68
     * @param StepDefinition $stepDefinition
69
     * @param array          $formValues
70
     */
71
    public function markStepAsValidated(StepDefinition $stepDefinition, array $formValues)
72
    {
73
        $this->validationService->markStepAsValidated($stepDefinition, $formValues);
74
    }
75
76
    /**
77
     * @see \Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareValidationService::addValidatedFields
78
     *
79
     * @param array $validatedFields
80
     */
81
    public function addValidatedFields(array $validatedFields)
82
    {
83
        $this->validationService->addValidatedFields($validatedFields);
84
    }
85
86
    /**
87
     * @see \Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareValidationService::stepDefinitionIsValid
88
     *
89
     * @param StepDefinition $stepDefinition
90
     * @return bool
91
     */
92
    public function stepIsValid(StepDefinition $stepDefinition)
93
    {
94
        return $this->validationService->stepDefinitionIsValid($stepDefinition);
95
    }
96
97
    /**
98
     * @see \Romm\Formz\Middleware\Item\Step\Service\StepMiddlewareValidationService::getFirstInvalidStep
99
     *
100
     * @param Step $step
101
     * @return StepDefinition|null
102
     */
103
    public function getFirstInvalidStep(Step $step)
104
    {
105
        return $this->validationService->getFirstInvalidStep($step);
106
    }
107
108
    /**
109
     * @param StepDefinition $step
110
     * @param bool           $removeConditionalSteps
111
     * @return StepDefinition
112
     */
113
    public function getNextStepDefinition(StepDefinition $step, $removeConditionalSteps = false)
114
    {
115
        $nextStep = null;
116
117
        if ($step->hasDivergence()) {
118
            $divergenceSteps = $step->getDivergenceSteps();
119
120
            foreach ($divergenceSteps as $divergenceStep) {
121
                if (true === $this->getStepDefinitionConditionResult($divergenceStep)) {
122
                    $nextStep = $divergenceStep;
123
                    break;
124
                }
125
            }
126
        }
127
128
        if (null === $nextStep) {
129
            while ($step->hasNextStep()) {
130
                $step = $step->getNextStep();
131
132
                if ($step->hasActivation()) {
133
                    if (true === $this->getStepDefinitionConditionResult($step)) {
134
                        $nextStep = $step;
135
                        break;
136
                    } elseif (true === $removeConditionalSteps) {
137
                        $this->persistence->removeStep($step);
138
                    }
139
                } else {
140
                    $nextStep = $step;
141
                    break;
142
                }
143
            }
144
        }
145
146
        return $nextStep;
147
    }
148
149
    /**
150
     * @param StepDefinition $stepDefinition
151
     * @param Redirect       $redirect
152
     */
153
    public function moveForwardToStep(StepDefinition $stepDefinition, Redirect $redirect)
154
    {
155
        $this->persistence->setStepLevel($stepDefinition);
156
        $this->redirectToStep($stepDefinition->getStep(), $redirect);
157
    }
158
159
    /**
160
     * Redirects the current request to the given step.
161
     *
162
     * @param Step     $step
163
     * @param Redirect $redirect
164
     */
165
    public function redirectToStep(Step $step, Redirect $redirect)
166
    {
167
        $redirect->toPage($step->getPageUid())
168
            ->toExtension($step->getExtension())
169
            ->toController($step->getController())
170
            ->toAction($step->getAction())
171
            ->withArguments([
172
                'fz-hash' => [
173
                    $this->formObject->getName() => $this->formObject->getFormHash()
174
                ]
175
            ])
176
            ->dispatch();
177
    }
178
179
    /**
180
     * @param Step $step
181
     * @return StepDefinition|null
182
     */
183
    public function getStepDefinition(Step $step)
184
    {
185
        return $this->findStep($step, $this->getFirstStepDefinition());
186
    }
187
188
    /**
189
     * @param StepDefinition $stepDefinition
190
     * @return bool
191
     */
192
    public function getStepDefinitionConditionResult(StepDefinition $stepDefinition)
193
    {
194
        $conditionProcessor = ConditionProcessorFactory::getInstance()->get($this->getFormObject());
195
        $tree = $conditionProcessor->getActivationConditionTreeForStep($stepDefinition);
196
        $todo = new FormValidatorExecutor($this->getFormObject(), new FormValidatorDataObject()); // @todo
197
        $dataObject = new PhpConditionDataObject($this->getFormObject()->getForm(), $todo);
198
199
        return $tree->getPhpResult($dataObject);
200
    }
201
202
    /**
203
     * @param Step           $step
204
     * @param StepDefinition $stepDefinition
205
     * @return StepDefinition|null
206
     */
207
    protected function findStep(Step $step, StepDefinition $stepDefinition)
208
    {
209
        if ($stepDefinition->getStep() === $step) {
210
            return $stepDefinition;
211
        }
212
213
        if ($stepDefinition->hasNextStep()) {
214
            $result = $this->findStep($step, $stepDefinition->getNextStep());
215
216
            if ($result instanceof StepDefinition) {
217
                return $result;
218
            }
219
        }
220
221
        if ($stepDefinition->hasDivergence()) {
222
            foreach ($stepDefinition->getDivergenceSteps() as $divergenceStep) {
223
                $result = $this->findStep($step, $divergenceStep);
224
225
                if ($result instanceof StepDefinition) {
226
                    return $result;
227
                }
228
            }
229
        }
230
231
        return null;
232
    }
233
234
    /**
235
     * @return FormStepPersistence
236
     */
237
    public function getStepPersistence()
238
    {
239
        return $this->persistence;
240
    }
241
242
    /**
243
     * @return FormObject
244
     */
245
    public function getFormObject()
246
    {
247
        return $this->formObject;
248
    }
249
250
    /**
251
     * @return StepDefinition
252
     */
253
    public function getFirstStepDefinition()
254
    {
255
        return $this->formObject->getDefinition()->getSteps()->getFirstStepDefinition();
256
    }
257
}
258