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

Passed
Pull Request — master (#957)
by Henrique
02:11
created

NestedValidationException   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 197
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 32
dl 0
loc 197
ccs 89
cts 89
cp 1
rs 9.6
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
C getIterator() 0 44 8
A isOmissible() 0 11 3
A getRecursiveIterator() 0 9 1
A addRelated() 0 5 1
A getRelated() 0 7 2
A setRelated() 0 7 2
B getMessages() 0 26 5
A renderMessage() 0 7 2
A getFullMessage() 0 17 4
A findTemplates() 0 10 4
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;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Respect\Validation\Exceptions\Exception. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
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
     *
33
     * @return self
34
     */
35 118
    public function addRelated(ValidationException $exception)
36
    {
37 118
        $this->getRelated()->attach($exception);
38
39 118
        return $this;
40
    }
41
42
    /**
43
     * @return RecursiveIteratorIterator
44
     */
45 106
    private function getRecursiveIterator()
46
    {
47 106
        $exceptionIterator = new RecursiveExceptionIterator($this);
48 106
        $recursiveIteratorIterator = new RecursiveIteratorIterator(
49 106
            $exceptionIterator,
50 106
            RecursiveIteratorIterator::SELF_FIRST
51
        );
52
53 106
        return $recursiveIteratorIterator;
54
    }
55
56
    /**
57
     * Returns weather an exception should be omitted or not.
58
     *
59
     * @param Exception $exception
60
     *
61
     * @return bool
62
     */
63 105
    private function isOmissible(Exception $exception)
64
    {
65 105
        if (!$exception instanceof self) {
66 99
            return false;
67
        }
68
69 11
        $relatedExceptions = $exception->getRelated();
70 11
        $relatedExceptions->rewind();
71 11
        $childException = $relatedExceptions->current();
72
73 11
        return 1 === $relatedExceptions->count() && !$childException instanceof NonOmissibleException;
74
    }
75
76
    /**
77
     * @return SplObjectStorage
78
     */
79 106
    public function getIterator()
80
    {
81 106
        $childrenExceptions = new SplObjectStorage();
82
83 106
        $recursiveIteratorIterator = $this->getRecursiveIterator();
84 106
        $exceptionIterator = $recursiveIteratorIterator->getInnerIterator();
85
86 106
        $lastDepth = 0;
87 106
        $lastDepthOriginal = 0;
88 106
        $knownDepths = [];
89 106
        foreach ($recursiveIteratorIterator as $childException) {
90 105
            if ($this->isOmissible($childException)) {
91 5
                continue;
92
            }
93
94 105
            $currentDepth = $lastDepth;
95 105
            $currentDepthOriginal = $recursiveIteratorIterator->getDepth() + 1;
96
97 105
            if (isset($knownDepths[$currentDepthOriginal])) {
98 9
                $currentDepth = $knownDepths[$currentDepthOriginal];
99 105
            } elseif ($currentDepthOriginal > $lastDepthOriginal
100 105
                && ($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 10
                ++$currentDepth;
102
            }
103
104 105
            if (!isset($knownDepths[$currentDepthOriginal])) {
105 105
                $knownDepths[$currentDepthOriginal] = $currentDepth;
106
            }
107
108 105
            $lastDepth = $currentDepth;
109 105
            $lastDepthOriginal = $currentDepthOriginal;
110
111 105
            $childrenExceptions->attach(
112 105
                $childException,
113
                [
114 105
                    'depth' => $currentDepth,
115 105
                    'depth_original' => $currentDepthOriginal,
116 105
                    'previous_depth' => $lastDepth,
117 105
                    'previous_depth_original' => $lastDepthOriginal,
118
                ]
119
            );
120
        }
121
122 106
        return $childrenExceptions;
123
    }
124
125 7
    public function getMessages(array $templates = []): array
126
    {
127 7
        $messages = [$this->getId() => $this->renderMessage($this, $templates)];
128 7
        foreach ($this->getRelated() as $exception) {
129 7
            $id = $exception->getId();
130 7
            if (!$exception instanceof self) {
131 7
                $messages[$id] = $this->renderMessage(
132 7
                    $exception,
133 7
                    $this->findTemplates($templates, $this->getId())
134
                );
135 7
                continue;
136
            }
137
138 4
            $messages[$id] = $exception->getMessages($this->findTemplates($templates, $id, $this->getId()));
139 4
            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

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

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