Completed
Push — master ( 22fd50...798002 )
by Neomerx
03:53
created

BlockInterpreter   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 513
Duplicated Lines 23.2 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 48
lcom 1
cbo 6
dl 119
loc 513
rs 8.4864
c 0
b 0
f 0

20 Methods

Rating   Name   Duplication   Size   Complexity  
A execute() 0 14 1
A executeStarts() 15 15 3
A executeEnds() 15 15 3
A executeBlock() 0 20 2
B executeBlockImpl() 0 30 5
A executeProcedureBlock() 0 18 1
B executeIfBlock() 0 24 2
A executeAndBlock() 22 22 2
A executeOrBlock() 23 23 2
A getBlocks() 0 7 1
A getBlocksWithStart() 12 12 2
A getBlocksWithEnd() 12 12 2
A getBlockType() 0 8 1
A captureSuccessfulBlockResultIfEnabled() 0 14 3
A executeProcedureStart() 10 10 1
A executeProcedureEnd() 10 10 1
A addBlockErrors() 0 16 2
B debugCheckLooksLikeBlocksArray() 0 13 5
A debugCheckBlocksExist() 0 12 4
B debugHasKnownBlockType() 0 16 5

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like BlockInterpreter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use BlockInterpreter, and based on these observations, apply Extract Interface, too.

1
<?php namespace Limoncello\Validation\Execution;
2
3
/**
4
 * Copyright 2015-2017 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use Limoncello\Validation\Contracts\Captures\CaptureAggregatorInterface;
20
use Limoncello\Validation\Contracts\Errors\ErrorAggregatorInterface;
21
use Limoncello\Validation\Contracts\Execution\ContextInterface;
22
use Limoncello\Validation\Contracts\Execution\ContextStorageInterface;
23
use Limoncello\Validation\Errors\Error;
24
use Limoncello\Validation\Rules\BaseRule;
25
26
/**
27
 * @package Limoncello\Validation
28
 *
29
 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
30
 */
