48 private const SECTION_LAST =
'last';
53 private const TYPE_STORE =
'STORE';
58 private const SITE_TYPE_DEFAULT =
'PAGE';
63 private const BLOCKS_TAG =
'landing_blocks';
74 private const AVAILABLE_FILTERS = [
75 self::FILTER_SKIP_COMMON_BLOCKS,
76 self::FILTER_SKIP_SYSTEM_BLOCKS,
77 self::FILTER_SKIP_HIDDEN_BLOCKS,
79 private const DEFAULT_ACTIVE_FILTERS = [
80 self::FILTER_SKIP_SYSTEM_BLOCKS,
81 self::FILTER_SKIP_HIDDEN_BLOCKS,
85 private array $filters = self::DEFAULT_ACTIVE_FILTERS;
91 private array $repository = [];
93 private ?
string $siteType;
97 if (Type::getCurrentScopeId())
99 $this->siteType = Type::getCurrentScopeId();
103 $this->
setSiteType(Landing::getSiteType() ?: self::SITE_TYPE_DEFAULT);
106 $this->sendSetFiltersEvent();
116 $this->siteType =
$type;
117 if (!in_array($this->siteType, array_keys(Site::getTypes())))
119 $this->siteType = self::SITE_TYPE_DEFAULT;
127 private function sendSetFiltersEvent(): void
129 $event =
new Event(
'landing',
'onBlockRepoSetFilters');
137 if (
$result->getType() !== EventResult::ERROR)
139 $modified =
$result->getModified();
141 $enable = array_merge($enable, (
array)($modified[
'ENABLE'] ?? []));
142 $disable = array_merge($disable, (
array)($modified[
'DISABLE'] ?? []));
146 foreach (array_unique($enable) as
$filter)
150 foreach (array_unique($disable) as
$filter)
163 if (
$filter === self::FILTER_DEFAULTS)
165 $this->filters = self::DEFAULT_ACTIVE_FILTERS;
170 $this->filters = array_unique($this->filters);
183 if (in_array(
$filter, self::AVAILABLE_FILTERS))
185 $this->filters = array_filter(
187 function ($currentFilter) use (
$filter) {
188 return $currentFilter !==
$filter;
203 return in_array(
$filter, $this->filters);
214 foreach ($repo as $sectionCode => $category)
216 if ($sectionCode === self::SECTION_LAST)
221 $blocks = array_keys(($category[
'items'] ?? []));
222 if (in_array(
$code, $blocks,
true))
238 if (!empty($this->repository))
240 return $this->getPreparedRepository();
243 return $this->loadRepositoryData()->getPreparedRepository();
246 private function loadRepositoryData(): static
250 $enableNamespace =
Config::get(
'enable_namespace');
251 $enableNamespace = $enableNamespace ? (
array)$enableNamespace : [];
254 $cache = new \CPHPCache();
256 $cacheStarted =
false;
257 $cacheId = LANGUAGE_ID;
259 $cacheId .=
'version:2';
260 $cacheId .=
'disable:' . implode(
',', $disableNamespace);
261 $cacheId .=
'enable:' . implode(
',', $enableNamespace);
262 $cacheId .=
'specType:' . ($this->siteType ??
'');
263 $cachePath =
'landing/blocks';
264 if ($cache->initCache($cacheTime, $cacheId, $cachePath))
266 $this->repository = $cache->getVars();
267 if (is_array($this->repository) && !empty($this->repository))
269 return $this->fillLastUsedBlocks();
272 if ($cache->startDataCache($cacheTime, $cacheId, $cachePath))
274 $cacheStarted =
true;
292 foreach ($namespaces as $subdir)
298 is_dir(
$path .
'/' . $subdir)
303 $sectionsPath =
$path .
'/' . $subdir .
'/.sections.php';
304 if (file_exists($sectionsPath))
306 $sections = array_merge(
308 (
array)include $sectionsPath
311 if (!isset($sections[self::SECTION_LAST]))
313 $sections[self::SECTION_LAST] = [
314 'name' => Loc::getMessage(
'LD_BLOCK_SECTION_LAST'),
318 while ((($entry = readdir(
$handle)) !==
false))
320 $descriptionPath =
$path .
'/' . $subdir .
'/' . $entry .
'/.description.php';
321 $previewPathJpg =
$path .
'/' . $subdir .
'/' . $entry .
'/' . Block::PREVIEW_FILE_NAME;
322 if ($entry !==
'.' && $entry !==
'..' && file_exists($descriptionPath))
324 Loc::loadLanguageFile($descriptionPath);
330 self::BLOCKS_DIR .
'/' . $subdir .
'/' . $entry .
'/' . Block::PREVIEW_FILE_NAME
338 'namespace' => $subdir,
342 'section' =>
$description[
'block'][
'section'] ??
'other',
344 'description' =>
$description[
'block'][
'description'] ??
'',
345 'preview' => file_exists($previewPathJpg)
348 'restricted' =>
false,
351 'only_for_license' =>
$description[
'block'][
'only_for_license'] ??
'',
364 foreach ($blocksRepo as $block)
366 if ($block[
'app_code'])
368 $apps[] = $block[
'app_code'];
373 $apps = array_unique($apps);
376 foreach ($blocksRepo as &$block)
380 && isset($apps[$block[
'app_code']])
381 && $apps[$block[
'app_code']][
'PAYMENT_ALLOW'] ==
'N'
384 $block[
'app_expired'] =
true;
389 $blocks += $blocksRepo;
393 $favoriteBlocks = [];
394 $favoriteMyBlocks = [];
395 $res = Internals\BlockTable::getList([
397 'ID',
'CODE',
'FAVORITE_META',
'CREATED_BY_ID',
406 'limit' => self::FAVOURITE_BLOCKS_LIMIT,
408 $countFavoriteBlocks = 0;
409 while ($row =
$res->fetch())
411 $countFavoriteBlocks++;
412 if (isset($blocks[$row[
'CODE']]))
414 if (!is_array($row[
'FAVORITE_META']))
418 $meta = $row[
'FAVORITE_META'];
419 $meta[
'preview'] = $meta[
'preview'] ?? 0;
420 $meta[
'favorite'] =
true;
421 $meta[
'favoriteMy'] = ((int)$row[
'CREATED_BY_ID'] === $currentUser);
422 if ($meta[
'preview'] > 0 && $countFavoriteBlocks < self::FAVOURITE_BLOCKS_LIMIT_WITH_PREVIEW)
428 unset($meta[
'preview']);
430 if (isset($meta[
'section']))
432 $meta[
'section'] = (
array)$meta[
'section'];
436 $blocks[$row[
'CODE']],
439 $code = $row[
'CODE'] .
'@' . $row[
'ID'];
440 if ($item[
'type'] ===
'null')
446 ? ($favoriteMyBlocks[
$code] = $item)
447 : ($favoriteBlocks[
$code] = $item);
450 $blocks = $favoriteMyBlocks + $blocks + $favoriteBlocks;
453 $createNewSection =
function ($item)
457 'name' => isset($item[
'name'])
458 ? (string)$item[
'name']
460 'meta' => $item[
'meta'] ?? [],
462 'type' => $item[
'type'] ?? null,
463 'specialType' => $item[
'specialType'] ?? null,
464 'separator' =>
false,
472 foreach ($sections as
$code => $item)
474 $title = $item[
'name'] ?? $item;
477 $this->repository[
$code] = $createNewSection($item);
480 foreach ($blocks as
$key => $block)
482 if (!is_array($block[
'section']))
484 $block[
'section'] = [$block[
'section']];
486 foreach ($block[
'section'] as $section)
488 $section = trim($section);
495 if (!isset($this->repository[$section]))
497 if (isset($createdSects[$section]))
499 $section = $createdSects[$section];
503 $this->repository[$section] = $createNewSection($section);
506 $this->repository[$section][
'items'][
$key] = $block;
509 $this->repository[$section][
'new'] =
true;
515 if (!empty($blocksRepo) && !empty($apps))
517 $this->repository[
'separator_apps'] = [
518 'name' => Loc::getMessage(
'LANDING_BLOCK_SEPARATOR_PARTNER_2_MSGVER_1'),
522 foreach ($apps as
$app)
524 $this->repository[
$app[
'CODE']] = [
525 'name' =>
$app[
'APP_NAME'],
527 'separator' =>
false,
528 'app_code' =>
$app[
'CODE'],
533 foreach ($blocksRepo as
$key => $block)
535 if ($block[
'app_code'])
537 $this->repository[$block[
'app_code']][
'items'][
$key] = $block;
543 foreach ($this->repository as $codeCat => &$blocksCat)
545 $codeCat = mb_strtoupper($codeCat);
546 uasort($blocksCat[
'items'],
function ($item1, $item2) use ($codeCat)
548 if ($item1[
'repo_id'])
552 if ($item2[
'repo_id'])
557 ($item1[
'id'] && $item2[
'id'])
558 && mb_strpos($item1[
'id'],
'BX_' . $codeCat .
'_') === 0
559 && mb_strpos($item2[
'id'],
'BX_' . $codeCat .
'_') === 0
562 return ($item1[
'id'] > $item2[
'id']) ? 1 : -1;
573 $cache->endDataCache($this->repository);
580 return $this->fillLastUsedBlocks();
583 private function fillLastUsedBlocks(): static
585 $request = Application::getInstance()->getContext()->getRequest();
586 if (
$request->get(
'landing_mode') !==
'edit')
591 static $lastUsedItems =
null;
592 if ($lastUsedItems !==
null)
594 $this->repository[self::SECTION_LAST][
'items'] = $lastUsedItems;
599 $this->repository[self::SECTION_LAST][
'items'] = [];
600 $lastUsed = Block::getLastUsed();
601 if (
count($lastUsed) > 0)
603 foreach ($lastUsed as
$code)
605 $this->repository[self::SECTION_LAST][
'items'][
$code] = [];
607 foreach ($this->repository as $catCode => &$cat)
609 foreach ($cat[
'items'] as
$code => &$block)
612 in_array(
$code, $lastUsed)
613 && $catCode != self::SECTION_LAST
617 $block[
'section'][] = self::SECTION_LAST;
618 $this->repository[self::SECTION_LAST][
'items'][
$code] = $block;
626 foreach ($this->repository[self::SECTION_LAST][
'items'] as
$code => $block)
630 unset($this->repository[self::SECTION_LAST][
'items'][
$code]);
635 $lastUsedItems = $this->repository[self::SECTION_LAST][
'items'];
640 private function getPreparedRepository():
array
642 $prepared = $this->filterRepository($this->repository);
644 $event =
new Event(
'landing',
'onBlockGetRepository', [
645 'blocks' => $prepared,
650 if (
$result->getResultType() != EventResult::ERROR)
652 if (($modified =
$result->getModified()))
654 if (isset($modified[
'blocks']))
656 $prepared = array_merge($prepared, $modified[
'blocks']);
670 private function filterRepository(
array $repository):
array
679 $prepareType =
function (
string|
array $item): ?
array
683 if (in_array(
'PAGE',
$type))
688 in_array(
'NULL',
$type)
689 || in_array(
'',
$type)
702 $license = Loader::includeModule(
'bitrix24') ? \CBitrix24::getLicenseType() : null;
704 foreach ($repository as $sectionCode => $section)
706 $sectionTypes = $prepareType($section[
'type'] ?? []);
710 && empty($sectionTypes)
711 && $sectionCode !== self::SECTION_LAST
719 && $sectionTypes ===
null
726 is_array($sectionTypes)
727 && !empty($sectionTypes)
728 && !in_array($this->siteType, $sectionTypes,
true))
733 if ($sectionTypes === [self::TYPE_STORE] && !$isStoreEnabled)
738 $filtered[$sectionCode] = $section;
739 $filtered[$sectionCode][
'items'] = [];
741 foreach ($section[
"items"] ?? [] as $blockCode => $block)
743 $blockTypes = $prepareType($block[
'type'] ?? []);
747 && empty($blockTypes)
755 && $blockTypes ===
null
762 is_array($blockTypes)
763 && !empty($blockTypes)
764 && !in_array($this->siteType, $blockTypes,
true)
770 if (!empty($block[
'only_for_license']) && $block[
'only_for_license'] !==
$license)
777 && isset($block[
'system'])
778 && $block[
'system'] ===
true
784 $block[
'requires_updates'] =
785 ($block[
'version'] ??
null)
786 && version_compare($version, $block[
'version']) < 0;
788 $filtered[$sectionCode][
'items'][$blockCode] = $block;
791 if (empty($filtered[$sectionCode][
'items']))
793 unset($filtered[$sectionCode]);
824 BX_ROOT .
'/' . self::BLOCKS_DIR,
842 static $namespaces = [];
851 $enableNamespace =
Config::get(
'enable_namespace');
852 $enableNamespace = $enableNamespace ? (
array)$enableNamespace : [];
863 while ((($entry = readdir(
$handle)) !==
false))
865 if (!empty($enableNamespace))
867 if (in_array($entry, $enableNamespace))
869 $namespaces[] = $entry;
873 $entry !=
'.' && $entry !=
'..'
874 && is_dir(
$path .
'/' . $entry)
875 && !in_array($entry, $disableNamespace)
878 $namespaces[] = $entry;
884 $namespaces = array_unique($namespaces);
896 static $newBlocks =
null;
898 if ($newBlocks ===
null)
900 $newBlocks = unserialize(
Manager::getOption(
'new_blocks'), [
'allowed_classes' =>
false]);
901 if (!is_array($newBlocks))
906 !isset($newBlocks[
'date'])
907 || ((time() - $newBlocks[
'date']) > self::NEW_BLOCK_LT)
912 if (isset($newBlocks[
'items']))
914 $newBlocks = $newBlocks[
'items'];
918 return in_array($block, $newBlocks);
if(file_exists(( $_fname=__DIR__ . "/classes/general/update_db_updater.php"))) if(($_fname=getLocalPath("init.php")) !==false) if(( $_fname=getLocalPath("php_interface/init.php", BX_PERSONAL_ROOT)) !==false) if(($_fname=getLocalPath("php_interface/" . SITE_ID . "/init.php", BX_PERSONAL_ROOT)) !==false) if((!(defined("STATISTIC_ONLY") &&STATISTIC_ONLY &&!str_starts_with( $GLOBALS["APPLICATION"]->GetCurPage(), BX_ROOT . "/admin/"))) &&COption::GetOptionString("main", "include_charset", "Y")=="Y" &&LANG_CHARSET !='') if(COption::GetOptionString("main", "set_p3p_header", "Y")=="Y") $license
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)