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/factory/aware.php +300 -0 1.6.2 → 1.8.16 View file →
@@ -1,0 +1,300 @@
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 +}