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();
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: protected function newBaseQueryBuilder()
150: {
151:
152: $conn = $this->getConnection();
153: $grammar = $conn->getQueryGrammar();
154:
155: if ($grammar instanceof OracleGrammar) {
156: return new QueryBuilder($conn, $grammar, $conn->getPostProcessor());
157: }
158:
159: 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: