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 (#957)
by Henrique
02:45
created

NestedValidationException::getIterator()   C

Complexity

Conditions 8
Paths 8

Size

Total Lines 44
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 44
ccs 21
cts 21
cp 1
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 27
nc 8
nop 0
crap 8
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 Exception;
17
use IteratorAggregate;
18
use RecursiveIteratorIterator;
19
use SplObjectStorage;
20
use function count;
21
use function is_array;
22
23
class NestedValidationException extends ValidationException implements IteratorAggregate
24
{
25
    /**
26
     * @var SplObjectStorage
27
     */
28
    private $exceptions = [];
29
30
    /**
31
     * @param ValidationException $exception
32 123
     *
33
     * @return self
34 123
     */
35
    public function addRelated(ValidationException $exception)
36 123
    {
37
        $this->getRelated()->attach($exception);
38
39
        return $this;
40
    }
41
42
    /**
43
     * @return RecursiveIteratorIterator
44
     */
45 8
    private function getRecursiveIterator()
46
    {
47 8
        $exceptionIterator = new RecursiveExceptionIterator($this);
48 5
        $recursiveIteratorIterator = new RecursiveIteratorIterator(
49
            $exceptionIterator,
50
            RecursiveIteratorIterator::SELF_FIRST
51 6
        );
52 2
53
        return $recursiveIteratorIterator;
54
    }
55 4
56 4
    /**
57
     * Returns weather an exception should be omitted or not.
58
     *
59 1
     * @param ExceptionInterface $exception
60
     *
61
     * @return bool
62
     */
63
    private function isOmissible(ExceptionInterface $exception)
64
    {
65
        if (!$exception instanceof self) {
66
            return false;
67 8
        }
68
69 8
        $relatedExceptions = $exception->getRelated();
70
        $relatedExceptions->rewind();
71 8
        $childException = $relatedExceptions->current();
72 8
73 8
        return 1 === $relatedExceptions->count() && !$childException instanceof NonOmissibleExceptionInterface;
74
    }
75 8
76 4
    /**
77
     * @return SplObjectStorage
78
     */
79 8
    public function getIterator()
80
    {
81 8
        $childrenExceptions = new SplObjectStorage();
82 1
83 1
        $recursiveIteratorIterator = $this->getRecursiveIterator();
84
        $exceptionIterator = $recursiveIteratorIterator->getInnerIterator();
85
86 8
        $lastDepth = 0;
87 8
        $lastDepthOriginal = 0;
88 4
        $knownDepths = [];
89
        foreach ($recursiveIteratorIterator as $childException) {
90
            if ($this->isOmissible($childException)) {
91 8
                continue;
92
            }
93
94 8
            $currentDepth = $lastDepth;
95
            $currentDepthOriginal = $recursiveIteratorIterator->getDepth() + 1;
96
97
            if (isset($knownDepths[$currentDepthOriginal])) {
98
                $currentDepth = $knownDepths[$currentDepthOriginal];
99
            } elseif ($currentDepthOriginal > $lastDepthOriginal
100 5
                && ($this->hasCustomTemplate() || 1 != $exceptionIterator->count())) {
0 ignored issues
show
Bug introduced by
The method count() does not exist on Iterator. It seems like you code against a sub-type of Iterator such as SplDoublyLinkedList or HttpMessage or HttpRequestPool or Zend\Stdlib\PriorityList or Yaf_Config_Simple or SplFixedArray or SplObjectStorage or Yaf\Session or SQLiteResult or Imagick or TheSeer\Tokenizer\TokenCollection or Yaf_Session or SplPriorityQueue or Yaf\Config\Simple or Yaf\Config\Ini or MongoCursor or Zend\Stdlib\FastPriorityQueue or Yaf_Config_Ini or SplHeap or MongoGridFSCursor or CachingIterator or PHP_Token_Stream or Phar or ArrayIterator or GlobIterator or Phar or Phar or Respect\Validation\Excep...ursiveExceptionIterator or RecursiveCachingIterator or RecursiveArrayIterator or SimpleXMLIterator or Phar. ( Ignorable by Annotation )

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

100
                && ($this->hasCustomTemplate() || 1 != $exceptionIterator->/** @scrutinizer ignore-call */ count())) {
Loading history...
101
                ++$currentDepth;
102 5
            }
103 5
104
            if (!isset($knownDepths[$currentDepthOriginal])) {
105 5
                $knownDepths[$currentDepthOriginal] = $currentDepth;
106 5
            }
107 5
108
            $lastDepth = $currentDepth;
109
            $lastDepthOriginal = $currentDepthOriginal;
110 5
111
            $childrenExceptions->attach(
112
                $childException,
113
                [
114
                    'depth' => $currentDepth,
115
                    'depth_original' => $currentDepthOriginal,
116 118
                    'previous_depth' => $lastDepth,
117
                    'previous_depth_original' => $lastDepthOriginal,
118 118
                ]
119 118
            );
120 118
        }
121 118
122
        return $childrenExceptions;
123
    }
124 118
125
    public function getMessages(array $templates = []): array
126
    {
127
        $messages = [$this->getId() => $this->renderMessage($this, $this->getId(), $templates)];
128
        foreach ($this->getRelated() as $exception) {
129
            $id = $exception->getId();
130
            if (!$exception instanceof self) {
131
                $messages[$id] = $this->renderMessage(
132
                    $exception,
133
                    $id,
134 112
                    $this->findTemplates($templates, $this->getId())
135
                );
136 112
                continue;
137 106
            }
138
139
            $messages[$id] = $exception->getMessages($this->findTemplates($templates, $id, $this->getId()));
140 17
            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

140
            if (count(/** @scrutinizer ignore-type */ $messages[$id]) > 1) {
Loading history...
141 17
                continue;
142 17
            }
143
144 17
            $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

144
            $messages[$id] = current(/** @scrutinizer ignore-type */ $messages[$exception->getId()]);
Loading history...
145
        }
146
147
        if (count($messages) > 1) {
148
            unset($messages[$this->getId()]);
149
        }
150 113
151
        return $messages;
152 113
    }
153
154 113
    /**
155 113
     * @return string
156
     */
157 113
    public function getFullMessage()
158 113
    {
159 113
        $marker = '-';
160 113
        $messages = [];
161 112
        $exceptions = $this->getIterator();
162 11
163
        if ($this->hasCustomTemplate() || 1 != count($exceptions)) {
164
            $messages[] = sprintf('%s %s', $marker, $this->getMessage());
165 112
        }
166 112
167
        foreach ($exceptions as $exception) {
168 112
            $depth = $exceptions[$exception]['depth'];
169 13
            $prefix = str_repeat(' ', $depth * 2);
170 112
            $messages[] = sprintf('%s%s %s', $prefix, $marker, $exception->getMessage());
171 112
        }
172 13
173
        return implode(PHP_EOL, $messages);
174
    }
175 112
176 112
    /**
177
     * @return SplObjectStorage
178
     */
179 112
    public function getRelated()
180 112
    {
181
        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:26.
Loading history...
182 112
            $this->exceptions = new SplObjectStorage();
183 112
        }
184
185 112
        return $this->exceptions;
186 112
    }
187 112
188 112
    /**
189
     * @param array $exceptions
190
     *
191
     * @return self
192
     */
193 113
    public function setRelated(array $exceptions)
194
    {
195
        foreach ($exceptions as $exception) {
196
            $this->addRelated($exception);
197
        }
198
199 4
        return $this;
200
    }
201 4
202 4
    private function renderMessage(ValidationException $exception, $id, array $templates): string
203 4
    {
204
        if (isset($templates[$id])) {
205
            $exception->updateTemplate($templates[$id]);
206 4
        }
207 4
208
        return $exception->getMessage();
209
    }
210 4
211
    private function findTemplates(array $templates, ...$ids): array
212
    {
213
        while (count($ids) > 0) {
214
            $id = array_shift($ids);
215
            if (isset($templates[$id]) && is_array($templates[$id])) {
216 106
                $templates = $templates[$id];
217
            }
218 106
        }
219 106
220 106
        return $templates;
221
    }
222
}
223