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

Factory::exception()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 16
nc 6
nop 3
dl 0
loc 26
ccs 17
cts 17
cp 1
crap 6
rs 8.439
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;
15
16
use function array_map;
17
use function array_merge;
18
use function array_unshift;
19
use function class_exists;
20
use function in_array;
21
use function lcfirst;
22
use function Respect\Stringifier\stringify;
0 ignored issues
show
introduced by
The function Respect\Stringifier\stringify was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
23
use ReflectionClass;
24
use ReflectionObject;
25
use Respect\Validation\Exceptions\ComponentException;
26
use Respect\Validation\Exceptions\InvalidClassException;
27
use Respect\Validation\Exceptions\ValidationException;
28
use function sprintf;
29
use function trim;
30
31
/**
32
 * Factory of objects.
33
 *
34
 * @author Henrique Moody <[email protected]>
35
 *
36
 * @since 0.8.0
37
 */
38
final class Factory
39
{
40
    private const DEFAULT_RULES_NAMESPACES = [
41
        'Respect\\Validation\\Rules',
42
        'Respect\\Validation\\Rules\\Locale',
43
        'Respect\\Validation\\Rules\\SubdivisionCode',
44
    ];
45
46
    private const DEFAULT_EXCEPTIONS_NAMESPACES = [
47
        'Respect\\Validation\\Exceptions',
48
        'Respect\\Validation\\Exceptions\\Locale',
49
        'Respect\\Validation\\Exceptions\\SubdivisionCode',
50
    ];
51
52
    /**
53
     * Default instance of the Factory.
54
     *
55
     * @var Factory
56
     */
57
    private static $defaultInstance;
58
59
    /**
60
     * @var string[]
61
     */
62
    private $rulesNamespaces = [];
63
64
    /**
65
     * @var string[]
66
     */
67
    private $exceptionsNamespaces = [];
68
69
    /**
70
     * Initializes the factory with the defined namespaces.
71
     *
72
     * If the default namespace is not in the array, it will be add to the end
73
     * of the array.
74
     *
75
     * @param string[] $rulesNamespaces
76
     * @param string[] $exceptionsNamespaces
77
     */
78 302
    public function __construct(array $rulesNamespaces, array $exceptionsNamespaces)
79
    {
80 302
        $this->rulesNamespaces = $rulesNamespaces;
81 302
        $this->exceptionsNamespaces = $exceptionsNamespaces;
82 302
    }
83
84
    /**
85
     * Define the default instance of the Factory.
86
     *
87
     * @param Factory $defaultInstance
88
     */
89 1
    public static function setDefaultInstance(self $defaultInstance): void
90
    {
91 1
        self::$defaultInstance = $defaultInstance;
92 1
    }
93
94
    /**
95
     * Returns the default instance of the Factory.
96
     *
97
     * @return Factory
98
     */
99 293
    public static function getDefaultInstance(): self
100
    {
101 293
        if (!self::$defaultInstance instanceof self) {
0 ignored issues
show
introduced by
The condition ! self::defaultInstance instanceof self can never be true.
Loading history...
102 289
            self::$defaultInstance = new self(self::DEFAULT_RULES_NAMESPACES, self::DEFAULT_EXCEPTIONS_NAMESPACES);
103
        }
104
105 293
        return self::$defaultInstance;
106
    }
107
108
    /**
109
     * Creates a rule.
110
     *
111
     * @param string $ruleName
112
     * @param array $arguments
113
     *
114
     * @throws ComponentException
115
     *
116
     * @return Validatable
117
     */
118 297
    public function rule(string $ruleName, array $arguments = []): Validatable
119
    {
120 297
        foreach ($this->rulesNamespaces as $namespace) {
121 297
            $className = trim($namespace, '\\').'\\'.ucfirst($ruleName);
122 297
            if (!class_exists($className)) {
123 3
                continue;
124
            }
125
126 295
            return $this->getReflection($className, Validatable::class)->newInstanceArgs($arguments);
127
        }
128
129 2
        throw new ComponentException(sprintf('"%s" is not a valid rule name', $ruleName));
130
    }
131
132
    /**
133
     * Creates an exception.
134
     *
135
     * @param Validatable $validatable
136
     * @param mixed $input
137
     * @param array $extraParams
138
     *
139
     * @throws ComponentException
140
     *
141
     * @return ValidationException
142
     */
143 223
    public function exception(Validatable $validatable, $input, array $extraParams = []): ValidationException
144
    {
145 223
        $reflection = new ReflectionObject($validatable);
146 223
        $ruleName = $reflection->getShortName();
147 223
        foreach ($this->exceptionsNamespaces as $namespace) {
148 222
            $exceptionName = sprintf('%s\\%sException', trim($namespace, '\\'), $ruleName);
149 222
            if (!class_exists($exceptionName)) {
150 5
                continue;
151
            }
152
153 222
            $params = ['input' => $input] + $extraParams;
154 222
            foreach ($reflection->getProperties() as $property) {
155 222
                $property->setAccessible(true);
156 222
                $params += [$property->getName() => $property->getValue($validatable)];
157
            }
158
159 222
            $exception = $this->getReflection($exceptionName, ValidationException::class)->newInstance();
160 222
            $exception->configure($validatable->getName() ?: stringify($input), $params);
161 222
            if (isset($params['template'])) {
162 5
                $exception->setTemplate($params['template']);
163
            }
164
165 222
            return $exception;
166
        }
167
168 1
        throw new ComponentException(sprintf('Cannot find exception for "%s" rule', lcfirst($ruleName)));
169
    }
170
171
    /**
172
     * @param string $className
173
     * @param string $parentClassName
174
     *
175
     * @return ReflectionClass
176
     *
177
     * @throws InvalidClassException
178
     */
179 300
    private function getReflection(string $className, string $parentClassName): ReflectionClass
180
    {
181 300
        $reflection = new ReflectionClass($className);
182 300
        if (!$reflection->isSubclassOf($parentClassName)) {
183 1
            throw new InvalidClassException(sprintf('"%s" must be an instance of "%s"' , $className, $parentClassName));
184
        }
185
186 299
        if (!$reflection->isInstantiable()) {
187 1
            throw new InvalidClassException(sprintf('"%s" must be instantiable' , $className));
188
        }
189
190 298
        return $reflection;
191
    }
192
}
193