Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Pull Request — master (#1062)
by Henrique
03:39
created

NestedValidationException::getRecursiveIterator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 9
c 0
b 0
f 0
ccs 6
cts 6
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of Respect/Validation.
5
 *
6
 * (c) Alexandre Gomes Gaigalas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the "LICENSE.md"
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Respect\Validation\Exceptions;
15
16
use IteratorAggregate;
17
use RecursiveIteratorIterator;
18
use SplObjectStorage;
19
use const PHP_EOL;
20
use function count;
21
use function implode;
22
use function is_array;
23
use function str_repeat;
24
25
class NestedValidationException extends ValidationException implements IteratorAggregate
26
{
27
    /**
28
     * @var SplObjectStorage
29
     */
30
    private $exceptions = [];
31
32
    /**
33
     * @param ValidationException $exception
34
     *
35
     * @return self
36
     */
37 142
    public function addRelated(ValidationException $exception)
38
    {
39 142
        $this->getRelated()->attach($exception);
40
41 142
        return $this;
42
    }
43
44
    /**
45
     * @return RecursiveIteratorIterator
46
     */
47 129
    private function getRecursiveIterator()
48
    {
49 129
        $exceptionIterator = new RecursiveExceptionIterator($this);
50 129
        $recursiveIteratorIterator = new RecursiveIteratorIterator(
51 129
            $exceptionIterator,
52 129
            RecursiveIteratorIterator::SELF_FIRST
53
        );
54
55 129
        return $recursiveIteratorIterator;
56
    }
57
58
    /**
59
     * Returns weather an exception should be omitted or not.
60
     *
61
     * @param Exception $exception
62
     *
63
     * @return bool
64
     */
65 129
    private function isOmissible(Exception $exception): bool
66
    {
67 129
        if (!$exception instanceof self) {
68 121
            return false;
69
        }
70
71 129
        if (1 !== $exception->getRelated()->count()) {
72 19
            return false;
73
        }
74
75 124
        $exception->getRelated()->rewind();
76 124
        $childException = $exception->getRelated()->current();
77 124
        if ($childException->getMessage() === $exception->getMessage()) {
78 2
            return true;
79
        }
80
81 123
        if ($exception->hasCustomTemplate()) {
82
            return $childException->hasCustomTemplate();
83
        }
84
85 123
        return !$childException instanceof NonOmissibleException;
86
    }
87
88
    /**
89
     * @return SplObjectStorage
90
     */
91 129
    public function getIterator()
92
    {
93 129
        $childrenExceptions = new SplObjectStorage();
94
95 129
        $recursiveIteratorIterator = $this->getRecursiveIterator();
96 129
        $exceptionIterator = $recursiveIteratorIterator->getInnerIterator();
0 ignored issues
show
Unused Code introduced by
The assignment to $exceptionIterator is dead and can be removed.
Loading history...
97
98 129
        $lastDepth = 0;
99 129
        $lastDepthOriginal = 0;
100 129
        $knownDepths = [];
101 129
        foreach ($recursiveIteratorIterator as $childException) {
102 128
            if ($this->isOmissible($childException)) {
103 6
                continue;
104
            }
105
106 128
            $currentDepth = $lastDepth;
107 128
            $currentDepthOriginal = $recursiveIteratorIterator->getDepth() + 1;
108
109 128
            if (isset($knownDepths[$currentDepthOriginal])) {
110 10
                $currentDepth = $knownDepths[$currentDepthOriginal];
111 128
            } elseif ($currentDepthOriginal > $lastDepthOriginal) {
112 128
                ++$currentDepth;
113
            }
114
115 128
            if (!isset($knownDepths[$currentDepthOriginal])) {
116 128
                $knownDepths[$currentDepthOriginal] = $currentDepth;
117
            }
118
119 128
            $lastDepth = $currentDepth;
120 128
            $lastDepthOriginal = $currentDepthOriginal;
121
122 128
            $childrenExceptions->attach(
123 128
                $childException,
124
                [
125 128
                    'depth' => $currentDepth,
126 128
                    'depth_original' => $currentDepthOriginal,
127 128
                    'previous_depth' => $lastDepth,
128 128
                    'previous_depth_original' => $lastDepthOriginal,
129
                ]
130
            );
131
        }
132
133 129
        return $childrenExceptions;
134
    }
135
136 8
    public function getMessages(array $templates = []): array
137
    {
138 8
        $messages = [$this->getId() => $this->renderMessage($this, $templates)];
139 8
        foreach ($this->getRelated() as $exception) {
140 8
            $id = $exception->getId();
141 8
            if (!$exception instanceof self) {
142 8
                $messages[$id] = $this->renderMessage(
143 8
                    $exception,
144 8
                    $this->findTemplates($templates, $this->getId())
145
                );
146 8
                continue;
147
            }
148
149 5
            $messages[$id] = $exception->getMessages($this->findTemplates($templates, $id, $this->getId()));
150 5
            if (count($messages[$id]) > 1) {
0 ignored issues
show
Bug introduced by
$messages[$id] of type string is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

150
            if (count(/** @scrutinizer ignore-type */ $messages[$id]) > 1) {
Loading history...
151 2
                continue;
152
            }
153
154 5
            $messages[$id] = current($messages[$exception->getId()]);
0 ignored issues
show
Bug introduced by
$messages[$exception->getId()] of type string is incompatible with the type array expected by parameter $array of current(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

154
            $messages[$id] = current(/** @scrutinizer ignore-type */ $messages[$exception->getId()]);
Loading history...
155
        }
156
157 8
        if (count($messages) > 1) {
158 8
            unset($messages[$this->getId()]);
159
        }
160
161 8
        return $messages;
162
    }
163
164
    /**
165
     * @return string
166
     */
167 129
    public function getFullMessage()
168
    {
169 129
        $messages = [];
170 129
        $leveler = 1;
171
172 129
        if (!$this->isOmissible($this)) {
173 11
            $leveler = 0;
174 11
            $messages[] = sprintf('- %s', $this->getMessage());
175
        }
176
177 129
        $exceptions = $this->getIterator();
178 129
        foreach ($exceptions as $exception) {
179 128
            $messages[] = sprintf(
180 128
                '%s- %s',
181 128
                str_repeat(' ', ($exceptions[$exception]['depth'] - $leveler) * 2),
182 128
                $exception->getMessage()
183
            );
184
        }
185
186 129
        return implode(PHP_EOL, $messages);
187
    }
188
189
    private function getCount(ValidationException $exception): int
0 ignored issues
show
Unused Code introduced by
The method getCount() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
190
    {
191
        if ($exception instanceof NestedValidationException) {
192
            return $exception->getRelated()->count();
193
        }
194
195
        return 0;
196
    }
197
198
    /**
199
     * @return SplObjectStorage|ValidationException[]
200
     */
201 143
    public function getRelated()
202
    {
203 143
        if (!$this->exceptions instanceof SplObjectStorage) {
0 ignored issues
show
introduced by
$this->exceptions is always a sub-type of SplObjectStorage. If $this->exceptions can have other possible types, add them to library/Exceptions/NestedValidationException.php:28.
Loading history...
204 143
            $this->exceptions = new SplObjectStorage();
205
        }
206
207 143
        return $this->exceptions;
208
    }
209
210
    /**
211
     * @param array $exceptions
212
     *
213
     * @return self
214
     */
215 140
    public function setRelated(array $exceptions)
216
    {
217 140
        foreach ($exceptions as $exception) {
218 140
            $this->addRelated($exception);
219
        }
220
221 140
        return $this;
222
    }
223
224 8
    private function renderMessage(ValidationException $exception, array $templates): string
225
    {
226 8
        if (isset($templates[$exception->getId()])) {
227 2
            $exception->updateTemplate($templates[$exception->getId()]);
228
        }
229
230 8
        return $exception->getMessage();
231
    }
232
233 8
    private function findTemplates(array $templates, ...$ids): array
234
    {
235 8
        while (count($ids) > 0) {
236 8
            $id = array_shift($ids);
237 8
            if (isset($templates[$id]) && is_array($templates[$id])) {
238 1
                $templates = $templates[$id];
239
            }
240
        }
241
242 8
        return $templates;
243
    }
244
}
245