Completed
Push — wip/steps ( 551eb2...b236f9 )
by Romain
03:12
created

StepMiddlewareService::findStepDefinition()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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