31
final class BlockInterpreter
32
{
33
    /**
34
     * @param mixed                      $input
35
     * @param array                      $serializedBlocks
36
     * @param ContextStorageInterface    $context
37
     * @param CaptureAggregatorInterface $captures
38
     * @param ErrorAggregatorInterface   $errors
39
     *
40
     * @return void
41
     *
42
     * @SuppressWarnings(PHPMD.StaticAccess)
43
     */
44
    public static function execute(
45
        $input,
46
        array $serializedBlocks,
47
        ContextStorageInterface $context,
48
        CaptureAggregatorInterface $captures,
49
        ErrorAggregatorInterface $errors
50
    ): void {
51
        $blockIndex = BlockSerializer::FIRST_BLOCK_INDEX;
52
53
        $blocks = static::getBlocks($serializedBlocks);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
54
        static::executeStarts(static::getBlocksWithStart($serializedBlocks), $blocks, $context, $errors);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
55
        static::executeBlock($input, $blockIndex, $blocks, $context, $captures, $errors);
56
        static::executeEnds(static::getBlocksWithEnd($serializedBlocks), $blocks, $context, $errors);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
57
    }
58
59
    /**
60
     * @param int[]                    $indexes
61
     * @param array                    $blocks
62
     * @param ContextStorageInterface  $context
63
     * @param ErrorAggregatorInterface $errors
64
     *
65
     * @return void
66
     *
67
     * @SuppressWarnings(PHPMD.StaticAccess)
68
     */
69 View Code Duplication
    public static function executeStarts(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
70
        array $indexes,
71
        array $blocks,
72
        ContextStorageInterface $context,
73
        ErrorAggregatorInterface $errors
74
    ): void {
75
        foreach ($indexes as $index) {
76
            $context->setCurrentBlockId($index);
77
            $block      = $blocks[$index];
78
            $errorsInfo = static::executeProcedureStart($block, $context);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
79
            if (empty($errorsInfo) === false) {
80
                static::addBlockErrors($errorsInfo, $context, $errors);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
81
            }
82
        }
83
    }
84
85
    /**
86
     * @param int[]                    $indexes
87
     * @param array                    $blocks
88
     * @param ContextStorageInterface  $context
89
     * @param ErrorAggregatorInterface $errors
90
     *
91
     * @return void
92
     *
93
     * @SuppressWarnings(PHPMD.StaticAccess)
94
     */
95 View Code Duplication
    public static function executeEnds(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
96
        array $indexes,
97
        array $blocks,
98
        ContextStorageInterface $context,
99
        ErrorAggregatorInterface $errors
100
    ): void {
101
        foreach ($indexes as $index) {
102
            $context->setCurrentBlockId($index);
103
            $block      = $blocks[$index];
104
            $errorsInfo = static::executeProcedureEnd($block, $context);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
105
            if (empty($errorsInfo) === false) {
106
                static::addBlockErrors($errorsInfo, $context, $errors);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
107
            }
108
        }
109
    }
110
111
    /**
112
     * @param mixed                      $input
113
     * @param int                        $blockIndex
114
     * @param array                      $blocks
115
     * @param ContextStorageInterface    $context
116
     * @param CaptureAggregatorInterface $captures
117
     * @param ErrorAggregatorInterface   $errors
118
     *
119
     * @return void
120
     *
121
     * @SuppressWarnings(PHPMD.StaticAccess)
122
     */
123
    public static function executeBlock(
124
        $input,
125
        int $blockIndex,
126
        array $blocks,
127
        ContextStorageInterface $context,
128
        CaptureAggregatorInterface $captures,
129
        ErrorAggregatorInterface $errors
130
    ): void {
131
        $result = static::executeBlockImpl(
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
132
            $input,
133
            $blockIndex,
134
            $blocks,
135
            $context,
136
            $captures
137
        );
138
        if (BlockReplies::isResultSuccessful($result) === false) {
139
            $errorsInfo = BlockReplies::extractResultErrorsInfo($result);
140
            static::addBlockErrors($errorsInfo, $context, $errors);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
141
        }
142
    }
143
144
    /**
145
     * @param mixed                      $input
146
     * @param int                        $blockIndex
147
     * @param array                      $blocks
148
     * @param ContextStorageInterface    $context
149
     * @param CaptureAggregatorInterface $captures
150
     *
151
     * @return array
152
     *
153
     * @SuppressWarnings(PHPMD.StaticAccess)
154
     */
155
    private static function executeBlockImpl(
156
        $input,
157
        int $blockIndex,
158
        array $blocks,
159
        ContextStorageInterface $context,
160
        CaptureAggregatorInterface $captures
161
    ): array {
162
        assert(array_key_exists($blockIndex, $blocks));
163
164
        $blockType = static::getBlockType($blocks[$blockIndex]);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
165
        $context->setCurrentBlockId($blockIndex);
166
        switch ($blockType) {
167
            case BlockSerializer::TYPE__PROCEDURE:
168
                $result = static::executeProcedureBlock($input, $blockIndex, $blocks, $context, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
169
                break;
170
            case BlockSerializer::TYPE__IF_EXPRESSION:
171
                $result = static::executeIfBlock($input, $blockIndex, $blocks, $context, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
172
                break;
173
            case BlockSerializer::TYPE__AND_EXPRESSION:
174
                $result = static::executeAndBlock($input, $blockIndex, $blocks, $context, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
175
                break;
176
            case BlockSerializer::TYPE__OR_EXPRESSION:
177
            default:
178
                assert($blockType === BlockSerializer::TYPE__OR_EXPRESSION);
179
                $result = static::executeOrBlock($input, $blockIndex, $blocks, $context, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
180
                break;
181
        }
182
183
        return $result;
184
    }
185
186
    /**
187
     * @param mixed                      $input
188
     * @param int                        $blockIndex
189
     * @param array                      $blocks
190
     * @param ContextStorageInterface    $context
191
     * @param CaptureAggregatorInterface $captures
192
     *
193
     * @return array
194
     *
195
     * @SuppressWarnings(PHPMD.StaticAccess)
196
     */
197
    private static function executeProcedureBlock(
198
        $input,
199
        int $blockIndex,
200
        array $blocks,
201
        ContextStorageInterface $context,
202
        CaptureAggregatorInterface $captures
203
    ): array {
204
        $block = $blocks[$blockIndex];
205
        assert(static::getBlockType($block) === BlockSerializer::TYPE__PROCEDURE);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
206
207
        $procedure = $block[BlockSerializer::PROCEDURE_EXECUTE_CALLABLE];
208
        assert(is_callable($procedure));
209
        $result = call_user_func($procedure, $input, $context);
210
211
        static::captureSuccessfulBlockResultIfEnabled($result, $block, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
212
213
        return $result;
214
    }
215
216
    /**
217
     * @param mixed                      $input
218
     * @param int                        $blockIndex
219
     * @param array                      $blocks
220
     * @param ContextStorageInterface    $context
221
     * @param CaptureAggregatorInterface $captures
222
     *
223
     * @return array
224
     *
225
     * @SuppressWarnings(PHPMD.StaticAccess)
226
     */
227
    private static function executeIfBlock(
228
        $input,
229
        int $blockIndex,
230
        array $blocks,
231
        ContextStorageInterface $context,
232
        CaptureAggregatorInterface $captures
233
    ): array {
234
        $block = $blocks[$blockIndex];
235
        assert(static::getBlockType($block) === BlockSerializer::TYPE__IF_EXPRESSION);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
236
237
        $conditionCallable = $block[BlockSerializer::IF_EXPRESSION_CONDITION_CALLABLE];
238
        assert(is_callable($conditionCallable));
239
        $conditionResult = call_user_func($conditionCallable, $input, $context);
240
        assert(is_bool($conditionResult));
241
242
        $index = $block[$conditionResult === true ?
243
            BlockSerializer::IF_EXPRESSION_ON_TRUE_BLOCK : BlockSerializer::IF_EXPRESSION_ON_FALSE_BLOCK];
244
245
        $result = static::executeBlockImpl($input, $index, $blocks, $context, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
246
247
        static::captureSuccessfulBlockResultIfEnabled($result, $block, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
248
249
        return $result;
250
    }
251
252
    /**
253
     * @param mixed                      $input
254
     * @param int                        $blockIndex
255
     * @param array                      $blocks
256
     * @param ContextStorageInterface    $context
257
     * @param CaptureAggregatorInterface $captures
258
     *
259
     * @return array
260
     *
261
     * @SuppressWarnings(PHPMD.StaticAccess)
262
     */
263 View Code Duplication
    private static function executeAndBlock(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
264
        $input,
265
        int $blockIndex,
266
        array $blocks,
267
        ContextStorageInterface $context,
268
        CaptureAggregatorInterface $captures
269
    ): array {
270
        $block = $blocks[$blockIndex];
271
        assert(static::getBlockType($block) === BlockSerializer::TYPE__AND_EXPRESSION);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
272
273
        $primaryIndex = $block[BlockSerializer::AND_EXPRESSION_PRIMARY];
274
        $result       = static::executeBlockImpl($input, $primaryIndex, $blocks, $context, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
275
        if (BlockReplies::isResultSuccessful($result) === true) {
276
            $nextInput      = BlockReplies::extractResultOutput($result);
277
            $secondaryIndex = $block[BlockSerializer::AND_EXPRESSION_SECONDARY];
278
            $result         = static::executeBlockImpl($nextInput, $secondaryIndex, $blocks, $context, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
279
        }
280
281
        static::captureSuccessfulBlockResultIfEnabled($result, $block, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
282
283
        return $result;
284
    }
285
286
    /**
287
     * @param mixed                      $input
288
     * @param int                        $blockIndex
289
     * @param array                      $blocks
290
     * @param ContextStorageInterface    $context
291
     * @param CaptureAggregatorInterface $captures
292
     *
293
     * @return array
294
     *
295
     * @SuppressWarnings(PHPMD.StaticAccess)
296
     * @SuppressWarnings(PHPMD.ElseExpression)
297
     */
298 View Code Duplication
    private static function executeOrBlock(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
299
        $input,
300
        int $blockIndex,
301
        array $blocks,
302
        ContextStorageInterface $context,
303
        CaptureAggregatorInterface $captures
304
    ): array {
305
        $block = $blocks[$blockIndex];
306
        assert(static::getBlockType($block) === BlockSerializer::TYPE__OR_EXPRESSION);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
307
308
        $primaryIndex      = $block[BlockSerializer::OR_EXPRESSION_PRIMARY];
309
        $resultFromPrimary = static::executeBlockImpl($input, $primaryIndex, $blocks, $context, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
310
        if (BlockReplies::isResultSuccessful($resultFromPrimary) === true) {
311
            $result = $resultFromPrimary;
312
        } else {
313
            $secondaryIndex = $block[BlockSerializer::OR_EXPRESSION_SECONDARY];
314
            $result         = static::executeBlockImpl($input, $secondaryIndex, $blocks, $context, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
315
        }
316
317
        static::captureSuccessfulBlockResultIfEnabled($result, $block, $captures);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
318
319
        return $result;
320
    }
321
322
    /**
323
     * @param array $serializedBlocks
324
     *
325
     * @return array
326
     *
327
     * @SuppressWarnings(PHPMD.StaticAccess)
328
     */
329
    private static function getBlocks(array $serializedBlocks): array
330
    {
331
        $blocks = BlockSerializer::unserializeBlocks($serializedBlocks);
332
        assert(static::debugCheckLooksLikeBlocksArray($blocks));
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
333
334
        return $blocks;
335
    }
336
337
    /**
338
     * @param array $serializedBlocks
339
     *
340
     * @return array
341
     *
342
     * @SuppressWarnings(PHPMD.StaticAccess)
343
     */
344 View Code Duplication
    private static function getBlocksWithStart(array $serializedBlocks): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
345
    {
346
        $blocksWithStart = BlockSerializer::unserializeBlocksWithStart($serializedBlocks);
347
348
        // check result contain only block indexes and the blocks are procedures
349
        assert(
350
            is_array($blocks = static::getBlocks($serializedBlocks)) &&
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
351
            static::debugCheckBlocksExist($blocksWithStart, $blocks, BlockSerializer::TYPE__PROCEDURE)
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
352
        );
353
354
        return $blocksWithStart;
355
    }
356
357
    /**
358
     * @param array $serializedBlocks
359
     *
360
     * @return array
361
     *
362
     * @SuppressWarnings(PHPMD.StaticAccess)
363
     */
364 View Code Duplication
    private static function getBlocksWithEnd(array $serializedBlocks): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
365
    {
366
        $blocksWithEnd = BlockSerializer::unserializeBlocksWithEnd($serializedBlocks);
367
368
        // check result contain only block indexes and the blocks are procedures
369
        assert(
370
            is_array($blocks = static::getBlocks($serializedBlocks)) &&
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
371
            static::debugCheckBlocksExist($blocksWithEnd, $blocks, BlockSerializer::TYPE__PROCEDURE)
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
372
        );
373
374
        return $blocksWithEnd;
375
    }
376
377
    /**
378
     * @param array $block
379
     *
380
     * @return int
381
     *
382
     * @SuppressWarnings(PHPMD.StaticAccess)
383
     */
384
    private static function getBlockType(array $block): int
385
    {
386
        assert(static::debugHasKnownBlockType($block));
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
387
388
        $type = $block[BlockSerializer::TYPE];
389
390
        return $type;
391
    }
392
393
    /**
394
     * @param array                      $result
395
     * @param array                      $block
396
     * @param CaptureAggregatorInterface $captures
397
     *
398
     * @return void
399
     *
400
     * @SuppressWarnings(PHPMD.StaticAccess)
401
     */
402
    private static function captureSuccessfulBlockResultIfEnabled(
403
        array $result,
404
        array $block,
405
        CaptureAggregatorInterface $captures
406
    ): void {
407
        if (BlockReplies::isResultSuccessful($result) === true) {
408
            $isCaptureEnabled = $block[BlockSerializer::PROPERTIES][BaseRule::PROPERTY_IS_CAPTURE_ENABLED] ?? false;
409
            if ($isCaptureEnabled === true) {
410
                $name  = $block[BlockSerializer::PROPERTIES][BaseRule::PROPERTY_NAME];
411
                $value = BlockReplies::extractResultOutput($result);
412
                $captures->remember($name, $value);
413
            }
414
        }
415
    }
416
417
    /**
418
     * @param array            $procedureBlock
419
     * @param ContextInterface $context
420
     *
421
     * @return array
422
     *
423
     * @SuppressWarnings(PHPMD.StaticAccess)
424
     */
425 View Code Duplication
    private static function executeProcedureStart(array $procedureBlock, ContextInterface $context): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
426
    {
427
        assert(static::getBlockType($procedureBlock) === BlockSerializer::TYPE__PROCEDURE);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
428
        $callable = $procedureBlock[BlockSerializer::PROCEDURE_START_CALLABLE];
429
        assert(is_callable($callable) === true);
430
        $errors = call_user_func($callable, $context);
431
        assert(is_array($errors));
432
433
        return $errors;
434
    }
435
436
    /**
437
     * @param array            $procedureBlock
438
     * @param ContextInterface $context
439
     *
440
     * @return array
441
     *
442
     * @SuppressWarnings(PHPMD.StaticAccess)
443
     */
444 View Code Duplication
    private static function executeProcedureEnd(array $procedureBlock, ContextInterface $context): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
445
    {
446
        assert(static::getBlockType($procedureBlock) === BlockSerializer::TYPE__PROCEDURE);
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
447
        $callable = $procedureBlock[BlockSerializer::PROCEDURE_END_CALLABLE];
448
        assert(is_callable($callable) === true);
449
        $errors = call_user_func($callable, $context);
450
        assert(is_array($errors));
451
452
        return $errors;
453
    }
454
455
    /**
456
     * @param array                    $errorsInfo
457
     * @param ContextStorageInterface  $context
458
     * @param ErrorAggregatorInterface $errors
459
     *
460
     * @return void
461
     */
462
    private static function addBlockErrors(
463
        array $errorsInfo,
464
        ContextStorageInterface $context,
465
        ErrorAggregatorInterface $errors
466
    ): void {
467
        foreach ($errorsInfo as $errorInfo) {
468
            $index        = $errorInfo[BlockReplies::ERROR_INFO_BLOCK_INDEX];
469
            $value        = $errorInfo[BlockReplies::ERROR_INFO_VALUE];
470
            $errorCode    = $errorInfo[BlockReplies::ERROR_INFO_CODE];
471
            $errorContext = $errorInfo[BlockReplies::ERROR_INFO_CONTEXT];
472
473
            $name = $context->setCurrentBlockId($index)->getProperties()->getProperty(BaseRule::PROPERTY_NAME);
474
475
            $errors->add(new Error($name, $value, $errorCode, $errorContext));
476
        }
477
    }
478
479
    /**
480
     * @param array $blocks
481
     *
482
     * @return bool
483
     *
484
     * @SuppressWarnings(PHPMD.StaticAccess)
485
     */
486
    private static function debugCheckLooksLikeBlocksArray(array $blocks): bool
487
    {
488
        foreach ($blocks as $index => $block) {
489
            if (is_int($index) === false ||
490
                is_array($block) === false ||
491
                static::debugHasKnownBlockType($block) === false
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
492
            ) {
493
                return false;
494
            }
495
        }
496
497
        return true;
498
    }
499
500
    /**
501
     * @param array $blockIndexes
502
     * @param array $blockList
503
     * @param int   $blockType
504
     *
505
     * @return bool
506
     *
507
     * @SuppressWarnings(PHPMD.StaticAccess)
508
     */
509
    private static function debugCheckBlocksExist(array $blockIndexes, array $blockList, int $blockType): bool
510
    {
511
        foreach ($blockIndexes as $index) {
512
            if (array_key_exists($index, $blockList) === false ||
513
                static::getBlockType($blockList[$index]) !== $blockType
0 ignored issues
show
Comprehensibility introduced by
Since Limoncello\Validation\Execution\BlockInterpreter is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
514
            ) {
515
                return false;
516
            }
517
        }
518
519
        return true;
520
    }
521
522
    /**
523
     * @param array $block
524
     *
525
     * @return bool
526
     */
527
    private static function debugHasKnownBlockType(array $block): bool
528
    {
529
        $result = false;
530
531
        if (array_key_exists(BlockSerializer::TYPE, $block) === true) {
532
            $type = $block[BlockSerializer::TYPE];
533
534
            $result =
535
                $type === BlockSerializer::TYPE__PROCEDURE ||
536
                $type === BlockSerializer::TYPE__AND_EXPRESSION ||
537
                $type === BlockSerializer::TYPE__OR_EXPRESSION ||
538
                $type === BlockSerializer::TYPE__IF_EXPRESSION;
539
        }
540
541
        return $result;
542
    }
543
}
544