PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
← All changes | admin/helpers/src/mvc/model.php +429 -355 1.6.5 → 1.8.16 View file →
@@ -13,420 +13,494 @@
13 13
14 14 /**
15 15 * VikBooking MVC base model declaration.
16 16 *
17 - * @since 1.5.10
17 + * @since 1.15.10 (J) - 1.5.10 (WP)
18 18 */
19 19 abstract class VBOMvcModel extends JObject
20 20 {
21 - /**
22 - * Cached used to store the supported columns of the requested database tables.
23 - *
24 - * @var string
25 - */
26 - protected static $fields = [];
21 + /**
22 + * Cached used to store the supported columns of the requested database tables.
23 + *
24 + * @var string
25 + */
26 + protected static $fields = [];
27 27
28 - /**
29 - * The database table name.
30 - *
31 - * @var string
32 - */
33 - protected $tableName = null;
28 + /**
29 + * The database table name.
30 + *
31 + * @var string
32 + */
33 + protected $tableName = null;
34 34
35 - /**
36 - * The database table primary key name.
37 - *
38 - * @var string
39 - */
40 - protected $tableKeyName = 'id';
35 + /**
36 + * The database table primary key name.
37 + *
38 + * @var string
39 + */
40 + protected $tableKeyName = 'id';
41 41
42 - /**
43 - * Returns a new instance of the requested model.
44 - *
45 - * @param string $name The model name.
46 - * @param array $options The model configuration.
47 - *
48 - * @return VBOMvcModel
49 - */
50 - public static function getInstance($name, array $options = [])
51 - {
52 - /**
53 - * Trigger hook to allow third party plugins to extend the default models in VikBooking without
54 - * altering a single line of code from the core of the plugin.
55 - *
56 - * It is either possible to swap the name or to return a new instance of VBOMvcModel.
57 - *
58 - * @param string &$name A reference to the requested model.
59 - * @param array &$options A reference to the model configuration.
60 - *
61 - * @return mixed
62 - */
63 - $results = VBOFactory::getPlatform()->getDispatcher()->filter('onBeforeCreateModelVikBooking', [&$name, &$options]);
42 + /**
43 + * Returns a new instance of the requested model.
44 + *
45 + * @param string $name The model name.
46 + * @param array $options The model configuration.
47 + *
48 + * @return VBOMvcModel
49 + */
50 + public static function getInstance($name, array $options = [])
51 + {
52 + /**
53 + * Trigger hook to allow third party plugins to extend the default models in VikBooking without
54 + * altering a single line of code from the core of the plugin.
55 + *
56 + * It is either possible to swap the name or to return a new instance of VBOMvcModel.
57 + *
58 + * @param string &$name A reference to the requested model.
59 + * @param array &$options A reference to the model configuration.
60 + *
61 + * @return mixed
62 + */
63 + $results = VBOFactory::getPlatform()->getDispatcher()->filter('onBeforeCreateModelVikBooking', [&$name, &$options]);
64 64
65 - // filter the returned values to take only the first valid instance
66 - $results = array_filter($results, function($data)
67 - {
68 - return $data instanceof VBOMvcModel;
69 - });
65 + // filter the returned values to take only the first valid instance
66 + $results = array_filter($results, function($data)
67 + {
68 + return $data instanceof VBOMvcModel;
69 + });
70 70
71 - if ($results)
72 - {
73 - // class returned by a plugin, directly use it
74 - return $results[0];
75 - }
71 + if ($results)
72 + {
73 + // class returned by a plugin, directly use it
74 + return reset($results);
75 + }
76 76
77 - // fallback to the default classes in VikBooking
78 - $suffix = str_replace('_', ' ', $name);
79 - $suffix = str_replace(' ', '', ucwords($suffix));
77 + // fallback to the default classes in VikBooking
78 + $suffix = str_replace('_', ' ', $name);
79 + $suffix = str_replace(' ', '', ucwords($suffix));
80 80
81 - $modelClass = 'VBOModel' . $suffix;
81 + $modelClass = 'VBOModel' . $suffix;
82 82
83 - if (!class_exists($modelClass))
84 - {
85 - throw new Exception(sprintf('Model [%s] not found', $name), 404);
86 - }
83 + if (!class_exists($modelClass))
84 + {
85 + throw new Exception(sprintf('Model [%s] not found', $name), 404);
86 + }
87 87
88 - return new $modelClass($options);
89 - }
88 + return new $modelClass($options);
89 + }
90 90
91 - /**
92 - * Returns the model name.
93 - *
94 - * @return string
95 - */
96 - public function getName()
97 - {
98 - if (preg_match("/^VBOModel([a-z0-9_]+)$/i", get_class($this), $match))
99 - {
100 - return strtolower($match[1]);
101 - }
91 + /**
92 + * Returns the model name.
93 + *
94 + * @return string
95 + */
96 + public function getName()
97 + {
98 + if (preg_match("/^VBOModel([a-z0-9_]+)$/i", get_class($this), $match))
99 + {
100 + return strtolower($match[1]);
101 + }
102 102
103 - // unable to extract model name from class, use the file name
104 - return basename(__FILE__, '.php');
105 - }
103 + // unable to extract model name from class, use the file name
104 + return basename(__FILE__, '.php');
105 + }
106 106
107 - /**
108 - * Basic item loading implementation.
109 - *
110 - * @param mixed $pk An optional primary key value to load the row by, or an array of fields to match.
111 - * If not set the instance property value is used.
112 - *
113 - * @return mixed The record object on success, null otherwise.
114 - */
115 - public function getItem($pk)
116 - {
117 - $db = JFactory::getDbo();
107 + /**
108 + * Basic item loading implementation.
109 + *
110 + * @param mixed $pk An optional primary key value to load the row by, or an array of fields to match.
111 + * If not set the instance property value is used.
112 + *
113 + * @return ?object The record object on success, null otherwise.
114 + */
115 + public function getItem($pk)
116 + {
117 + $db = JFactory::getDbo();
118 118
119 - $query = $db->getQuery(true)
120 - ->select('*')
121 - ->from($db->qn($this->tableName));
119 + $query = $db->getQuery(true)
120 + ->select('*')
121 + ->from($db->qn($this->tableName));
122 122
123 - if (is_array($pk))
124 - {
125 - foreach ($pk as $column => $value)
126 - {
127 - $query->where($db->qn($column) . ' = ' . $db->q($value));
128 - }
129 - }
130 - else
131 - {
132 - $query->where($db->qn($this->tableKeyName) . ' = ' . (int) $pk);
133 - }
123 + if (is_array($pk))
124 + {
125 + foreach ($pk as $column => $value)
126 + {
127 + $query->where($db->qn($column) . ' = ' . $db->q($value));
128 + }
129 + }
130 + else
131 + {
132 + $query->where($db->qn($this->tableKeyName) . ' = ' . (int) $pk);
133 + }
134 134
135 - $db->setQuery($query, 0, 1);
135 + $db->setQuery($query, 0, 1);
136 136
137 - return $db->loadObject();
138 - }
137 + return $db->loadObject();
138 + }
139 139
140 - /**
141 - * Method to save the form data.
142 - *
143 - * @param mixed $data The form data.
144 - *
145 - * @return mixed The primary key of the saved item, false otherwise.
146 - */
147 - public function save($data)
148 - {
149 - $data = (array) $data;
140 + /**
141 + * Items loading implementation.
142 + *
143 + * @param array $clauses List of associative columns to fetch
144 + * (column => [operator, value] or column => value)
145 + * @param int $start Query limit start.
146 + * @param int $lim Query limit value.
147 + * @param array $cols Optional list of columns to fetch.
148 + * @param array $ordering Optional associative list of ordering columns.
149 + *
150 + * @return array List of record objects.
151 + *
152 + * @since 1.18.8 (J) - 1.8.8 (WP)
153 + */
154 + public function getItems(array $clauses = [], int $start = 0, int $lim = 0, array $cols = [], array $ordering = [])
155 + {
156 + $db = JFactory::getDbo();
150 157
151 - // let the children bind the data array before save
152 - if (!$this->preflight($data))
153 - {
154 - return false;
155 - }
158 + $q = $db->getQuery(true);
156 159
157 - // check if we have an empty record
158 - $isNew = empty($data[$this->tableKeyName]);
160 + if (!$cols)
161 + {
162 + $q->select('*');
163 + }
164 + else
165 + {
166 + $q->select(array_map([$db, 'qn'], $cols));
167 + }
159 168
160 - // store the object within the database
161 - $pk = $this->store((array) $data);
169 + $q->from($db->qn($this->tableName));
162 170
163 - if (!$pk)
164 - {
165 - return false;
166 - }
171 + foreach ($clauses as $column => $data)
172 + {
173 + if (!is_array($data))
174 + {
175 + // convert structure
176 + $data = ['value' => $data];
177 + }
167 178
168 - // let the children perform extra actions after saving
169 - $this->postflight((array) $data, $isNew);
179 + if (is_null($data['value']))
180 + {
181 + $q->where($db->qn($column) . ' IS NULL');
182 + }
183 + else
184 + {
185 + $q->where($db->qn($column) . ' ' . ($data['operator'] ?? '=') . ' ' . $db->q($data['value']));
186 + }
187 + }
170 188
171 - return $pk;
172 - }
189 + if ($ordering)
190 + {
191 + // sort by given columns
192 + foreach ($ordering as $orderColumn => $orderSort)
193 + {
194 + if (!is_string($orderSort))
195 + {
196 + continue;
197 + }
173 198
174 - /**
175 - * Method to delete one or more records.
176 - *
177 - * @param mixed $pks An array of record primary keys.
178 - *
179 - * @return boolean True if successful, false if an error occurs.
180 - */
181 - public function delete($pks)
182 - {
183 - if (!$pks)
184 - {
185 - // nothing to delete
186 - return false;
187 - }
199 + // set ordering column
200 + $q->order($db->qn($orderColumn) . ' ' . (!strcasecmp($orderSort, 'ASC') ? 'ASC' : 'DESC'));
201 + }
202 + }
203 + else
204 + {
205 + // default ordering column
206 + $q->order($db->qn($this->tableKeyName) . ' ASC');
207 + }
188 208
189 - if (!is_array($pks))
190 - {
191 - // wrap in an array
192 - $pks = [$pks];
193 - }
209 + $db->setQuery($q, $start, $lim);
194 210
195 - $app = JFactory::getApplication();
211 + return $db->loadObjectList();
212 + }
196 213
197 - $affected = true;
214 + /**
215 + * Method to save the form data.
216 + *
217 + * @param mixed $data The form data.
218 + *
219 + * @return mixed The primary key of the saved item, false otherwise.
220 + */
221 + public function save($data)
222 + {
223 + $data = (array) $data;
198 224
199 - foreach ($pks as $pk)
200 - {
201 - // fetch item details
202 - $item = $this->getItem($pk);
225 + // let the children bind the data array before save
226 + if (!$this->preflight($data))
227 + {
228 + return false;
229 + }
203 230
204 - if (!$item)
205 - {
206 - continue;
207 - }
231 + // check if we have an empty record
232 + $isNew = empty($data[$this->tableKeyName]);
208 233
209 - /**
210 - * Runs before deleting the given data.
211 - * It is possible to validate here whether the item should be deleted or not.
212 - *
213 - * @param object $data The record to delete.
214 - * @param self $model The current model.
215 - *
216 - * @return boolean False to abort the deleting process.
217 - *
218 - * @since 1.5.10
219 - */
220 - $results = $app->triggerEvent('onBeforeDeleteVikBooking' . ucfirst($this->getName()), [$item, $this]);
234 + // store the object within the database
235 + $pk = $this->store((array) $data);
221 236
222 - // check whether a plugin aborted the deleting process
223 - if (in_array(false, $results, true))
224 - {
225 - continue;
226 - }
237 + if (!$pk)
238 + {
239 + return false;
240 + }
227 241
228 - // remove item
229 - $result = $this->remove($item);
242 + // let the children perform extra actions after saving
243 + $this->postflight((array) $data, $isNew);
230 244
231 - /**
232 - * Runs after deleting the given data.
233 - * It is possible to perform here some extra actions.
234 - *
235 - * @param object $data The deleted item.
236 - * @param boolean $success True in case of success, false otherwise.
237 - * @param self $model The current model.
238 - *
239 - * @return void
240 - *
241 - * @since 1.5.10
242 - */
243 - $app->triggerEvent('onAfterDeleteVikBooking' . ucfirst($this->getName()), [$item, $result, $this]);
245 + return $pk;
246 + }
244 247
245 - $affected = $affected || $result;
246 - }
248 + /**
249 + * Method to delete one or more records.
250 + *
251 + * @param mixed $pks An array of record primary keys.
252 + *
253 + * @return bool True if successful, false if an error occurs.
254 + */
255 + public function delete($pks)
256 + {
257 + if (!$pks)
258 + {
259 + // nothing to delete
260 + return false;
261 + }
247 262
248 - return $affected;
249 - }
263 + if (!is_array($pks))
264 + {
265 + // wrap in an array
266 + $pks = [$pks];
267 + }
250 268
251 - /**
252 - * Runs before saving the given data.
253 - * It is possible to inject here additional properties to save.
254 - *
255 - * @param array &$data A reference to the data to save.
256 - *
257 - * @return boolean True on success, false otherwise.
258 - */
259 - protected function preflight(array &$data)
260 - {
261 - $app = JFactory::getApplication();
269 + $app = JFactory::getApplication();
262 270
263 - /**
264 - * Runs before saving the given data.
265 - * It is possible to inject here additional properties to save.
266 - *
267 - * @param array &$data A reference to the data to save.
268 - * @param self $model The current model.
269 - *
270 - * @return boolean False to abort the saving process.
271 - *
272 - * @since 1.5.10
273 - */
274 - $results = $app->triggerEvent('onBeforeSaveVikBooking' . ucfirst($this->getName()), [&$data, $this]);
271 + $affected = true;
275 272
276 - // check whether a plugin aborted the saving process
277 - if (in_array(false, $results, true))
278 - {
279 - return false;
280 - }
273 + foreach ($pks as $pk)
274 + {
275 + // fetch item details
276 + $item = $this->getItem($pk);
281 277
282 - return true;
283 - }
278 + if (!$item)
279 + {
280 + continue;
281 + }
284 282
285 - /**
286 - * Converts the array data into an object compatible with the database
287 - * structure of the specified table.
288 - *
289 - * @param array $data The requested data.
290 - *
291 - * @return object The object ready to be saved.
292 - */
293 - protected function prepareSaveData(array $data)
294 - {
295 - $table = new stdClass;
283 + /**
284 + * Runs before deleting the given data.
285 + * It is possible to validate here whether the item should be deleted or not.
286 + *
287 + * @param object $data The record to delete.
288 + * @param self $model The current model.
289 + *
290 + * @return bool False to abort the deleting process.
291 + *
292 + * @since 1.5.10
293 + */
294 + $results = $app->triggerEvent('onBeforeDeleteVikBooking' . ucfirst($this->getName()), [$item, $this]);
296 295
297 - // bind only the columns supported by the database table
298 - foreach ($this->getTableColumns() as $field => $type)
299 - {
300 - if (isset($data[$field]))
301 - {
302 - // always encode in JSON format non-scalar values
303 - if (!is_scalar($data[$field]))
304 - {
305 - $data[$field] = json_encode($data[$field]);
306 - }
296 + // check whether a plugin aborted the deleting process
297 + if (in_array(false, $results, true))
298 + {
299 + continue;
300 + }
307 301
308 - $table->{$field} = $data[$field];
309 - }
310 - }
302 + // remove item
303 + $result = $this->remove($item);
311 304
312 - return $table;
313 - }
305 + /**
306 + * Runs after deleting the given data.
307 + * It is possible to perform here some extra actions.
308 + *
309 + * @param object $data The deleted item.
310 + * @param bool $success True in case of success, false otherwise.
311 + * @param self $model The current model.
312 + *
313 + * @return void
314 + *
315 + * @since 1.5.10
316 + */
317 + $app->triggerEvent('onAfterDeleteVikBooking' . ucfirst($this->getName()), [$item, $result, $this]);
314 318
315 - /**
316 - * Saves the specified data into the database.
317 - *
318 - * @param array $data The requested data.
319 - *
320 - * @return mixed The primary key value of the saved record (true if missing).
321 - * Returns false in case of failure.
322 - */
323 - final protected function store(array $data)
324 - {
325 - // construct the object that will be saved
326 - $table = $this->prepareSaveData($data);
319 + $affected = $affected || $result;
320 + }
327 321
328 - if (!$table)
329 - {
330 - return false;
331 - }
322 + return $affected;
323 + }
332 324
333 - $db = JFactory::getDbo();
325 + /**
326 + * Runs before saving the given data.
327 + * It is possible to inject here additional properties to save.
328 + *
329 + * @param array &$data A reference to the data to save.
330 + *
331 + * @return bool True on success, false otherwise.
332 + */
333 + protected function preflight(array &$data)
334 + {
335 + $app = JFactory::getApplication();
334 336
335 - if (!empty($table->{$this->tableKeyName}))
336 - {
337 - // update needed
338 - $res = $db->updateObject($this->tableName, $table, $this->tableKeyName);
339 - }
340 - else
341 - {
342 - // insert needed
343 - $res = $db->insertObject($this->tableName, $table, $this->tableKeyName);
344 - }
337 + /**
338 + * Runs before saving the given data.
339 + * It is possible to inject here additional properties to save.
340 + *
341 + * @param array &$data A reference to the data to save.
342 + * @param self $model The current model.
343 + *
344 + * @return bool False to abort the saving process.
345 + *
346 + * @since 1.5.10
347 + */
348 + $results = $app->triggerEvent('onBeforeSaveVikBooking' . ucfirst($this->getName()), [&$data, $this]);
345 349
346 - if (!$res)
347 - {
348 - // something went wrong while saving the record
349 - return false;
350 - }
350 + // check whether a plugin aborted the saving process
351 + if (in_array(false, $results, true))
352 + {
353 + return false;
354 + }
351 355
352 - // check again whether the PK has been filled
353 - if (empty($table->{$this->tableKeyName}))
354 - {
355 - // no PK, just return true
356 - return true;
357 - }
356 + return true;
357 + }
358 358
359 - return $table->{$this->tableKeyName};
360 - }
359 + /**
360 + * Converts the array data into an object compatible with the database
361 + * structure of the specified table.
362 + *
363 + * @param array $data The requested data.
364 + *
365 + * @return object The object ready to be saved.
366 + */
367 + protected function prepareSaveData(array $data)
368 + {
369 + $table = new stdClass;
361 370
362 - /**
363 - * Runs after saving the given data.
364 - * It is possible to perform here some extra actions.
365 - *
366 - * @param array $data The saved data.
367 - * @param boolean True in case of insert, false in case of update.
368 - *
369 - * @return void
370 - */
371 - protected function postflight(array $data, $isNew)
372 - {
373 - $app = JFactory::getApplication();
371 + // bind only the columns supported by the database table
372 + foreach ($this->getTableColumns() as $field => $type)
373 + {
374 + if (isset($data[$field]))
375 + {
376 + // always encode in JSON format non-scalar values
377 + if (!is_scalar($data[$field]))
378 + {
379 + $data[$field] = json_encode($data[$field]);
380 + }
374 381
375 - /**
376 - * Runs after saving the given data.
377 - * It is possible to perform here some extra actions.
378 - *
379 - * @param array $data The saved data.
380 - * @param boolean $isNew True in case of insert, false in case of update.
381 - * @param self $model The current model.
382 - *
383 - * @return void
384 - *
385 - * @since 1.5.10
386 - */
387 - $app->triggerEvent('onAfterSaveVikBooking' . ucfirst($this->getName()), [$data, $isNew, $this]);
388 - }
382 + $table->{$field} = $data[$field];
383 + }
384 + }
389 385
390 - /**
391 - * Removes the specified item from the database.
392 - *
393 - * @param object $item The record to delete.
394 - *
395 - * @return boolean True if deleted, false otherwise.
396 - */
397 - protected function remove($item)
398 - {
399 - $db = JFactory::getDbo();
386 + return $table;
387 + }
400 388
401 - $query = $db->getQuery(true)
402 - ->delete($db->qn($this->tableName))
403 - ->where($db->qn($this->tableKeyName) . ' = ' . $db->q($item->{$this->tableKeyName}));
389 + /**
390 + * Saves the specified data into the database.
391 + *
392 + * @param array $data The requested data.
393 + *
394 + * @return mixed The primary key value of the saved record (true if missing).
395 + * Returns false in case of failure.
396 + */
397 + final protected function store(array $data)
398 + {
399 + // construct the object that will be saved
400 + $table = $this->prepareSaveData($data);
404 401
405 - $db->setQuery($query);
406 - $db->execute();
402 + if (!$table)
403 + {
404 + return false;
405 + }
407 406
408 - return (bool) $db->getAffectedRows();
409 - }
407 + $db = JFactory::getDbo();
410 408
411 - /**
412 - * Returns all the columns supported by the database table of this model.
413 - *
414 - * @return array
415 - */
416 - public function getTableColumns()
417 - {
418 - if (!isset(static::$fields[$this->tableName]))
419 - {
420 - try
421 - {
422 - static::$fields[$this->tableName] = JFactory::getDbo()->getTableColumns($this->tableName);
423 - }
424 - catch (Exception $e)
425 - {
426 - static::$fields[$this->tableName] = [];
427 - }
428 - }
429 -
430 - return static::$fields[$this->tableName];
431 - }
409 + if (!empty($table->{$this->tableKeyName}))
410 + {
411 + // update needed
412 + $res = $db->updateObject($this->tableName, $table, $this->tableKeyName);
413 + }
414 + else
415 + {
416 + // insert needed
417 + $res = $db->insertObject($this->tableName, $table, $this->tableKeyName);
418 + }
419 +
420 + if (!$res)
421 + {
422 + // something went wrong while saving the record
423 + return false;
424 + }
425 +
426 + // check again whether the PK has been filled
427 + if (empty($table->{$this->tableKeyName}))
428 + {
429 + // no PK, just return true
430 + return true;
431 + }
432 +
433 + return $table->{$this->tableKeyName};
434 + }
435 +
436 + /**
437 + * Runs after saving the given data.
438 + * It is possible to perform here some extra actions.
439 + *
440 + * @param array $data The saved data.
441 + * @param bool True in case of insert, false in case of update.
442 + *
443 + * @return void
444 + */
445 + protected function postflight(array $data, $isNew)
446 + {
447 + $app = JFactory::getApplication();
448 +
449 + /**
450 + * Runs after saving the given data.
451 + * It is possible to perform here some extra actions.
452 + *
453 + * @param array $data The saved data.
454 + * @param bool $isNew True in case of insert, false in case of update.
455 + * @param self $model The current model.
456 + *
457 + * @return void
458 + *
459 + * @since 1.5.10
460 + */
461 + $app->triggerEvent('onAfterSaveVikBooking' . ucfirst($this->getName()), [$data, $isNew, $this]);
462 + }
463 +
464 + /**
465 + * Removes the specified item from the database.
466 + *
467 + * @param object $item The record to delete.
468 + *
469 + * @return bool True if deleted, false otherwise.
470 + */
471 + protected function remove($item)
472 + {
473 + $db = JFactory::getDbo();
474 +
475 + $query = $db->getQuery(true)
476 + ->delete($db->qn($this->tableName))
477 + ->where($db->qn($this->tableKeyName) . ' = ' . $db->q($item->{$this->tableKeyName}));
478 +
479 + $db->setQuery($query);
480 + $db->execute();
481 +
482 + return (bool) $db->getAffectedRows();
483 + }
484 +
485 + /**
486 + * Returns all the columns supported by the database table of this model.
487 + *
488 + * @return array
489 + */
490 + public function getTableColumns()
491 + {
492 + if (!isset(static::$fields[$this->tableName]))
493 + {
494 + try
495 + {
496 + static::$fields[$this->tableName] = JFactory::getDbo()->getTableColumns($this->tableName);
497 + }
498 + catch (Exception $e)
499 + {
500 + static::$fields[$this->tableName] = [];
501 + }
502 + }
503 +
504 + return static::$fields[$this->tableName];
505 + }
432 506 }