Test Failed
Push — master ( 4bdf7b...97fe68 )
by Kirill
02:15
created

Type::isValid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\Reflection;
11
12
use Railt\Reflection\Common\Serializable;
13
use Railt\Reflection\Contracts\Definition\Behaviour\ProvidesType;
14
use Railt\Reflection\Contracts\TypeInterface;
15
16
/**
17
 * Class Type
18
 */
19
class Type implements TypeInterface
20
{
21
    use Serializable;
22
23
    /**
24
     * @var array|string[]
25
     */
26
    private const TYPES_LIST = self::DEPENDENT_TYPES + self::ROOT_TYPES;
27
28
    /**
29
     * @var Type[]
30
     */
31
    private static $instances = [];
32
33
    /**
34
     * @var array[]|string[][]
35
     */
36
    private static $inheritance = [];
37
38
    /**
39
     * @var string
40
     */
41
    protected $name;
42
43
    /**
44
     * @var array|string[]
45
     */
46
    private $parent;
47
48
    /**
49
     * BaseType constructor.
50
     * @param string $name
51
     */
52 1
    private function __construct(string $name)
53
    {
54 1
        $this->name   = $name;
55 1
        $this->parent = $this->getInheritanceSequence($name);
56 1
    }
57
58
    /**
59
     * @param string $name
60
     * @return array
61
     */
62 1
    private function getInheritanceSequence(string $name): array
63
    {
64 1
        if (self::$inheritance === []) {
65
            $this->bootInheritance(new \SplStack(), static::INHERITANCE_TREE);
66
        }
67
68 1
        return self::$inheritance[$name] ?? [static::ROOT_TYPE];
69
    }
70
71
    /**
72
     * @param \SplStack $stack
73
     * @param array $children
74
     */
75
    private function bootInheritance(\SplStack $stack, array $children = []): void
76
    {
77
        $push = function (string $type) use ($stack): void {
78
            self::$inheritance[$type]   = \array_values(\iterator_to_array($stack));
79
            self::$inheritance[$type][] = static::ROOT_TYPE;
80
81
            $stack->push($type);
82
        };
83
84
        foreach ($children as $type => $child) {
85
            switch (true) {
86
                case \is_string($child):
87
                    $push($child);
88
                    break;
89
90
                case \is_array($child):
91
                    $push($type);
92
                    $this->bootInheritance($stack, $child);
93
                    break;
94
            }
95
96
            $stack->pop();
97
        }
98
    }
99
100
    /**
101
     * @param string|ProvidesType $type
102
     * @return Type|\Railt\Reflection\Contracts\TypeInterface
103
     */
104 98
    public static function of($type): Type
105
    {
106
        switch (true) {
107 98
            case \is_string($type):
108 98
                return self::$instances[$type] ?? (self::$instances[$type] = new static($type));
109
110
            case $type instanceof ProvidesType:
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
111
                return $type::getType();
112
        }
113
114
        return static::of(static::ANY);
115
    }
116
117
    /**
118
     * {@inheritDoc}
119
     */
120
    public function isInputable(): bool
121
    {
122
        return \in_array($this->name, static::ALLOWS_TO_INPUT, true);
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128
    public function isReturnable(): bool
129
    {
130
        return \in_array($this->name, static::ALLOWS_TO_OUTPUT, true);
131
    }
132
133
    /**
134
     * {@inheritDoc}
135
     */
136
    public function isDependent(): bool
137
    {
138
        return \in_array($this->name, static::DEPENDENT_TYPES, true);
139
    }
140
141
    /**
142
     * {@inheritDoc}
143
     */
144 90
    public function instanceOf(TypeInterface $type): bool
145
    {
146 90
        $needle = $type->getName();
147
148 90
        return $this->is($needle) || \in_array($needle, $this->parent, true);
149
    }
150
151
    /**
152
     * {@inheritDoc}
153
     */
154 98
    public function is(string $type): bool
155
    {
156 98
        return $this->getName() === $type;
157
    }
158
159
    /**
160
     * {@inheritDoc}
161
     */
162 98
    public function getName(): string
163
    {
164 98
        return $this->name;
165
    }
166
167
    /**
168
     * {@inheritDoc}
169
     */
170 90
    public function __toString(): string
171
    {
172 90
        return $this->getName();
173
    }
174
175
    /**
176
     * {@inheritDoc}
177
     */
178
    public static function isValid(string $name): bool
179
    {
180
        return \in_array($name, self::TYPES_LIST, true);
181
    }
182
}
183