Update::getWhere()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 8
rs 10
ccs 5
cts 5
cp 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace QB\Generic\Statement;
6
7
use QB\Generic\Clause\Table;
8
use QB\Generic\Expr\Expr;
9
use QB\Generic\IQueryPart;
10
use RuntimeException;
11
12
class Update implements IUpdate
13
{
14
    /** @var array<int,Table|string> */
15
    protected array $tables = [];
16
17
    /** @var string[] */
18
    protected array $modifiers = [];
19
20
    /** @var array<string,mixed> */
21
    protected array $rawValues = [];
22
23
    /** @var IQueryPart[] */
24
    protected array $whereParts = [];
25
26
    /**
27
     * @param Table|string ...$tables
28
     */
29 11
    public function __construct(Table|string ...$tables)
30
    {
31 11
        $this->tables = array_merge($this->tables, $tables);
32 11
    }
33
34
    /**
35
     * @param string ...$modifiers
36
     *
37
     * @return $this
38
     */
39 1
    public function modifier(string ...$modifiers): static
40
    {
41 1
        $this->modifiers = array_merge($this->modifiers, $modifiers);
42
43 1
        return $this;
44
    }
45
46
    /**
47
     * @param array<string,mixed> $values
48
     *
49
     * @return $this
50
     */
51 9
    public function values(array $values): static
52
    {
53 9
        $this->rawValues = $values;
54
55 9
        return $this;
56
    }
57
58
    /**
59
     * @param IQueryPart|string ...$whereParts
60
     *
61
     * @return $this
62
     */
63 9
    public function where(IQueryPart|string ...$whereParts): static
64
    {
65 9
        foreach ($whereParts as $wherePart) {
66 9
            $this->whereParts[] = is_string($wherePart) ? new Expr($wherePart) : $wherePart;
67
        }
68
69 9
        return $this;
70
    }
71
72
    /**
73
     * @return string
74
     */
75 9
    public function __toString(): string
76
    {
77 9
        if (!$this->isValid()) {
78 2
            throw new RuntimeException('Under-initialized UPDATE query. Table, values and where are necessary');
79
        }
80
81 7
        $sqlParts = array_merge(
82 7
            [$this->getCommand()],
83 7
            $this->getSet(),
84 7
            $this->getWhere(),
85
        );
86
87 7
        $sqlParts = array_filter($sqlParts);
88
89 7
        return implode(PHP_EOL, $sqlParts);
90
    }
91
92
    /**
93
     * @return bool
94
     */
95 9
    public function isValid(): bool
96
    {
97 9
        return count($this->tables) === 1 && count($this->rawValues) > 0 && count($this->whereParts) > 0;
98
    }
99
100
    /**
101
     * @return string
102
     */
103 7
    protected function getCommand(): string
104
    {
105 7
        $sql   = [];
106 7
        $sql[] = 'UPDATE';
107 7
        $sql[] = implode(' ', $this->modifiers);
108 7
        $sql[] = $this->tables[0];
109
110 7
        $sql = array_filter($sql);
111
112 7
        return implode(' ', $sql);
113
    }
114
115
    /**
116
     * @return string[]
117
     */
118 7
    protected function getSet(): array
119
    {
120 7
        $values = [];
121 7
        foreach ($this->rawValues as $column => $value) {
122 7
            if ($value === null) {
123 1
                $values[] = sprintf('%s = NULL', $column);
124 7
            } elseif (is_scalar($value)) {
125 7
                $values[] = sprintf('%s = %s', $column, $value);
126 2
            } elseif ($value instanceof Expr) {
127 2
                $values[] = sprintf("%s = ?", $column);
128
            } else {
129 1
                $values[] = sprintf("%s = '%s'", $column, json_encode($value));
130
            }
131
        }
132
133 7
        return ['SET ' . implode(', ', $values)];
134
    }
135
136
    /**
137
     * @return string[]
138
     */
139 7
    protected function getWhere(): array
140
    {
141 7
        $whereParts = [];
142 7
        foreach ($this->whereParts as $wherePart) {
143 7
            $whereParts[] = (string)$wherePart;
144
        }
145
146 7
        return ['WHERE ' . implode(' AND ', $whereParts)];
147
    }
148
149
    /**
150
     * @return array
151
     */
152 2
    public function getParams(): array
153
    {
154 2
        $params = [];
155
156 2
        foreach ($this->rawValues as $values) {
157 2
            if ($values instanceof IQueryPart) {
158 2
                $params = array_merge($params, $values->getParams());
159
            }
160
        }
161
162 2
        foreach ($this->whereParts as $wherePart) {
163 2
            $params = array_merge($params, $wherePart->getParams());
164
        }
165
166 2
        return $params;
167
    }
168
}
169