3namespace Bitrix\Landing;
5use Bitrix\Landing\Block\BlockRepo;
6use Bitrix\Landing\Internals\BlockTable;
7use Bitrix\Landing\Metrika\Types;
8use Bitrix\Landing\Site\Type;
9use Bitrix\Main\Application;
10use Bitrix\Main\Config\Option;
12use Bitrix\Main\EventResult;
13use Bitrix\Main\Page\Asset;
14use Bitrix\Main\Localization\Loc;
15use Bitrix\Main\ModuleManager;
16use Bitrix\Main\UI\Extension;
17use Bitrix\Rest\AppTable;
19Loc::loadMessages(__FILE__);
27 'CREATED_BY_ID',
'MODIFIED_BY_ID',
'DATE_CREATE',
28 'DATE_MODIFY',
'DATE_PUBLIC',
'INITIATOR_APP_CODE',
'VIEWS',
'TPL_CODE',
29 'ACTIVE',
'PUBLIC',
'SITE_CODE',
'SITE_SPECIAL',
'RULE',
30 'SITE_VERSION',
'SITE_LANG',
'SITE_TPL_CODE',
37 'DATE_MODIFY',
'DATE_PUBLIC',
'ACTIVE',
'PUBLIC',
228 $this->error =
new Error;
233 isset(
$params[
'force_deleted'])
234 &&
$params[
'force_deleted'] ===
true
237 $filter[
'=DELETED'] = [
'Y',
'N'];
238 $filter[
'=SITE.DELETED'] = [
'Y',
'N'];
241 isset(
$params[
'check_permissions'])
242 &&
$params[
'check_permissions'] ===
false
245 $filter[
'CHECK_PERMISSIONS'] =
'N';
246 $this->checkPermissions =
false;
249 isset(
$params[
'disable_link_preview'])
250 &&
$params[
'disable_link_preview'] ===
true
253 $this->disableLinkPreview =
true;
258 $landing = self::getList(
array(
261 'SITE_TPL_ID' =>
'SITE.TPL_ID',
262 'SITE_TPL_CODE' =>
'SITE.TPL_CODE',
263 'SITE_CODE' =>
'SITE.CODE',
264 'SITE_TYPE' =>
'SITE.TYPE',
265 'SITE_SPECIAL' =>
'SITE.SPECIAL',
266 'SITE_TITLE' =>
'SITE.TITLE',
267 'SITE_VERSION' =>
'SITE.VERSION',
268 'SITE_LANG' =>
'SITE.LANG',
269 'DOMAIN_ID' =>
'SITE.DOMAIN_ID',
270 'SITE_LANDING_ID_INDEX' =>
'SITE.LANDING_ID_INDEX',
276 if (!empty($landing[
'FOLDER_ID']))
279 foreach ($breadCrumbs as $crumb)
281 if ($crumb[
'DELETED'] ===
'Y')
288 if (
$id && isset($landing) && is_array($landing))
295 self::$siteType = (string)$landing[
'SITE_TYPE'];
296 $this->
title = $landing[
'TITLE'];
297 $this->code = $landing[
'CODE'];
298 $this->xmlId = $landing[
'XML_ID'];
299 $this->
id = (int)$landing[
'ID'];
300 $this->
version = (int)$landing[
'VERSION'];
301 $this->siteId = (int)$landing[
'SITE_ID'];
302 $this->siteTitle = $landing[
'SITE_TITLE'];
303 $this->domainId = (int)$landing[
'DOMAIN_ID'];
304 $this->folderId = (int)$landing[
'FOLDER_ID'];
305 $this->active = $landing[
'ACTIVE'] ==
'Y';
306 if ($this->checkPermissions)
313 'TPL_ID' => $landing[
'SITE_TPL_ID'],
314 'LANDING_ID_INDEX' => $landing[
'SITE_LANDING_ID_INDEX'],
316 $siteTplId = max($landing[
'SITE_TPL_ID'], 0);
317 $this->tplId = (int)$landing[
'TPL_ID'] > 0
318 ? (
int)$landing[
'TPL_ID']
323 $this->mainInstance =
false;
325 if ($landing[
'SITE_TPL_ID'] > 0 && !$landing[
'TPL_ID'])
327 $this->tplType =
'site';
332 Block::cloneForEdit($this);
339 ||
$params[
'skip_blocks'] !==
true
344 $params[
'blocks_limit'] ??
null,
346 'id' =>
$params[
'blocks_id'] ?? 0,
347 'deleted' => isset(
$params[
'deleted']) &&
$params[
'deleted'] ===
true,
352 foreach (self::META_KEYS as
$key)
354 $this->metaData[
$key] = $landing[
$key];
360 $this->error->addError(
362 Loc::getMessage(
'LANDING_NOT_FOUND')
364 $this->
title = Loc::getMessage(
'LANDING_TITLE_NOT_FOUND');
377 if (in_array(
$key, self::META_KEYS_MODIFIABLE,
true))
379 $this->metaData[
$key] = $value;
390 public static function ping(
$id, $deleted =
false)
392 $returnCheckDelete =
false;
399 if (self::$checkDelete)
401 $returnCheckDelete =
true;
402 self::$checkDelete =
false;
404 $filter[
'=DELETED'] = [
'Y',
'N'];
407 $check = self::getList([
414 if ($returnCheckDelete)
416 self::$checkDelete =
true;
419 return (
boolean)$check->fetch();
429 self::$editMode = (boolean)$mode;
438 return self::$editMode;
448 self::$previewMode = (boolean)$mode;
457 return self::$previewMode;
466 return self::$checkDelete;
475 self::$checkDelete =
false;
484 self::$checkDelete =
true;
493 self::$enabledUpdate =
false;
502 self::$enabledUpdate =
true;
511 return self::$checkUniqueAddress;
520 self::$checkUniqueAddress =
false;
529 self::$checkUniqueAddress =
true;
552 $result = new \Bitrix\Main\Result;
555 Loc::getMessage(
'LANDING_BLOCK_UNABLE_DEL_INC'),
556 'UNABLE_DELETE_INCLUDE'
571 if (
$result->getType() == EventResult::ERROR)
573 $return = new \Bitrix\Main\Result;
585 if (($currentScope =
Site\Type::getCurrentScopeId()))
590 $landing = self::createInstance(
$id, [
'skip_blocks' =>
true]);
596 if (
$res->isSuccess())
598 $landing->clearFolderIndex();
621 if (
$result->getType() == EventResult::ERROR)
623 $return = new \Bitrix\Main\Result;
648 $result = new \Bitrix\Main\Entity\DeleteResult();
653 $params[
'force_deleted'] =
true;
659 foreach ([
'draft',
'public'] as
$code)
661 self::setEditMode(
$code ==
'draft');
662 $landing = self::createInstance(
$id,
$params);
663 if ($landing->exist())
665 foreach ($landing->getBlocks() as $block)
667 if ($block->getAccess() < $block::ACCESS_X)
671 Loc::getMessage(
'LANDING_BLOCK_ACCESS_DENIED'),
682 if (!$landing->getError()->isEmpty())
685 $landing->getError()->getErrors()[0]
698 self::setEditMode(
$code ==
'draft');
699 $landing = self::createInstance(
$id,
$params);
700 if ($landing->exist())
702 Block::deleteAll(
$id);
709 if (
$res->isSuccess())
711 $landing->clearFolderIndex();
729 return Hook::getForLanding(
$id);
742 foreach (self::getHooks(
$id) as $hook)
744 $fields += $hook->getPageFields();
758 $hookFiles = Hook::HOOKS_CODES_FILES;
759 $fields = self::getAdditionalFields($landingId);
771 if (in_array(
$key, $hookFiles))
815 return self::$variables;
826 self::$dynamicFilterId = $filterId;
827 self::$dynamicElementId = $elementId;
840 self::$dynamicFilterId
853 return self::$dynamicElementId;
862 return self::$dynamicFilterId && self::$dynamicElementId;
872 public function getPreview(?
int $id =
null,
bool $skipCloud =
false, ?
string $publicUrl =
null): ?string
885 return rtrim($publicUrl,
'/') .
'/preview.jpg';
888 static $hookPics =
null;
890 if ($hookPics ===
null)
900 if (isset($hookPics[
$id]))
902 $pic = $hookPics[
$id];
903 if (intval($pic) > 0)
922 public function getPublicUrl(
$id =
false, $absolute =
true, $createPubPath =
false, &$fullUrl = [])
929 $previewMode = self::$previewMode && !$this->disableLinkPreview;
931 $hostUrl = Domain::getHostUrl();
934 $bitrix24originalVar = $bitrix24;
936 $domainDefault =
null;
945 'SITE_ID_INDEX' =>
'SITE.LANDING_ID_INDEX',
946 'SITE_PROTOCOL' =>
'SITE.DOMAIN.PROTOCOL',
947 'SITE_DOMAIN' =>
'SITE.DOMAIN.DOMAIN',
948 'SITE_CODE' =>
'SITE.CODE',
949 'SITE_TYPE' =>
'SITE.TYPE',
950 'SITE_SMN_ID' =>
'SITE.SMN_SITE_ID',
954 '=DELETED' => [
'Y',
'N'],
955 'CHECK_PERMISSIONS' =>
'N',
958 while ($row =
$res->fetch())
960 if ($row[
'SITE_TYPE'] ==
'SMN')
966 $bitrix24 = $bitrix24originalVar;
968 $domainReplace =
false;
969 $row[
'SITE_ID_ORIG'] = $row[
'SITE_ID'];
971 if (!$row[
'SITE_DOMAIN'])
975 $domainDefault = Domain::getList(
array(
977 'ID' => Domain::getCurrentId(),
981 if (isset($domainDefault[
'PROTOCOL']))
983 $row[
'SITE_PROTOCOL'] = $domainDefault[
'PROTOCOL'];
985 if (isset($domainDefault[
'DOMAIN']))
987 $row[
'SITE_DOMAIN'] = $domainDefault[
'DOMAIN'];
989 $domainReplace =
true;
994 $row[
'SITE_PROTOCOL'] =
'https';
996 if ($domainReplace || !$bitrix24 || $disableCloud)
1000 $row[
'SITE_SMN_ID'] ? $row[
'SITE_SMN_ID'] :
$siteId,
1003 $pubPath = rtrim($pubPath,
'/');
1006 if (!ModuleManager::isModuleInstalled(
'bitrix24'))
1010 $row[
'SITE_SMN_ID'] ? $row[
'SITE_SMN_ID'] :
$siteId,
1014 if (isset($row[
'SITE_ID']))
1016 if ($siteKeyCode ==
'CODE')
1018 $row[
'SITE_ID'] = $row[
'SITE_CODE'];
1022 $row[
'SITE_ID'] =
'/' . $row[
'SITE_ID'] .
'/';
1028 if ($siteKeyCode ==
'CODE')
1030 $publicHash = Site::getPublicHash(trim($row[
'SITE_CODE'],
'/'), $row[
'SITE_DOMAIN']);
1034 $publicHash = Site::getPublicHash($row[
'SITE_ID_ORIG'], $row[
'SITE_DOMAIN']);
1039 $row[
'CODE'] .=
'/';
1043 $lastFolderItem = [];
1044 $fullUrl[$row[
'ID']] = ($absolute ? $hostUrl :
'') .
1046 ($bitrix24 ? $row[
'SITE_ID'] :
'/') .
1048 ($row[
'FOLDER_ID'] ? ltrim(
Folder::getFullPath($row[
'FOLDER_ID'], $row[
'SITE_ID_ORIG'], $lastFolderItem),
'/') :
'');
1049 $folderIndex = $row[
'ID'] == ($lastFolderItem[
'INDEX_ID'] ?? 0)
1051 !($lastFolderItem[
'INDEX_ID'] ?? 0)
1052 && ($row[
'CODE'] ??
null)
1053 && ($lastFolderItem[
'CODE'] ??
null)
1054 && trim($row[
'CODE'],
'/') === $lastFolderItem[
'CODE']
1056 $data[$row[
'ID']] = $fullUrl[$row[
'ID']] .
1057 (($row[
'ID'] == $row[
'SITE_ID_INDEX'] || $folderIndex || $row[
'RULE']) ?
'' : $row[
'CODE']);
1060 $fullUrl[$row[
'ID']] .= $row[
'CODE'];
1065 $lastFolderItem = [];
1066 $fullUrl[$row[
'ID']] = (
1069 $row[
'SITE_PROTOCOL'] .
'://' .
1074 (($domainReplace || !$bitrix24) ? $pubPath :
'') .
1075 ((
$previewMode && !$bitrix24) ?
'/preview/' . $publicHash :
'') .
1076 (($domainReplace && $bitrix24) ? $row[
'SITE_ID'] :
'/') .
1077 ((
$previewMode && $bitrix24) ?
'preview/' . $publicHash .
'/' :
'') .
1078 ($row[
'FOLDER_ID'] ? ltrim(
Folder::getFullPath($row[
'FOLDER_ID'], $row[
'SITE_ID_ORIG'], $lastFolderItem),
'/') :
'');
1079 $folderIndex = $row[
'ID'] == $lastFolderItem[
'INDEX_ID'] || !$lastFolderItem[
'INDEX_ID'] && trim($row[
'CODE'],
'/') === $lastFolderItem[
'CODE'];
1080 $data[$row[
'ID']] = $fullUrl[$row[
'ID']] .
1081 (($row[
'ID'] == $row[
'SITE_ID_INDEX'] || $folderIndex || $row[
'RULE']) ?
'' : $row[
'CODE']);
1084 $fullUrl[$row[
'ID']] .= $row[
'CODE'];
1095 return array_pop(
$data);
1115 $className = \CBitrixComponent::includeComponentClass(
$componentName);
1116 $demoCmp =
new $className;
1118 $demoCmp->arParams = [
1119 'PATH' => mb_substr($landingUrl, mb_strlen($publicationPath)),
1120 'DRAFT_MODE' =>
'Y',
1122 'SITE_TYPE' => self::getSiteType(),
1123 'CHECK_PERMISSIONS' =>
'N',
1124 'NOT_CHECK_DOMAIN' =>
'Y',
1125 'NOT_SEND_HTTP_STATUS' =>
'Y',
1129 return $demoCmp->detectPage() ?:
null;
1140 $editMode = $this->mainInstance && $blockEditMode;
1142 if (!isset(
$params[
'parse_link']))
1147 if (!isset(
$params[
'apply_template']))
1149 $params[
'apply_template'] =
true;
1152 if (!isset(
$params[
'check_permissions']))
1154 $params[
'check_permissions'] =
true;
1157 if (!
$params[
'check_permissions'])
1163 if ($this->mainInstance)
1171 if ($this->mainInstance)
1173 if ($this->folderId)
1176 foreach ($chains as $chain)
1180 $chain[
'INDEX_ID'] ?
'#landing' . $chain[
'INDEX_ID'] :
'#'
1184 elseif (($this->siteRow[
'LANDING_ID_INDEX'] ?? 0) != $this->
id)
1188 '#landing' . $this->
id
1198 'server_name' =>
$_SERVER[
'SERVER_NAME'],
1199 'xml_id' => $this->xmlId,
1200 'blocks' => (
new BlockRepo())->getRepository(),
1202 'attrs' => Block::getAttrs(),
1204 'saveOriginalFileName' => Option::get(
'main',
'save_original_file_name') ===
'Y',
1214 if (
$result->getResultType() != EventResult::ERROR)
1216 if (($modified =
$result->getModified()))
1218 if (isset($modified[
'options']) && is_array($modified[
'options']))
1226 Asset::getInstance()->addString(
1228 'BX.ready(function(){'
1229 .
'if (typeof BX.Landing.Main !== "undefined")'
1231 .
'BX.Landing.Env.createInstance(' . \CUtil::phpToJSObject(
$options,
false,
false,
true) .
');'
1232 .
'BX.Landing.Main.createInstance(' . $this->
id .
');'
1242 if (
$params[
'apply_template'] && $this->mainInstance)
1250 $content =
'<div class="landing-main"' .
1251 ' data-site="' . $this->siteId .
'"' .
1252 ' data-landing="' . $this->
id .
'">' .
1261 foreach ($this->blocks as $block)
1263 $block->view($blockEditMode, $this);
1266 if ($this->mainInstance)
1270 $contentMain = ob_get_contents();
1280 if (mb_strpos(
$content,
'#CONTENT#') !==
false)
1282 $replace[
'#CONTENT#'] =
'<a id="workarea"></a>' . $contentMain;
1285 if (mb_strpos(
$content . $contentMain,
'#crm') !==
false)
1293 array_keys($replace),
1294 array_values($replace),
1300 if (!$blockEditMode && $this->mainInstance)
1304 false, 0,
false,
true
1306 $breadcrumb = ob_get_contents();
1322 if (
$params[
'parse_link'] ===
true && !$blockEditMode)
1331 if (!
$params[
'check_permissions'])
1343 if ($this->tplType ==
'site')
1364 'ID' => $this->tplId,
1372 $template[
'CONTENT'] =
'<div class="landing-main">' .
1379 '>#CONTENT#<' =>
' data-site="' . $this->siteId .
1380 '" data-landing="' . $this->
id .
1394 foreach ($this->
getAreas() as $area => $lid)
1397 $landing = self::createInstance($lid,
array(
1399 'check_permissions' =>
false,
1400 'disable_link_preview' => $this->disableLinkPreview,
1402 if ($landing->exist())
1409 $replace[
'>#AREA_' . $area .
'#<'] =
' data-site="' . $landing->getSiteId() .
1410 '" data-landing="' . $lid .
1411 '" data-rights="' . implode(
',',
$rights) .
1412 '">#AREA_' . $area .
'#<';
1414 $replace[
'#AREA_' . $area .
'#'] = ob_get_contents();
1419 array_keys($replace),
1420 array_values($replace),
1431 $content =
'<div class="landing-main" ' .
1432 'data-site="' . $this->siteId .
'" ' .
1433 'data-landing="' . $this->
id .
'">' .
1447 return $this->tplId;
1457 $pattern =
'/([",\'\;]{1})(page:|block:|user:|help:)?#(landing|block|dynamic|user|helpdesk=|slider=)([\w\_]+)\@{0,1}([^\'"]*)([",\'\&]{1})/is';
1458 $patternWithoutUser =
'/([",\'\;]{1})(page:|block:)?#(landing|block|dynamic)([\d\_]+)\@{0,1}([^\'"]*)([",\'\&]{1})/is';
1459 static $isIframe =
null;
1468 if ($isIframe ===
null)
1470 $request = Application::getInstance()->getContext()->getRequest();
1471 $isIframe =
$request->get(
'IFRAME') ==
'Y';
1475 if (self::$previewMode)
1478 '/href\="(product:)?#catalog(Element|Section)([\d]+)"/i',
1483 mb_strtolower($href[2])
1494 $replace[
'</form>'] =
'<input type="hidden" name="IFRAME" value="Y" /></form>';
1498 if ($this->siteRow[
'LANDING_ID_INDEX'] > 0)
1500 $replace[
'#system_mainpage'] =
'#landing' . $this->siteRow[
'LANDING_ID_INDEX'];
1506 array_keys($replace),
1507 array_values($replace),
1516 'LANDING' =>
array(),
1519 'DYNAMIC' =>
array(),
1524 if (mb_strtoupper(
$matches[3][
$i]) ==
'LANDING')
1528 else if (mb_strtoupper(
$matches[3][
$i]) ==
'DYNAMIC')
1530 [$dynamicId, ] = explode(
'_',
$matches[4][
$i]);
1531 $urls[
'DYNAMIC'][] = $dynamicId;
1533 else if (mb_strtoupper(
$matches[3][
$i]) ==
'USER')
1548 $anchorsId =
array();
1549 $anchorsPublicId =
array();
1550 if (!empty($urls[
'BLOCK']))
1552 $urls[
'BLOCK'] = Block::getRowByBlockId(
1555 'ID',
'LID',
'PARENT_ID',
'ANCHOR',
1558 foreach ($urls[
'BLOCK'] as $bid => &$bidRow)
1562 && $bidRow[
'PARENT_ID']
1565 $anchorsPublicId[$bid] = $bidRow[
'PARENT_ID'];
1569 $anchorsId[$bid] = $bidRow[
'ANCHOR']
1571 : Block::getAnchor($bidRow[
'ID'])
1574 $bidRow = $bidRow[
'LID'];
1577 $urls[
'LANDING'] = array_unique(array_merge(
1582 $urls[
'LANDING'] = array_unique(array_merge(
1587 if ($anchorsPublicId)
1589 $anchorsPublicIdTmp = Block::getRowByBlockId(
1592 'ID',
'LID',
'PARENT_ID',
'ANCHOR',
1595 foreach ($anchorsPublicId as $bid => $bidParent)
1597 if (!isset($anchorsPublicIdTmp[$bidParent]))
1601 $bidParent = $anchorsPublicIdTmp[$bidParent];
1602 $anchorsPublicId[$bid] = $bidParent[
'ANCHOR']
1604 : Block::getAnchor($bidParent[
'ID'])
1608 $anchorsPublicId += $anchorsId;
1612 if (!empty($urls[
'LANDING']))
1620 foreach ($urls[
'LANDING'] as $lid => &
$url)
1622 $lidEncoded[] = $lid;
1626 $url .=
'?IFRAME=Y';
1631 if (!empty($urls[
'BLOCK']))
1633 foreach ($urls[
'BLOCK'] as $bid => $lid)
1635 if (isset($urls[
'LANDING'][$lid]))
1637 if (!in_array($lid, $lidEncoded))
1641 $urls[
'LANDING'][$lid] .= ($isIframe ?
'?IFRAME=Y' :
'');
1642 $urls[
'BLOCK'][$bid] = $urls[
'LANDING'][$lid] .
'#' . $anchorsPublicId[$bid];
1646 unset($urls[
'BLOCK'][$bid]);
1651 if (!empty($urls[
'LANDING']))
1653 krsort($urls[
'LANDING']);
1655 $patternWithoutUser,
1656 function (
$matches) use ($urls, $landingFull, $isIframe)
1663 if (($underPos = mb_strpos(
$matches[4],
'_')) !==
false)
1665 $dynamicPart = mb_substr(
$matches[4], $underPos);
1668 [$dynamicId, ] = explode(
'_',
$matches[4]);
1676 if (isset($landingFull[
$matches[4]]))
1678 $landingUrl = $landingFull[
$matches[4]];
1680 $url = mb_substr($landingUrl, 0, mb_strlen($landingUrl) - 1);
1681 $url .= $dynamicPart . ($isIframe ?
'/?IFRAME=Y' :
'/');
1700 $landingUrls =
array();
1701 foreach ($urls[
'LANDING'] as $lid =>
$url)
1703 $landingUrls[
'@#landing' . $lid.
'@'] =
$url;
1707 if (!empty($urls[
'USER']))
1709 $patternForPseudoUrlUser =
'/data-pseudo-url="{\S*(user:)?#user([\d\_]+)\S*}"/is';
1711 $patternForPseudoUrlUser,
1714 $url =
"'" . Domain::getHostUrl() .
'/company/personal/user/' .
$matches[2] .
"/'";
1715 return 'onClick="BX.SidePanel.Instance.open('.
$url .
')" ';
1719 $patternForUser =
'/(user:)?#(user)([\d\_]+)/is';
1724 return Domain::getHostUrl() .
'/company/personal/user/' .
$matches[3] .
'/';
1731 if (!empty($urls[
'HELP']))
1733 $patternForHelpdesk =
'/help:#helpdesk=(\d+)/i';
1735 $patternForHelpdesk,
1738 return "javascript:BX.Helper.show('redirect=detail&code=" .
$matches[1] .
"')";
1743 $patternForSlider =
'/help:#slider=(\w+)/i';
1748 return "javascript:BX.UI.InfoHelper.show('" .
$matches[1] .
"')";
1764 $hooksExec =
array();
1766 foreach (Hook::getForSite($this->siteId) as $hook)
1768 if ($hook->enabled())
1771 $hooksExec[$hook->getCode()] = $hook;
1775 foreach (Hook::getForLanding($this->
id) as $hook)
1777 if ($hook->enabled())
1779 $hooksExec[$hook->getCode()] = $hook;
1783 foreach ($hooksExec as $hook)
1787 || $hook->enabledInEditMode()
1797 if ($hook->getCode() ===
'GMAP')
1799 $hook->setSiteId($this->siteId);
1811 return $this->
id > 0;
1820 return $this->active;
1838 return $this->xmlId;
1865 return $this->metaData;
1874 if (!$this->checkPermissions)
1888 if (!$this->checkPermissions)
1902 if (!$this->checkPermissions)
1916 return $this->folderId;
1934 return $this->siteTitle;
1943 return $this->domainId;
1952 return self::$siteType;
1958 ($this->
getMeta()[
'SITE_SPECIAL'] ??
'N') ===
'Y'
1959 && ($this->
getMeta()[
'SITE_CODE'] ??
'') !==
''
1962 return Type::getSiteSpecialType($this->
getMeta()[
'SITE_CODE']);
1981 'ID' => $this->siteId,
1984 if ($row =
$res->fetch())
1986 return $row[
'SMN_SITE_ID'];
1999 return $this->blocks;
2011 return isset($this->blocks[
$id])
2012 ? $this->blocks[
$id]
2024 if ($block->exist())
2026 $this->blocks[$block->getId()] = $block;
2047 $error = $this->error->getFirstError();
2049 return new \Bitrix\Main\Error(
2064 static $touched = [];
2066 if (isset($touched[$this->
id]))
2071 $touched[$this->id] =
true;
2073 if (self::update($this->
id, [
'PUBLIC' =>
'N'])->isSuccess())
2075 Site::touch($this->siteId);
2085 $needUpdate =
false;
2091 $hookEditMode = Hook::getEditMode();
2094 Hook::setEditMode(
true);
2096 Hook::publicationSite($this->siteId);
2097 Hook::publicationLanding($this->
id);
2100 Hook::setEditMode(
false);
2163 self::update($this->
id, [
2165 'DATE_MODIFY' =>
false,
2166 'MODIFIED_BY_ID' =>
false,
2184 $specialType === Type::PSEUDO_SCOPE_CODE_FORMS
2185 ? Metrika\Categories::CrmForms
2196 $metrika->setError(
'access_denied');
2208 $metrika->setError(implode(
'|',
$errors));
2212 $metrika->setType($metrikaFields?->type);
2213 $metrika->setSubSection($metrikaFields?->subSection);
2214 $metrika->setElement($metrikaFields?->element);
2215 $metrika->setParam(3,
'siteId', $this->siteId);
2242 static $siteUpdated = [];
2247 'DATE_MODIFY' =>
false,
2249 if (
$res->isSuccess())
2252 !in_array($this->siteId, $siteUpdated)
2257 Site::update($this->siteId,
array());
2261 'id' => $this->
getId(),
2269 $this->error->addFromResult(
$res);
2285 Metrika\Categories::getBySiteType(self::$siteType),
2291 $this->error->addError(
2293 Loc::getMessage(
'LANDING_BLOCK_ACCESS_DENIED')
2296 if (self::$siteType === Type::SCOPE_CODE_MAINPAGE)
2299 ->setError(
'ACCESS_DENIED')
2307 if (!isset(
$data[
'PUBLIC']))
2309 $data[
'PUBLIC'] = $this::$editMode ?
'N' :
'Y';
2312 $block = Block::createFromRepository($this,
$code,
$data);
2316 if ($saveInLastUsed)
2318 Block::markAsUsed(
$code);
2324 if (History::isActive())
2326 $history =
new History($this->
id, History::ENTITY_TYPE_LANDING);
2327 $history->push(
'ADD_BLOCK', [
'block' => $block]);
2330 if (self::$siteType === Type::SCOPE_CODE_MAINPAGE)
2335 return $block->getId();
2338 if (self::$siteType === Type::SCOPE_CODE_MAINPAGE)
2341 ->setError(
'BLOCK_NOT_FOUND')
2357 if (isset($this->blocks[
$id]))
2360 $this->error->copyError(
2365 unset($this->blocks[
$id]);
2373 $this->error->addError(
2375 Loc::getMessage(
'LANDING_BLOCK_NOT_FOUND')
2391 if (!isset($this->blocks[
$id]))
2397 Metrika\Categories::getBySiteType(self::$siteType),
2402 isset($this->blocks[
$id]) &&
2404 $this->blocks[
$id]->getLandingId() == $this->
getId()
2407 if ($this->blocks[
$id]->getAccess() >= $this->blocks[
$id]::ACCESS_X)
2409 $this->blocks[
$id]->markDeleted($mark);
2412 Assets\PreProcessing::blockUndeleteProcessing(
2416 if ($this->blocks[
$id]->save())
2418 if (self::$siteType === Type::SCOPE_CODE_MAINPAGE)
2421 ->parametrizeMetrikaByBlock($metrika, $this->blocks[
$id])
2428 if (History::isActive())
2430 $history =
new History($this->
id, History::ENTITY_TYPE_LANDING);
2431 $history->push(
'REMOVE_BLOCK', [
'block' => $this->blocks[
$id]]);
2434 unset($this->blocks[
$id]);
2448 $this->error->copyError(
2452 if (self::$siteType === Type::SCOPE_CODE_MAINPAGE)
2455 ->setError(
'SAVE_ERROR')
2463 $this->error->addError(
2465 Loc::getMessage(
'LANDING_BLOCK_ACCESS_DENIED')
2467 if (self::$siteType === Type::SCOPE_CODE_MAINPAGE)
2470 ->setError(
'ACCESS_DENIED')
2480 $this->error->addError(
2482 Loc::getMessage(
'LANDING_BLOCK_NOT_FOUND')
2484 if (self::$siteType === Type::SCOPE_CODE_MAINPAGE)
2487 ->setError(
'BLOCK_NOT_FOUND')
2505 $metrika->setType(Types::widgetPartner);
2508 $appCode = $manifest[
'block'][
'app_code'] ??
null;
2511 $metrika->setParam(1,
'appCode', $appCode);
2512 $app = AppTable::getList([
2514 '=CODE' => $appCode,
2517 if (
$app &&
$app[
'STATUS'] === AppTable::STATUS_LOCAL)
2526 ->setType(Types::widgetSystem)
2527 ->setParam(1,
'appCode',
'system')
2531 $metrika->setParam(2,
'widgetId', $block->
getCode());
2545 if (isset($this->blocks[
$id]))
2547 $result = $this->blocks[
$id]->changeLanding($lid);
2548 $this->error->copyError($this->blocks[
$id]->
getError());
2551 unset($this->blocks[
$id]);
2558 $this->error->addError(
2560 Loc::getMessage(
'LANDING_BLOCK_NOT_FOUND')
2573 uasort($this->blocks,
function (
$a, $b)
2575 if (
$a->getSort() == $b->getSort())
2577 return (
$a->getId() < $b->getId()) ? -1 : 1;
2580 return (
$a->getSort() < $b->getSort()) ? -1 : 1;
2583 foreach ($this->blocks as
$id => $block)
2585 $block->saveSort($sort);
2599 if (isset($this->blocks[
$id]))
2601 $blocks = array_keys($this->blocks);
2607 $targetKey =
$i + (
$action ===
'up' ? -1 : 1);
2608 if (isset(
$blocks[$targetKey]))
2610 $thisBlock = $this->blocks[
$id];
2611 $targetBlock = $this->blocks[
$blocks[$targetKey]];
2612 $thisBlockSort = $thisBlock->getSort();
2613 $targetBlockSort = $targetBlock->getSort();
2615 $thisBlock->setSort($targetBlockSort);
2616 $targetBlock->setSort($thisBlockSort);
2617 $res1 = $thisBlock->save();
2618 $res2 = $targetBlock->save();
2620 $this->error->copyError($thisBlock->getError());
2621 $this->error->copyError($targetBlock->getError());
2628 return $res1 && $res2;
2631 $this->error->addError(
2633 Loc::getMessage(
'LANDING_BLOCK_WRONG_SORT')
2642 $this->error->addError(
2644 Loc::getMessage(
'LANDING_BLOCK_NOT_FOUND')
2660 if (History::isActive())
2662 $history =
new History($this->
id, History::ENTITY_TYPE_LANDING);
2663 $history->push(
'SORT_BLOCK', [
2665 'lid' => $this->
getId(),
2685 if (History::isActive())
2687 $history =
new History($this->
id, History::ENTITY_TYPE_LANDING);
2688 $history->push(
'SORT_BLOCK', [
2690 'lid' => $this->
getId(),
2710 if (isset($this->blocks[
$id]))
2712 if ($this->blocks[
$id]->setActive(
$action ==
'show'))
2714 if (
$res = $this->blocks[
$id]->save())
2719 $this->error->copyError($this->blocks[
$id]->
getError());
2725 $this->error->addError(
2727 Loc::getMessage(
'LANDING_BLOCK_NOT_FOUND')
2763 if ((
int)$bewBlockId > 0)
2766 $this->blocks[$bewBlockId]->changeLanding(0) &&
2767 $this->blocks[$bewBlockId]->changeFavoriteMeta($meta)
2770 Block::markAsUsed($this->blocks[$bewBlockId]->
getCode() .
'@' . $bewBlockId);
2771 \Bitrix\Landing\Block::clearRepositoryCache();
2772 if ($meta[
'preview'] ??
null)
2779 $this->error->copyError($this->blocks[$bewBlockId]->
getError());
2795 $block =
new Block($blockId);
2796 if (!$block || empty($block->getMeta()[
'FAVORITE_META']))
2798 $this->error->addError(
2800 Loc::getMessage(
'LANDING_BLOCK_NOT_FOUND')
2807 $block->getAccess() < Block::ACCESS_X
2811 $this->error->addError(
2813 Loc::getMessage(
'LANDING_BLOCK_ACCESS_DENIED')
2819 if (BlockTable::delete($blockId)->isSuccess())
2822 Block::removeAsUsed($block->getCode() .
'@' . $block->getId());
2823 Block::clearRepositoryCache();
2839 $block = intval($block);
2841 $afterId = isset(
$params[
'AFTER_ID']) ? (int)
$params[
'AFTER_ID'] : 0;
2842 $fromLandingRow = Block::getRowByBlockId($block, [
'ID',
'LID',
'SITE_TYPE' =>
'LANDING.SITE.TYPE']);
2843 $fromLandingId = $fromLandingRow[
'LID'] ??
null;
2845 $same = $this->
id == $fromLandingId;
2848 if ($currentScopeId !== $fromLandingRow[
'SITE_TYPE'])
2855 $fromLanding = clone $this;
2859 $fromLanding = self::createInstance($fromLandingId);
2863 if ($this->
exist() && $fromLanding->exist())
2865 $fromLandingBlocks = $fromLanding->getBlocks();
2869 $res = $fromLanding->transferBlock($block, $this->
id);
2870 $this->error->copyError($fromLanding->getError());
2873 $newBlock = $fromLandingBlocks[$block];
2877 elseif (isset($fromLandingBlocks[$block]))
2879 $srcBlock = $fromLandingBlocks[$block];
2880 $newBlock = Block::createFromRepository(
2882 $srcBlock->getCode(),
2884 'ACTIVE' => $srcBlock->isActive() ?
'Y' :
'N',
2885 'DESIGNED' => $srcBlock->isDesigned() ?
'Y' :
'N',
2886 'ACCESS' => $srcBlock->getAccess(),
2887 'SORT' => $srcBlock->getSort(),
2888 'CONTENT' => $srcBlock->getContent(),
2889 'SOURCE_PARAMS' => $srcBlock->getDynamicParams(),
2895 $newBlock->saveContent(
2896 $srcBlock->getContent()
2912 if ($afterId > 0 && isset($this->blocks[$afterId]))
2914 $targetBlock = $this->blocks[$afterId];
2918 $blocksTmp = array_values($this->blocks);
2919 $targetBlock = array_pop($blocksTmp);
2923 $newBlock->setSort($targetBlock->getSort() + 1);
2931 if ($this->error->isEmpty())
2933 if ($move && !$same)
2935 $fromLanding->touch();
2940 $this->error->copyError($fromLanding->getError());
2942 if ($currentScopeId !== $fromLandingRow[
'SITE_TYPE'])
2947 if ($this->error->isEmpty())
2952 return $newBlock ? $newBlock->getId() :
null;
2965 'AFTER_ID' => $afterId,
2969 $this->error->addError(
2971 Loc::getMessage(
'LANDING_BLOCK_NOT_FOUND')
2987 $landing = self::createInstance($lid);
2989 if ($this->
exist() && $landing->exist())
2993 foreach ($landing->getBlocks() as $block)
2995 $newBlock = Block::createFromRepository(
2999 'ACTIVE' => $block->isActive() ?
'Y' :
'N',
3000 'DESIGNED' => $block->isDesigned() ?
'Y' :
'N',
3001 'PUBLIC' => $block->isPublic() ?
'Y' :
'N',
3002 'ACCESS' => $block->getAccess(),
3003 'SORT' => $block->getSort(),
3004 'CONTENT' => $block->getContent(),
3005 'SOURCE_PARAMS' => $block->getDynamicParams(),
3009 $oldNew[$block->getId()] = $newBlock;
3010 $references[$block->getId()] = $newBlock->getId();
3018 foreach ($oldNew as $oldId => $newBlock)
3030 '#block' . $newBlock->getId(),
3041 $this->error->copyError($this->
getError());
3042 $this->error->copyError($landing->getError());
3051 if ($this->folderId)
3053 $resFolder = Folder::getList([
3058 'ID' => $this->folderId,
3059 'INDEX_ID' => $this->
id,
3062 if ($resFolder->fetch())
3064 Folder::update($this->folderId, [
3076 private function canPublicAfterCopy(): bool
3079 $folderId = $this->getFolderId();
3082 if (!$this->canPublication())
3095 foreach ($crumbs as $crumb)
3098 if ($crumb[
'ACTIVE'] ===
'Y')
3104 $res = self::getList([
3110 'FOLDER_ID' => $crumb[
'ID'],
3121 $res = Folder::getList([
3127 'PARENT_ID' => $crumb[
'ID'],
3148 public function move(?
int $toSiteId =
null, ?
int $toFolderId =
null): bool
3150 if (!$this->
exist())
3163 $this->error->addError(
3165 Loc::getMessage(
'LANDING_SITE_ACCESS_DENIED')
3173 $this->error->addError(
3174 'DELETE_ACCESS_DENIED',
3175 Loc::getMessage(
'LANDING_DELETE_ACCESS_DENIED')
3181 $result = self::update($this->
id, [
3184 'CODE' => $this->code,
3185 'SITE_ID' => $toSiteId,
3186 'FOLDER_ID' => $toFolderId,
3192 if ($this->active && $this->canPublicAfterCopy($toFolderId))
3198 $this->error->addFromResult(
$result);
3211 public function copy(?
int $toSiteId =
null, ?
int $toFolderId =
null,
bool $withoutBlocks =
false,
bool $skipSystem =
false): ?int
3225 if ($toFolderId !==
null)
3232 $folderRow = Site::getFolder(
$folderId);
3233 if (intval($folderRow[
'SITE_ID'] ??
null) !== $toSiteId)
3244 '=TITLE' => $landingRow[
'TITLE'],
3247 'SITE_ID' => $toSiteId,
3252 'CODE' => $landingRow[
'CODE'],
3255 'TITLE' => $addCopyMark
3256 ? $landingRow[
'TITLE'] .
' ' . Loc::getMessage(
'LANDING_COPY_SUFFIX')
3257 : $landingRow[
'TITLE'],
3258 'SYS' => $skipSystem ?
'N' : $landingRow[
'SYS'],
3259 'XML_ID' => $landingRow[
'XML_ID'],
3260 'TPL_CODE' => $landingRow[
'TPL_CODE'],
3261 'INITIATOR_APP_CODE' => $landingRow[
'INITIATOR_APP_CODE'],
3262 'DESCRIPTION' => $landingRow[
'DESCRIPTION'],
3263 'TPL_ID' => $landingRow[
'TPL_ID'],
3264 'SITE_ID' => $toSiteId,
3265 'SITEMAP' => $landingRow[
'SITEMAP'],
3270 if (
$res->isSuccess())
3272 Landing::setEditMode();
3273 $landingNew = Landing::createInstance(
$res->getId());
3274 if ($landingNew->exist())
3276 if (!$withoutBlocks)
3278 $landingNew->copyAllBlocks($this->
id);
3283 $landingNew->getId()
3288 $landingNew->getId()
3296 if ($landingRow[
'ACTIVE'] ===
'Y' && $landingNew->canPublicAfterCopy($toFolderId))
3298 $landingNew->publication();
3301 return $landingNew->getId();
3303 $this->error->copyError($landingNew->getError());
3307 $this->error->addFromResult(
$res);
3324 'AFTER_ID' => $afterId,
3328 $this->error->addError(
3330 Loc::getMessage(
'LANDING_BLOCK_NOT_FOUND')
3345 if (self::$enabledUpdate)
3351 return new \Bitrix\Main\Result;
3364 $result = new \Bitrix\Main\Entity\AddResult;
3367 $res = Site::getList([
3379 Loc::getMessage(
'LANDING_SITE_ERROR')
3388 $res = self::getList([
3390 'ID',
'FOLDER_ID',
'FOLDER',
'ACTIVE',
3397 if (!($landing =
$res->fetch()))
3401 Loc::getMessage(
'LANDING_NOT_FOUND')
3406 if ($landing[
'FOLDER'] ===
'Y')
3408 $landing[
'FOLDER_ID'] = $landing[
'ID'];
3414 $className = \CBitrixComponent::includeComponentClass(
$componentName);
3416 $demoCmp =
new $className;
3418 $demoCmp->arParams = [
3419 'TYPE' =>
$fields[
'SITE_TYPE'] ?? ((
$site[
'TYPE'] ==
'STORE' ||
$site[
'TYPE'] ==
'SMN') ?
'PAGE' :
$site[
'TYPE']),
3421 'SITE_WORK_MODE' =>
'N',
3422 'DISABLE_REDIRECT' =>
'Y',
3423 'DONT_LEAVE_FRAME' =>
'N',
3424 'FOLDER_ID' => $landing[
'FOLDER_ID'] ??
$fields[
'FOLDER_ID'] ?? 0,
3429 &&
$fields[
'PREPARE_BLOCKS'] ===
true
3430 && is_array(
$fields[
'PREPARE_BLOCKS_DATA'])
3433 $demoCmp->arParams[
'PREPARE_BLOCKS_DATA'] =
$fields[
'PREPARE_BLOCKS_DATA'];
3443 if (($landing[
'ACTIVE'] ??
'N') ===
'Y')
3445 Landing::createInstance($landingId)->publication();
3450 foreach ($demoCmp->getErrors() as
$code =>
$title)
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
static addUniqueAgent(string $funcName, array $params=[], int $time=7200, ?int $nextExecDelay=null)
static rebuildWebpackForLanding($lid=[])
static processingLanding(int $landingId)
static processingLanding(int $landingId)
getManifest(bool $extended=false, bool $missCache=false, array $params=array())
static getReplacesForContent(int $siteId, bool $attributesReplace=true)
static copyLandingFiles($from, $to)
static addToBlock(int $blockId, $fileId, bool $temp=false)
static deleteFromAsset(int $assetId, $fileId=[])
static copyBlockFiles($from, $to)
static deleteFromBlock($blockId, $fileId=array())
static deleteFromLanding($lid, $fileId=array())
static getFilesFromBlockContent($blockId, $content)
static getFilePath($fileId)
static getFullPath(int $folderId, ?int $siteId=null, array &$lastFolder=[])
static getBreadCrumbs(int $folderId, ?int $siteId=null)
static getAllImages($entityType=Hook::ENTITY_TYPE_LANDING)
static migrateFromTypoThemes(int $lid, int $siteId)
static beforeLandingView()
static afterLandingView()
__construct($id, $params=array())
static getDynamicFilter()
static disableCheckDeleted()
static setPreviewMode($mode=true)
static setVariables(array $vars)
setMetaData(array $metaData)
publication($blockId=null, ?Metrika\FieldsDto $metrikaFields=null)
moveBlock(int $id, int $afterId)
static getAdditionalFieldsAsArray(int $landingId, bool $skipEmpty=true)
addBlockToCollection(\Bitrix\Landing\Block $block)
applyTemplate($content=null)
static update($id, $fields=array())
move(?int $toSiteId=null, ?int $toFolderId=null)
changeParentOfBlock(int $block, array $params)
static setEditMode($mode=true)
static getAdditionalFields($id)
static isDynamicDetailPage()
static getDynamicElementId()
static disableCheckUniqueAddress()
unFavoriteBlock(int $blockId)
copyBlock(int $id, int $afterId)
view(array $params=array())
static markDelete(int $id)
sortBlock(int $id, string $action)
static isCheckUniqueAddress()
markDeletedBlock($id, $mark)
static ping($id, $deleted=false)
static resolveIdByPublicUrl(string $landingUrl, int $siteId)
getPreview(?int $id=null, bool $skipCloud=false, ?string $publicUrl=null)
activateBlock($id, $action)
static setDynamicParams($filterId, $elementId)
copy(?int $toSiteId=null, ?int $toFolderId=null, bool $withoutBlocks=false, bool $skipSystem=false)
const META_KEYS_MODIFIABLE
favoriteBlock(int $id, array $meta=[])
static enableCheckDeleted()
static createInstance($id, array $params=array())
static saveAdditionalFields($id, array $data)
addBlock(string $code, array $data=array(), bool $saveInLastUsed=false)
static $checkUniqueAddress
getPublicUrl($id=false, $absolute=true, $createPubPath=false, &$fullUrl=[])
static enableCheckUniqueAddress()
parseLocalUrl(string $content)
parametrizeMetrikaByBlock(Metrika\Metrika $metrika, Block $block)
copyAllBlocks($lid, $replaceLinks=true, array &$references=[])
static getPublicationPath($siteCode=null, $siteId=null, $createPubPath=false)
static setPageTitle($title, $single=false)
static getUrlFromFile($file)
static landingPublication(Landing $landing, $_245979103=null, bool $_1014965041=false)
static getIblockURL($elementId, $urlType)
static hasAccessForLanding($landingId, $accessType)
static getOperationsForSite($siteId)
static setScope($scope, array $params=[])
static getCurrentScopeId()
static getFilter($filterId)
static getForLanding($id)
static landingIsArea(int|array $lid)
static setForLanding($id, array $data=array())
static updateLanding(int $lid)
static updateLanding(int $lid)
static getList(array $parameters=array())
static getStyle(Element $node, $singleStyle=true)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
$_SERVER["DOCUMENT_ROOT"]
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
htmlspecialcharsbx($string, $flags=ENT_COMPAT, $doubleEncode=true)
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
<? endif;?> window document title
if(empty($signedUserToken)) $key
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
if(!Loader::includeModule('sale')) $pattern