PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.6
VikBooking Hotel Booking Engine & PMS v1.6.6
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
vikbooking / admin / helpers / src / mvc / model.php

model.php in VikBooking Hotel Booking Engine & PMS 1.6.6, at admin/helpers/src/mvc/model.php

433 lines 9.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2021 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * VikBooking MVC base model declaration.
16 *
17 * @since 1.5.10
18 */
19 abstract class VBOMvcModel extends JObject
20 {
21 /**
22 * Cached used to store the supported columns of the requested database tables.
23 *
24 * @var string
25 */
26 protected static $fields = [];
27
28 /**
29 * The database table name.
30 *
31 * @var string
32 */
33 protected $tableName = null;
34
35 /**
36 * The database table primary key name.
37 *
38 * @var string
39 */
40 protected $tableKeyName = 'id';
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]);
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 });
70
71 if ($results)
72 {
73 // class returned by a plugin, directly use it
74 return $results[0];
75 }
76
77 // fallback to the default classes in VikBooking
78 $suffix = str_replace('_', ' ', $name);
79 $suffix = str_replace(' ', '', ucwords($suffix));
80
81 $modelClass = 'VBOModel' . $suffix;
82
83 if (!class_exists($modelClass))
84 {
85 throw new Exception(sprintf('Model [%s] not found', $name), 404);
86 }
87
88 return new $modelClass($options);
89 }
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 }
102
103 // unable to extract model name from class, use the file name
104 return basename(__FILE__, '.php');
105 }
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();
118
119 $query = $db->getQuery(true)
120 ->select('*')
121 ->from($db->qn($this->tableName));
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 }
134
135 $db->setQuery($query, 0, 1);
136
137 return $db->loadObject();
138 }
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;
150
151 // let the children bind the data array before save
152 if (!$this->preflight($data))
153 {
154 return false;
155 }
156
157 // check if we have an empty record
158 $isNew = empty($data[$this->tableKeyName]);
159
160 // store the object within the database
161 $pk = $this->store((array) $data);
162
163 if (!$pk)
164 {
165 return false;
166 }
167
168 // let the children perform extra actions after saving
169 $this->postflight((array) $data, $isNew);
170
171 return $pk;
172 }
173
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 }
188
189 if (!is_array($pks))
190 {
191 // wrap in an array
192 $pks = [$pks];
193 }
194
195 $app = JFactory::getApplication();
196
197 $affected = true;
198
199 foreach ($pks as $pk)
200 {
201 // fetch item details
202 $item = $this->getItem($pk);
203
204 if (!$item)
205 {
206 continue;
207 }
208
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]);
221
222 // check whether a plugin aborted the deleting process
223 if (in_array(false, $results, true))
224 {
225 continue;
226 }
227
228 // remove item
229 $result = $this->remove($item);
230
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]);
244
245 $affected = $affected || $result;
246 }
247
248 return $affected;
249 }
250
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();
262
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]);
275
276 // check whether a plugin aborted the saving process
277 if (in_array(false, $results, true))
278 {
279 return false;
280 }
281
282 return true;
283 }
284
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;
296
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 }
307
308 $table->{$field} = $data[$field];
309 }
310 }
311
312 return $table;
313 }
314
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);
327
328 if (!$table)
329 {
330 return false;
331 }
332
333 $db = JFactory::getDbo();
334
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 }
345
346 if (!$res)
347 {
348 // something went wrong while saving the record
349 return false;
350 }
351
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 }
358
359 return $table->{$this->tableKeyName};
360 }
361
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();
374
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 }
389
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();
400
401 $query = $db->getQuery(true)
402 ->delete($db->qn($this->tableName))
403 ->where($db->qn($this->tableKeyName) . ' = ' . $db->q($item->{$this->tableKeyName}));
404
405 $db->setQuery($query);
406 $db->execute();
407
408 return (bool) $db->getAffectedRows();
409 }
410
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 }
432 }
433