Completed
Push — wip/steps ( a8cc5a...1510c1 )
by Romain
10:51
created

getFirstInvalidStep()   C

Complexity

Conditions 9
Paths 18

Size

Total Lines 59
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 59
rs 6.9133
cc 9
eloc 28
nc 18
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Core\Core;
17
use Romm\Formz\Error\FormResult;
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\Service\Step\FormStepPersistence;
22
use Romm\Formz\Middleware\Item\FormValidation\FormValidationMiddlewareOption;
23
use Romm\Formz\Validation\Validator\Form\AbstractFormValidator;
24
25
class StepMiddlewareValidationService
26
{
27
    /**
28
     * @var FormObject
29
     */
30
    protected $formObject;
31
32
    /**
33
     * @var StepMiddlewareService
34
     */
35
    protected $service;
36
37
    /**
38
     * @var FormStepPersistence
39
     */
40
    protected $persistence;
41
42
    /**
43
     * @param StepMiddlewareService $service
44
     */
45
    public function __construct(StepMiddlewareService $service)
46
    {
47
        $this->service = $service;
48
        $this->formObject = $service->getFormObject();
49
        $this->persistence = $service->getStepPersistence();
50
    }
51
52
    /**
53
     * Marks the given step as validated: no errors were found during validation
54
     * with the given values array.
55
     *
56
     * @param StepDefinition $stepDefinition
57
     * @param array          $formValues
0 ignored issues
show
Bug introduced by
There is no parameter named $formValues. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
58
     */
59
    public function markStepAsValidated(StepDefinition $stepDefinition/*, array $formValues*/) // @todo tmp-delete?
60
    {
61
        $this->persistence->markStepAsValidated($stepDefinition);
62
63
        // @todo tmp-delete?
64
//        if ($this->persistence->hasStepFormValues($stepDefinition)
65
//            && serialize($formValues) !== serialize($this->persistence->getStepFormValues($stepDefinition))
66
//        ) {
67
//            $this->persistence->resetValidationData();
68
//        }
69
    }
70
71
    /**
72
     * @param array $validatedFields
73
     */
74
    public function addValidatedFields(array $validatedFields)
75
    {
76
        $this->persistence->addValidatedFields($validatedFields);
77
    }
78
79
    /**
80
     * Checks that the previous step has already been validated, meaning the
81
     * user has the right to stand in the given step.
82
     *
83
     * @param StepDefinition $stepDefinition
84
     * @return bool
85
     */
86
    public function stepDefinitionIsValid(StepDefinition $stepDefinition)
87
    {
88
        if (false === $stepDefinition->hasPreviousDefinition()) {
89
            /*
90
             * No previous step definition found: the user stands on the first
91
             * step, it always has the right to stand there.
92
             */
93
            return true;
94
        }
95
96
        $previousStep = $stepDefinition->getPreviousDefinition()->getStep();
97
        $stepLevel = $stepDefinition->getStepLevel();
98
99
        return $this->persistence->stepWasValidated($previousStep)
100
            && true === $this->persistence->hasStepIdentifierAtLevel($stepLevel)
101
            && $stepDefinition->getStep()->getIdentifier() === $this->persistence->getStepIdentifierAtLevel($stepLevel);
102
    }
103
104
    /**
105
     * Searches for the first invalid step among previous steps from the given
106
     * step.
107
     *
108
     * All previous steps are listed, then for each one we check if submitted
109
     * form values has been saved in the step persistence, in which case the
110
     * step validation is launched again with the current form configuration.
111
     *
112
     * @param Step $step
113
     * @return StepDefinition|null
114
     */
115
    public function getFirstInvalidStep(Step $step)
116
    {
117
        $firstStep = $this->service->getFirstStepDefinition();
118
119
        if ($step === $firstStep->getStep()) {
120
            /*
121
             * The first step is always valid.
122
             */
123
            return null;
124
        }
125
126
        /*
127
         * If there is no form instance, and the request is not in the first
128
         * step, obviously the user should not be there.
129
         */
130
        if (false === $this->formObject->hasForm()) {
131
            return $firstStep;
132
        }
133
134
        /** @var StepDefinition[] $stepDefinitionsToTest */
135
        $stepDefinitionsToTest = [];
136
        $invalidStepDefinition = null;
137
        $stepDefinition = $this->service->getStepDefinition($step);
138
139
        while ($stepDefinition->hasPreviousDefinition()) {
140
            $stepDefinition = $stepDefinition->getPreviousDefinition();
141
142
            if ($stepDefinition->hasActivation()) {
143
                if (true === $this->service->getStepDefinitionConditionResult($stepDefinition)) {
144
                    array_unshift($stepDefinitionsToTest, $stepDefinition);
145
                }
146
            } else {
147
                array_unshift($stepDefinitionsToTest, $stepDefinition);
148
            }
149
        }
150
151
        foreach ($stepDefinitionsToTest as $stepDefinition) {
152
            $step = $stepDefinition->getStep();
153
154
            /*
155
             * If the form was already validated, no need to do it again.
156
             */
157
            if ($this->persistence->stepWasValidated($step)) {
158
                continue;
159
            }
160
161
            $result = $this->validateStep($step);
162
163
            if ($result->hasErrors()) {
164
                $invalidStepDefinition = $stepDefinition;
165
                break;
166
            } else {
167
                $this->persistence->markStepAsValidated($stepDefinition);
168
                $this->persistence->addValidatedFields($result->getValidatedFields());
169
            }
170
        }
171
172
        return $invalidStepDefinition;
173
    }
174
175
    /**
176
     * Validates (again) the given step with the form data that were previously
177
     * submitted and fetched from the step persistence.
178
     *
179
     * @param Step $step
180
     * @return FormResult
181
     */
182
    protected function validateStep(Step $step)
183
    {
184
        $form = $this->formObject->getForm();
185
186
        /** @var FormValidationMiddlewareOption $formValidationMiddlewareOptions */
187
        $formValidationMiddlewareOptions = $this->formObject
188
            ->getDefinition()
189
            ->getPresetMiddlewares()
190
            ->getFormValidationMiddleware()
191
            ->getOptions();
192
193
        /** @var AbstractFormValidator $validator */
194
        $validator = Core::instantiate(
195
            $formValidationMiddlewareOptions->getFormValidatorClassName(),
196
            [
197
                'name'  => $this->formObject->getName(),
198
                'form'  => $form,
199
                'dummy' => true
200
            ]
201
        );
202
203
        $validator->getDataObject()->setValidatedStep($step);
204
205
        return $validator->validate($form);
206
    }
207
}
208