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 ( f3bc39...ab602a )
by Henrique
03:52
created

Factory::withRuleNamespace()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 0
cts 0
cp 0
crap 2
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;
15
16
use ReflectionClass;
17
use ReflectionException;
18
use ReflectionObject;
19
use Respect\Validation\Exceptions\ComponentException;
20
use Respect\Validation\Exceptions\InvalidClassException;
21
use Respect\Validation\Exceptions\ValidationException;
22
use function lcfirst;
23
use function sprintf;
24
use function trim;
25
use function ucfirst;
26
27
/**
28
 * Factory of objects.
29
 *
30
 * @author Augusto Pascutti <[email protected]>
31
 * @author Henrique Moody <[email protected]>
32
 */
33
final class Factory
34
{
35
    /**
36
     * Default instance of the Factory.
37
     *
38
     * @var Factory
39
     */
40
    private static $defaultInstance;
41
42
    /**
43
     * @var string[]
44
     */
45
    private $rulesNamespaces = ['Respect\\Validation\\Rules'];
46
47
    /**
48
     * @var string[]
49
     */
50
    private $exceptionsNamespaces = ['Respect\\Validation\\Exceptions'];
51
52
    /**
53
     * @var callable
54
     */
55
    private $translator = 'strval';
56
57
    public function withRuleNamespace(string $rulesNamespace): self
58
    {
59
        $clone = clone $this;
60
        $clone->rulesNamespaces[] = trim($rulesNamespace, '\\');
61
62
        return $clone;
63
    }
64
65
    public function withExceptionNamespace(string $exceptionsNamespace): self
66
    {
67
        $clone = clone $this;
68
        $clone->exceptionsNamespaces[] = trim($exceptionsNamespace, '\\');
69
70
        return $clone;
71
    }
72
73
    public function withTranslator(callable $translator): self
74
    {
75
        $clone = clone $this;
76
        $clone->translator = $translator;
77
78
        return $clone;
79 197
    }
80
81
    /**
82
     * Define the default instance of the Factory.
83
     */
84 197
    public static function setDefaultInstance(self $defaultInstance): void
85 197
    {
86 197
        self::$defaultInstance = $defaultInstance;
87
    }
88 197
89 197
    /**
90 197
     * Returns the default instance of the Factory.
91
     */
92 197
    public static function getDefaultInstance(): self
93 197
    {
94
        if (self::$defaultInstance === null) {
95
            self::$defaultInstance = new self();
96
        }
97
98 4
        return self::$defaultInstance;
99
    }
100 4
101 4
    /**
102
     * Creates a rule.
103
     *
104
     * @param mixed[] $arguments
105
     *
106 186
     * @throws ComponentException
107
     */
108 186
    public function rule(string $ruleName, array $arguments = []): Validatable
109 181
    {
110 181
        foreach ($this->rulesNamespaces as $namespace) {
111 181
            try {
112
                /** @var Validatable $rule */
113 175
                $rule = $this
114 181
                    ->createReflectionClass($namespace.'\\'.ucfirst($ruleName), Validatable::class)
115
                    ->newInstanceArgs($arguments);
116
117
                return $rule;
118 186
            } catch (ReflectionException $exception) {
119
                continue;
120
            }
121
        }
122
123
        throw new ComponentException(sprintf('"%s" is not a valid rule name', $ruleName));
124
    }
125
126
    /**
127
     * Creates an exception.
128 189
     *
129
     * @param mixed $input
130 189
     * @param mixed[] $extraParams
131
     *
132
     * @throws ComponentException
133
     */
134 189
    public function exception(Validatable $validatable, $input, array $extraParams = []): ValidationException
135 186
    {
136
        $reflection = new ReflectionObject($validatable);
137 186
        $ruleName = $reflection->getShortName();
138 4
        $params = ['input' => $input] + $extraParams + $this->extractPropertiesValues($validatable, $reflection);
139 2
        $id = lcfirst($ruleName);
140
        if ($validatable->getName()) {
141
            $id = $params['name'] = $validatable->getName();
142
        }
143 1
        foreach ($this->exceptionsNamespaces as $namespace) {
144
            try {
145
                return $this->createValidationException($namespace.'\\'.$ruleName.'Exception', $id, $input, $params);
146
            } catch (ReflectionException $exception) {
147
                continue;
148
            }
149
        }
150
151
        return new ValidationException($input, $id, $params, $this->translator);
152
    }
153
154 184
    /**
155
     * Creates a reflection based on class name.
156 184
     *
157 184
     * @throws InvalidClassException
158 184
     * @throws ReflectionException
159 184
     */
160 184
    private function createReflectionClass(string $name, string $parentName): ReflectionClass
161 20
    {
162
        $reflection = new ReflectionClass($name);
163 184
        if (!$reflection->isSubclassOf($parentName) && $parentName !== $name) {
164
            throw new InvalidClassException(sprintf('"%s" must be an instance of "%s"', $name, $parentName));
165 184
        }
166 4
167 4
        if (!$reflection->isInstantiable()) {
168
            throw new InvalidClassException(sprintf('"%s" must be instantiable', $name));
169
        }
170
171 1
        return $reflection;
172
    }
173
174
    /**
175
     * Creates a Validation exception.
176
     *
177
     * @param mixed $input
178
     * @param mixed[] $params
179
     *
180 196
     * @throws InvalidClassException
181
     * @throws ReflectionException
182 196
     */
183 194
    private function createValidationException(
184 1
        string $exceptionName,
185
        string $id,
186
        $input,
187 193
        array $params
188 1
    ): ValidationException {
189
        /** @var ValidationException $exception */
190
        $exception = $this->createReflectionClass($exceptionName, ValidationException::class)
191 192
            ->newInstance($input, $id, $params, $this->translator);
192
        if (isset($params['template'])) {
193
            $exception->updateTemplate($params['template']);
194
        }
195
196
        return $exception;
197
    }
198
199
    /**
200
     * @return mixed[]
201
     */
202
    private function extractPropertiesValues(Validatable $validatable, ReflectionClass $reflection): array
203
    {
204 197
        $values = [];
205
        foreach ($reflection->getProperties() as $property) {
206
            $property->setAccessible(true);
207 197
208 197
            $propertyValue = $property->getValue($validatable);
209
            if ($propertyValue === null) {
210 197
                continue;
211 197
            }
212 197
213 197
            $values[$property->getName()] = $propertyValue;
214
        }
215
216
        $parentReflection = $reflection->getParentClass();
217
        if ($parentReflection !== false) {
218
            return $values + $this->extractPropertiesValues($validatable, $parentReflection);
219
        }
220
221
        return $values;
222
    }
223
}
224