These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php declare(strict_types = 1); |
||
2 | |||
3 | namespace DaveRandom\CallbackValidator; |
||
4 | |||
5 | final class MatchTester |
||
6 | { |
||
7 | /** |
||
8 | * Thou shalt not instantiate |
||
9 | */ |
||
10 | private function __construct() { } |
||
11 | |||
12 | /** |
||
13 | * Lookup table of all built-in types |
||
14 | */ |
||
15 | private static $builtInTypes = [ |
||
16 | BuiltInTypes::STRING => true, |
||
17 | BuiltInTypes::INT => true, |
||
18 | BuiltInTypes::FLOAT => true, |
||
19 | BuiltInTypes::BOOL => true, |
||
20 | BuiltInTypes::ARRAY => true, |
||
21 | BuiltInTypes::CALLABLE => true, |
||
22 | BuiltInTypes::VOID => true, |
||
23 | BuiltInTypes::ITERABLE => true, |
||
24 | ]; |
||
25 | |||
26 | /** |
||
27 | * Lookup table of scalar types |
||
28 | */ |
||
29 | private static $scalarTypes = [ |
||
30 | BuiltInTypes::STRING => true, |
||
31 | BuiltInTypes::INT => true, |
||
32 | BuiltInTypes::FLOAT => true, |
||
33 | BuiltInTypes::BOOL => true, |
||
34 | ]; |
||
35 | |||
36 | /** |
||
37 | * @param string|null $superTypeName |
||
38 | * @param bool $superTypeNullable |
||
39 | * @param string|null $subTypeName |
||
40 | * @param bool $subTypeNullable |
||
41 | * @param bool $weak |
||
42 | * @return bool |
||
43 | */ |
||
44 | 84 | public static function isMatch($superTypeName, $superTypeNullable, $subTypeName, $subTypeNullable, $weak) |
|
45 | { |
||
46 | // If the super type is unspecified, anything is a match |
||
47 | 84 | if ($superTypeName === null) { |
|
48 | return true; |
||
49 | } |
||
50 | |||
51 | // If the sub type is unspecified, nothing is a match |
||
52 | 84 | if ($subTypeName === null) { |
|
53 | return false; |
||
54 | } |
||
55 | |||
56 | 84 | $superTypeName = (string)$superTypeName; |
|
1 ignored issue
–
show
Coding Style
introduced
by
Loading history...
|
|||
57 | 84 | $subTypeName = (string)$subTypeName; |
|
1 ignored issue
–
show
|
|||
58 | |||
59 | // Sub type cannot be nullable unless the super type is as well |
||
60 | 84 | if ($subTypeNullable && !$superTypeNullable) { |
|
61 | // nullable void doesn't really make sense but for completeness... |
||
62 | 24 | return $superTypeName === BuiltInTypes::VOID && $subTypeName === BuiltInTypes::VOID; |
|
63 | } |
||
64 | |||
65 | // If the string is an exact match it's definitely acceptable |
||
66 | 64 | if ($superTypeName === $subTypeName) { |
|
67 | 8 | return true; |
|
68 | } |
||
69 | |||
70 | // Check iterable |
||
71 | 62 | View Code Duplication | if ($superTypeName === BuiltInTypes::ITERABLE) { |
1 ignored issue
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
72 | 24 | return $subTypeName === BuiltInTypes::ARRAY |
|
73 | 18 | || $subTypeName === \Traversable::class |
|
74 | 24 | || \is_subclass_of($subTypeName, \Traversable::class); |
|
75 | } |
||
76 | |||
77 | // Check callable |
||
78 | 44 | View Code Duplication | if ($superTypeName === BuiltInTypes::CALLABLE) { |
1 ignored issue
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
79 | 24 | return $subTypeName === \Closure::class |
|
80 | 18 | || \method_exists($subTypeName, '__invoke') |
|
81 | 24 | || \is_subclass_of($subTypeName, \Closure::class); |
|
82 | } |
||
83 | |||
84 | // If the super type is built-in, check whether casting rules can succeed |
||
85 | 26 | if (isset(self::$builtInTypes[$superTypeName])) { |
|
86 | // Fail immediately in strict mode |
||
87 | 26 | if (!$weak) { |
|
88 | 13 | return false; |
|
89 | } |
||
90 | |||
91 | // Nothing else satisfies array, callable, void or iterable |
||
92 | 13 | if (!isset(self::$scalarTypes[$superTypeName])) { |
|
93 | 4 | return false; |
|
94 | } |
||
95 | |||
96 | // Scalars can all cast to each other |
||
97 | 9 | if (isset(self::$scalarTypes[$subTypeName])) { |
|
98 | 3 | return true; |
|
99 | } |
||
100 | |||
101 | // Classes with __toString() satisfy string |
||
102 | 6 | if ($superTypeName === BuiltInTypes::STRING && \method_exists($subTypeName, '__toString')) { |
|
1 ignored issue
–
show
|
|||
103 | 3 | return true; |
|
104 | } |
||
105 | |||
106 | 3 | return false; |
|
107 | } |
||
108 | |||
109 | // We now know the super type is not built-in and there's no string match, sub type must not be built-in |
||
110 | if (isset(self::$builtInTypes[$subTypeName])) { |
||
111 | return false; |
||
112 | } |
||
113 | |||
114 | return \is_subclass_of($subTypeName, $superTypeName); |
||
115 | } |
||
116 | } |
||
117 |