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 | libraries/adapter/mvc/model.php +405 -0 1.6.2 → 1.8.16 View file →
@@ -1,0 +1,405 @@
1 +<?php
2 +/**
3 + * @package VikWP - Libraries
4 + * @subpackage adapter.mvc
5 + * @author E4J s.r.l.
6 + * @copyright Copyright (C) 2023 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 +JLoader::import('adapter.application.object');
15 +
16 +/**
17 + * The model class used by the MVC framework.
18 + * A model can be used by a controller or a view to handle
19 + * a certain entity of the plugin.
20 + *
21 + * The model can be invoked when the value contained
22 + * in $_REQUEST['task'] is equals to 'ComponentModel' + $_REQUEST['task'].
23 + *
24 + * e.g. $_REQUEST['task'] = 'groups.save' -> ComponentModelGroups
25 + *
26 + * @since 10.0
27 + */
28 +abstract class JModel extends JObject
29 +{
30 + /**
31 + * A list of model instances.
32 + *
33 + * @var array
34 + */
35 + protected static $instances = array();
36 +
37 + /**
38 + * A list of included paths.
39 + *
40 + * @var array
41 + * @since 10.1.24
42 + */
43 + protected static $paths = array();
44 +
45 + /**
46 + * The model name.
47 + * e.g. ComponentModel[NAME]
48 + *
49 + * @var string
50 + */
51 + protected $_name = null;
52 +
53 + /**
54 + * The component name.
55 + * e.g. [COMPONENT]ModelName
56 + *
57 + * @var string
58 + */
59 + protected $_component = null;
60 +
61 + /**
62 + * The application client.
63 + *
64 + * @var string
65 + */
66 + protected $_client = null;
67 +
68 + /**
69 + * The database table name.
70 + *
71 + * @var array
72 + * @since 10.1.35
73 + */
74 + protected $_config;
75 +
76 + /**
77 + * Tries to load the specified model, only creating it if
78 + * it doesn't exist yet.
79 + *
80 + * @param string $type The model type to instantiate
81 + * @param string $prefix Prefix for the model class name.
82 + * @param array $config Configuration array for model.
83 + *
84 + * @return mixed The model instance if found, otherwise null.
85 + *
86 + * @since 10.1.35 Switch the ordering of $type and $prefix argument.
87 + * @since 10.1.35 Added $config argument.
88 + * @since 10.1.35 Removed $client, $table and $pk arguments.
89 + */
90 + public static function getInstance($type, $prefix = '', $config = array())
91 + {
92 + /**
93 + * For backward compatibility, we should check whether the 3rd argument is passed,
94 + * meaning that we need to force a client section in which to load the model.
95 + *
96 + * @since 10.1.35
97 + */
98 + if (is_string($config))
99 + {
100 + $config = ['client' => $config];
101 + }
102 + else
103 + {
104 + $config = (array) $config;
105 + }
106 +
107 + if (empty($config['client']))
108 + {
109 + $config['client'] = JFactory::getApplication()->isAdmin() ? 'admin' : 'site';
110 + }
111 +
112 + /**
113 + * The current version of JModel is not using the same arguments as
114 + * specified by Joomla, since the model name is always passed as
115 + * first argument.
116 + *
117 + * For this reason, we need to swap the prefix and the name when
118 + * passed using Joomla standards. This can be done when at least one
119 + * of the following conditions is verified:
120 + *
121 + * - the name contains 'model' word
122 + * - the name is actually the folder name and the prefix isn't
123 + *
124 + * @since 10.1.24
125 + */
126 + if (preg_match("/model/i", $type)
127 + || (is_dir(WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $type) && !is_dir(WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . strtolower($prefix))))
128 + {
129 + // swap name with prefix
130 + $tmp = $type;
131 + $type = $prefix;
132 + $prefix = $tmp;
133 + }
134 +
135 + // remove 'model' from prefix (if any) and make it lowercase
136 + $prefix = strtolower(preg_replace("/model/i", '', $prefix));
137 +
138 + $sign = serialize(array($prefix, $type, $config['client']));
139 +
140 + if (!isset(static::$instances[$sign]))
141 + {
142 + static::$instances[$sign] = false;
143 +
144 + // create classname
145 + $classname = ucfirst($prefix) . 'Model' . ucfirst($type);
146 +
147 + /**
148 + * Merge default include path (the fallback) with specified directories.
149 + * Then iterate the list to find the first available model.
150 + *
151 + * @since 10.1.24
152 + */
153 + $paths = array_merge(
154 + // default include path
155 + array(
156 + /**
157 + * Search also inside the libraries folder of the current plugin.
158 + * Prioritize this folder to avoid conflicts with deprecated files.
159 + *
160 + * @since 10.1.35
161 + */
162 + implode(DIRECTORY_SEPARATOR, array(WP_PLUGIN_DIR, $prefix, 'libraries', 'mvc', $config['client'], 'models')),
163 + implode(DIRECTORY_SEPARATOR, array(WP_PLUGIN_DIR, $prefix, $config['client'], 'models')),
164 + ),
165 + // specified include paths
166 + self::addIncludePath()
167 + );
168 +
169 + /**
170 + * Iterate paths until we find an existing file (or till the list is empty).
171 + *
172 + * @since 10.1.54 Keep iterating until we find a compatible class instead of
173 + * a compatible file, since different plugins might support the
174 + * same file name.
175 + */
176 + for ($i = 0, $path = null; $i < count($paths) && !static::$instances[$sign]; $i++)
177 + {
178 + // create path
179 + $path = $paths[$i] . DIRECTORY_SEPARATOR . strtolower($type) . '.php';
180 +
181 + // make sure the file exists
182 + if (is_file($path))
183 + {
184 + // include model
185 + require_once $path;
186 +
187 + // make sure the class exists
188 + if (class_exists($classname))
189 + {
190 + // cache model instance
191 + static::$instances[$sign] = new $classname($config);
192 + }
193 + }
194 + }
195 + }
196 +
197 + return static::$instances[$sign];
198 + }
199 +
200 + /**
201 + * Add a directory where the class should search for models.
202 + * You may either pass a string or an array of directories.
203 + *
204 + * @param mixed $path A path or array of paths to search.
205 + *
206 + * @return array An array with directory elements.
207 + *
208 + * @since 10.1.24
209 + */
210 + public static function addIncludePath($path = null)
211 + {
212 + if (!empty($path))
213 + {
214 + JLoader::import('adapter.filesystem.path');
215 +
216 + foreach ((array) $path as $includePath)
217 + {
218 + $includePath = JPath::clean($includePath);
219 +
220 + // check if the path is a dir
221 + if (!is_dir($includePath))
222 + {
223 + // extract name between component and models
224 + if (preg_match("/components[\/\\\\]com_([a-z0-9_]+)[\/\\\\]models/", $includePath, $match))
225 + {
226 + // access adapters of current plugin
227 + $option = JFactory::getApplication()->input->get('option');
228 + // strip initial com_ from option name
229 + $option = preg_replace("/^com_/", '', $option);
230 +
231 + // rewrite include path
232 + $includePath = JPath::clean(WP_PLUGIN_DIR . '/' . $option . '/libraries/adapter/mvc/models/' . end($match));
233 + }
234 + }
235 +
236 + // make sure the folder is not already in the list
237 + if (!in_array($includePath, static::$paths))
238 + {
239 + // push directory as first
240 + array_unshift(static::$paths, $includePath);
241 + }
242 + }
243 + }
244 +
245 + return static::$paths;
246 + }
247 +
248 + /**
249 + * Class constructor.
250 + *
251 + * @param array $config An array of configuration options.
252 + *
253 + * @since 10.1.35 Added $config argument.
254 + * @since 10.1.35 Removed $table and $pk arguments.
255 + */
256 + public function __construct($config = array())
257 + {
258 + $option = $this->getComponentName();
259 +
260 + if (!array_key_exists('table_path', $config) && $option)
261 + {
262 + /**
263 + * In case the client hasn't been provided, assume we should load the models
264 + * from the same path of the current application client (admin or site).
265 + *
266 + * @since 10.1.55
267 + */
268 + if (empty($config['client']))
269 + {
270 + $config['client'] = JFactory::getApplication()->isAdmin() ? 'admin' : 'site';
271 + }
272 +
273 + $config['table_path'] = [
274 + JPath::clean(WP_PLUGIN_DIR . '/' . $option . '/libraries/mvc/' . $config['client'] . '/tables'),
275 + JPath::clean(WP_PLUGIN_DIR . '/' . $option . '/' . $config['client'] . '/tables'),
276 + ];
277 + }
278 +
279 + // set the default view search path
280 + if (!empty($config['table_path']))
281 + {
282 + $this->addTablePath($config['table_path']);
283 + }
284 +
285 + $this->_config = $config;
286 + }
287 +
288 + /**
289 + * Adds to the stack of model table paths in LIFO order.
290 + *
291 + * @param mixed $path The directory as a string or directories as an array to add.
292 + *
293 + * @return void
294 + *
295 + * @since 10.1.35
296 + */
297 + public function addTablePath($path)
298 + {
299 + JTable::addIncludePath($path);
300 + }
301 +
302 + /**
303 + * Method to get a table object.
304 + *
305 + * @param string $name The table name.
306 + * @param string $prefix The class prefix.
307 + * @param array $options Configuration array for table.
308 + *
309 + * @return JTable A table object.
310 + *
311 + * @since 10.1.35
312 + */
313 + public function getTable($name = '', $prefix = 'JTable', $options = array())
314 + {
315 + if (!$name)
316 + {
317 + $name = $this->getName();
318 + }
319 +
320 + return JTable::getInstance($name, $prefix, $options);
321 + }
322 +
323 + /**
324 + * Returns the model name.
325 + *
326 + * @return string Model name.
327 + */
328 + public function getModelName()
329 + {
330 + if (is_null($this->_name))
331 + {
332 + $class = get_class($this);
333 +
334 + if (preg_match("/Model(.*?)$/", $class, $match))
335 + {
336 + $this->_name = strtolower($match[1]);
337 + }
338 + else
339 + {
340 + $this->_name = $class;
341 + }
342 + }
343 +
344 + return $this->_name;
345 + }
346 +
347 + /**
348 + * Returns the model name.
349 + * Proxy for getModelName() method.
350 + *
351 + * @return string Model name.
352 + *
353 + * @since 1.0.1.35
354 + */
355 + public function getName()
356 + {
357 + return $this->getModelName();
358 + }
359 +
360 + /**
361 + * Returns the component name.
362 + *
363 + * @return string Component name.
364 + */
365 + public function getComponentName()
366 + {
367 + if (is_null($this->_component))
368 + {
369 + $class = get_class($this);
370 +
371 + if (preg_match("/(.*?)Model/", $class, $match))
372 + {
373 + $this->_component = strtolower($match[1]);
374 + }
375 + else
376 + {
377 + $this->_component = $class;
378 + }
379 + }
380 +
381 + return $this->_component;
382 + }
383 +
384 + /**
385 + * Returns the application client folder (admin or site).
386 + *
387 + * @return string The client.
388 + */
389 + public function getClientFolder()
390 + {
391 + if (is_null($this->_client))
392 + {
393 + $this->_client = JFactory::getApplication()->isAdmin() ? 'admin' : 'site';
394 + }
395 +
396 + return $this->_client;
397 + }
398 +}
399 +
400 +/**
401 + * Alias for JModel, which is still used by the components.
402 + *
403 + * @since 10.1.24
404 + */
405 +class_alias('JModel', 'JModelLegacy');