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:19
created

NestedValidationException::renderMessage()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 2
crap 6
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|ValidationException[]
27
     */
28
    private $exceptions = [];
29
30
    /**
31
     * @return SplObjectStorage|ValidationException[]
32
     */
33 2
    public function getRelated(): SplObjectStorage
34
    {
35 2
        if (!$this->exceptions instanceof SplObjectStorage) {
36 2
            $this->exceptions = new SplObjectStorage();
37
        }
38
39 2
        return $this->exceptions;
40
    }
41
42
    /**
43
     * @param array $exceptions
44
     *
45
     * @return self
46
     */
47
    public function setRelated(array $exceptions): self
48
    {
49
        foreach ($exceptions as $exception) {
50
            $this->addRelated($exception);
51
        }
52
53
        return $this;
54
    }
55
56
    /**
57
     * @param ValidationException $exception
58
     *
59
     * @return self
60
     */
61 2
    public function addRelated(ValidationException $exception)
62
    {
63 2
        $this->getRelated()->attach($exception);
64
65 2
        return $this;
66
    }
67
68
    /**
69
     * @return SplObjectStorage|ValidationException[]
70
     */
71
    public function getIterator(): SplObjectStorage
72
    {
73
        $childrenExceptions = new SplObjectStorage();
74
75
        $recursiveIteratorIterator = $this->getRecursiveIterator();
76
        $exceptionIterator = $recursiveIteratorIterator->getInnerIterator();
77
78
        $currentDepth = 0;
79
        $originalLastDepth = 0;
80
        $knownDepths = [];
81
        foreach ($recursiveIteratorIterator as $childException) {
82
            if ($this->isOmissible($childException)) {
83
                continue;
84
            }
85
86
            $originalCurrentDepth = $recursiveIteratorIterator->getDepth() + 1;
87
            if (isset($knownDepths[$originalCurrentDepth])) {
88
                $currentDepth = $knownDepths[$originalCurrentDepth];
89
            } elseif ($originalCurrentDepth > $originalLastDepth
90
                && ($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

90
                && ($this->hasCustomTemplate() || 1 != $exceptionIterator->/** @scrutinizer ignore-call */ count())) {
Loading history...
91
                $knownDepths[$originalCurrentDepth] = ++$currentDepth;
92
            }
93
94
            $childrenExceptions->attach($childException, $currentDepth);
95
96
            $originalLastDepth = $originalCurrentDepth;
97
        }
98
99
        return $childrenExceptions;
100
    }
101
102
    public function getMessages(array $templates = []): array
103
    {
104
        $messages = [$this->getId() => $this->renderMessage($this, $templates)];
105
        foreach ($this->getRelated() as $exception) {
106
            $id = $exception->getId();
107
            if (!$exception instanceof self) {
108
                $messages[$id] = $this->renderMessage(
109
                    $exception,
110
                    $this->findTemplates($templates, $this->getId())
111
                );
112
                continue;
113
            }
114
115
            $messages[$id] = $exception->getMessages($this->findTemplates($templates, $id, $this->getId()));
116
            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

116
            if (count(/** @scrutinizer ignore-type */ $messages[$id]) > 1) {
Loading history...
117
                continue;
118
            }
119
120
            $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

120
            $messages[$id] = current(/** @scrutinizer ignore-type */ $messages[$exception->getId()]);
Loading history...
121
        }
122
123
        if (count($messages) > 1) {
124
            unset($messages[$this->getId()]);
125
        }
126
127
        return $messages;
128
    }
129
130
    /**
131
     * @return string
132
     */
133
    public function getFullMessage(): string
134
    {
135
        $marker = '-';
136
        $messages = [];
137
        $exceptions = $this->getIterator();
138
139
        if ($this->hasCustomTemplate() || 1 != count($exceptions)) {
140
            $messages[] = sprintf('%s %s', $marker, $this->getMessage());
141
        }
142
143
        foreach ($exceptions as $exception) {
144
            $prefix = str_repeat(' ', $exceptions[$exception] * 2);
145
            $messages[] = sprintf('%s%s %s', $prefix, $marker, $exception->getMessage());
146
        }
147
148
        return implode(PHP_EOL, $messages);
149
    }
150
151
    private function getRecursiveIterator(): RecursiveIteratorIterator
152
    {
153
        $exceptionIterator = new RecursiveExceptionIterator($this);
154
        $recursiveIteratorIterator = new RecursiveIteratorIterator(
155
            $exceptionIterator,
156
            RecursiveIteratorIterator::SELF_FIRST
157
        );
158
159
        return $recursiveIteratorIterator;
160
    }
161
162
    private function isOmissible(Exception $exception): bool
163
    {
164
        if (!$exception instanceof self) {
165
            return false;
166
        }
167
168
        $relatedExceptions = $exception->getRelated();
169
        $relatedExceptions->rewind();
170
        $childException = $relatedExceptions->current();
171
172
        return 1 === $relatedExceptions->count() && !$childException instanceof NonOmissibleException;
173
    }
174
175
    private function renderMessage(ValidationException $exception, array $templates): string
176
    {
177
        if (isset($templates[$exception->getId()])) {
178
            $exception->updateTemplate($templates[$exception->getId()]);
179
        }
180
181
        return $exception->getMessage();
182
    }
183
184
    private function findTemplates(array $templates, ...$ids): array
185
    {
186
        while (count($ids) > 0) {
187
            $id = array_shift($ids);
188
            if (isset($templates[$id]) && is_array($templates[$id])) {
189
                $templates = $templates[$id];
190
            }
191
        }
192
193
        return $templates;
194
    }
195
}
196