Passed
Push — main ( 5e0bcd...9ce40a )
by Peter
02:12
created

Insert::addFrom()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace QB\Generic\Statement;
6
7
use QB\Generic\Clause\Table;
8
9
class Insert implements IInsert
10
{
11
    /** @var array<int,string|Table> */
12
    protected array $tables = [];
13
14
    /** @var string[] */
15
    protected array $modifiers = [];
16
17
    /** @var array<int|string,string> */
18
    protected array $columns = [];
19
20
    /** @var array<int,mixed> */
21
    protected array $values = [];
22
23
    /**
24
     * @param string|Table $table
25
     *
26
     * @return $this
27
     */
28
    public function setInto(string|Table $table): static
29
    {
30
        $this->tables = [$table];
31
32
        return $this;
33
    }
34
35
    /**
36
     * @param string ...$modifiers
37
     *
38
     * @return $this
39
     */
40
    public function addModifier(string ...$modifiers): static
41
    {
42
        $this->modifiers = array_merge($this->modifiers, $modifiers);
43
44
        return $this;
45
    }
46
47
    /**
48
     * @param string      $column
49
     * @param string|null $alias
50
     *
51
     * @return $this
52
     */
53
    public function addColumn(string $column, ?string $alias = null): static
54
    {
55
        if ($alias === null) {
56
            $this->columns[] = $column;
57
        } else {
58
            $this->columns[$alias] = $column;
59
        }
60
61
        return $this;
62
    }
63
64
    /**
65
     * @param string ...$columns
66
     *
67
     * @return $this
68
     */
69
    public function addColumns(string ...$columns): static
70
    {
71
        foreach ($columns as $rawColumn) {
72
            if (strpos($rawColumn, ' AS ')) {
73
                $parts                    = explode(' AS ', $rawColumn);
74
                $this->columns[$parts[1]] = $parts[0];
75
            } else {
76
                $this->columns[] = $rawColumn;
77
            }
78
        }
79
80
        return $this;
81
    }
82
83
    /**
84
     * @param mixed ...$values
85
     *
86
     * @return $this
87
     */
88
    public function addValues(...$values): static
89
    {
90
        if (count($this->columns) && count($values) !== count($this->columns)) {
91
            throw new \InvalidArgumentException('number of values does not match the number of columns');
92
        }
93
94
        $this->values[] = $values;
95
96
        return $this;
97
    }
98
99
    /**
100
     * @return string
101
     */
102
    public function __toString(): string
103
    {
104
        if (!$this->isValid()) {
105
            throw new \RuntimeException('under-initialized INSERT query');
106
        }
107
108
        $insert = $this->insert();
109
110
        $sqlParts = array_merge(
111
            [$insert],
112
            $this->values(),
113
        );
114
115
        $sqlParts = array_filter($sqlParts);
116
117
        return implode(PHP_EOL, $sqlParts);
118
    }
119
120
    public function isValid(): bool
121
    {
122
        return count($this->tables) === 1 && count($this->values) > 0;
123
    }
124
125
    protected function insert(): string
126
    {
127
        $sql = [];
128
        $sql[] = 'INSERT';
129
        $sql[] = $this->getModifiers();
130
        $sql[] = 'INTO';
131
        $sql[] = $this->tables[0];
132
133
        $sql = array_filter($sql);
134
135
        $sql = implode(' ', $sql);
136
137
        if (count($this->columns) === 0) {
138
            return $sql;
139
        }
140
141
        $columnParts = [];
142
        foreach ($this->columns as $alias => $column) {
143
            if (is_numeric($alias)) {
144
                $columnParts[] = $column;
145
            } else {
146
                $columnParts[] = "$column AS $alias";
147
            }
148
        }
149
150
        return $sql . ' (' . implode(', ', $columnParts) . ')';
151
    }
152
153
    protected function getModifiers(): string
154
    {
155
        if (empty($this->modifiers)) {
156
            return '';
157
        }
158
159
        return implode(' ', $this->modifiers);
160
    }
161
162
    protected function values(): array
163
    {
164
        $columnCount = count($this->columns) > 0 ? count($this->columns) : count($this->values[0]);
165
166
        $values = array_fill(0, $columnCount, '?');
167
168
        $row = sprintf('(%s)', implode(', ', $values));
169
170
        $rows = array_fill(0, count($this->values), $row);
171
172
        return ['VALUES ' . implode(",\n", $rows)];
173
    }
174
175
    /**
176
     * @return array
177
     */
178
    public function getParams(): array
179
    {
180
        $params = [];
181
182
        foreach ($this->values as $values) {
183
            foreach ($values as $value) {
184
                $params[] = [$value, \PDO::PARAM_STR];
185
            }
186
        }
187
188
        return $params;
189
    }
190
191
    /**
192
     * @return array
193
     */
194
    public function getValues(): array
195
    {
196
        return array_merge(...$this->values);
197
    }
198
}
199