PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / trunk
VikAppointments Services Booking Calendar vtrunk
trunk 1.2.17 1.2.18 1.2.19
vikappointments / libraries / adapter / loader / loader.php
vikappointments / libraries / adapter / loader Last commit date
loader.php 2 years ago utils.php 2 years ago
loader.php
364 lines
1 <?php
2 /**
3 * @package VikWP - Libraries
4 * @subpackage adapter.loader
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 /**
15 * Plugin smart loader class.
16 *
17 * @since 10.0
18 */
19 abstract class JLoader
20 {
21 /**
22 * The list containing all the resources loaded.
23 *
24 * @var array
25 */
26 protected static $includes = array();
27
28 /**
29 * The list containing all the filename aliases.
30 *
31 * @var array
32 */
33 protected static $aliases = array();
34
35 /**
36 * Base path to load resources.
37 *
38 * @var string
39 */
40 public static $base = '';
41
42 /**
43 * Container for namespace => path map.
44 *
45 * @var array
46 * @since 10.1.34
47 */
48 protected static $namespaces = array();
49
50 /**
51 * Loads the specified file.
52 *
53 * @param string $key The class name to look for (dot notation).
54 * @param string $base Search this directory for the class.
55 *
56 * @return boolean True on success, otherwise false.
57 */
58 public static function import($key, $base = null)
59 {
60 // if no base provided, use the default one
61 if (empty($base))
62 {
63 $base = static::$base;
64 }
65
66 $sign = serialize(array($key, $base));
67
68 // if the resource is not loaded, try to do it
69 if (!isset(static::$includes[$sign]))
70 {
71 $success = false;
72
73 // remove trailing slash (if any)
74 $base = rtrim($base, DIRECTORY_SEPARATOR);
75
76 $parts = explode('.', $key);
77 $class = array_pop($parts);
78
79 // if the file has been registered with an alias, replace it with the original one
80 if (isset(static::$aliases[$class]))
81 {
82 $class = static::$aliases[$class];
83 }
84
85 // re-insert class to build the relative path
86 $parts[] = $class;
87
88 // build the path
89 $path = implode(DIRECTORY_SEPARATOR, $parts);
90
91 // if the file exists, load it
92 if (is_file($base . DIRECTORY_SEPARATOR . $path . '.php'))
93 {
94 $success = (bool) include_once $base . DIRECTORY_SEPARATOR . $path . '.php';
95 }
96
97 // cache the loading status
98 static::$includes[$sign] = $success;
99 }
100
101 return static::$includes[$sign];
102 }
103
104 /**
105 * Register an alias of a given class filename.
106 * This is useful for those files that contain a dot in their name.
107 *
108 * @param string $name The filename to register.
109 * @param string $alias The alias to use.
110 */
111 public static function registerAlias($name, $alias)
112 {
113 if (!isset(static::$aliases[$alias]))
114 {
115 static::$aliases[$alias] = $name;
116 }
117 }
118
119 /**
120 * Register a namespace to the autoloader. When loaded, namespace paths are searched in a "last in, first out" order.
121 *
122 * @param string $namespace A case sensitive Namespace to register.
123 * @param string $path A case sensitive absolute file path to the library root where classes of the given namespace can be found.
124 * @param boolean $reset True to reset the namespace with only the given lookup path.
125 * @param boolean $prepend If true, push the path to the beginning of the namespace lookup paths array.
126 *
127 * @return void
128 *
129 * @throws RuntimeException
130 *
131 * @since 10.1.41
132 */
133 public static function registerNamespace($namespace, $path, $reset = false, $prepend = false)
134 {
135 // make sure the library path exists
136 if (!is_dir($path))
137 {
138 throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500);
139 }
140
141 // trim leading and trailing backslashes from namespace, allowing "\Parent\Child", "Parent\Child\"
142 // and "\Parent\Child\" to be treated the same way
143 $namespace = trim($namespace, '\\');
144
145 // if the namespace is not yet registered or we have an explicit reset flag then set the path
146 if ($reset || !isset(self::$namespaces[$namespace]))
147 {
148 self::$namespaces[$namespace] = array($path);
149 }
150 // otherwise we want to simply add the path to the namespace
151 else
152 {
153 if ($prepend)
154 {
155 array_unshift(self::$namespaces[$namespace], $path);
156 }
157 else
158 {
159 self::$namespaces[$namespace][] = $path;
160 }
161 }
162 }
163
164 /**
165 * Method to setup the autoloaders for the WordPress Platform.
166 *
167 * @return void
168 *
169 * @since 10.1.41
170 */
171 public static function setup()
172 {
173 // register the framework auto-loader
174 spl_autoload_register(array('JLoader', 'loadFramework'));
175
176 // register the PSR based autoloader
177 spl_autoload_register(array('JLoader', 'loadByPsr'));
178 }
179
180 /**
181 * Auto-loads framework classes at runtime.
182 *
183 * @param string $class The fully qualified class name to autoload.
184 *
185 * @return boolean True on success, false otherwise.
186 *
187 * @since 10.1.41
188 */
189 public static function loadFramework($class)
190 {
191 $original = $class;
192
193 // add support for VikWP class prefix
194 $class = preg_replace("/^VikWP/", 'J', $class);
195
196 // observe only the classes that starts with "J"
197 if (!preg_match("/^J/", $class))
198 {
199 return false;
200 }
201
202 switch ($class)
203 {
204 case 'JPagination':
205 $result = JLoader::import('adapter.pagination.pagination');
206 break;
207
208 case 'JView':
209 case 'JViewLegacy':
210 $result = JLoader::import('adapter.mvc.view');
211 break;
212
213 case 'JController':
214 case 'JControllerLegacy':
215 $result = JLoader::import('adapter.mvc.controller');
216 break;
217
218 case 'JControllerAdmin':
219 $result = JLoader::import('adapter.mvc.controllers.admin');
220 break;
221
222 case 'JComponentHelper':
223 $result = JLoader::import('adapter.component.helper');
224 break;
225
226 case 'JModuleHelper':
227 $result = JLoader::import('adapter.module.helper');
228 break;
229
230 case 'JPath':
231 $result = JLoader::import('adapter.filesystem.path');
232 break;
233
234 case 'JFile':
235 $result = JLoader::import('adapter.filesystem.file');
236 break;
237
238 case 'JArchive':
239 $result = JLoader::import('adapter.filesystem.archive');
240 break;
241
242 case 'JFolder':
243 $result = JLoader::import('adapter.filesystem.folder');
244 break;
245
246 case 'JForm':
247 $result = JLoader::import('adapter.form.form');
248 break;
249
250 case 'JFormField':
251 $result = JLoader::import('adapter.form.field');
252 break;
253
254 case 'JRegistry':
255 $result = JLoader::import('adapter.application.registry');
256 break;
257
258 case 'JVersion':
259 $result = JLoader::import('adapter.application.version');
260 break;
261
262 default:
263 /**
264 * Autoload the native form fields.
265 *
266 * @since 10.1.51
267 */
268 if (preg_match("/^JFormField([a-z0-9]+)$/i", $class, $match))
269 {
270 $result = JLoader::import('adapter.form.fields.' . strtolower($match[1]));
271 }
272 else
273 {
274 $result = false;
275 }
276 }
277
278 // in case the loaded class exists and the requested on starts with VikWP,
279 // create an alias to support a more appropriate notation
280 if (class_exists($class) && preg_match("/^VikWP/", $original))
281 {
282 class_alias($class, $original);
283 $result = true;
284 }
285
286 return $result;
287 }
288
289 /**
290 * Method to autoload classes that are namespaced to the PSR-4 standard.
291 *
292 * @param string $class The fully qualified class name to autoload.
293 *
294 * @return boolean True on success, false otherwise.
295 *
296 * @since 10.1.41
297 */
298 public static function loadByPsr($class)
299 {
300 $class = self::stripFirstBackslash($class);
301
302 // find the location of the last NS separator
303 $pos = strrpos($class, '\\');
304
305 // If one is found, we're dealing with a NS'd class.
306 if ($pos !== false)
307 {
308 $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)) . DIRECTORY_SEPARATOR;
309 $className = substr($class, $pos + 1);
310 }
311 // if not, no need to parse path
312 else
313 {
314 $classPath = null;
315 $className = $class;
316 }
317
318 $classPath .= $className . '.php';
319
320 // loop through registered namespaces until we find a match
321 foreach (self::$namespaces as $ns => $paths)
322 {
323 if (strpos($class, "{$ns}\\") === 0)
324 {
325 $nsPath = trim(str_replace('\\', DIRECTORY_SEPARATOR, $ns), DIRECTORY_SEPARATOR);
326
327 // loop through paths registered to this namespace until we find a match
328 foreach ($paths as $path)
329 {
330 $classFilePath = realpath($path . DIRECTORY_SEPARATOR . substr_replace($classPath, '', 0, strlen($nsPath) + 1));
331
332 // we do not allow files outside the namespace root to be loaded
333 if (strpos($classFilePath, realpath($path)) !== 0)
334 {
335 continue;
336 }
337
338 // we check for class_exists to handle case-sensitive file systems
339 if (is_file($classFilePath) && !class_exists($class, false))
340 {
341 return (bool) include_once $classFilePath;
342 }
343 }
344 }
345 }
346
347 return false;
348 }
349
350 /**
351 * Strips the first backslash from the given class if present.
352 *
353 * @param string $class The class to strip the first prefix from.
354 *
355 * @return string The striped class name.
356 *
357 * @since 10.1.41
358 */
359 private static function stripFirstBackslash($class)
360 {
361 return $class && $class[0] === '\\' ? substr($class, 1) : $class;
362 }
363 }
364