Completed
Push — master ( 690c53...b92a26 )
by Kirill
03:02
created

Type::getInheritanceSequence()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 3
cts 4
cp 0.75
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2.0625
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\Definition\TypeDefinition;
15
use Railt\Reflection\Contracts\Type as TypeInterface;
16
use Railt\Reflection\Exception\ReflectionException;
17
use Railt\Reflection\Exception\TypeConflictException;
18
19
/**
20
 * Class Type
21
 */
22
class Type implements TypeInterface
23
{
24
    use Serializable;
25
26
    /**
27
     * @var Type[]
28
     */
29
    private static $instances = [];
30
31
    /**
32
     * @var array[]|string[][]
33
     */
34
    private static $inheritance = [];
35
36
    /**
37
     * @var array|string[]
38
     */
39
    private $parent;
40
41
    /**
42
     * @var string
43
     */
44
    protected $name;
45
46
    /**
47
     * BaseType constructor.
48
     * @param string $name
49
     */
50 1
    private function __construct(string $name)
51
    {
52 1
        $this->name = $name;
53 1
        $this->parent = $this->getInheritanceSequence($name);
54 1
    }
55
56
    /**
57
     * @return bool
58
     */
59
    public function isInputable(): bool
60
    {
61
        return \in_array($this->name, static::ALLOWS_TO_INPUT, true);
62
    }
63
64
    /**
65
     * @return bool
66
     */
67
    public function isReturnable(): bool
68
    {
69
        return \in_array($this->name, static::ALLOWS_TO_OUTPUT, true);
70
    }
71
72
    /**
73
     * @param string $name
74
     * @return array
75
     */
76 1
    private function getInheritanceSequence(string $name): array
77
    {
78 1
        if (self::$inheritance === []) {
79
            $this->bootInheritance(new \SplStack(), static::INHERITANCE_TREE);
80
        }
81
82 1
        return self::$inheritance[$name] ?? [static::ROOT_TYPE];
83
    }
84
85
    /**
86
     * @param \SplStack $stack
87
     * @param array $children
88
     */
89
    private function bootInheritance(\SplStack $stack, array $children = []): void
90
    {
91
        $push = function (string $type) use ($stack): void {
92
            self::$inheritance[$type] = \array_values(\iterator_to_array($stack));
93
            self::$inheritance[$type][] = static::ROOT_TYPE;
94
95
            $stack->push($type);
96
        };
97
98
        foreach ($children as $type => $child) {
99
            switch (true) {
100
                case \is_string($child):
101
                    $push($child);
102
                    break;
103
104
                case \is_array($child):
105
                    $push($type);
106
                    $this->bootInheritance($stack, $child);
107
                    break;
108
            }
109
110
            $stack->pop();
111
        }
112
    }
113
114
    /**
115
     * @param string|ProvidesType $type
116
     * @return Type|\Railt\Reflection\Contracts\Type
117
     */
118 98
    public static function of($type): Type
119
    {
120
        switch (true) {
121 98
            case \is_string($type):
122 98
                return self::$instances[$type] ?? (self::$instances[$type] = new static($type));
123
124
            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...
125
                return $type::getType();
126
        }
127
128
        return static::of(static::ANY);
129
    }
130
131
    /**
132
     * @return bool
133
     */
134
    public function isDependent(): bool
135
    {
136
        return \in_array($this->name, static::DEPENDENT_TYPES, true);
137
    }
138
139
    /**
140
     * @param TypeInterface $type
141
     * @return bool
142
     */
143 90
    public function instanceOf(TypeInterface $type): bool
144
    {
145 90
        $needle = $type->getName();
146
147 90
        return $this->is($needle) || \in_array($needle, $this->parent, true);
148
    }
149
150
    /**
151
     * @param string $type
152
     * @return bool
153
     */
154 98
    public function is(string $type): bool
155
    {
156 98
        return $this->getName() === $type;
157
    }
158
159
    /**
160
     * @return string
161
     */
162 98
    public function getName(): string
163
    {
164 98
        return $this->name;
165
    }
166
167
    /**
168
     * @return string
169
     */
170 90
    public function __toString(): string
171
    {
172 90
        return $this->getName();
173
    }
174
}
175