1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Yajra\Oci8\Eloquent; |
4
|
|
|
|
5
|
|
|
use Illuminate\Database\Eloquent\Builder; |
6
|
|
|
use Illuminate\Database\Eloquent\Model; |
7
|
|
|
use Illuminate\Database\Query\Builder as IlluminateQueryBuilder; |
8
|
|
|
use Yajra\Oci8\Oci8Connection; |
9
|
|
|
use Yajra\Oci8\Query\Grammars\OracleGrammar; |
10
|
|
|
use Yajra\Oci8\Query\OracleBuilder as QueryBuilder; |
11
|
|
|
|
12
|
|
|
class OracleEloquent extends Model |
13
|
|
|
{ |
14
|
|
|
/** |
15
|
|
|
* List of binary (blob) columns. |
16
|
|
|
* |
17
|
|
|
* @var array |
18
|
|
|
*/ |
19
|
|
|
protected $binaries = []; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* List of binary fields for storage. |
23
|
|
|
* |
24
|
|
|
* @var array |
25
|
|
|
*/ |
26
|
|
|
protected $binaryFields = []; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Sequence name variable |
30
|
|
|
* |
31
|
|
|
* @var string |
32
|
|
|
*/ |
33
|
|
|
protected $sequence = null; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Get model's sequence name |
37
|
|
|
* |
38
|
|
|
* @return string |
39
|
|
|
*/ |
40
|
|
|
public function getSequenceName() |
41
|
|
|
{ |
42
|
|
|
if ($this->sequence) { |
43
|
|
|
return $this->sequence; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
return $this->getTable() . '_' . $this->getKeyName() . '_seq'; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Set sequence name. |
51
|
|
|
* |
52
|
|
|
* @param string $name |
53
|
|
|
* @return $this |
54
|
|
|
*/ |
55
|
|
|
public function setSequenceName($name) |
56
|
|
|
{ |
57
|
|
|
$this->sequence = $name; |
58
|
|
|
|
59
|
|
|
return $this; |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Update the model in the database. |
64
|
|
|
* |
65
|
|
|
* @param array $attributes |
66
|
|
|
* @param array $options |
67
|
|
|
* @return bool|int |
68
|
|
|
*/ |
69
|
|
|
public function update(array $attributes = [], array $options = []) |
70
|
|
|
{ |
71
|
|
|
if (! $this->exists) { |
72
|
|
|
// If dirty attributes contains binary field |
73
|
|
|
// extract binary fields to new array |
74
|
|
|
if ($this->extractBinaries($dirty)) { |
75
|
|
|
return $this->newQuery()->updateLob($attributes, $this->binaryFields, $this->getKeyName()); |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
return $this->newQuery()->update($attributes); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
return $this->fill($attributes)->save($options); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Extract binary fields from given attributes. |
86
|
|
|
* |
87
|
|
|
* @param array $attributes |
88
|
|
|
* @return array |
89
|
|
|
*/ |
90
|
|
|
protected function extractBinaries(&$attributes) |
91
|
|
|
{ |
92
|
|
|
// If attributes contains binary field |
93
|
|
|
// extract binary fields to new array |
94
|
|
|
$binaries = []; |
95
|
|
|
if ($this->checkBinary($attributes) && $this->getConnection() instanceof Oci8Connection) { |
96
|
|
|
foreach ($attributes as $key => $value) { |
97
|
|
|
if (in_array($key, $this->binaries)) { |
98
|
|
|
$binaries[$key] = $value; |
99
|
|
|
unset($attributes[$key]); |
100
|
|
|
} |
101
|
|
|
} |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
return $this->binaryFields = $binaries; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Check if attributes contains binary field. |
109
|
|
|
* |
110
|
|
|
* @param array $attributes |
111
|
|
|
* @return boolean |
112
|
|
|
*/ |
113
|
|
|
protected function checkBinary(array $attributes) |
114
|
|
|
{ |
115
|
|
|
foreach ($attributes as $key => $value) { |
116
|
|
|
// if attribute is in binary field list |
117
|
|
|
if (in_array($key, $this->binaries)) { |
118
|
|
|
return true; |
119
|
|
|
} |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
return false; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Get the table qualified key name. |
127
|
|
|
* |
128
|
|
|
* @return string |
129
|
|
|
*/ |
130
|
|
|
public function getQualifiedKeyName() |
131
|
|
|
{ |
132
|
|
|
$pos = strpos($this->getTable(), '@'); |
133
|
|
|
|
134
|
|
|
if ($pos === false) { |
135
|
|
|
return $this->getTable() . '.' . $this->getKeyName(); |
136
|
|
|
} else { |
137
|
|
|
$table = substr($this->getTable(), 0, $pos); |
138
|
|
|
$dbLink = substr($this->getTable(), $pos); |
139
|
|
|
|
140
|
|
|
return $table . '.' . $this->getKeyName() . $dbLink; |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Get a new query builder instance for the connection. |
146
|
|
|
* |
147
|
|
|
* @return \Illuminate\Database\Query\Builder|\Yajra\Oci8\Query\OracleBuilder |
148
|
|
|
*/ |
149
|
15 |
|
protected function newBaseQueryBuilder() |
150
|
|
|
{ |
151
|
|
|
|
152
|
15 |
|
$conn = $this->getConnection(); |
153
|
15 |
|
$grammar = $conn->getQueryGrammar(); |
154
|
|
|
|
155
|
15 |
|
if ($grammar instanceof OracleGrammar) { |
156
|
3 |
|
return new QueryBuilder($conn, $grammar, $conn->getPostProcessor()); |
157
|
|
|
} |
158
|
|
|
|
159
|
12 |
|
return new IlluminateQueryBuilder($conn, $grammar, $conn->getPostProcessor()); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Perform a model update operation. |
164
|
|
|
* |
165
|
|
|
* @param \Illuminate\Database\Eloquent\Builder $query |
166
|
|
|
* @param array $options |
167
|
|
|
* @return boolean |
168
|
|
|
*/ |
169
|
|
|
protected function performUpdate(Builder $query, array $options = []) |
170
|
|
|
{ |
171
|
|
|
$dirty = $this->getDirty(); |
172
|
|
|
|
173
|
|
|
if (count($dirty) > 0) { |
174
|
|
|
// If the updating event returns false, we will cancel the update operation so |
175
|
|
|
// developers can hook Validation systems into their models and cancel this |
176
|
|
|
// operation if the model does not pass validation. Otherwise, we update. |
177
|
|
|
if ($this->fireModelEvent('updating') === false) { |
178
|
|
|
return false; |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
// First we need to create a fresh query instance and touch the creation and |
182
|
|
|
// update timestamp on the model which are maintained by us for developer |
183
|
|
|
// convenience. Then we will just continue saving the model instances. |
184
|
|
|
if ($this->timestamps && array_get($options, 'timestamps', true)) { |
185
|
|
|
$this->updateTimestamps(); |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
// Once we have run the update operation, we will fire the "updated" event for |
189
|
|
|
// this model instance. This will allow developers to hook into these after |
190
|
|
|
// models are updated, giving them a chance to do any special processing. |
191
|
|
|
$dirty = $this->getDirty(); |
192
|
|
|
|
193
|
|
|
if (count($dirty) > 0) { |
194
|
|
|
// If dirty attributes contains binary field |
195
|
|
|
// extract binary fields to new array |
196
|
|
|
$this->updateBinary($query, $dirty, $options); |
197
|
|
|
|
198
|
|
|
$this->fireModelEvent('updated', false); |
199
|
|
|
} |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
return true; |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* Update model with binary (blob) fields. |
207
|
|
|
* |
208
|
|
|
* @param Builder $query |
209
|
|
|
* @param array $dirty |
210
|
|
|
* @param array $options |
211
|
|
|
*/ |
212
|
|
|
protected function updateBinary(Builder $query, $dirty, $options = []) |
213
|
|
|
{ |
214
|
|
|
if ($this->extractBinaries($dirty)) { |
215
|
|
|
$this->setKeysForSaveQuery($query)->updateLob($dirty, $this->binaryFields, $this->getKeyName()); |
216
|
|
|
} else { |
217
|
|
|
$this->setKeysForSaveQuery($query)->update($dirty, $options); |
|
|
|
|
218
|
|
|
} |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* Perform a model insert operation. |
223
|
|
|
* |
224
|
|
|
* @param \Illuminate\Database\Eloquent\Builder $query |
225
|
|
|
* @param array $options |
226
|
|
|
* @return bool |
227
|
|
|
*/ |
228
|
|
|
protected function performInsert(Builder $query, array $options = []) |
229
|
|
|
{ |
230
|
|
|
if ($this->fireModelEvent('creating') === false) { |
231
|
|
|
return false; |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
// First we'll need to create a fresh query instance and touch the creation and |
235
|
|
|
// update timestamps on this model, which are maintained by us for developer |
236
|
|
|
// convenience. After, we will just continue saving these model instances. |
237
|
|
|
if ($this->timestamps && array_get($options, 'timestamps', true)) { |
238
|
|
|
$this->updateTimestamps(); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
// If the model has an incrementing key, we can use the "insertGetId" method on |
242
|
|
|
// the query builder, which will give us back the final inserted ID for this |
243
|
|
|
// table from the database. Not all tables have to be incrementing though. |
244
|
|
|
$attributes = $this->attributes; |
245
|
|
|
|
246
|
|
|
if ($this->incrementing) { |
247
|
|
|
$this->insertAndSetId($query, $attributes); |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
// If the table is not incrementing we'll simply insert this attributes as they |
251
|
|
|
// are, as this attributes arrays must contain an "id" column already placed |
252
|
|
|
// there by the developer as the manually determined key for these models. |
253
|
|
|
else { |
254
|
|
|
// If attributes contains binary field |
255
|
|
|
// extract binary fields to new array |
256
|
|
|
if ($this->extractBinaries($attributes)) { |
257
|
|
|
$query->getQuery()->insertLob($attributes, $this->binaryFields, $this->getKeyName()); |
258
|
|
|
} else { |
259
|
|
|
$query->insert($attributes); |
260
|
|
|
} |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
// We will go ahead and set the exists property to true, so that it is set when |
264
|
|
|
// the created event is fired, just in case the developer tries to update it |
265
|
|
|
// during the event. This will allow them to do so and run an update here. |
266
|
|
|
$this->exists = true; |
267
|
|
|
|
268
|
|
|
$this->wasRecentlyCreated = true; |
269
|
|
|
|
270
|
|
|
$this->fireModelEvent('created', false); |
271
|
|
|
|
272
|
|
|
return true; |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Insert the given attributes and set the ID on the model. |
277
|
|
|
* |
278
|
|
|
* @param \Illuminate\Database\Eloquent\Builder $query |
279
|
|
|
* @param array $attributes |
280
|
|
|
* @return int|void |
281
|
|
|
*/ |
282
|
|
|
protected function insertAndSetId(Builder $query, $attributes) |
283
|
|
|
{ |
284
|
|
|
if ($binaries = $this->extractBinaries($attributes)) { |
285
|
|
|
$id = $query->getQuery()->insertLob($attributes, $binaries, $keyName = $this->getKeyName()); |
286
|
|
|
} else { |
287
|
|
|
$id = $query->insertGetId($attributes, $keyName = $this->getKeyName()); |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
$this->setAttribute($keyName, $id); |
291
|
|
|
} |
292
|
|
|
} |
293
|
|
|
|
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
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.