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 (#678)
by Henrique
03:16
created

Factory::setDefaultInstance()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
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
namespace Respect\Validation;
13
14
use Doctrine\Common\Annotations\SimpleAnnotationReader;
15
use ReflectionClass;
16
use Respect\Validation\Annotations\Template;
17
use Respect\Validation\Annotations\Templates;
18
use Respect\Validation\Exceptions\ComponentException;
19
use Respect\Validation\Exceptions\InvalidRuleException;
20
use Respect\Validation\Exceptions\RuleNotFoundException;
21
use Respect\Validation\Message\Formatter;
22
23
/**
24
 * Factory to create rules.
25
 *
26
 * @author Henrique Moody <[email protected]>
27
 *
28
 * @since 0.8.0
29
 */
30
final class Factory
31
{
32
    /**
33
     * @var string[]
34
     */
35
    private $namespaces;
36
37
    /**
38
     * @var ReflectionClass[]
39
     */
40
    private $reflections;
41
42
    /**
43
     * @var self
44
     */
45
    private static $defaultInstance;
46
47
    /**
48
     * Initializes the rule with the defined namespaces.
49
     *
50
     * If the default namespace is not in the array, it will be add to the end
51
     * of the array.
52
     *
53
     * @param array $namespaces
54
     */
55 11
    public function __construct(array $namespaces = [])
56
    {
57 11
        if (!in_array(__NAMESPACE__, $namespaces)) {
58 9
            $namespaces[] = __NAMESPACE__;
59
        }
60
61 11
        $this->namespaces = $namespaces;
62 11
    }
63
64
    /**
65
     * Defines the default instance of the factory.
66
     *
67
     * @param Factory $factory
68
     */
69 1
    public static function setDefaultInstance(self $factory)
70
    {
71 1
        self::$defaultInstance = $factory;
0 ignored issues
show
Documentation Bug introduced by
It seems like $factory of type object<self> is incompatible with the declared type object<Respect\Validation\Factory> of property $defaultInstance.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
72 1
    }
73
74
    /**
75
     * Returns the default instance of the factory.
76
     *
77
     * @return self
78
     */
79 2
    public static function getDefaultInstance(): self
80
    {
81 2
        if (!self::$defaultInstance instanceof self) {
82 1
            self::$defaultInstance = new self();
83
        }
84
85 2
        return self::$defaultInstance;
86
    }
87
88
    /**
89
     * Returns a list of namespaces.
90
     *
91
     * @return array
92
     */
93 9
    public function getNamespaces(): array
94
    {
95 9
        return $this->namespaces;
96
    }
97
98
    /**
99
     * Creates a rule based on its name with the defined arguments.
100
     *
101
     * @param string $ruleName
102
     * @param array  $arguments
103
     *
104
     * @throws ComponentException When the rule cannot be created
105
     *
106
     * @return Rule
107
     */
108 6
    public function rule(string $ruleName, array $arguments = []): Rule
109
    {
110 6
        foreach ($this->getNamespaces() as $namespace) {
111 6
            $className = rtrim($namespace, '\\').'\\Rules\\'.ucfirst($ruleName);
112 6
            if (!class_exists($className)) {
113 1
                continue;
114
            }
115
116 5
            $reflection = $this->getReflection($className);
117
118 5
            if (!$reflection->isSubclassOf(Rule::class)) {
119 1
                throw new InvalidRuleException(sprintf('"%s" is not a valid rule', $className));
120
            }
121
122 4
            if (!$reflection->isInstantiable()) {
123 1
                throw new InvalidRuleException(sprintf('"%s" is not instantiable', $className));
124
            }
125
126 3
            return $reflection->newInstanceArgs($arguments);
127
        }
128
129 1
        throw new RuleNotFoundException(sprintf('Could not find "%s" rule', $ruleName));
130
    }
131
132
    private function getMessage(ReflectionClass $reflection, Result $result): string
133
    {
134
        $reader = new SimpleAnnotationReader();
135
        $reader->addNamespace('Respect\\Validation\\Annotations');
136
137
        $templates = $reader->getClassAnnotation($reflection, Templates::class);
138
139
        $template = $this->chooseTemplate($templates, $result);
0 ignored issues
show
Documentation introduced by
$templates is of type object|null, but the function expects a object<Respect\Validation\Annotations\Templates>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
140
141
        $formatter = new Formatter(2, 3);
142
143
        return $formatter->create($result->getInput(), $result->getProperties(), $template->message);
144
    }
145
146
    public function exception(Result $result)
147
    {
148
        $exceptionName = str_replace('Rule', 'Exception', get_class($result->getRule())).'Exception';
149
150
        $reflection = $this->getReflection($exceptionName);
151
        $message = $this->getMessage($reflection, $result);
152
153
        return $reflection->newInstance($message);
154
    }
155
156
    private function chooseTemplate(Templates $templates, Result $result): Template
157
    {
158
        $templatesList = $templates->regular;
159
        if ($result->isInverted()) {
160
            $templatesList = $templates->inverted;
161
        }
162
163
        $templateId = 'standard';
164
        $properties = $result->getProperties();
165
        if (isset($properties['templateId'])) {
166
            $templateId = $properties['templateId'];
167
        }
168
169
        foreach ($templatesList as $template) {
170
            if ($template->id != $templateId) {
171
                continue;
172
            }
173
174
            return $template;
175
        }
176
177
        return current($templateLists);
0 ignored issues
show
Bug introduced by
The variable $templateLists does not exist. Did you mean $templatesList?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
178
    }
179
180
    /**
181
     * Creates a ReflectionClass object based on a class name.
182
     *
183
     * This method always return the same object for a given class name in order
184
     * to improve performance.
185
     *
186
     * @param string $className
187
     *
188
     * @return ReflectionClass
189
     */
190 5
    private function getReflection(string $className): ReflectionClass
191
    {
192 5
        if (!isset($this->reflections[$className])) {
193 5
            $this->reflections[$className] = new ReflectionClass($className);
194
        }
195
196 5
        return $this->reflections[$className];
197
    }
198
}
199