1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
asset.php
См. документацию.
1<?php
2
3namespace Bitrix\Main\Page;
4
5use Bitrix\Main;
6use Bitrix\Main\IO;
7use Bitrix\Main\Config\Option;
8use Bitrix\Main\Web\Json;
9
10class Asset
11{
12 private static $instance;
13
15 private $targetList;
16
18 private $target;
19
21 private $css = [];
22
24 private $js = [];
25
27 private $strings = [
28 AssetLocation::BEFORE_CSS => [],
29 AssetLocation::AFTER_CSS => [],
30 AssetLocation::AFTER_JS_KERNEL => [],
31 AssetLocation::AFTER_JS => [],
32 ];
33
35 private $moduleInfo = ['CSS' => [], 'JS' => []];
36 private $kernelAsset = ['CSS' => [], 'JS' => []];
37 private $assetList = ['CSS' => [], 'SOURCE_CSS' => [], 'JS' => [], 'SOURCE_JS' => []];
38 private $fileList = ['CSS' => [], 'JS' => []];
39 private $mode = AssetMode::STANDARD;
40
41 private $ajax;
42 private $xhtmlStyle = '/';
43
44 private $optimizeCss = true;
45 private $optimizeJs = true;
46
47 private $headString = false;
48 private $headScript = false;
49 private $bodyScript = false;
50 private $moveJsToBody = null;
51
52 private $templateExists = false;
53 private $siteTemplateID = '';
54 private $templatePath = '';
55 private $documentRoot = '';
56 private $dbType = 'MYSQL';
57 private $assetCSSCnt = 0;
58 private $assetJSCnt = 0;
59
60 const SOURCE_MAP_TAG = "\n//# sourceMappingURL=";
61 const HEADER_START_TAG = "; /* Start:\"";
62 const HEADER_END_TAG = "\"*/";
63 const version = 1;
64
65 private function __construct()
66 {
67 //use self::getInstance()
68 $this->targetList['KERNEL'] = [
69 'NAME' => 'KERNEL',
70 'START' => true,
71 'CSS_RES' => [],
72 'JS_RES' => [],
73 'CSS_LIST' => [],
74 'JS_LIST' => [],
75 'STRING_LIST' => [],
76 'UNIQUE' => true,
77 'PREFIX' => 'kernel',
78 'BODY' => false,
79 'MODE' => AssetMode::ALL
80 ];
81
82 $this->targetList['BODY'] = $this->targetList['TEMPLATE'] = $this->targetList['PAGE'] = $this->targetList['KERNEL'];
83 $this->targetList['PAGE']['NAME'] = 'PAGE';
84 $this->targetList['PAGE']['UNIQUE'] = false;
85 $this->targetList['PAGE']['PREFIX'] = 'page';
86 $this->targetList['TEMPLATE']['NAME'] = 'TEMPLATE';
87 $this->targetList['TEMPLATE']['UNIQUE'] = false;
88 $this->targetList['TEMPLATE']['PREFIX'] = 'template';
89 $this->targetList['BODY']['NAME'] = 'BODY';
90 $this->targetList['BODY']['UNIQUE'] = false;
91 $this->targetList['BODY']['PREFIX'] = 'body';
92
94 $this->targetList['KERNEL']['CSS_LIST']['KERNEL_main'] = [];
95 $this->targetList['KERNEL']['JS_LIST']['KERNEL_main'] = [];
96
97 $this->target = &$this->targetList['TEMPLATE'];
98 $this->documentRoot = Main\Loader::getDocumentRoot();
99 }
100
105 private function __clone()
106 {
107 //you can't clone it
108 }
109
115 public static function getInstance()
116 {
117 if (is_null(self::$instance))
118 {
119 self::$instance = new Asset();
120 }
121
122 return self::$instance;
123 }
124
130 public function setMode($mode = AssetMode::STANDARD)
131 {
132 $this->mode = $mode;
133 }
134
139 public static function gzipEnabled()
140 {
141 static $gzip = null;
142 if ($gzip === null)
143 {
144 $gzip = (
145 Option::get('main','compres_css_js_files', 'N') == 'Y'
146 && extension_loaded('zlib')
147 && function_exists('gzopen')
148 );
149 }
150 return $gzip;
151 }
152
157 public function enableOptimizeCss()
158 {
159 $this->optimizeCss = true;
160 }
161
166 public function disableOptimizeCss()
167 {
168 $this->optimizeCss = false;
169 }
170
175 public function enableOptimizeJs()
176 {
177 $this->optimizeJs = true;
178 }
179
184 public function disableOptimizeJs()
185 {
186 $this->optimizeJs = false;
187 }
188
193 public function setXhtml($value)
194 {
195 $this->xhtmlStyle = ($value === true ? '/':'');
196 }
197
203 public function setMaxCss($value)
204 {
205
206 }
207
213 public function setShowHeadString($value = true)
214 {
215 $this->headString = $value;
216 }
217
222 public function getShowHeadString()
223 {
224 return $this->headString;
225 }
226
232 public function setShowHeadScript($value = true)
233 {
234 $this->headScript = $value;
235 }
236
242 public function setShowBodyScript($value = true)
243 {
244 $this->bodyScript = $value;
245 }
246
251 public function setAjax()
252 {
253 $newInstance = self::$instance = new Asset();
254 $newInstance->ajax = true;
255 return $newInstance;
256 }
257
261 public function getTargetName()
262 {
263 return $this->target['NAME'];
264 }
265
269 public function getTarget()
270 {
271 return $this->target;
272 }
273
280 public function startSet($id = '', $mode = AssetMode::ALL)
281 {
282 return $this->startTarget($id, $mode);
283 }
284
291 public function startTarget($id = '', $mode = AssetMode::ALL)
292 {
293 $id = strtoupper(trim($id));
294 if ($id == '')
295 {
296 return false;
297 }
298
299 if ($id == 'TEMPLATE')
300 {
301 $this->templateExists = true;
302 }
303
304 if (
305 ($this->target['NAME'] == 'TEMPLATE' || $this->target['NAME'] == 'PAGE')
306 && ($id == 'TEMPLATE' || $id == 'PAGE')
307 )
308 {
309 $this->target['START'] = false;
310 $this->targetList[$id]['START'] = true;
311 $this->target = &$this->targetList[$id];
312 }
313 elseif ($id != 'TEMPLATE' && $id != 'PAGE')
314 {
315 if (isset($this->targetList[$id]))
316 {
317 return false;
318 }
319
320 $this->stopTarget();
321 $this->targetList[$id] = [
322 'NAME' => $id,
323 'START' => true,
324 'JS_RES' => [],
325 'CSS_RES' => [],
326 'JS_LIST' => [],
327 'CSS_LIST' => [],
328 'STRING_LIST' => [],
329 'BODY' => false,
330 'UNIQUE' => false,
331 'MODE' => $mode
332 ];
333 $this->target = &$this->targetList[$id];
334 }
335 return true;
336 }
337
343 public function stopTarget($id = '')
344 {
345 $id = strtoupper(trim($id));
346 if ($id == 'TEMPLATE')
347 {
348 if($this->target['NAME'] == 'TEMPLATE')
349 {
350 $this->target['START'] = false;
351 $this->target = &$this->targetList['PAGE'];
352 }
353 else
354 {
355 $this->targetList['TEMPLATE']['START'] = false;
356 }
357 }
358 else
359 {
360 if ($this->target['NAME'] == 'TEMPLATE')
361 {
362 return false;
363 }
364 elseif ($this->targetList['TEMPLATE']['START'])
365 {
366 $this->target['START'] = false;
367 $this->target = &$this->targetList['TEMPLATE'];
368 }
369 else
370 {
371 $this->target['START'] = false;
372 $this->target = &$this->targetList['PAGE'];
373 }
374 }
375
376 return true;
377 }
378
385 public function getAssetInfo($id, $mode)
386 {
387 $id = strtoupper(trim($id));
388 $emptyData = ['JS' => [], 'BUNDLE_JS' => [], 'CSS' => [], 'BUNDLE_CSS' => [], 'STRINGS' => []];
389
390 if (!isset($this->targetList[$id]))
391 {
392 return $emptyData;
393 }
394
395 static $cacheInfo = [
396 AssetMode::STANDARD => null,
397 AssetMode::COMPOSITE => null,
398 AssetMode::ALL => null,
399 AssetMode::SPECIAL => null
400 ];
401
402 if ($cacheInfo[$mode] === null)
403 {
404 $cacheInfo[$mode] = $emptyData;
405
406 foreach ($this->strings as $location)
407 {
408 foreach ($location as $item)
409 {
410 if ($mode == $item['MODE'])
411 {
412 $cacheInfo[$mode]['STRINGS'][$item['TARGET'][0]][] = $item['CONTENT'];
413 }
414 }
415 }
416
417 foreach (['JS', 'CSS'] as $type)
418 {
419 foreach ($this->getTargetList($type) as $set)
420 {
421 $cache = &$cacheInfo[$mode][$type][$set['NAME']];
422 $cacheFull = &$cacheInfo[$mode]['BUNDLE_'.$type][$set['NAME']];
423
424 if (!is_array($cache))
425 {
426 $cache = [];
427 }
428
429 if (!is_array($cacheFull))
430 {
431 $cacheFull = [];
432 }
433
434 $fileList = $this->fileList[$type][$set['NAME']] ?? [];
435 $targetList = $this->targetList['KERNEL'][$type.'_LIST'][$set['NAME']] ?? [];
436
437 $items = [];
438 if ($mode === $set['MODE'] && isset($fileList['FILES']))
439 {
440 $items = $fileList['FILES'];
441 }
442 elseif (isset($fileList['UP_NEW_FILES']))
443 {
444 $items = $fileList['UP_NEW_FILES'];
445 }
446
447 if (empty($items))
448 {
449 continue;
450 }
451
452 foreach ($items as $item)
453 {
454 $cache[] = $item;
455
456 if (isset($fileList['FULL_FILES'][$item]))
457 {
458 $cacheFull = array_merge($cacheFull, $fileList['FULL_FILES'][$item]);
459 }
460
461 if ($set['PARENT_NAME'] == 'KERNEL')
462 {
463 foreach ($targetList['WHERE_USED'] as $target => $tmp)
464 {
465 $cacheInfo[$mode][$type][$target][] = $item;
466
467 if (isset($fileList['FULL_FILES'][$item]))
468 {
469 if (!isset($cacheInfo[$mode]['BUNDLE_'.$type][$target]))
470 {
471 $cacheInfo[$mode]['BUNDLE_'.$type][$target] = [];
472 }
473
474 $cacheInfo[$mode]['BUNDLE_'.$type][$target] = array_merge(
475 $cacheInfo[$mode]['BUNDLE_'.$type][$target],
476 $fileList['FULL_FILES'][$item]
477 );
478 }
479 }
480 }
481 }
482 }
483 }
484 }
485
486 return [
487 'JS' => $cacheInfo[$mode]['JS'][$id] ?? [],
488 'BUNDLE_JS' => $cacheInfo[$mode]['BUNDLE_JS'][$id] ?? [],
489 'CSS' => $cacheInfo[$mode]['CSS'][$id] ?? [],
490 'BUNDLE_CSS' => $cacheInfo[$mode]['BUNDLE_CSS'][$id] ?? [],
491 'STRINGS' => $cacheInfo[$mode]['STRINGS'][$id] ?? []
492 ];
493 }
494
500 public function compositeTarget($id = '')
501 {
502 $id = strtoupper(trim($id));
503 if ($id == '' || !isset($this->targetList[$id]))
504 {
505 return false;
506 }
507 else
508 {
509 $this->targetList[$id]['MODE'] = AssetMode::COMPOSITE;
510 }
511 return true;
512 }
513
519 public function getTargetList($type = 'CSS')
520 {
521 static $res = ['CSS_LIST' => null, 'JS_LIST' => null];
522 $key = ($type == 'CSS' ? 'CSS_LIST' : 'JS_LIST');
523
524 if ($res[$key] === null)
525 {
526 foreach ($this->targetList as $targetName => $targetInfo)
527 {
528 $res[$key][] = [
529 'NAME' => $targetName,
530 'PARENT_NAME' => $targetName,
531 'UNIQUE' => $targetInfo['UNIQUE'],
532 'PREFIX' => ($targetInfo['PREFIX'] ?? ''),
533 'MODE' => $targetInfo['MODE'],
534 'MODULE_NAME' => ($targetInfo['MODULE_NAME'] ?? ''),
535 ];
536
537 if (!empty($targetInfo[$key]))
538 {
539 foreach ($targetInfo[$key] as $subSetName => $val)
540 {
541 $res[$key][] = [
542 'NAME' => $subSetName,
543 'PARENT_NAME' => $targetName,
544 'UNIQUE' => ($val['UNIQUE'] ?? ''),
545 'PREFIX' => ($val['PREFIX'] ?? ''),
546 'MODE' => ($val['MODE'] ?? 0),
547 'MODULE_NAME' => ($val['MODULE_NAME'] ?? ''),
548 ];
549 }
550 }
551 }
552 }
553 return $res[$key];
554 }
555
564 function addString($str, $unique = false, $location = AssetLocation::AFTER_JS_KERNEL, $mode = null)
565 {
566 if ($str == '')
567 {
568 return false;
569 }
570
571 if ($unique)
572 {
573 $chkSum = md5($str);
574 $this->strings[$location][$chkSum]['CONTENT'] = $str;
575 $this->strings[$location][$chkSum]['TARGET'][] = $this->getTargetName();
576 $this->strings[$location][$chkSum]['MODE'] = $mode;
577 }
578 else
579 {
580 $this->strings[$location][] = ['CONTENT' => $str, 'MODE' => $mode, 'TARGET' => [$this->getTargetName()]];
581 }
582 return true;
583 }
584
590 public function getStrings($location = AssetLocation::AFTER_JS_KERNEL)
591 {
592 static $firstExec = true;
593 if ($firstExec)
594 {
595 $this->prepareString();
596 $firstExec = false;
597 }
598
599 $res = '';
600 if ($location == AssetLocation::AFTER_CSS && \CJSCore::IsCoreLoaded())
601 {
602 $res = "<script>if(!window.BX)window.BX={};if(!window.BX.message)window.BX.message=function(mess){if(typeof mess==='object'){for(let i in mess) {BX.message[i]=mess[i];} return true;}};</script>\n";
603 }
604
605 if (isset($this->strings[$location]))
606 {
607 foreach ($this->strings[$location] as $item)
608 {
609 if ($this->mode & $item['MODE'])
610 {
611 $res .= $item['CONTENT']."\n";
612 }
613 }
614 }
615
616 return ($res == '') ? '' : $res."\n";
617 }
618
625 public function addCss($path, $additional = false)
626 {
627 if ($path == '')
628 {
629 return false;
630 }
631
632 $css = $this->getAssetPath($path);
633 $this->css[$css]['TARGET'][] = $this->getTargetName();
634 $this->css[$css]['ADDITIONAL'] = (isset($this->css[$css]['ADDITIONAL']) && $this->css[$css]['ADDITIONAL'] ? true : $additional);
635 return true;
636 }
637
644 public function addJs($path, $additional = false)
645 {
646 if ($path == '')
647 {
648 return false;
649 }
650
651 $js = $this->getAssetPath($path);
652 $this->js[$js]['TARGET'][] = $this->getTargetName();
653 $this->js[$js]['ADDITIONAL'] = (isset($this->js[$js]['ADDITIONAL']) && $this->js[$js]['ADDITIONAL'] ? true : $additional);
654 return true;
655 }
656
663 public static function fixCssIncludes($content, $path)
664 {
665 $path = IO\Path::getDirectory($path);
666 $content = preg_replace_callback(
667 '#([;\s:]*(?:url|@import)\s*\‍(\s*)(\'|"|)(.+?)(\2)\s*\‍)#si',
668 function ($matches) use ($path)
669 {
670 return $matches[1].Asset::replaceUrlCSS($matches[3], $matches[2], addslashes($path)).")";
671 },
673 );
674
675 $content = preg_replace_callback(
676 '#(\s*@import\s*)([\'"])([^\'"]+)(\2)#si',
677 function ($matches) use ($path)
678 {
679 return $matches[1].Asset::replaceUrlCSS($matches[3], $matches[2], addslashes($path));
680 },
682 );
683
684 return $content;
685 }
686
693 public function groupJs($from = '', $to = '')
694 {
695 if (empty($from) || empty($to))
696 {
697 return;
698 }
699
700 $to = $this->movedJsTo($to);
701 if (array_key_exists($from, $this->moduleInfo['JS']))
702 {
703 $this->moduleInfo['JS'][$from]['MODULE_ID'] = $to;
704 }
705 else
706 {
707 $this->moduleInfo['JS'][$from] = ['MODULE_ID' => $to, 'FILES_INFO' => false, 'BODY' => false];
708 }
709
710 foreach ($this->moduleInfo['JS'] as $moduleID => $moduleInfo)
711 {
712 if ($moduleInfo['MODULE_ID'] == $from)
713 {
714 $this->moduleInfo['JS'][$moduleID]["MODULE_ID"] = $to;
715 }
716 }
717 }
718
725 public function groupCss($from = '', $to = '')
726 {
727 if (empty($from) || empty($to))
728 {
729 return;
730 }
731
732 $to = $this->movedCssTo($to);
733 if (array_key_exists($from, $this->moduleInfo['CSS']))
734 {
735 $this->moduleInfo['CSS'][$from]['MODULE_ID'] = $to;
736 }
737 else
738 {
739 $this->moduleInfo['CSS'][$from] = ['MODULE_ID' => $to, 'FILES_INFO' => false];
740 }
741
742 foreach ($this->moduleInfo['CSS'] as $moduleID => $moduleInfo)
743 {
744 if($moduleInfo['MODULE_ID'] == $from)
745 {
746 $this->moduleInfo['CSS'][$moduleID]["MODULE_ID"] = $to;
747 }
748 }
749 }
750
755 private function movedJsTo($to)
756 {
757 if (isset($this->moduleInfo['JS'][$to]['MODULE_ID']) && $this->moduleInfo['JS'][$to]['MODULE_ID'] != $to)
758 {
759 $to = $this->movedJsTo($this->moduleInfo['JS'][$to]['MODULE_ID']);
760 }
761
762 return $to;
763 }
764
769 private function movedCssTo($to)
770 {
771 if (isset($this->moduleInfo['CSS'][$to]['MODULE_ID']) && $this->moduleInfo['CSS'][$to]['MODULE_ID'] != $to)
772 {
773 $to = $this->movedCssTo($this->moduleInfo['JS'][$to]['MODULE_ID']);
774 }
775
776 return $to;
777 }
778
784 public function moveJs($module = '')
785 {
786 if (empty($module) || $module === "main")
787 {
788 return;
789 }
790
791 if (array_key_exists($module, $this->moduleInfo['JS']))
792 {
793 $this->moduleInfo['JS'][$module]['BODY'] = true;
794 }
795 else
796 {
797 $this->moduleInfo['JS'][$module] = ['MODULE_ID' => $module, 'FILES_INFO' => false, 'BODY' => true];
798 }
799 }
800
806 public function setJsToBody($flag)
807 {
808 $this->moveJsToBody = (bool)$flag;
809 }
810
814 protected function getJsToBody()
815 {
816 if ($this->moveJsToBody === null)
817 {
818 $this->moveJsToBody = Option::get("main", "move_js_to_body") === "Y" && (!defined("ADMIN_SECTION") || ADMIN_SECTION !== true);
819 }
820 return $this->moveJsToBody;
821 }
822
829 public function moveJsToBody(&$content)
830 {
831 if (!$this->getJsToBody())
832 {
833 return;
834 }
835
836 $js = "";
837 $offset = 0;
838 $newContent = "";
839 $areas = $this->getScriptAreas($content);
840 foreach ($areas as $area)
841 {
842 if (str_contains($area->attrs, "data-skip-moving") || !self::isValidScriptType($area->attrs))
843 {
844 continue;
845 }
846
847 $js .= substr($content, $area->openTagStart, $area->closingTagEnd - $area->openTagStart);
848 $newContent .= substr($content, $offset, $area->openTagStart - $offset);
849 $offset = $area->closingTagEnd;
850 }
851
852 if ($js === "")
853 {
854 return;
855 }
856
857 $newContent .= substr($content, $offset);
858 $bodyEnd = strripos($newContent, "</body>");
859 if ($bodyEnd === false)
860 {
861 $content = $newContent.$js;
862 }
863 else
864 {
865 $content = substr_replace($newContent, $js, $bodyEnd, 0);
866 }
867 }
868
874 private function getScriptAreas($content)
875 {
876 $openTag = "<script";
877 $closingTag = "</script";
878 $ending = ">";
879
880 $offset = 0;
881 $areas = [];
882 $content = strtolower($content);
883 while (($openTagStart = strpos($content, $openTag, $offset)) !== false)
884 {
885 $endingPos = strpos($content, $ending, $openTagStart);
886 if ($endingPos === false)
887 {
888 break;
889 }
890
891 $attrsStart = $openTagStart + strlen($openTag);
892 $attrs = substr($content, $attrsStart, $endingPos - $attrsStart);
893 $openTagEnd = $endingPos + strlen($ending);
894
895 $realClosingTag = $closingTag.$ending;
896 $closingTagStart = strpos($content, $realClosingTag, $openTagEnd);
897 if ($closingTagStart === false)
898 {
899 $offset = $openTagEnd;
900 continue;
901 }
902
903 $closingTagEnd = $closingTagStart + strlen($realClosingTag);
904 while (isset($content[$closingTagEnd]) && $content[$closingTagEnd] === "\n")
905 {
906 $closingTagEnd++;
907 }
908
909 $area = new \stdClass();
910 $area->attrs = $attrs;
911 $area->openTagStart = $openTagStart;
912 $area->openTagEnd = $openTagEnd;
913 $area->closingTagStart = $closingTagStart;
914 $area->closingTagEnd = $closingTagEnd;
915 $areas[] = $area;
916
917 $offset = $closingTagEnd;
918 }
919
920 return $areas;
921 }
922
926 public function canMoveJsToBody()
927 {
928 return
929 $this->getJsToBody() &&
930 !Main\Application::getInstance()->getContext()->getRequest()->isAjaxRequest() &&
931 !defined("BX_BUFFER_SHUTDOWN");
932 }
933
940 private static function isValidScriptType($attrs)
941 {
942 if ($attrs === "" || !preg_match("/type\\s*=\\s*(['\"]?)(.*?)\\1/i", $attrs, $match))
943 {
944 return true;
945 }
946
947 $type = mb_strtolower($match[2]);
948 return $type === "" || $type === "text/javascript" || $type === "application/javascript";
949 }
950
951
959 public static function replaceUrlCss($url, $quote, $path)
960 {
961 if (
962 str_contains($url, "://")
963 || str_contains($url, "data:")
964 || str_starts_with($url, "#")
965 )
966 {
967 return $quote.$url.$quote;
968 }
969
970 $url = trim(stripslashes($url), "'\" \r\n\t");
971 if (str_starts_with($url, "/"))
972 {
973 return $quote.$url.$quote;
974 }
975
976 return $quote.$path.'/'.$url.$quote;
977 }
978
984 public static function getAssetPath($src)
985 {
986 if (($p = mb_strpos($src, "?")) > 0 && !\CMain::IsExternalLink($src))
987 {
988 $src = mb_substr($src, 0, $p);
989 }
990 return $src;
991 }
992
996 public function optimizeCss()
997 {
998 $optimize = $this->optimizeCss
999 && (!defined("ADMIN_SECTION") || ADMIN_SECTION !== true)
1000 && Option::get('main', 'optimize_css_files', 'N') == 'Y'
1001 && !$this->ajax;
1002
1003 return $optimize;
1004 }
1005
1009 public function optimizeJs()
1010 {
1011 $optimize = $this->optimizeJs
1012 && (!defined("ADMIN_SECTION") || ADMIN_SECTION !== true)
1013 && Option::get('main', 'optimize_js_files', 'N') == 'Y'
1014 && !$this->ajax;
1015
1016 return $optimize;
1017 }
1018
1022 public static function canUseMinifiedAssets()
1023 {
1024 static $canLoad = null;
1025 if ($canLoad === null)
1026 {
1027 $canLoad = Option::get("main","use_minified_assets", "Y") == "Y";
1028 }
1029
1030 return $canLoad;
1031 }
1032
1036 public function sliceKernel()
1037 {
1038 return (!defined("ADMIN_SECTION") || ADMIN_SECTION !== true);
1039 }
1040
1048 public function insertCss($css, $label = false, $inline = false)
1049 {
1050 if ($label === true)
1051 {
1052 $label = ' data-template-style="true" ';
1053 }
1054 elseif ($label === false)
1055 {
1056 $label = '';
1057 }
1058
1059 if ($inline)
1060 {
1061 return "<style type=\"text/css\" {$label}>\n{$css}\n</style>\n";
1062 }
1063 else
1064 {
1065 return "<link href=\"{$css}\" type=\"text/css\" {$label} rel=\"stylesheet\" {$this->xhtmlStyle}>\n";
1066 }
1067 }
1068
1076 public function insertJs($js, $label = '', $inline = false)
1077 {
1078 if ($inline)
1079 {
1080 return "<script {$label}>\n{$js}\n</script>\n";
1081 }
1082 else
1083 {
1084 return "<script {$label} src=\"$js\"></script>\n";
1085 }
1086 }
1087
1092 private function setTemplateID()
1093 {
1094 static $firstExec = true;
1095 if ($firstExec && !$this->ajax && (!defined("ADMIN_SECTION") || ADMIN_SECTION !== true))
1096 {
1097 if (defined("SITE_TEMPLATE_PREVIEW_MODE"))
1098 {
1099 $this->templatePath = BX_PERSONAL_ROOT.'/tmp/templates/__bx_preview';
1100 }
1101 elseif (defined('SITE_TEMPLATE_ID'))
1102 {
1103 $this->siteTemplateID = SITE_TEMPLATE_ID;
1104 $this->templatePath = SITE_TEMPLATE_PATH;
1105 }
1106 else
1107 {
1108 $this->siteTemplateID = '.default';
1109 $this->templatePath = BX_PERSONAL_ROOT."/templates/.default";
1110 }
1111 $firstExec = false;
1112 }
1113 }
1114
1119 private function addTemplateCss()
1120 {
1121 if (
1122 !$this->ajax
1123 && (!defined("ADMIN_SECTION") || ADMIN_SECTION !== true)
1124 && $this->templateExists
1125 )
1126 {
1127 $this->css[$this->templatePath . '/styles.css']['TARGET'][] = 'TEMPLATE';
1128 $this->css[$this->templatePath . '/styles.css']['ADDITIONAL'] = false;
1129
1130 $this->css[$this->templatePath . '/template_styles.css']['TARGET'][] = 'TEMPLATE';
1131 $this->css[$this->templatePath . '/template_styles.css']['ADDITIONAL'] = false;
1132 }
1133 }
1134
1139 private function prepareString()
1140 {
1141 foreach ($this->strings as $location => $stringLocation)
1142 {
1143 foreach ($stringLocation as $key => $item)
1144 {
1146 $this->strings[$location][$key]['MODE'] = ($item['MODE'] === null ? $this->targetList[$item['TARGET'][0]]['MODE'] : $item['MODE']);
1147 }
1148 }
1149 }
1150
1158 private function getAssetPaths($assetPath)
1159 {
1160 $paths = [$assetPath];
1161 if (self::canUseMinifiedAssets() && preg_match("/(.+)\\.(js|css)$/i", $assetPath, $matches))
1162 {
1163 array_unshift($paths, $matches[1].".min.".$matches[2]);
1164 }
1165
1166 $result = null;
1167 $maxMtime = 0;
1168 foreach ($paths as $path)
1169 {
1170 $filePath = $this->documentRoot.$path;
1171 if (file_exists($filePath) && ($mtime = filemtime($filePath)) > $maxMtime && filesize($filePath) > 0)
1172 {
1173 $maxMtime = $mtime;
1174 $result = [
1175 "PATH" => $path,
1176 "FILE_PATH" => $filePath,
1177 "FULL_PATH" => \CUtil::GetAdditionalFileURL($path, true),
1178 ];
1179 }
1180 }
1181
1182 return $result;
1183 }
1184
1193 public function getFullAssetPath($sourcePath)
1194 {
1195 $result = $this->getAssetPaths($sourcePath);
1196
1197 if (is_array($result))
1198 {
1199 return $result["FULL_PATH"];
1200 }
1201 if (\CMain::IsExternalLink($sourcePath))
1202 {
1203 return $sourcePath;
1204 }
1205
1206 return null;
1207 }
1208
1215 private function prepareCss() : void
1216 {
1217 $additional = [];
1218
1219 foreach ($this->css as $css => $set)
1220 {
1222 $assetTID = $set['ADDITIONAL'] ? 'TEMPLATE' : $set['TARGET'][0];
1223 $cssInfo = [
1224 'PATH' => $css,
1225 'FULL_PATH' => false,
1226 'FILE_PATH' => false,
1227 'SKIP' => false,
1228 'TARGET' => $assetTID,
1229 'EXTERNAL' => \CMain::IsExternalLink($css),
1230 'ADDITIONAL' => $set['ADDITIONAL']
1231 ];
1232
1233 if ($cssInfo['EXTERNAL'])
1234 {
1235 if ($set['ADDITIONAL'])
1236 {
1237 $tmpKey = 'TEMPLATE';
1238 $tmpPrefix = 'template';
1239 }
1240 else
1241 {
1242 $tmpKey = 'KERNEL';
1243 $tmpPrefix = 'kernel';
1244 }
1245
1246 $cssInfo['MODULE_ID'] = $this->assetCSSCnt;
1247 $cssInfo['TARGET'] = $tmpKey.'_'.$this->assetCSSCnt;
1248 $cssInfo['PREFIX'] = $tmpPrefix.'_'.$this->assetCSSCnt;
1249 $cssInfo['FULL_PATH'] = $cssInfo['PATH'];
1250 $cssInfo['SKIP'] = true;
1251 $this->assetCSSCnt++;
1252
1253 $this->targetList[$tmpKey]['CSS_LIST'][$cssInfo['TARGET']] = [
1254 'TARGET' => $cssInfo['TARGET'],
1255 'PREFIX' => $cssInfo['PREFIX'],
1256 'MODE' => $this->targetList[$assetTID]['MODE'],
1257 'UNIQUE' => false,
1258 'WHERE_USED' => []
1259 ];
1260 }
1261 else
1262 {
1263 if (($paths = $this->getAssetPaths($css)) !== null)
1264 {
1265 $cssInfo["PATH"] = $css;
1266 $cssInfo["FILE_PATH"] = $paths["FILE_PATH"];
1267 $cssInfo["FULL_PATH"] = $paths["FULL_PATH"];
1268 }
1269 else
1270 {
1271 unset($this->css[$css]);
1272 continue;
1273 }
1274
1275 $moduleInfo = $this->isKernelCSS($cssInfo['PATH']);
1276 if ($moduleInfo)
1277 {
1278 if ($this->sliceKernel() && $this->optimizeCss() && is_array($moduleInfo))
1279 {
1280 $cssInfo['MODULE_ID'] = $moduleInfo['MODULE_ID'];
1281 $cssInfo['TARGET'] = 'KERNEL_'.$moduleInfo['MODULE_ID'];
1282 $cssInfo['PREFIX'] = 'kernel_'.$moduleInfo['MODULE_ID'];
1283 $cssInfo['SKIP'] = $moduleInfo['SKIP'] ?? false;
1284 }
1285 else
1286 {
1287 $cssInfo['MODULE_ID'] = $this->assetCSSCnt;
1288 $cssInfo['TARGET'] = 'KERNEL_'.$this->assetCSSCnt;
1289 $cssInfo['PREFIX'] = 'kernel_'.$this->assetCSSCnt;
1290 $cssInfo['SKIP'] = true;
1291 $this->assetCSSCnt++;
1292 }
1293
1294 if (isset($this->targetList['KERNEL']['CSS_LIST'][$cssInfo['TARGET']]['MODE']))
1295 {
1296 $this->targetList['KERNEL']['CSS_LIST'][$cssInfo['TARGET']]['MODE'] |= $this->targetList[$assetTID]['MODE'];
1297 }
1298 else
1299 {
1300 $this->targetList['KERNEL']['CSS_LIST'][$cssInfo['TARGET']] = [
1301 'TARGET' => $cssInfo['TARGET'],
1302 'PREFIX' => $cssInfo['PREFIX'],
1303 'MODE' => $set['ADDITIONAL'] ? $this->targetList[$set['TARGET'][0]]['MODE'] : $this->targetList[$assetTID]['MODE'],
1304 'UNIQUE' => true,
1305 'WHERE_USED' => []
1306 ];
1307 }
1308
1309 if (is_array($moduleInfo))
1310 {
1311 $this->targetList['KERNEL']['CSS_LIST'][$cssInfo['TARGET']]['MODULE_NAME'] = $moduleInfo['MODULE_ID'];
1312 }
1313
1314 // Add information about sets where used
1315 foreach ($set['TARGET'] as $setID)
1316 {
1317 $this->targetList['KERNEL']['CSS_LIST'][$cssInfo['TARGET']]['WHERE_USED'][$setID] = true;
1318 }
1319 }
1320 elseif (strncmp($cssInfo['PATH'], '/bitrix/js/', 11) != 0 /*||*/ )
1321 {
1322 $cssInfo['SKIP'] = !(
1323 strncmp($cssInfo['PATH'], '/bitrix/panel/', 14) != 0
1324 && strncmp($cssInfo['PATH'], '/bitrix/themes/', 15) != 0
1325 && strncmp($cssInfo['PATH'], '/bitrix/modules/', 16) != 0
1326 );
1327 }
1328 }
1329
1330 if ($cssInfo['ADDITIONAL'])
1331 {
1332 $additional[] = $cssInfo;
1333 }
1334 else
1335 {
1336 $this->css[$cssInfo['TARGET']][] = $cssInfo;
1337 }
1338
1339 unset($this->css[$css]);
1340 }
1341
1342 foreach ($additional as $cssInfo)
1343 {
1344 $this->css[$cssInfo['TARGET']][] = $cssInfo;
1345 }
1346 }
1347
1354 private function prepareJs()
1355 {
1356 $additional = [];
1357 foreach ($this->js as $js => $set)
1358 {
1360 $assetTID = $set['ADDITIONAL'] ? 'TEMPLATE' : $set['TARGET'][0];
1361 $jsInfo = [
1362 'PATH' => $js,
1363 'FULL_PATH' => false,
1364 'FILE_PATH' => false,
1365 'SKIP' => false,
1366 'TARGET' => $assetTID,
1367 'EXTERNAL' => \CMain::IsExternalLink($js),
1368 'BODY' => false,
1369 'ADDITIONAL' => $set['ADDITIONAL']
1370 ];
1371
1372 if ($jsInfo['EXTERNAL'])
1373 {
1374 if ($set['ADDITIONAL'])
1375 {
1376 $tmpKey = 'TEMPLATE';
1377 $tmpPrefix = 'template';
1378 }
1379 else
1380 {
1381 $tmpKey = 'KERNEL';
1382 $tmpPrefix = 'kernel';
1383 }
1384
1385 $jsInfo['MODULE_ID'] = $this->assetJSCnt;
1386 $jsInfo['TARGET'] = $tmpKey.'_'.$this->assetJSCnt;
1387 $jsInfo['PREFIX'] = $tmpPrefix.'_'.$this->assetJSCnt;
1388 $jsInfo['FULL_PATH'] = $jsInfo['PATH'];
1389 $jsInfo['SKIP'] = true;
1390 $this->assetJSCnt++;
1391
1392 $this->targetList[$tmpKey]['JS_LIST'][$jsInfo['TARGET']] = [
1393 'TARGET' => $jsInfo['TARGET'],
1394 'PREFIX' => $jsInfo['PREFIX'],
1395 'MODE' => $this->targetList[$assetTID]['MODE'],
1396 'UNIQUE' => false,
1397 'WHERE_USED' => []
1398 ];
1399 }
1400 else
1401 {
1402 if (($paths = $this->getAssetPaths($js)) !== null)
1403 {
1404 $jsInfo["PATH"] = $js;
1405 $jsInfo["FILE_PATH"] = $paths["FILE_PATH"];
1406 $jsInfo["FULL_PATH"] = $paths["FULL_PATH"];
1407 }
1408 else
1409 {
1410 unset($this->js[$js]);
1411 continue;
1412 }
1413
1414 if ($moduleInfo = $this->isKernelJS($jsInfo['PATH']))
1415 {
1416 if ($this->sliceKernel() && $this->optimizeJs())
1417 {
1418 $jsInfo['MODULE_ID'] = $moduleInfo['MODULE_ID'];
1419 $jsInfo['TARGET'] = 'KERNEL_'.$moduleInfo['MODULE_ID'];
1420 $jsInfo['PREFIX'] = 'kernel_'.$moduleInfo['MODULE_ID'];
1421 $jsInfo['SKIP'] = $moduleInfo['SKIP'] ?? false;
1422 $jsInfo['BODY'] = $moduleInfo['BODY'];
1423 }
1424 else
1425 {
1426 $jsInfo['MODULE_ID'] = $this->assetJSCnt;
1427 $jsInfo['TARGET'] = 'KERNEL_'.$this->assetJSCnt;
1428 $jsInfo['PREFIX'] = 'kernel_'.$this->assetJSCnt;
1429 $jsInfo['SKIP'] = true;
1430 $this->assetJSCnt++;
1431 }
1432
1433 if ($jsInfo['BODY'])
1434 {
1435 $this->targetList['BODY']['JS_LIST'][$jsInfo['TARGET']] = [
1436 'TARGET' => $jsInfo['TARGET'],
1437 'PREFIX' => $jsInfo['PREFIX'],
1438 'MODE' => $this->targetList[$assetTID]['MODE'],
1439 'UNIQUE' => true,
1440 'WHERE_USED' => []
1441 ];
1442 }
1443 else
1444 {
1445 if (isset($this->targetList['KERNEL']['JS_LIST'][$jsInfo['TARGET']]['MODE']))
1446 {
1447 $this->targetList['KERNEL']['JS_LIST'][$jsInfo['TARGET']]['MODE'] |= $this->targetList[$assetTID]['MODE'];
1448 }
1449 else
1450 {
1451 $this->targetList['KERNEL']['JS_LIST'][$jsInfo['TARGET']] = [
1452 'TARGET' => $jsInfo['TARGET'],
1453 'PREFIX' => $jsInfo['PREFIX'],
1454 'MODE' => $set['ADDITIONAL'] ? $this->targetList[$set['TARGET'][0]]['MODE'] : $this->targetList[$assetTID]['MODE'],
1455 'UNIQUE' => true,
1456 'WHERE_USED' => []
1457 ];
1458 }
1459 }
1460
1461 // Add information about sets where used
1462 foreach ($set['TARGET'] as $setID)
1463 {
1464 $this->targetList['KERNEL']['JS_LIST'][$jsInfo['TARGET']]['WHERE_USED'][$setID] = true;
1465 }
1466 }
1467 elseif (strncmp($jsInfo['PATH'], '/bitrix/js/', 11) != 0)
1468 {
1469 $jsInfo['SKIP'] = !(
1470 strncmp($jsInfo['PATH'], '/bitrix/panel/', 14) != 0
1471 && strncmp($jsInfo['PATH'], '/bitrix/themes/', 15) != 0
1472 && strncmp($jsInfo['PATH'], '/bitrix/modules/', 16) != 0
1473 );
1474 }
1475 }
1476
1477 if ($jsInfo['ADDITIONAL'])
1478 {
1479 $additional[] = $jsInfo;
1480 }
1481 else
1482 {
1483 $this->js[$jsInfo['TARGET']][] = $jsInfo;
1484 }
1485 unset($this->js[$js]);
1486 }
1487
1488 // Clean body scripts
1489 foreach ($this->targetList['BODY']['JS_LIST'] as $item)
1490 {
1491 unset($this->targetList['KERNEL']['JS_LIST'][$item['TARGET']]);
1492 }
1493
1494 foreach ($additional as $jsInfo)
1495 {
1496 $this->js[$jsInfo['TARGET']][] = $jsInfo;
1497 }
1498 }
1499
1507 public function getCss($type = AssetShowTargetType::ALL)
1508 {
1509 $res = '';
1510 $additional = [];
1511 static $setList = [];
1512 static $ajaxList = [];
1513
1514 if (empty($setList))
1515 {
1516 $this->setTemplateID();
1517 $this->addTemplateCss();
1518 $this->prepareCss();
1519 $setList = $this->getTargetList();
1520 $optimizeCss = $this->optimizeCss();
1521
1522 foreach ($setList as $setInfo)
1523 {
1524 if (!isset($this->css[$setInfo['NAME']]))
1525 {
1526 continue;
1527 }
1528
1529 $data = '';
1530 if (!empty($this->moduleInfo['CSS'][$setInfo['MODULE_NAME']]['DATA']))
1531 {
1532 $data = $this->moduleInfo['CSS'][$setInfo['MODULE_NAME']]['DATA'];
1533 }
1534
1535 $location = '';
1536 if (!empty($this->moduleInfo['CSS'][$setInfo['MODULE_NAME']]['LOCATION']))
1537 {
1538 $location = $this->moduleInfo['CSS'][$setInfo['MODULE_NAME']]['LOCATION'];
1539 }
1540
1541 $resCss = '';
1542 $listAsset = [];
1543 $showLabel = ($setInfo['NAME'] == 'TEMPLATE');
1544
1545 foreach ($this->css[$setInfo['NAME']] as $cssFile)
1546 {
1547 $css = $cssFile['FULL_PATH'];
1548 if ($this->ajax)
1549 {
1550 $this->assetList['CSS'][] = $cssFile['PATH'];
1551 $ajaxList[] = $css;
1552 }
1553 elseif ($cssFile['EXTERNAL'])
1554 {
1555 $resCss .= $this->insertCss($css, $showLabel);
1556 $this->fileList['CSS'][$setInfo['NAME']]['FILES'][] = $css;
1557 }
1558 elseif ($optimizeCss)
1559 {
1560 if ($cssFile['SKIP'])
1561 {
1562 $resCss .= $this->insertCss($css, $showLabel);
1563 $this->fileList['CSS'][$setInfo['NAME']]['FILES'][] = $css;
1564 }
1565 else
1566 {
1567 $listAsset[] = $cssFile;
1568 }
1569 }
1570 else
1571 {
1572 $resCss .= $this->insertCss($css, $showLabel);
1573 $this->fileList['CSS'][$setInfo['NAME']]['FILES'][] = $css;
1574 }
1575 }
1576
1577 $optimizedAsset = $this->optimizeAsset($listAsset, $setInfo['UNIQUE'], $setInfo['PREFIX'], $setInfo['NAME'], 'css', $data);
1578
1579 $resCss = $optimizedAsset['RESULT'].$resCss;
1580 if ($location == AssetLocation::AFTER_CSS)
1581 {
1582 $additional[] = [
1583 'FILES' => $optimizedAsset['FILES'],
1584 'SOURCE_FILES' => $optimizedAsset['SOURCE_FILES'],
1585 'RES' => $resCss
1586 ];
1587 }
1588 else
1589 {
1590 $this->assetList['CSS'][$setInfo['PARENT_NAME']][$setInfo['NAME']] = $optimizedAsset['FILES'];
1591 $this->assetList['SOURCE_CSS'][$setInfo['PARENT_NAME']][$setInfo['NAME']] = ($optimizedAsset['SOURCE_FILES'] ?? []);
1592 $this->targetList[$setInfo['PARENT_NAME']]['CSS_RES'][$setInfo['NAME']][] = $resCss;
1593 }
1594 }
1595
1596 foreach ($additional as $bundle)
1597 {
1598 $templateFiles = $this->assetList['CSS']['TEMPLATE']['TEMPLATE'] ?? [];
1599
1600 $this->assetList['CSS']['TEMPLATE']['TEMPLATE'] = array_merge($templateFiles, $bundle['FILES']);
1601 $this->assetList['SOURCE_CSS']['TEMPLATE']['TEMPLATE'] = array_merge($templateFiles, $bundle['SOURCE_FILES']);
1602 $this->targetList['TEMPLATE']['CSS_RES']['TEMPLATE'][] = $bundle['RES'];
1603 }
1604
1605 unset($additional, $templateFiles, $bundle);
1606 }
1607
1608 if ($this->ajax && !empty($ajaxList))
1609 {
1610 $res .= '<script>'."BX.loadCSS(['".implode("','", $ajaxList)."']);".'</script>';
1611 }
1612
1613 if ($type == AssetShowTargetType::KERNEL)
1614 {
1615 $res .= $this->showAsset($setList, 'css', 'KERNEL');
1616 }
1617 elseif ($type == AssetShowTargetType::TEMPLATE_PAGE)
1618 {
1619 foreach ($this->targetList as $setName => $set)
1620 {
1621 if ($setName != 'TEMPLATE' && $setName != 'KERNEL')
1622 {
1623 $res .= $this->showAsset($setList, 'css', $setName);
1624 }
1625 }
1626
1627 $res .= $this->showAsset($setList, 'css', 'TEMPLATE');
1628 }
1629 else
1630 {
1631 foreach ($this->targetList as $setName => $set)
1632 {
1633 if ($setName != 'TEMPLATE')
1634 {
1635 $res .= $this->showAsset($setList, 'css', $setName);
1636 }
1637 }
1638
1639 $res .= $this->showAsset($setList, 'css', 'TEMPLATE');
1640 }
1641
1642 return $res;
1643 }
1644
1652 function getJs($type = AssetShowTargetType::ALL)
1653 {
1654 static $setList = [];
1655
1656 $res = '';
1657 $type = (int) $type;
1658 $type = (($type == AssetShowTargetType::KERNEL && $this->headString && !$this->headScript) ? AssetShowTargetType::ALL : $type);
1659 $optimize = $this->optimizeJs();
1660 if (empty($setList))
1661 {
1662 $this->prepareJs();
1663 $setList = $this->getTargetList('JS');
1664
1665 foreach ($setList as $setInfo)
1666 {
1667 if (!isset($this->js[$setInfo['NAME']]))
1668 {
1669 continue;
1670 }
1671
1672 $data = '';
1673 if (!empty($this->moduleInfo['JS'][$setInfo['MODULE_NAME']]['DATA']))
1674 {
1675 $data = $this->moduleInfo['JS'][$setInfo['MODULE_NAME']]['DATA'];
1676 }
1677
1678 $resJs = '';
1679 $listAsset = [];
1680 foreach ($this->js[$setInfo['NAME']] as $jsFile)
1681 {
1682 $js = $jsFile['FULL_PATH'];
1683 if ($optimize)
1684 {
1685 if ($jsFile['SKIP'])
1686 {
1687 $this->fileList['JS'][$setInfo['NAME']]['FILES'][] = $js;
1688 $resJs .= "<script src=\"{$js}\"></script>\n";
1689 }
1690 else
1691 {
1692 $listAsset[] = $jsFile;
1693 }
1694 }
1695 else
1696 {
1697 $this->fileList['JS'][$setInfo['NAME']]['FILES'][] = $js;
1698 $resJs .= "<script src=\"{$js}\"></script>\n";
1699 }
1700 }
1701 $optAsset = $this->optimizeAsset($listAsset, $setInfo['UNIQUE'], $setInfo['PREFIX'], $setInfo['NAME'], 'js', $data);
1702 $this->assetList['JS'][$setInfo['PARENT_NAME']][$setInfo['NAME']] = $optAsset['FILES'];
1703 $this->assetList['SOURCE_JS'][$setInfo['PARENT_NAME']][$setInfo['NAME']] = ($optAsset['SOURCE_FILES'] ?? []);
1704 $this->targetList[$setInfo['PARENT_NAME']]['JS_RES'][$setInfo['NAME']][] = $optAsset['RESULT'].$resJs;
1705 }
1706 unset($optAsset, $resJs, $listAsset);
1707 }
1708
1709 if ($type == AssetShowTargetType::KERNEL && ($this->mode & $this->targetList['KERNEL']['MODE']))
1710 {
1711 $setName = 'KERNEL';
1712 $res .= $this->getStrings(AssetLocation::AFTER_CSS);
1713 $res .= $this->showAsset($setList,'js', $setName);
1714 $res .= $this->showFilesList();
1715 $res .= $this->getStrings(AssetLocation::AFTER_JS_KERNEL);
1716
1717 if (!$this->bodyScript)
1718 {
1719 $res .= $this->getStrings(AssetLocation::BODY_END);
1720 $res .= $this->showAsset($setList,'js', 'BODY');
1721 }
1722 }
1723 elseif ($type == AssetShowTargetType::TEMPLATE_PAGE)
1724 {
1725 foreach ($this->targetList as $setName => $set)
1726 {
1727 if ($setName != 'KERNEL' && $setName != 'BODY')
1728 {
1729 $setName = $this->fixJsSetOrder($setName);
1730 $res .= $this->showAsset($setList,'js', $setName);
1731 }
1732 }
1733 $res .= $this->getStrings(AssetLocation::AFTER_JS);
1734 }
1735 elseif ($type == AssetShowTargetType::BODY && ($this->mode & $this->targetList['BODY']['MODE']))
1736 {
1737 $setName = 'BODY';
1738 $res .= $this->getStrings(AssetLocation::BODY_END);
1739 $res .= $this->showAsset($setList,'js', $setName);
1740 }
1741 else
1742 {
1743 foreach ($this->targetList as $setName => $set)
1744 {
1745 if ($this->mode & $set['MODE'])
1746 {
1747 $setName = $this->fixJsSetOrder($setName);
1748 if ($setName == 'KERNEL')
1749 {
1750 $res .= $this->getStrings(AssetLocation::AFTER_CSS);
1751 $res .= $this->showAsset($setList, 'js', $setName);
1752 $res .= $this->showFilesList();
1753 $res .= $this->getStrings(AssetLocation::AFTER_JS_KERNEL);
1754
1755 if (!$this->bodyScript)
1756 {
1757 $res .= $this->getStrings(AssetLocation::BODY_END);
1758 $res .= $this->showAsset($setList,'js', 'BODY');
1759 }
1760 }
1761 elseif ($setName != 'BODY')
1762 {
1763 $res .= $this->showAsset($setList, 'js', $setName);
1764 }
1765 }
1766 }
1767
1768 $res .= $this->getStrings(AssetLocation::AFTER_JS);
1769 }
1770
1771 return (trim($res) == '' ? $res : $res."\n");
1772 }
1773
1779 public static function getLocationByName($location)
1780 {
1781 if ($location === false || $location === 'DEFAULT')
1782 {
1783 $location = AssetLocation::AFTER_JS_KERNEL;
1784 }
1785 elseif ($location === true)
1786 {
1787 $location = AssetLocation::AFTER_CSS;
1788 }
1789
1790 return $location;
1791 }
1792
1797 public function showFilesList()
1798 {
1799 $res = '';
1800 if (!\CJSCore::IsCoreLoaded())
1801 {
1802 return $res;
1803 }
1804
1805 if (!empty($this->assetList['JS']))
1806 {
1807 $assets = [];
1808 foreach ($this->getTargetList('JS') as $set)
1809 {
1810 if ($this->mode & $set['MODE']
1811 && isset($this->assetList['SOURCE_JS'][$set['PARENT_NAME']][$set['NAME']])
1812 && is_array($this->assetList['SOURCE_JS'][$set['PARENT_NAME']][$set['NAME']]))
1813 {
1814 $assets = array_merge($assets, $this->assetList['SOURCE_JS'][$set['PARENT_NAME']][$set['NAME']]);
1815 }
1816 }
1817
1818 if (!empty($assets))
1819 {
1820 $res .= '<script>BX.setJSList(' . Json::encode($assets) . ');</script>';
1821 $res .= "\n";
1822 }
1823 }
1824
1825 if (!empty($this->assetList['CSS']))
1826 {
1827 $assets = [];
1828 foreach ($this->getTargetList('CSS') as $set)
1829 {
1830 if ($this->mode & $set['MODE']
1831 && isset($this->assetList['SOURCE_CSS'][$set['PARENT_NAME']][$set['NAME']])
1832 && is_array($this->assetList['SOURCE_CSS'][$set['PARENT_NAME']][$set['NAME']])
1833 )
1834 {
1835 $assets = array_merge($assets, $this->assetList['SOURCE_CSS'][$set['PARENT_NAME']][$set['NAME']]);
1836 }
1837 }
1838
1839 if (!empty($assets))
1840 {
1841 $res .= '<script>BX.setCSSList(' . Json::encode($assets) . ');</script>';
1842 $res .= "\n";
1843 }
1844 }
1845 return $res;
1846 }
1847
1855 function addCssKernelInfo($module = '', $css = [], $settings = [])
1856 {
1857 if (empty($module) || empty($css))
1858 {
1859 return;
1860 }
1861
1862 if (!array_key_exists($module, $this->moduleInfo['CSS']))
1863 {
1864 $this->moduleInfo['CSS'][$module] = [
1865 'MODULE_ID' => $module,
1866 'BODY' => false,
1867 'FILES_INFO' => true,
1868 'IS_KERNEL' => true,
1869 'DATA' => '',
1870 'SKIP' => false
1871 ];
1872 }
1873
1874 foreach ($css as $key)
1875 {
1876 $key = self::getAssetPath($key);
1877 $this->kernelAsset['CSS'][$key] = $module;
1878 }
1879
1880 $this->moduleInfo['CSS'][$module]['FILES_INFO'] = true;
1881 if (!empty($settings['DATA']))
1882 {
1883 $this->moduleInfo['CSS'][$module]['DATA'] = $settings['DATA'];
1884 }
1885
1886 if (!empty($settings['LOCATION']))
1887 {
1888 $this->moduleInfo['CSS'][$module]['LOCATION'] = $settings['LOCATION'];
1889 }
1890 }
1891
1899 function addJsKernelInfo($module = '', $js = [], $settings = [])
1900 {
1901 if (empty($module) || empty($js))
1902 {
1903 return;
1904 }
1905
1906 if (!array_key_exists($module, $this->moduleInfo['JS']))
1907 {
1908 $this->moduleInfo['JS'][$module] = [
1909 'MODULE_ID' => $module,
1910 'BODY' => false,
1911 'FILES_INFO' => true,
1912 'IS_KERNEL' => true,
1913 'DATA' => '',
1914 'SKIP' => false
1915 ];
1916 }
1917
1918 foreach ($js as $key)
1919 {
1920 $key = self::getAssetPath($key);
1921 $this->kernelAsset['JS'][$key] = $module;
1922 }
1923
1924 $this->moduleInfo['JS'][$module]['FILES_INFO'] = true;
1925 if (!empty($settings['DATA']))
1926 {
1927 $this->moduleInfo['JS'][$module]['DATA'] = $settings['DATA'];
1928 }
1929 }
1930
1936 function isKernelCSS($css)
1937 {
1939 if (!($this->sliceKernel() && $this->optimizeCss()))
1940 {
1941 return ((strncmp($css, '/bitrix/js/', 11) == 0) || (strncmp($css, '/bitrix/css/', 12) == 0));
1942 }
1943
1945 if (array_key_exists($css, $this->kernelAsset['CSS']))
1946 {
1947 return $this->moduleInfo['CSS'][$this->kernelAsset['CSS'][$css]];
1948 }
1949 elseif ((strncmp($css, '/bitrix/js/', 11) == 0) || (strncmp($css, '/bitrix/css/', 12) == 0))
1950 {
1951 $tmp = explode('/', $css);
1952 $moduleID = $tmp['3'];
1953 unset($tmp);
1954
1955 if (empty($moduleID))
1956 {
1957 return false;
1958 }
1959
1960 return [
1961 'MODULE_ID' => $moduleID.'_'.$this->assetCSSCnt++,
1962 'BODY' => false,
1963 'FILES_INFO' => false,
1964 'IS_KERNEL' => true,
1965 'DATA' => '',
1966 'SKIP' => true
1967 ];
1968 }
1969
1970 return false;
1971 }
1972
1978 function isKernelJS($js)
1979 {
1981 if (!($this->sliceKernel() && $this->optimizeJs()))
1982 {
1983 return (strncmp($js, '/bitrix/js/', 11) == 0);
1984 }
1985
1987 if (array_key_exists($js, $this->kernelAsset['JS']))
1988 {
1989 return $this->moduleInfo['JS'][$this->kernelAsset['JS'][$js]];
1990 }
1991 elseif (strncmp($js, '/bitrix/js/', 11) == 0)
1992 {
1993 $tmp = explode('/', $js);
1994 $moduleID = $tmp['3'];
1995 unset($tmp);
1996
1997 if (empty($moduleID))
1998 {
1999 return false;
2000 }
2001
2002 return [
2003 'MODULE_ID' => $moduleID.'_'.$this->assetJSCnt++,
2004 'BODY' => false,
2005 'FILES_INFO' => false,
2006 'IS_KERNEL' => true,
2007 'DATA' => '',
2008 'SKIP' => true
2009 ];
2010 }
2011
2012 return false;
2013 }
2014
2021 public function setUnique($setID = '', $uniqueID = '')
2022 {
2023 $setID = preg_replace('#[^a-z0-9_]#i', '', $setID);
2024 $uniqueID = preg_replace('#[^a-z0-9_]#i', '', $uniqueID);
2025 if (!(empty($setID) || empty($uniqueID)) && isset($this->targetList[$setID]))
2026 {
2027 $this->targetList[$setID]['UNIQUE'] = true;
2028 $this->targetList[$setID]['PREFIX'] .= ($uniqueID == '' ? '' : '_'.$uniqueID);
2029 return true;
2030 }
2031 return false;
2032 }
2033
2041 private function showAsset($setList = [], $type = 'css', $setName = '')
2042 {
2043 $res = '';
2044 $type = ($type == 'css' ? 'CSS_RES' : 'JS_RES');
2045 $skipCheck = ($setName == '');
2046
2047 foreach ($setList as $setInfo)
2048 {
2049 if (
2050 ($skipCheck || $setName == $setInfo['PARENT_NAME'])
2051 && $this->mode & $setInfo['MODE']
2052 && isset($this->targetList[$setInfo['PARENT_NAME']][$type][$setInfo['NAME']]))
2053 {
2054 $res .= implode("\n", $this->targetList[$setInfo['PARENT_NAME']][$type][$setInfo['NAME']]);
2055 }
2056 }
2057
2058 return $res;
2059 }
2060
2066 private function fixJsSetOrder($setName = '')
2067 {
2068 if ($setName == 'PAGE')
2069 {
2070 $setName = 'TEMPLATE';
2071 }
2072 elseif ($setName == 'TEMPLATE')
2073 {
2074 $setName = 'PAGE';
2075 }
2076
2077 return $setName;
2078 }
2079
2085 public static function getAssetTime($file = '')
2086 {
2087 $qpos = mb_strpos($file, '?');
2088 if ($qpos === false)
2089 {
2090 return false;
2091 }
2092 $qpos++;
2093
2094 return mb_substr($file, $qpos);
2095 }
2096
2102 private function getAssetChecksum($assetList = [])
2103 {
2104 $result = [];
2105 foreach ($assetList as $asset)
2106 {
2107 $result[$asset['PATH']] = $asset['FULL_PATH'];
2108 }
2109 ksort($result);
2110
2111 return md5(implode('_', $result));
2112 }
2113
2122 private function isAssetChanged($assetList = [], $infoFile = '', $optimFile = '', $unique = false)
2123 {
2124 $result = [
2125 'FILE' => [],
2126 'ACTION' => 'NO',
2127 'FILE_EXIST' => false,
2128 'FILES_INFO' => []
2129 ];
2130
2131 if (file_exists($infoFile) && file_exists($optimFile))
2132 {
2134 include($infoFile);
2135
2137 $result['FILES_INFO'] = is_array($filesInfo) ? $filesInfo : [];
2138 $result['FILE_EXIST'] = true;
2139 if ($unique)
2140 {
2141 if (is_array($filesInfo))
2142 {
2143 foreach ($assetList as $asset)
2144 {
2145 if (isset($filesInfo[$asset['PATH']]))
2146 {
2147 if ($this->getAssetTime($asset['FULL_PATH']) != $filesInfo[$asset['PATH']])
2148 {
2149 $result = [
2150 'FILE' => $assetList,
2151 'ACTION' => 'NEW',
2152 'FILES_INFO' => []
2153 ];
2154 break;
2155 }
2156 }
2157 else
2158 {
2159 $result['FILE'][] = $asset;
2160 $result['ACTION'] = 'UP';
2161 }
2162 }
2163 }
2164 else
2165 {
2166 $result = [
2167 'FILE' => $assetList,
2168 'ACTION' => 'NEW',
2169 'FILES_INFO' => []
2170 ];
2171 }
2172 }
2173 }
2174 else
2175 {
2176 $result['FILE'] = $assetList;
2177 $result['ACTION'] = 'NEW';
2178 }
2179
2180 return $result;
2181 }
2182
2194 private function optimizeAsset($files = [], $unique = false, $prefix = 'default', $setName = '', $type = 'css', $data = '')
2195 {
2196 if ((!is_array($files) || empty($files)))
2197 {
2198 return ['RESULT' => '', 'FILES' => []];
2199 }
2200
2201 $this->setTemplateID();
2202 $res = $comments = $contents = '';
2203 $prefix = trim($prefix);
2204 $prefix = mb_strlen($prefix) < 1 ? 'default' : $prefix;
2205 $add2End = (strncmp($prefix, 'kernel', 6) == 0);
2206 $type = ($type == 'js' ? 'js' : 'css');
2207
2208 // when we can't write files
2209 $noCheckOnly = !defined('BX_HEADFILES_CACHE_CHECK_ONLY');
2210 $prefix = ($unique ? $prefix : $prefix.'_'.$this->getAssetChecksum($files));
2211
2212 $optimPath = BX_PERSONAL_ROOT.'/cache/'.$type.'/'.SITE_ID.'/'.$this->siteTemplateID.'/'.$prefix.'/';
2213
2214 $infoFile = $this->documentRoot.BX_PERSONAL_ROOT.'/managed_cache/'.$this->dbType.'/'.$type.'/'.SITE_ID.'/'.$this->siteTemplateID.'/'.$prefix.'/info_v'.self::version.'.php';
2215
2216 $optimFile = $optimPath.$prefix.'_v'.self::version.($type == 'css' ? '.css' : '.js');
2217 $optimFName = $this->documentRoot.$optimFile;
2218
2219 $tmpInfo = $this->isAssetChanged($files, $infoFile, $optimFName, $unique);
2220 $filesInfo = $tmpInfo['FILES_INFO'];
2221 $action = $tmpInfo['ACTION'];
2222 $files = $tmpInfo['FILE'];
2223 $optimFileExist = $tmpInfo['FILE_EXIST'] ?? false;
2224
2225 $writeResult = ($action != 'NEW');
2226 $currentFileList = &$this->fileList[strtoupper($type)][$setName];
2227
2228 if ($action != 'NO')
2229 {
2230 foreach ($tmpInfo['FILE'] as $newFile)
2231 {
2232 $currentFileList['UP_NEW_FILES'][] = $newFile['FULL_PATH'];
2233 }
2234
2235 if ($action == 'UP')
2236 {
2237 if ($noCheckOnly)
2238 {
2239 $contents .= file_get_contents($optimFName);
2240 }
2241 else
2242 {
2243 $writeResult = false;
2244 }
2245 }
2246
2247 $needWrite = false;
2248 if ($noCheckOnly)
2249 {
2250 $newContent = '';
2251 $mapNeeded = false;
2252 foreach ($files as $file)
2253 {
2254 $assetContent = file_get_contents($file['FILE_PATH']);
2255 if ($type == 'css')
2256 {
2257 $comments .= "/* ".$file['FULL_PATH']." */\n";
2258 $assetContent = $this->fixCSSIncludes($assetContent, $file['PATH']);
2259 $assetContent = "\n/* Start:".$file['FULL_PATH']."*/\n".$assetContent."\n/* End */\n";
2260 $newContent .= "\n".$assetContent;
2261 }
2262 else
2263 {
2264 $info = [
2265 "full" => $file['FULL_PATH'],
2266 "source" => $file['PATH'],
2267 "min" => "",
2268 "map" => "",
2269 ];
2270
2271 if (preg_match("/\\.min\\.js$/i", $file['FILE_PATH']))
2272 {
2273 $sourceMap = self::cutSourceMap($assetContent);
2274 if ($sourceMap <> '')
2275 {
2276 $dirPath = IO\Path::getDirectory($file['PATH']);
2277 $info["map"] = $dirPath."/".$sourceMap;
2278 $info["min"] = self::getAssetPath($file['FULL_PATH']);
2279 $mapNeeded = true;
2280 }
2281 }
2282
2283 $comments .= "; /* ".$file['FULL_PATH']."*/\n";
2284 $newContent .= "\n".self::HEADER_START_TAG.serialize($info).self::HEADER_END_TAG."\n".$assetContent."\n/* End */\n;";
2285 }
2286
2287 $filesInfo[$file['PATH']] = $this->getAssetTime($file['FULL_PATH']);
2288 $needWrite = true;
2289 }
2290
2291 if ($needWrite)
2292 {
2293 $sourceMap = self::cutSourceMap($contents);
2294 $mapNeeded = $mapNeeded || $sourceMap <> '';
2295
2296 // Write packed files and meta information
2297 $contents = ($add2End ? $comments.$contents.$newContent : $newContent.$contents.$comments);
2298 if ($mapNeeded)
2299 {
2300 $contents .= self::SOURCE_MAP_TAG.$prefix.".map.js";
2301 }
2302
2303 if ($writeResult = $this->write($optimFName, $contents))
2304 {
2305 $cacheInfo = '<?php $filesInfo = [';
2306
2307 foreach ($filesInfo as $key => $hash)
2308 {
2309 $cacheInfo .= '"'.EscapePHPString($key).'" => "'.$hash.'",';
2310 }
2311
2312 $cacheInfo .= "]; ?>";
2313 $this->write($infoFile, $cacheInfo, false);
2314
2315 if ($mapNeeded)
2316 {
2317 $this->write($this->documentRoot.$optimPath.$prefix.".map.js", self::generateSourceMap($prefix.".js", $contents), false);
2318 }
2319 }
2320 }
2321 elseif ($optimFileExist)
2322 {
2323 $writeResult = true;
2324 }
2325 unset($contents);
2326 }
2327 }
2328
2329 $label = (($type == 'css') && ($prefix == 'template' || str_starts_with($prefix, 'template_')) ? ' data-template-style="true" ' : '');
2330
2331 $bundleFile = '';
2332 $extendData = ($data != '' ? ' '.trim($data) : '');
2333 $extendData .= ($label != '' ? ' '.trim($label) : '');
2334
2335 if ($writeResult || $unique && $action == 'UP')
2336 {
2337 $bundleFile = \CUtil::GetAdditionalFileURL($optimFile);
2338 $currentFileList['FILES'][] = $bundleFile;
2339
2340 if ($type == 'css')
2341 {
2342 $res .= $this->insertCss($bundleFile, $extendData);
2343 }
2344 else
2345 {
2346 $res .= $this->insertJs($bundleFile, $extendData);
2347 }
2348 }
2349
2350 if (!$writeResult)
2351 {
2352 foreach ($files as $file)
2353 {
2354 $currentFileList['FILES'][] = $file['FULL_PATH'];
2355 if ($type == 'css')
2356 {
2357 $res .= $this->insertCss($file['FULL_PATH'], $extendData);
2358 }
2359 else
2360 {
2361 $res .= $this->insertJs($file['FULL_PATH'], $extendData);
2362 }
2363 }
2364 }
2365
2366 $resultFiles = [];
2367 if (is_array($filesInfo))
2368 {
2369 foreach ($filesInfo as $key => $hash)
2370 {
2371 $resultFiles[] = $key.'?'.$hash;
2372
2373 }
2374 }
2375
2376 unset($files);
2377
2378 if ($bundleFile != '')
2379 {
2380 $currentFileList['FULL_FILES'][$bundleFile] = $resultFiles;
2381 }
2382 return ['RESULT' => $res, 'FILES' => $resultFiles, 'SOURCE_FILES' => array_keys($filesInfo)];
2383 }
2384
2390 private static function cutSourceMap(&$content)
2391 {
2392 $sourceMapName = "";
2393
2394 $length = strlen($content);
2395 $position = $length > 512 ? $length - 512 : 0;
2396 $lastLine = strpos($content, self::SOURCE_MAP_TAG, $position);
2397 if ($lastLine !== false)
2398 {
2399 $nameStart = $lastLine + strlen(self::SOURCE_MAP_TAG);
2400 if (($newLinePos = strpos($content, "\n", $nameStart)) !== false)
2401 {
2402 $sourceMapName = substr($content, $nameStart, $newLinePos - $nameStart);
2403 }
2404 else
2405 {
2406 $sourceMapName = substr($content, $nameStart);
2407 }
2408
2409 $sourceMapName = trim($sourceMapName);
2410 $content = substr($content, 0, $lastLine);
2411 }
2412
2413 return $sourceMapName;
2414 }
2415
2421 private static function getFilesInfo($content)
2422 {
2423 $offset = 0;
2424 $line = 0;
2425
2426 $result = [];
2427 while (($newLinePos = strpos($content, "\n", $offset)) !== false)
2428 {
2429 $line++;
2430 $offset = $newLinePos + 1;
2431 if (substr($content, $offset, strlen(self::HEADER_START_TAG)) === self::HEADER_START_TAG)
2432 {
2433 $endingPos = strpos($content, self::HEADER_END_TAG, $offset);
2434 if ($endingPos === false)
2435 {
2436 break;
2437 }
2438
2439 $startData = $offset + strlen(self::HEADER_START_TAG);
2440 $data = unserialize(substr($content, $startData, $endingPos - $startData), ['allowed_classes' => false]);
2441
2442 if (is_array($data))
2443 {
2444 $data["line"] = $line + 1;
2445 $result[] = $data;
2446 }
2447
2448 $offset = $endingPos;
2449 }
2450 }
2451
2452 return $result;
2453 }
2454
2461 private static function generateSourceMap($fileName, $content)
2462 {
2463 $files = self::getFilesInfo($content);
2464 $sections = "";
2465 foreach ($files as $file)
2466 {
2467 if (!isset($file["map"]) || mb_strlen($file["map"]) < 1)
2468 {
2469 continue;
2470 }
2471
2472 $filePath = Main\Loader::getDocumentRoot().$file["map"];
2473 if (file_exists($filePath) && ($content = file_get_contents($filePath)) !== false)
2474 {
2475 if ($sections !== "")
2476 {
2477 $sections .= ",";
2478 }
2479
2480 $dirPath = IO\Path::getDirectory($file["source"]);
2481 $sourceName = IO\Path::getName($file["source"]);
2482 $minName = IO\Path::getName($file["min"]);
2483
2484 $sourceMap = str_replace(
2485 [$sourceName, $minName],
2486 [$dirPath."/".$sourceName, $dirPath."/".$minName],
2487 $content
2488 );
2489 $sections .= '{"offset": { "line": '.$file["line"].', "column": 0 }, "map": '.$sourceMap.'}';
2490 }
2491 }
2492
2493 return '{"version":3, "file":"'.$fileName.'", "sections": ['.$sections.']}';
2494 }
2495
2503 function write($filePath, $content, $gzip = true)
2504 {
2505 $fnTmp = $filePath.'.tmp';
2506
2507 if (!CheckDirPath($filePath) || !$fh = fopen($fnTmp, "wb"))
2508 {
2509 return false;
2510 }
2511
2512 $written = fwrite($fh, $content);
2513 $len = strlen($content);
2514 fclose($fh);
2515
2516 if (file_exists($filePath))
2517 {
2518 @unlink($filePath);
2519 }
2520
2521 $result = false;
2522 if ($written === $len)
2523 {
2524 $result = true;
2525 rename($fnTmp, $filePath);
2526 @chmod($filePath, BX_FILE_PERMISSIONS);
2527 if ($gzip && self::gzipEnabled())
2528 {
2529 $fnTmpGz = $filePath.'.tmp.gz';
2530 $fnGz = $filePath.'.gz';
2531
2532 if ($gz = gzopen($fnTmpGz, 'wb9f'))
2533 {
2534 $writtenGz = @gzwrite ($gz, $content);
2535 gzclose($gz);
2536
2537 if (file_exists($fnGz))
2538 {
2539 @unlink($fnGz);
2540 }
2541
2542 if ($writtenGz === $len)
2543 {
2544 rename($fnTmpGz, $fnGz);
2545 @chmod($fnGz, BX_FILE_PERMISSIONS);
2546 }
2547
2548 if (file_exists($fnTmpGz))
2549 {
2550 @unlink($fnTmpGz);
2551 }
2552 }
2553 }
2554 }
2555
2556 if (file_exists($fnTmp))
2557 {
2558 @unlink($fnTmp);
2559 }
2560
2561 return $result;
2562 }
2563}
$path
Определения access_edit.php:21
$hash
Определения ajax_redirector.php:8
$type
Определения options.php:106
xml version
Определения yandex.php:67
static IsCoreLoaded()
Определения jscore.php:199
$moduleID
Определения options.php:7
$str
Определения commerceml2.php:63
$contents
Определения commerceml2.php:57
$content
Определения commerceml.php:144
if(!is_array($prop["VALUES"])) $tmp
Определения component_props.php:203
$data['IS_AVAILABLE']
Определения .description.php:13
if(errorBox) return true
Определения file_new.php:1035
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$p
Определения group_list_element_edit.php:23
$dbType
Определения autoload.php:6
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
if($NS['step']==6) if( $NS[ 'step']==7) if(COption::GetOptionInt('main', 'disk_space', 0) > 0) $info
Определения backup.php:924
CheckDirPath($path)
Определения tools.php:2707
__construct(?int $storeId, int $productId, string $barcode, int $userId)
Определения basestorebarcodeaction.php:38
$value
Определения Param.php:39
$files
Определения mysql_to_pgsql.php:30
$settings
Определения product_settings.php:43
return false
Определения prolog_main_admin.php:185
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$instance
Определения ps_b24_final.php:14
$fileName
Определения quickway.php:305
if(empty($signedUserToken)) $key
Определения quickway.php:257
const ADMIN_SECTION
Определения rss.php:2
$items
Определения template.php:224
$paths
Определения options.php:2080
$val
Определения options.php:1793
$location
Определения options.php:2729
$matches
Определения index.php:22
const SITE_ID
Определения sonet_set_content_view.php:12
$action
Определения file_dialog.php:21
$url
Определения iframe.php:7