Completed
Push — master ( 1bc299...b12741 )
by Kirill
03:33
created

TypeHint::matchIterable()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
cc 4
nc 4
nop 1
1
<?php
2
/**
3
 * This file is part of Properties 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 Serafim\Properties\Attribute;
11
12
/**
13
 * Class TypeHint
14
 */
15
class TypeHint implements HintInterface
16
{
17
    /**
18
     * @var string
19
     */
20
    private $name;
21
22
    /**
23
     * @var bool
24
     */
25
    private $iterable;
26
27
    /**
28
     * @var Matchable[]
29
     */
30
    private $matchers = [];
31
32
    /**
33
     * TypeHint constructor.
34
     * @param string $name
35
     * @param bool $iterable
36
     */
37
    public function __construct(string $name, bool $iterable = false)
38
    {
39
        $this->name = $name;
40
        $this->iterable = $iterable;
41
    }
42
43
    /**
44
     * @return string
45
     */
46
    public function getName(): string
47
    {
48
        return $this->name;
49
    }
50
51
    /**
52
     * @return bool
53
     */
54
    public function isIterable(): bool
55
    {
56
        return $this->iterable;
57
    }
58
59
    /**
60
     * @param Matchable $matcher
61
     * @return OrTypeHint
62
     */
63
    public function addMatcher(Matchable $matcher): Matchable
64
    {
65
        $this->matchers[] = $matcher;
66
67
        return $this;
68
    }
69
70
    /**
71
     * @param mixed $value
72
     * @return bool
73
     */
74
    public function match($value): bool
75
    {
76
        return $this->isIterable() ? $this->matchIterable($value) : $this->matchScalar($value);
77
    }
78
79
    /**
80
     * @param iterable|mixed $values
81
     * @return bool
82
     */
83
    private function matchIterable($values): bool
84
    {
85
        if (! \is_iterable($values)) {
86
            return false;
87
        }
88
89
        foreach ($values as $value) {
90
            if (! $this->matchScalar($value)) {
91
                return false;
92
            }
93
        }
94
95
        return true;
96
    }
97
98
    /**
99
     * @param mixed $value
100
     * @return bool
101
     */
102
    private function matchScalar($value): bool
103
    {
104
        switch (true) {
105
            case $this->isBuiltin():
106
                return $this->matchBuiltin($value);
107
108
            case $this->name === 'mixed':
109
                return true;
110
111
            case $this->name === 'null':
112
            case $this->name === 'void':
113
                return $value === null;
114
115
            case \class_exists($this->name):
116
                return $value instanceof $this->name;
117
118
            default:
119
                @\trigger_error('Unrecognized type-hint "' . $this->name . '"');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
120
                return true;
121
        }
122
    }
123
124
    /**
125
     * @return bool
126
     */
127
    private function isBuiltin(): bool
128
    {
129
        return \function_exists('\\is_' . $this->name);
130
    }
131
132
    /**
133
     * @param mixed $value
134
     * @return bool
135
     */
136
    private function matchBuiltin($value): bool
137
    {
138
        $function = '\\is_' . $this->name;
139
140
        return $function($value);
141
    }
142
}
143