Completed
Branch feature/pre-split (713d19)
by Anton
03:04
created

Parameter::resolveType()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 2
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Spiral\Database\Injections;
10
11
/**
12
 * Default implementation of ParameterInterface, provides ability to mock value or array of values
13
 * and automatically create valid query placeholder at moment of query compilation (? vs (?, ?, ?)).
14
 *
15
 * @todo implement custom sqlStatement value?
16
 */
17
class Parameter implements ParameterInterface
18
{
19
    /**
20
     * Use in constructor to automatically detect parameter type.
21
     */
22
    const DETECT_TYPE = 900888;
23
24
    /**
25
     * Mocked value or array of values.
26
     *
27
     * @var mixed|array
28
     */
29
    private $value = null;
30
31
    /**
32
     * Parameter type.
33
     *
34
     * @var int|null
35
     */
36
    private $type = null;
37
38
    /**
39
     * @param mixed $value
40
     * @param int   $type
41
     */
42
    public function __construct($value, int $type = self::DETECT_TYPE)
43
    {
44
        $this->value = $value;
45
        $this->resolveType($value, $type);
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function getValue()
52
    {
53
        return $this->value;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59
    public function setValue($value)
60
    {
61
        $this->value = $value;
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67
    public function withValue($value, int $type = self::DETECT_TYPE): Parameter
68
    {
69
        $parameter = clone $this;
70
        $parameter->value = $value;
71
        $parameter->resolveType($value, $type);
72
73
        return $parameter;
74
    }
75
76
    /**
77
     * Parameter type.
78
     *
79
     * @return int
80
     */
81
    public function getType(): int
82
    {
83
        return $this->type;
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89
    public function isArray(): bool
90
    {
91
        return is_array($this->value);
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function flatten(): array
98
    {
99
        if (!is_array($this->value)) {
100
            return [clone $this];
101
        }
102
103
        $result = [];
104
        foreach ($this->value as $value) {
105
            if (!$value instanceof ParameterInterface) {
106
                //Self copy
107
                $value = $this->withValue($value, self::DETECT_TYPE);
108
            }
109
110
            $result = array_merge($result, $value->flatten());
111
        }
112
113
        return $result;
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function sqlStatement(): string
120
    {
121
        if (is_array($this->value)) {
122
            //Array were mocked
123
            return '(' . trim(str_repeat('?, ', count($this->value)), ', ') . ')';
124
        }
125
126
        return '?';
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    public function __toString(): string
133
    {
134
        return $this->sqlStatement();
135
    }
136
137
    /**
138
     * @return array
139
     */
140
    public function __debugInfo()
141
    {
142
        return [
143
            'statement' => $this->sqlStatement(),
144
            'value'     => $this->value,
145
        ];
146
    }
147
148
    /**
149
     * @param mixed $value
150
     * @param int   $type
151
     */
152
    protected function resolveType($value, int $type)
153
    {
154
        if ($type == self::DETECT_TYPE) {
155
            if (!is_array($value)) {
156
                $this->type = $this->detectType($value);
157
            } else {
158
                $this->type = \PDO::PARAM_STMT;
159
            }
160
        } else {
161
            $this->type = $type;
162
        }
163
    }
164
165
    /**
166
     * @param mixed $value
167
     *
168
     * @return int
169
     */
170
    protected function detectType($value): int
171
    {
172
        switch (gettype($value)) {
173
            case 'boolean':
174
                return \PDO::PARAM_BOOL;
175
            case 'integer':
176
                return \PDO::PARAM_INT;
177
            case 'NULL':
178
                return \PDO::PARAM_NULL;
179
            default:
180
                return \PDO::PARAM_STR;
181
        }
182
    }
183
}
184