Test Failed
Push — master ( 3b7232...dbe410 )
by Kirill
02:20
created

Type   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 131
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 2

Test Coverage

Coverage 51.35%

Importance

Changes 0
Metric Value
wmc 14
lcom 3
cbo 2
dl 0
loc 131
ccs 19
cts 37
cp 0.5135
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getInheritanceSequence() 0 8 2
A bootInheritance() 0 24 4
A of() 0 4 1
A isDependent() 0 4 1
A instanceOf() 0 6 2
A is() 0 4 1
A getName() 0 4 1
A __toString() 0 4 1
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\Type as TypeInterface;
14
15
/**
16
 * Class Type
17
 */
18
class Type implements TypeInterface
19
{
20
    use Serializable;
21
22
    /**
23
     * @var Type[]
24
     */
25
    private static $instances = [];
26
27
    /**
28
     * @var array[]|string[][]
29
     */
30
    private static $inheritance = [];
31
32
    /**
33
     * @var array|string[]
34
     */
35
    private $parent;
36
37
    /**
38
     * @var string
39
     */
40
    protected $name;
41
42
    /**
43
     * BaseType constructor.
44
     * @param string $name
45
     */
46 9
    private function __construct(string $name)
47
    {
48 9
        \assert(\in_array($name, \array_merge(static::DEPENDENT_TYPES, static::ROOT_TYPES), true));
49
50 9
        $this->name = $name;
51 9
        $this->parent = $this->getInheritanceSequence($name);
52 9
    }
53
54
    /**
55
     * @param string $name
56
     * @return array
57
     */
58 9
    private function getInheritanceSequence(string $name): array
59
    {
60 9
        if (self::$inheritance === []) {
61
            $this->bootInheritance(new \SplStack(), static::INHERITANCE_TREE);
62
        }
63
64 9
        return self::$inheritance[$name] ?? [static::ROOT_TYPE];
65
    }
66
67
    /**
68
     * @param \SplStack $stack
69
     * @param array $children
70
     */
71
    private function bootInheritance(\SplStack $stack, array $children = []): void
72
    {
73
        $push = function (string $type) use ($stack): void {
74
            self::$inheritance[$type] = \array_values(\iterator_to_array($stack));
75
            self::$inheritance[$type][] = static::ROOT_TYPE;
76
77
            $stack->push($type);
78
        };
79
80
        foreach ($children as $type => $child) {
81
            switch (true) {
82
                case \is_string($child):
83
                    $push($child);
84
                    break;
85
86
                case \is_array($child):
87
                    $push($type);
88
                    $this->bootInheritance($stack, $child);
89
                    break;
90
            }
91
92
            $stack->pop();
93
        }
94
    }
95
96
    /**
97
     * @param string $type
98
     * @return Type
99
     */
100 130
    public static function of(string $type): Type
101
    {
102 130
        return self::$instances[$type] ?? (self::$instances[$type] = new static($type));
103
    }
104
105
    /**
106
     * @return bool
107
     */
108
    public function isDependent(): bool
109
    {
110
        return \in_array($this->name, static::DEPENDENT_TYPES, true);
111
    }
112
113
    /**
114
     * @param TypeInterface $type
115
     * @return bool
116
     */
117 130
    public function instanceOf(TypeInterface $type): bool
118
    {
119 130
        $needle = $type->getName();
120
121 130
        return $this->is($needle) || \in_array($needle, $this->parent, true);
122
    }
123
124
    /**
125
     * @param string $type
126
     * @return bool
127
     */
128 130
    public function is(string $type): bool
129
    {
130 130
        return $this->getName() === $type;
131
    }
132
133
    /**
134
     * @return string
135
     */
136 130
    public function getName(): string
137
    {
138 130
        return $this->name;
139
    }
140
141
    /**
142
     * @return string
143
     */
144 106
    public function __toString(): string
145
    {
146 106
        return $this->getName();
147
    }
148
}
149