Completed
Push — master ( ad7c73...1d0993 )
by Klaus
03:10
created

TypeHandler::isInputHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 19 and the first side effect is on line 2.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
declare(strict_types=1);
3
4
namespace Linio\Component\Input;
5
6
use Linio\Component\Input\Instantiator\InstantiatorInterface;
7
use Linio\Component\Input\Instantiator\SetInstantiator;
8
use Linio\Component\Input\Node\BaseNode;
9
use Linio\Component\Input\Node\BoolNode;
10
use Linio\Component\Input\Node\CollectionNode;
11
use Linio\Component\Input\Node\DateTimeNode;
12
use Linio\Component\Input\Node\FloatNode;
13
use Linio\Component\Input\Node\IntNode;
14
use Linio\Component\Input\Node\NumericNode;
15
use Linio\Component\Input\Node\ObjectNode;
16
use Linio\Component\Input\Node\ScalarCollectionNode;
17
use Linio\Component\Input\Node\StringNode;
18
19
class TypeHandler
20
{
21
    /**
22
     * @var array
23
     */
24
    protected $types;
25
26
    /**
27
     * @var InstantiatorInterface
28
     */
29
    protected $defaultInstantiator;
30
31
    public function __construct()
32
    {
33
        $this->types = [
34
            'bool' => BoolNode::class,
35
            'int' => IntNode::class,
36
            'float' => FloatNode::class,
37
            'double' => FloatNode::class,
38
            'numeric' => NumericNode::class,
39
            'string' => StringNode::class,
40
            'array' => BaseNode::class,
41
            'object' => ObjectNode::class,
42
            'datetime' => DateTimeNode::class,
43
        ];
44
45
        $this->defaultInstantiator = new SetInstantiator();
46
    }
47
48
    public function addType(string $name, string $class)
49
    {
50
        $this->types[$name] = $class;
51
    }
52
53
    public function getType(string $name): BaseNode
54
    {
55
        if (isset($this->types[$name])) {
56
            $type = new $this->types[$name]();
57
            $type->setTypeHandler($this);
58
59
            return $type;
60
        }
61
62
        if ($this->isInputHandler($name)) {
63
            $handler = new $name($this);
64
            $handler->define();
65
66
            return $handler->getRoot();
67
        }
68
69
        if ($this->isScalarCollectionType($name)) {
70
            $type = new ScalarCollectionNode();
71
            $type->setType($this->getCollectionType($name));
72
            $type->setTypeHandler($this);
73
74
            return $type;
75
        }
76
77
        if ($this->isClassType($name)) {
78
            $type = new ObjectNode();
79
            $type->setType($name);
80
            $type->setTypeHandler($this);
81
            $type->setInstantiator($this->defaultInstantiator);
82
83
            return $type;
84
        }
85
86
        if ($this->isCollectionType($name)) {
87
            $type = new CollectionNode();
88
            $type->setType($this->getCollectionType($name));
89
            $type->setTypeHandler($this);
90
            $type->setInstantiator($this->defaultInstantiator);
91
92
            return $type;
93
        }
94
95
        throw new \InvalidArgumentException('Unknown type name: ' . $name);
96
    }
97
98
    protected function isClassType(string $type): bool
99
    {
100
        return class_exists($type) && $type != 'datetime';
101
    }
102
103
    protected function isCollectionType(string $type): bool
104
    {
105
        $collectionType = $this->getCollectionType($type);
106
107
        if (!class_exists($collectionType)) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return class_exists($collectionType);.
Loading history...
108
            return false;
109
        }
110
111
        return true;
112
    }
113
114
    protected function isScalarCollectionType(string $type): bool
115
    {
116
        $collectionType = $this->getCollectionType($type);
117
118
        if (!function_exists('is_' . $collectionType)) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return function_exists('is_' . $collectionType);.
Loading history...
119
            return false;
120
        }
121
122
        return true;
123
    }
124
125
    protected function isInputHandler(string $type): bool
126
    {
127
        return is_subclass_of($type, InputHandler::class);
128
    }
129
130
    protected function getCollectionType(string $type): string
131
    {
132
        $pos = strrpos($type, '[]');
133
134
        if ($pos === false) {
135
            return $type;
136
        }
137
138
        return substr($type, 0, $pos);
139
    }
140
}
141