PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
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 1.7.3 All 36 releases
vikbooking / admin / helpers / src / factory / aware.php

aware.php in VikBooking Hotel Booking Engine & PMS trunk, at admin/helpers/src/factory/aware.php

301 lines 6.9 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 * Trait for VikBooking classes that may creates sub instances.
16 *
17 * @since 1.5.10
18 */
19 trait VBOFactoryAware
20 {
21 /**
22 * A list of paths to folders containing all the available cron jobs.
23 *
24 * @var array
25 */
26 private $includePaths = array();
27
28 /**
29 * Defines the class prefix of the instances that should be created
30 * through this factory.
31 *
32 * @var string
33 */
34 protected $instanceClassPrefix = '';
35
36 /**
37 * Defines the namespace separator of the class names, such as:
38 * - foo_bar_baz
39 * - foo.bar.baz
40 *
41 * @var string
42 */
43 protected $instanceNamespaceSeparator = '';
44
45 /**
46 * Gets a list of supported include paths.
47 *
48 * @return array
49 */
50 final public function getIncludePaths()
51 {
52 return $this->includePaths;
53 }
54
55 /**
56 * Adds one path to include in cron jobs search.
57 * Proxy of addIncludePaths().
58 *
59 * @param string $path The path to search for cron jobs.
60 *
61 * @return self This object to support chaining.
62 */
63 final public function addIncludePath($path)
64 {
65 return $this->addIncludePaths($path);
66 }
67
68 /**
69 * Adds one or more paths to include in cron jobs search.
70 *
71 * @param mixed $paths The path or array of paths to search for cron jobs.
72 *
73 * @return self This object to support chaining.
74 */
75 final public function addIncludePaths($paths)
76 {
77 if (empty($paths))
78 {
79 return $this;
80 }
81
82 $includePaths = $this->getIncludePaths();
83
84 // in case the path is an array,
85 if (!is_array($paths))
86 {
87 // always treat the given path as an array for a correct merging
88 $paths = [$paths];
89 }
90
91 // merge all the paths and make sure we have no duplicates
92 $includePaths = array_unique(array_merge($includePaths, $paths));
93
94 // update include paths
95 $this->setIncludePaths($includePaths);
96
97 return $this;
98 }
99
100 /**
101 * Sets the include paths to search for cron jobs.
102 *
103 * @param array $paths Array with paths to search in.
104 *
105 * @return self This object to support chaining.
106 */
107 final public function setIncludePaths($paths)
108 {
109 $this->includePaths = (array) $paths;
110
111 return $this;
112 }
113
114 /**
115 * Return all the installed instances that matches the specified query.
116 *
117 * @return array A list of the found instances.
118 */
119 final public function getInstances()
120 {
121 $paths = array();
122
123 foreach ($this->getIncludePaths() as $dir)
124 {
125 // recursively scan the directory in search of PHP files
126 $files = JFolder::files($dir, '.php$', $recursive = true, $full = true);
127
128 foreach ($files as $filePath)
129 {
130 $element = [];
131
132 // register file path
133 $element['path'] = $filePath;
134
135 // register element name
136 $element['name'] = ltrim(substr($filePath, strlen($dir)), DIRECTORY_SEPARATOR);
137
138 if ($this->instanceNamespaceSeparator)
139 {
140 // replace directory separators with namespace
141 $element['name'] = str_replace(DIRECTORY_SEPARATOR, $this->instanceNamespaceSeparator, $element['name']);
142 }
143
144 // get rid of PHP file extension
145 $element['name'] = basename($element['name'], '.php');
146
147 // inject element within the list
148 $paths[] = $element;
149 }
150 }
151
152 $list = array();
153
154 foreach ($paths as $p)
155 {
156 // require element file
157 require_once $p['path'];
158
159 try
160 {
161 // try to create the element object
162 $list[$p['name']] = $this->createInstance($p['name'], [], $autoload = false);
163 }
164 catch (Exception $e)
165 {
166 // unable to create the instance, go ahead
167 }
168 }
169
170 // sort elements by name since they might be located on different folders
171 $this->rearrangeInstances($list);
172
173 return $list;
174 }
175
176 /**
177 * Creates a new instance of the requested element.
178 *
179 * @param string $element The element name.
180 * @param array $args The class constructor arguments.
181 * @param boolean $autoload Whether to autoload the file or not.
182 *
183 * @return mixed
184 *
185 * @throws Exception
186 */
187 final public function createInstance($element, $args = [], $autoload = true)
188 {
189 // get rid of the file extension
190 $element = basename($element, '.php');
191
192 // convert the filename in classname
193 $classname = preg_replace("/[^a-zA-Z0-9]+/", ' ', $element);
194 $classname = str_replace(' ', '', ucwords($classname));
195 $classname = $this->instanceClassPrefix . $classname;
196
197 if (!class_exists($classname))
198 {
199 if ($autoload)
200 {
201 // detect file
202 $file = $this->findPath($element);
203
204 if (!$file)
205 {
206 // element file not found
207 throw new Exception(sprintf('The instance [%s] does not exist.', $element), 404);
208 }
209
210 // possible match detected, require the file
211 require_once $file;
212 }
213
214 if (!class_exists($classname))
215 {
216 // unable to detect the class file
217 throw new Exception(sprintf('Instance [%s] class not found.', $classname), 404);
218 }
219 }
220
221 if (!is_array($args))
222 {
223 // wrap arguments into an array for a correct instantiation
224 $args = [$args];
225 }
226
227 // create reflection of the element
228 $class = new ReflectionClass($classname);
229 // instantiate element class with the given arguments
230 $obj = $class->newInstanceArgs($args);
231
232 // make sure the object is a valid instance
233 if (!$this->isInstanceValid($obj))
234 {
235 throw new Exception(sprintf('The object [%s] is not a valid instance.', $classname), 406);
236 }
237
238 return $obj;
239 }
240
241 /**
242 * Gets the path of the specified element.
243 *
244 * @param string $element The element name.
245 *
246 * @return mixed The element path if exists, false otherwise.
247 */
248 final protected function findPath($element)
249 {
250 // convert element into a subfolder
251 if ($this->instanceNamespaceSeparator)
252 {
253 $element = str_replace($this->instanceNamespaceSeparator, DIRECTORY_SEPARATOR, $element);
254 }
255
256 foreach ($this->getIncludePaths() as $dir)
257 {
258 // build full path
259 $path = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $element . '.php';
260
261 // check whether the file exists
262 if (JFile::exists($path))
263 {
264 // match found, return file path
265 return $path;
266 }
267 }
268
269 // no match found
270 return false;
271 }
272
273 /**
274 * Children classes can override this method to rearrange the ordering
275 * of the elements created through this factory class.
276 *
277 * @param array &$list The list of instances.
278 *
279 * @return void
280 */
281 protected function rearrangeInstances(&$list)
282 {
283 // not enough information to rearrange the list...
284 }
285
286 /**
287 * Children classes can override this method to make sure that the
288 * created instance is compliant with the factory requirements.
289 *
290 * @param mixed $object The object to validate.
291 *
292 * @return boolean True if valid, false otherwise.
293 */
294 protected function isInstanceValid($object)
295 {
296 // the validation should be delegated to the class that
297 // inherits this trait methods
298 return true;
299 }
300 }
301