1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
loader.php
См. документацию.
1<?php
2
3namespace Bitrix\Main;
4
5use Bitrix\Main\Config\Configuration;
6use Bitrix\Main\DI\ServiceLocator;
7
12class Loader
13{
17 const SAFE_MODE = false;
18
19 const BITRIX_HOLDER = "bitrix";
20 const LOCAL_HOLDER = "local";
32 const MODULE_DEMO = 2;
38 const ALPHA_LOWER = "qwertyuioplkjhgfdsazxcvbnm";
40 const ALPHA_UPPER = "QWERTYUIOPLKJHGFDSAZXCVBNM";
41
42 protected static $safeModeModules = ["main" => true, "fileman" => true];
43 protected static $loadedModules = ["main" => true];
44 protected static $semiloadedModules = [];
45 protected static $modulesHolders = ["main" => self::BITRIX_HOLDER];
46 protected static $sharewareModules = [];
51 protected static $namespaces = [];
52 protected static $autoLoadClasses = [];
53 protected static $aliases = [];
54 protected static $classAliases = [];
58 protected static $requireThrowException = true;
59
67 public static function includeModule($moduleName)
68 {
69 if (!is_string($moduleName) || $moduleName == "")
70 {
71 throw new LoaderException("Empty module name");
72 }
73 if (!ModuleManager::isValidModule($moduleName))
74 {
75 throw new LoaderException(sprintf("Module name '%s' is not correct", $moduleName));
76 }
77
78 $moduleName = strtolower($moduleName);
79
80 if (self::SAFE_MODE)
81 {
82 if (!isset(self::$safeModeModules[$moduleName]))
83 {
84 return false;
85 }
86 }
87
88 if (isset(self::$loadedModules[$moduleName]))
89 {
90 return self::$loadedModules[$moduleName];
91 }
92
93 if (isset(self::$semiloadedModules[$moduleName]))
94 {
95 trigger_error("Module '" . $moduleName . "' is in loading progress", E_USER_WARNING);
96 }
97
98 $arInstalledModules = ModuleManager::getInstalledModules();
99 if (!isset($arInstalledModules[$moduleName]))
100 {
101 self::$loadedModules[$moduleName] = false;
102 return false;
103 }
104
106
107 $moduleHolder = self::LOCAL_HOLDER;
108 $pathToInclude = $documentRoot . "/" . $moduleHolder . "/modules/" . $moduleName;
109 if (!file_exists($pathToInclude))
110 {
111 $moduleHolder = self::BITRIX_HOLDER;
112 $pathToInclude = $documentRoot . "/" . $moduleHolder . "/modules/" . $moduleName;
113 if (!file_exists($pathToInclude))
114 {
115 self::$loadedModules[$moduleName] = false;
116 return false;
117 }
118 }
119
120 //register a PSR-4 base folder for the module
121 if (str_contains($moduleName, "."))
122 {
123 //partner's module
124 $baseName = str_replace(".", "\\", ucwords($moduleName, "."));
125 }
126 else
127 {
128 //bitrix's module
129 $baseName = "Bitrix\\" . ucfirst($moduleName);
130 }
131 self::registerNamespace($baseName, $documentRoot . "/" . $moduleHolder . "/modules/" . $moduleName . "/lib");
132
133 self::$modulesHolders[$moduleName] = $moduleHolder;
134
135 if (class_exists('\Dev\Main\Migrator\ModuleUpdater'))
136 {
137 \Dev\Main\Migrator\ModuleUpdater::checkUpdates($moduleName, $pathToInclude);
138 }
139
140 $res = true;
141 if (file_exists($pathToInclude . "/include.php"))
142 {
143 //recursion control
144 self::$semiloadedModules[$moduleName] = true;
145
146 $res = self::includeModuleInternal($pathToInclude . "/include.php");
147
148 unset(self::$semiloadedModules[$moduleName]);
149 }
150
151 self::$loadedModules[$moduleName] = ($res !== false);
152
153 if (!self::$loadedModules[$moduleName])
154 {
155 //unregister the namespace if "include" fails
156 self::unregisterNamespace($baseName);
157 }
158 else
159 {
160 ServiceLocator::getInstance()->registerByModuleSettings($moduleName);
161 }
162
163 return self::$loadedModules[$moduleName];
164 }
165
174 public static function requireModule($moduleName)
175 {
176 $included = self::includeModule($moduleName);
177
178 if (!$included && self::$requireThrowException)
179 {
180 throw new LoaderException("Required module `{$moduleName}` was not found");
181 }
182
183 return $included;
184 }
185
186 private static function includeModuleInternal($path)
187 {
189 global $DB, $MESS;
190 return include_once($path);
191 }
192
202 public static function includeSharewareModule($moduleName)
203 {
204 if (isset(self::$sharewareModules[$moduleName]))
205 {
206 return self::$sharewareModules[$moduleName];
207 }
208
209 $module = str_replace(".", "_", $moduleName);
210
211 if (self::includeModule($moduleName))
212 {
213 if (defined($module . "_DEMO") && constant($module . "_DEMO") == "Y")
214 {
215 self::$sharewareModules[$moduleName] = self::MODULE_DEMO;
216 }
217 else
218 {
219 self::$sharewareModules[$moduleName] = self::MODULE_INSTALLED;
220 }
221
222 return self::$sharewareModules[$moduleName];
223 }
224
225 if (defined($module . "_DEMO") && constant($module . "_DEMO") == "Y")
226 {
227 return (self::$sharewareModules[$moduleName] = self::MODULE_DEMO_EXPIRED);
228 }
229
230 return (self::$sharewareModules[$moduleName] = self::MODULE_NOT_FOUND);
231 }
232
233 public static function clearModuleCache($moduleName)
234 {
235 if (!is_string($moduleName) || $moduleName == "")
236 {
237 throw new LoaderException("Empty module name");
238 }
239
240 if ($moduleName !== "main")
241 {
242 unset(self::$loadedModules[$moduleName]);
243 unset(self::$modulesHolders[$moduleName]);
244 }
245
246 unset(self::$sharewareModules[$moduleName]);
247 }
248
254 public static function getDocumentRoot()
255 {
256 static $documentRoot = null;
257 if ($documentRoot === null)
258 {
259 $documentRoot = rtrim($_SERVER["DOCUMENT_ROOT"], "/\\");
260 }
261 return $documentRoot;
262 }
263
273 public static function registerAutoLoadClasses($moduleName, array $classes)
274 {
275 if (empty($classes))
276 {
277 return;
278 }
279 if (($moduleName !== null) && empty($moduleName))
280 {
281 throw new LoaderException(sprintf("Module name '%s' is not correct", $moduleName));
282 }
283
284 foreach ($classes as $class => $file)
285 {
286 $class = ltrim($class, "\\");
287 $class = strtolower($class);
288
289 self::$autoLoadClasses[$class] = [
290 "module" => $moduleName,
291 "file" => $file,
292 ];
293 }
294 }
295
301 public static function registerClassAliases(array $aliases): void
302 {
303 foreach ($aliases as $alias => $class)
304 {
305 $alias = strtolower(ltrim($alias, "\\"));
306 $class = strtolower(ltrim($class, "\\"));
307
308 // one class for an alias
309 self::$aliases[$alias] = $class;
310 // but many aliases for a class
311 self::$classAliases[$class][] = $alias;
312 }
313 }
314
315
323 public static function registerNamespace($namespace, $path)
324 {
325 $namespace = trim($namespace, "\\") . "\\";
326 $namespace = strtolower($namespace);
327
328 $path = rtrim($path, "/\\");
329 $depth = substr_count(rtrim($namespace, "\\"), "\\");
330
331 self::$namespaces[$namespace][] = [
332 "path" => $path,
333 "depth" => $depth,
334 ];
335 }
336
341 public static function unregisterNamespace($namespace)
342 {
343 $namespace = trim($namespace, "\\") . "\\";
344 $namespace = strtolower($namespace);
345
346 unset(self::$namespaces[$namespace]);
347 }
348
353 public static function registerHandler(callable $handler)
354 {
355 \spl_autoload_register($handler);
356 }
357
364 public static function autoLoad($className)
365 {
366 // fix web env
367 $className = ltrim($className, "\\");
368
369 $classLower = strtolower($className);
370
371 // dynamically define the alias for a class
372 if (isset(self::$aliases[$classLower]))
373 {
374 class_alias(self::$aliases[$classLower], $classLower);
375
376 return;
377 }
378
379 static $documentRoot = null;
380 if ($documentRoot === null)
381 {
383 }
384
385 if (isset(self::$autoLoadClasses[$classLower]))
386 {
387 // optimization via direct paths
388
389 $pathInfo = self::$autoLoadClasses[$classLower];
390 if ($pathInfo["module"] != "")
391 {
392 $module = $pathInfo["module"];
393 $holder = (self::$modulesHolders[$module] ?? self::BITRIX_HOLDER);
394
395 $filePath = (defined('REPOSITORY_ROOT') && $holder === self::BITRIX_HOLDER)
396 ? REPOSITORY_ROOT
397 : "{$documentRoot}/{$holder}/modules";
398
399 $filePath .= '/' . $module . "/" . $pathInfo["file"];
400
401 require_once($filePath);
402 }
403 else
404 {
405 require_once($documentRoot . $pathInfo["file"]);
406 }
407 }
408 else
409 {
410 // search the path in namespaces
411
412 if (preg_match("#[^\\\\/a-zA-Z0-9_]#", $className))
413 {
414 return;
415 }
416
417 $tryFiles = [[
418 "real" => $className,
419 "lower" => $classLower,
420 ]];
421
422 if (str_ends_with($classLower, "table"))
423 {
424 // old *Table stored in reserved files
425 $tryFiles[] = [
426 "real" => substr($className, 0, -5),
427 "lower" => substr($classLower, 0, -5),
428 ];
429 }
430
431 foreach ($tryFiles as $classInfo)
432 {
433 $classParts = explode("\\", $classInfo["lower"]);
434
435 //remove class name
436 array_pop($classParts);
437
438 while (!empty($classParts))
439 {
440 //go from the end
441 $namespace = implode("\\", $classParts) . "\\";
442
443 if (isset(self::$namespaces[$namespace]))
444 {
445 //found
446 foreach (self::$namespaces[$namespace] as $namespaceLocation)
447 {
448 $depth = $namespaceLocation["depth"];
449 $path = $namespaceLocation["path"];
450
451 $fileParts = explode("\\", $classInfo["real"]);
452
453 for ($i = 0; $i <= $depth; $i++)
454 {
455 array_shift($fileParts);
456 }
457
458 $classPath = implode("/", $fileParts);
459
460 $classPathLower = strtolower($classPath);
461
462 // final path lower case
463 $filePath = $path . '/' . $classPathLower . ".php";
464
465 if (file_exists($filePath))
466 {
467 require_once($filePath);
468 break 3;
469 }
470
471 // final path original case
472 $filePath = $path . '/' . $classPath . ".php";
473
474 if (file_exists($filePath))
475 {
476 require_once($filePath);
477 break 3;
478 }
479 }
480 }
481
482 //try the shorter namespace
483 array_pop($classParts);
484 }
485 }
486 }
487
488 // dynamically define the class aliases
489 if (isset(self::$classAliases[$classLower]))
490 {
491 foreach (self::$classAliases[$classLower] as $alias)
492 {
493 class_exists($alias);
494 }
495 }
496 }
497
503 public static function requireClass($className)
504 {
505 $file = ltrim($className, "\\"); // fix web env
506 $file = strtolower($file);
507
508 if (preg_match("#[^\\\\/a-zA-Z0-9_]#", $file))
509 {
510 return;
511 }
512
513 $tryFiles = [$file];
514
515 if (str_ends_with($file, "table"))
516 {
517 // old *Table stored in reserved files
518 $tryFiles[] = substr($file, 0, -5);
519 }
520
521 foreach ($tryFiles as $file)
522 {
523 $file = str_replace('\\', '/', $file);
524 $arFile = explode("/", $file);
525
526 if ($arFile[0] === "bitrix")
527 {
528 array_shift($arFile);
529
530 if (empty($arFile))
531 {
532 break;
533 }
534
535 $module = array_shift($arFile);
536 if ($module == null || empty($arFile))
537 {
538 break;
539 }
540 }
541 else
542 {
543 $module1 = array_shift($arFile);
544 $module2 = array_shift($arFile);
545
546 if ($module1 == null || $module2 == null || empty($arFile))
547 {
548 break;
549 }
550
551 $module = $module1 . "." . $module2;
552 }
553
554 if (!self::includeModule($module))
555 {
556 throw new LoaderException(sprintf(
557 "There is no `%s` class, module `%s` is unavailable", $className, $module
558 ));
559 }
560 }
561
562 self::autoLoad($className);
563 }
564
572 public static function getLocal($path, $root = null)
573 {
574 if ($root === null)
575 {
576 $root = self::getDocumentRoot();
577 }
578
579 if (file_exists($root . "/local/" . $path))
580 {
581 return $root . "/local/" . $path;
582 }
583 elseif (file_exists($root . "/bitrix/" . $path))
584 {
585 return $root . "/bitrix/" . $path;
586 }
587 else
588 {
589 return false;
590 }
591 }
592
600 public static function getPersonal($path)
601 {
602 $root = self::getDocumentRoot();
603 $personal = ($_SERVER["BX_PERSONAL_ROOT"] ?? "");
604
605 if ($personal <> '' && file_exists($root . $personal . "/" . $path))
606 {
607 return $root . $personal . "/" . $path;
608 }
609
610 return self::getLocal($path, $root);
611 }
612
619 {
620 self::$requireThrowException = (bool)$requireThrowException;
621 }
622
628 public static function includeComposerAutoload(): void
629 {
630 // load from config
631 $composerSettings = Configuration::getValue('composer');
632 if (empty($composerSettings['config_path']))
633 {
634 return;
635 }
636
637 $composerFilePath = (string)$composerSettings['config_path'];
638 if ($composerFilePath[0] !== '/')
639 {
640 $composerFilePath = realpath(
641 self::getDocumentRoot() . '/' . $composerFilePath
642 );
643 if (empty($composerFilePath))
644 {
645 return;
646 }
647 }
648
649 require_once dirname($composerFilePath) . '/vendor/autoload.php';
650 }
651
652 public static function getNamespaces(): array
653 {
654 return self::$namespaces;
655 }
656}
657
658class LoaderException extends \Exception
659{
660 public function __construct($message = "", $code = 0, \Exception $previous = null)
661 {
662 parent::__construct($message, $code, $previous);
663 }
664}
$path
Определения access_edit.php:21
__construct($message="", $code=0, \Exception $previous=null)
Определения loader.php:660
Определения loader.php:13
static $modulesHolders
Определения loader.php:45
static $classAliases
Определения loader.php:54
static registerClassAliases(array $aliases)
Определения loader.php:301
const ALPHA_UPPER
Определения loader.php:40
const LOCAL_HOLDER
Определения loader.php:20
const MODULE_INSTALLED
Определения loader.php:28
static $sharewareModules
Определения loader.php:46
static requireModule($moduleName)
Определения loader.php:174
const ALPHA_LOWER
Определения loader.php:38
static getDocumentRoot()
Определения loader.php:254
static includeModule($moduleName)
Определения loader.php:67
const MODULE_DEMO_EXPIRED
Определения loader.php:36
static clearModuleCache($moduleName)
Определения loader.php:233
static getNamespaces()
Определения loader.php:652
static $namespaces
Определения loader.php:51
static registerHandler(callable $handler)
Определения loader.php:353
static registerAutoLoadClasses($moduleName, array $classes)
Определения loader.php:273
static unregisterNamespace($namespace)
Определения loader.php:341
static registerNamespace($namespace, $path)
Определения loader.php:323
static $aliases
Определения loader.php:53
static $autoLoadClasses
Определения loader.php:52
static $loadedModules
Определения loader.php:43
const MODULE_NOT_FOUND
Определения loader.php:24
static includeSharewareModule($moduleName)
Определения loader.php:202
const SAFE_MODE
Определения loader.php:17
static includeComposerAutoload()
Определения loader.php:628
static $safeModeModules
Определения loader.php:42
static $semiloadedModules
Определения loader.php:44
static getLocal($path, $root=null)
Определения loader.php:572
static setRequireThrowException($requireThrowException)
Определения loader.php:618
static getPersonal($path)
Определения loader.php:600
static requireClass($className)
Определения loader.php:503
const MODULE_DEMO
Определения loader.php:32
const BITRIX_HOLDER
Определения loader.php:19
static autoLoad($className)
Определения loader.php:364
static $requireThrowException
Определения loader.php:58
static isValidModule(string $moduleName)
Определения modulemanager.php:184
static getInstalledModules()
Определения modulemanager.php:9
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
global $MESS
Определения bill.php:2
$_SERVER["DOCUMENT_ROOT"]
Определения cron_frame.php:9
global $DB
Определения cron_frame.php:29
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
foreach(['Bitrix\\Main'=> '/lib', 'Psr\\Container'=> '/vendor/psr/container/src', 'Psr\\Log'=> '/vendor/psr/log/src', 'Psr\\Http\\Message'=> '/vendor/psr/http-message/src', 'Psr\\Http\\Client'=> '/vendor/psr/http-client/src', 'Http\\Promise'=> '/vendor/php-http/promise/src', 'PHPMailer\\PHPMailer'=> '/vendor/phpmailer/phpmailer/src', 'GeoIp2'=> '/vendor/geoip2/geoip2/src', 'MaxMind\\Db'=> '/vendor/maxmind-db/reader/src/MaxMind/Db', 'PhpParser'=> '/vendor/nikic/php-parser/lib/PhpParser', 'Recurr'=> '/vendor/simshaun/recurr/src/Recurr',] as $namespace=> $namespacePath) $documentRoot
Определения autoload.php:27
$message
Определения payment.php:8
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$i
Определения factura.php:643