|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* Spiral Framework. |
|
4
|
|
|
* |
|
5
|
|
|
* @license MIT |
|
6
|
|
|
* @author Anton Titov (Wolfy-J) |
|
7
|
|
|
*/ |
|
8
|
|
|
|
|
9
|
|
|
namespace Spiral\Database\Builders; |
|
10
|
|
|
|
|
11
|
|
|
use Spiral\Database\Builders\Prototypes\AbstractAffect; |
|
12
|
|
|
use Spiral\Database\Entities\Driver; |
|
13
|
|
|
use Spiral\Database\Entities\QueryCompiler; |
|
14
|
|
|
use Spiral\Database\Exceptions\BuilderException; |
|
15
|
|
|
use Spiral\Database\Injections\FragmentInterface; |
|
16
|
|
|
use Spiral\Database\Injections\ParameterInterface; |
|
17
|
|
|
|
|
18
|
|
|
/** |
|
19
|
|
|
* Update statement builder. |
|
20
|
|
|
*/ |
|
21
|
|
|
class UpdateQuery extends AbstractAffect |
|
22
|
|
|
{ |
|
23
|
|
|
/** |
|
24
|
|
|
* Query type. |
|
25
|
|
|
*/ |
|
26
|
|
|
const QUERY_TYPE = QueryCompiler::UPDATE_QUERY; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* Column names associated with their values. |
|
30
|
|
|
* |
|
31
|
|
|
* @var array |
|
32
|
|
|
*/ |
|
33
|
|
|
protected $values = []; |
|
34
|
|
|
|
|
35
|
|
|
/** |
|
36
|
|
|
* {@inheritdoc} |
|
37
|
|
|
* |
|
38
|
|
|
* @param array $values Initial set of column updates. |
|
39
|
|
|
*/ |
|
40
|
|
|
public function __construct( |
|
41
|
|
|
Driver $driver, |
|
42
|
|
|
QueryCompiler $compiler, |
|
43
|
|
|
string $table = '', |
|
44
|
|
|
array $where = [], |
|
45
|
|
|
array $values = [] |
|
46
|
|
|
) { |
|
47
|
|
|
parent::__construct($driver, $compiler, $table, $where); |
|
48
|
|
|
|
|
49
|
|
|
$this->values = $values; |
|
50
|
|
|
} |
|
51
|
|
|
|
|
52
|
|
|
/** |
|
53
|
|
|
* Change target table. |
|
54
|
|
|
* |
|
55
|
|
|
* @param string $table Table name without prefix. |
|
56
|
|
|
* |
|
57
|
|
|
* @return self|$this |
|
58
|
|
|
*/ |
|
59
|
|
|
public function in(string $table): UpdateQuery |
|
60
|
|
|
{ |
|
61
|
|
|
$this->table = $table; |
|
62
|
|
|
|
|
63
|
|
|
return $this; |
|
64
|
|
|
} |
|
65
|
|
|
|
|
66
|
|
|
/** |
|
67
|
|
|
* Change value set to be updated, must be represented by array of columns associated with new |
|
68
|
|
|
* value to be set. |
|
69
|
|
|
* |
|
70
|
|
|
* @param array $values |
|
71
|
|
|
* |
|
72
|
|
|
* @return self|$this |
|
73
|
|
|
*/ |
|
74
|
|
|
public function values(array $values): UpdateQuery |
|
75
|
|
|
{ |
|
76
|
|
|
$this->values = $values; |
|
77
|
|
|
|
|
78
|
|
|
return $this; |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* Get list of columns associated with their values. |
|
83
|
|
|
* |
|
84
|
|
|
* @return array |
|
85
|
|
|
*/ |
|
86
|
|
|
public function getValues(): array |
|
87
|
|
|
{ |
|
88
|
|
|
return $this->values; |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
|
|
/** |
|
92
|
|
|
* Set update value. |
|
93
|
|
|
* |
|
94
|
|
|
* @param string $column |
|
95
|
|
|
* @param mixed $value |
|
96
|
|
|
* |
|
97
|
|
|
* @return self|$this |
|
98
|
|
|
*/ |
|
99
|
|
|
public function set(string $column, $value): UpdateQuery |
|
100
|
|
|
{ |
|
101
|
|
|
$this->values[$column] = $value; |
|
102
|
|
|
|
|
103
|
|
|
return $this; |
|
104
|
|
|
} |
|
105
|
|
|
|
|
106
|
|
|
/** |
|
107
|
|
|
* {@inheritdoc} |
|
108
|
|
|
*/ |
|
109
|
|
|
public function getParameters(QueryCompiler $compiler = null): array |
|
110
|
|
|
{ |
|
111
|
|
|
$compiler = $compiler ?? $this->compiler; |
|
112
|
|
|
|
|
113
|
|
|
$values = []; |
|
114
|
|
|
foreach ($this->values as $value) { |
|
115
|
|
|
if ($value instanceof QueryBuilder) { |
|
116
|
|
|
foreach ($value->getParameters() as $parameter) { |
|
117
|
|
|
$values[] = $parameter; |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
continue; |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
if ($value instanceof FragmentInterface && !$value instanceof ParameterInterface) { |
|
124
|
|
|
//Apparently sql fragment |
|
125
|
|
|
continue; |
|
126
|
|
|
} |
|
127
|
|
|
|
|
128
|
|
|
$values[] = $value; |
|
129
|
|
|
} |
|
130
|
|
|
|
|
131
|
|
|
//Join and where parameters are going after values |
|
132
|
|
|
return $this->flattenParameters( |
|
133
|
|
|
$compiler->orderParameters(self::QUERY_TYPE, $this->whereParameters, [], [], $values) |
|
134
|
|
|
); |
|
135
|
|
|
} |
|
136
|
|
|
|
|
137
|
|
|
/** |
|
138
|
|
|
* {@inheritdoc} |
|
139
|
|
|
*/ |
|
140
|
|
|
public function sqlStatement(QueryCompiler $compiler = null): string |
|
141
|
|
|
{ |
|
142
|
|
|
if (empty($this->values)) { |
|
143
|
|
|
throw new BuilderException('Update values must be specified'); |
|
|
|
|
|
|
144
|
|
|
} |
|
145
|
|
|
|
|
146
|
|
|
if (empty($compiler)) { |
|
147
|
|
|
$compiler = $this->compiler->resetQuoter(); |
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
return $compiler->compileUpdate($this->table, $this->values, $this->whereTokens); |
|
151
|
|
|
} |
|
152
|
|
|
} |
|
153
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignorePhpDoc annotation to the duplicate definition and it will be ignored.