TypeFactory::createType()   B
last analyzed

Complexity

Conditions 9
Paths 10

Size

Total Lines 34
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 9

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 21
c 1
b 0
f 0
nc 10
nop 1
dl 0
loc 34
ccs 21
cts 21
cp 1
crap 9
rs 8.0555
1
<?php
2
3
namespace Bdf\Serializer\Type;
4
5
/**
6
 * TypeFactory
7
 */
8
class TypeFactory
9
{
10
    /**
11
     * Alias of PHP builtin types gets by gettype.
12
     *
13
     * @var string[]
14
     */
15
    private static $mapping = [
16
        'object'        => \stdClass::class,
17
        'NULL'          => Type::TNULL,
18
        'unknown type'  => Type::MIXED,
19
//        'callback'  => 'callable',
20
    ];
21
22
    /**
23
     * The buildin types
24
     *
25
     * @var array
26
     */
27
    private static $builtin = [
28
        Type::STRING      => true,
29
        Type::INTEGER     => true,
30
        Type::FLOAT       => true,
31
        Type::DOUBLE      => true,
32
        Type::BOOLEAN     => true,
33
        Type::TNULL       => true,
34
        Type::TARRAY      => true,
35
        'int'             => true,
36
        'bool'            => true,
37
    ];
38
39
    /**
40
     * Creates a type string.
41
     *
42
     * @param string|object $type
43
     * @psalm-param class-string<T>|T $type
44
     *
45
     * @return (T is object ? Type<T> : Type<mixed>)
0 ignored issues
show
Documentation Bug introduced by
The doc comment (T at position 1 could not be parsed: Expected ')' at position 1, but found 'T'.
Loading history...
46
     *
47
     * @template T is object|string
48
     */
49 298
    public static function createType($type): Type
50
    {
51 298
        $collectionType = null;
52 298
        $collection = false;
53
54 298
        if (is_object($type)) {
55 8
            return new Type(get_class($type), false, false, null, $type);
56
        }
57
58
        // Cannot guess
59 296
        if (!$type || Type::MIXED === $type) {
60 104
            return self::mixedType();
61
        }
62
63 232
        if ('[]' === substr($type, -2)) { // Type[] syntax
64 28
            $collectionType = substr($type, 0, -2);
65 28
            $type = Type::TARRAY;
66 28
            $collection = true;
67 230
        } elseif ($type === Type::TARRAY) { // array
68 12
            $collectionType = Type::MIXED;
69 12
            $collection = true;
70 224
        } elseif (($pos = strpos($type, '<')) !== false && $type[strlen($type) - 1] === '>') { // Type<SubType> syntax
71 8
            $collectionType = substr($type, $pos + 1, -1);
72 8
            $type = substr($type, 0, $pos);
73
        }
74
75 232
        if ($collectionType) {
76 46
            $collectionType = self::createType($collectionType);
77
        } else {
78 224
            $collectionType = null; // Handle possible empty collection type name
79
        }
80
81
        /** @psalm-suppress ArgumentTypeCoercion */
82 232
        return new Type($type, self::isBuildinType($type), $collection, $collectionType);
83
    }
84
85
    /**
86
     * Creates a type from a value.
87
     *
88
     * @param T $value
89
     *
90
     * @return Type<T>
91
     *
92
     * @template T
93
     */
94 2
    public static function fromValue($value): Type
95
    {
96 2
        $type = self::normalizeType(gettype($value));
97
98 2
        return static::createType($type);
99
    }
100
101
    /**
102
     * Check whether the type is a php type.
103
     *
104
     * @param string $type
105
     *
106
     * @return boolean
107
     */
108 232
    public static function isBuildinType($type): bool
109
    {
110 232
        return isset(self::$builtin[$type]);
111
    }
112
113
    /**
114
     * Get the mixed type
115
     *
116
     * @return Type<mixed>
117
     */
118 112
    public static function mixedType(): Type
119
    {
120 112
        return new Type(Type::MIXED, true);
121
    }
122
123
    /**
124
     * Normalizes the type.
125
     *
126
     * @param string $type
127
     *
128
     * @return string
129
     */
130 2
    private static function normalizeType($type): string
131
    {
132 2
        if (isset(self::$mapping[$type])) {
133 2
            return self::$mapping[$type];
134
        }
135
136
        return $type;
137
    }
138
}
139