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
Push — master ( da1094...afab4e )
by Henrique
06:18
created

NestedValidationException::addChild()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
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
/**
26
 * Exception for nested validations.
27
 *
28
 * This exception allows to have exceptions inside itself and providers methods
29
 * to handle them and to retrieve nested messages based on itself and its
30
 * children.
31
 *
32
 * @author Alexandre Gomes Gaigalas <[email protected]>
33
 * @author Henrique Moody <[email protected]>
34
 * @author Jonathan Stewmon <[email protected]>
35
 * @author Wojciech Frącz <[email protected]>
36
 */
37
class NestedValidationException extends ValidationException implements IteratorAggregate
38
{
39
    /**
40
     * @var SplObjectStorage
41
     */
42
    private $exceptions;
43
44
    /**
45
     * Returns the exceptions that are children of the exception.
46
     *
47
     * @return SplObjectStorage|ValidationException[]
48
     */
49 143
    public function getChildren(): SplObjectStorage
50
    {
51 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:40.
Loading history...
52 143
            $this->exceptions = new SplObjectStorage();
53
        }
54
55 143
        return $this->exceptions;
56
    }
57
58
    /**
59
     * Adds a child to the exception.
60
     *
61
     * @param ValidationException $exception
62
     *
63
     * @return self
64
     */
65 142
    public function addChild(ValidationException $exception): self
66
    {
67 142
        $this->getChildren()->attach($exception);
68
69 142
        return $this;
70
    }
71
72
    /**
73
     * Adds children to the exception.
74
     *
75
     * @param ValidationException[] $exceptions
76
     *
77
     * @return self
78
     */
79 140
    public function addChildren(array $exceptions): self
80
    {
81 140
        foreach ($exceptions as $exception) {
82 140
            $this->addChild($exception);
83
        }
84
85 140
        return $this;
86
    }
87
88
    /**
89
     * @return SplObjectStorage
90
     */
91 129
    public function getIterator(): SplObjectStorage
92
    {
93 129
        $childrenExceptions = new SplObjectStorage();
94 129
        $recursiveIteratorIterator = $this->getRecursiveIterator();
95
96 129
        $lastDepth = 0;
97 129
        $lastDepthOriginal = 0;
98 129
        $knownDepths = [];
99 129
        foreach ($recursiveIteratorIterator as $childException) {
100 128
            if ($this->isOmissible($childException)) {
101 6
                continue;
102
            }
103
104 128
            $currentDepth = $lastDepth;
105 128
            $currentDepthOriginal = $recursiveIteratorIterator->getDepth() + 1;
106
107 128
            if (isset($knownDepths[$currentDepthOriginal])) {
108 10
                $currentDepth = $knownDepths[$currentDepthOriginal];
109 128
            } elseif ($currentDepthOriginal > $lastDepthOriginal) {
110 128
                ++$currentDepth;
111
            }
112
113 128
            if (!isset($knownDepths[$currentDepthOriginal])) {
114 128
                $knownDepths[$currentDepthOriginal] = $currentDepth;
115
            }
116
117 128
            $lastDepth = $currentDepth;
118 128
            $lastDepthOriginal = $currentDepthOriginal;
119
120 128
            $childrenExceptions->attach($childException, $currentDepth);
121
        }
122
123 129
        return $childrenExceptions;
124
    }
125
126
    /**
127
     * Returns a key->value array with all the messages of the exception.
128
     *
129
     * In this array the "keys" are the ids of the exceptions (defined name or
130
     * name of the rule) and the values are the message.
131
     *
132
     * Once templates are passed it overwrites the templates of the given
133
     * messages.
134
     *
135
     * @param array $templates
136
     *
137
     * @return array
138
     */
139 8
    public function getMessages(array $templates = []): array
140
    {
141 8
        $messages = [$this->getId() => $this->renderMessage($this, $templates)];
142 8
        foreach ($this->getChildren() as $exception) {
143 8
            $id = $exception->getId();
144 8
            if (!$exception instanceof self) {
145 8
                $messages[$id] = $this->renderMessage(
146 8
                    $exception,
147 8
                    $this->findTemplates($templates, $this->getId())
148
                );
149 8
                continue;
150
            }
151
152 5
            $messages[$id] = $exception->getMessages($this->findTemplates($templates, $id, $this->getId()));
153 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

153
            if (count(/** @scrutinizer ignore-type */ $messages[$id]) > 1) {
Loading history...
154 2
                continue;
155
            }
156
157 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

157
            $messages[$id] = current(/** @scrutinizer ignore-type */ $messages[$exception->getId()]);
Loading history...
158
        }
159
160 8
        if (count($messages) > 1) {
161 8
            unset($messages[$this->getId()]);
162
        }
163
164 8
        return $messages;
165
    }
166
167
    /**
168
     * Returns a string with all the messages of the exception.
169
     *
170
     * @return string
171
     */
172 129
    public function getFullMessage(): string
173
    {
174 129
        $messages = [];
175 129
        $leveler = 1;
176
177 129
        if (!$this->isOmissible($this)) {
178 11
            $leveler = 0;
179 11
            $messages[] = sprintf('- %s', $this->getMessage());
180
        }
181
182 129
        $exceptions = $this->getIterator();
183 129
        foreach ($exceptions as $exception) {
184 128
            $messages[] = sprintf(
185 128
                '%s- %s',
186 128
                str_repeat(' ', ($exceptions[$exception] - $leveler) * 2),
187 128
                $exception->getMessage()
188
            );
189
        }
190
191 129
        return implode(PHP_EOL, $messages);
192
    }
193
194 129
    private function getRecursiveIterator(): RecursiveIteratorIterator
195
    {
196 129
        return new RecursiveIteratorIterator(
197 129
            new RecursiveExceptionIterator($this),
198 129
            RecursiveIteratorIterator::SELF_FIRST
199
        );
200
    }
201
202 129
    private function isOmissible(Exception $exception): bool
203
    {
204 129
        if (!$exception instanceof self) {
205 121
            return false;
206
        }
207
208 129
        if (1 !== $exception->getChildren()->count()) {
209 19
            return false;
210
        }
211
212 124
        $exception->getChildren()->rewind();
213 124
        $childException = $exception->getChildren()->current();
214 124
        if ($childException->getMessage() === $exception->getMessage()) {
215 2
            return true;
216
        }
217
218 123
        if ($exception->hasCustomTemplate()) {
219
            return $childException->hasCustomTemplate();
220
        }
221
222 123
        return !$childException instanceof NonOmissibleException;
223
    }
224
225 8
    private function renderMessage(ValidationException $exception, array $templates): string
226
    {
227 8
        if (isset($templates[$exception->getId()])) {
228 2
            $exception->updateTemplate($templates[$exception->getId()]);
229
        }
230
231 8
        return $exception->getMessage();
232
    }
233
234 8
    private function findTemplates(array $templates, ...$ids): array
235
    {
236 8
        while (count($ids) > 0) {
237 8
            $id = array_shift($ids);
238 8
            if (isset($templates[$id]) && is_array($templates[$id])) {
239 1
                $templates = $templates[$id];
240
            }
241
        }
242
243 8
        return $templates;
244
    }
245
}
246