5use \Bitrix\Main\Application;
8use \Bitrix\Main\EventResult;
9use \Bitrix\Main\Page\Asset;
10use \Bitrix\Main\Localization\Loc;
11use \Bitrix\Main\ModuleManager;
21 'CREATED_BY_ID',
'MODIFIED_BY_ID',
'DATE_CREATE',
22 'DATE_MODIFY',
'DATE_PUBLIC',
'INITIATOR_APP_CODE',
'VIEWS',
'TPL_CODE',
23 'ACTIVE',
'PUBLIC',
'SITE_CODE',
'SITE_SPECIAL',
'RULE',
24 'SITE_VERSION',
'SITE_LANG',
'SITE_TPL_CODE'
31 'DATE_MODIFY',
'DATE_PUBLIC',
'ACTIVE',
'PUBLIC'
222 $this->error =
new Error;
227 isset($params[
'force_deleted']) &&
228 $params[
'force_deleted'] ===
true
231 $filter[
'=DELETED'] = [
'Y',
'N'];
232 $filter[
'=SITE.DELETED'] = [
'Y',
'N'];
235 isset($params[
'check_permissions']) &&
236 $params[
'check_permissions'] ===
false
239 $filter[
'CHECK_PERMISSIONS'] =
'N';
240 $this->checkPermissions =
false;
243 isset($params[
'disable_link_preview']) &&
244 $params[
'disable_link_preview'] ===
true
247 $this->disableLinkPreview =
true;
252 $landing = self::getList(array(
255 'SITE_TPL_ID' =>
'SITE.TPL_ID',
256 'SITE_TPL_CODE' =>
'SITE.TPL_CODE',
257 'SITE_CODE' =>
'SITE.CODE',
258 'SITE_TYPE' =>
'SITE.TYPE',
259 'SITE_SPECIAL' =>
'SITE.SPECIAL',
260 'SITE_TITLE' =>
'SITE.TITLE',
261 'SITE_VERSION' =>
'SITE.VERSION',
262 'SITE_LANG' =>
'SITE.LANG',
263 'DOMAIN_ID' =>
'SITE.DOMAIN_ID',
264 'SITE_LANDING_ID_INDEX' =>
'SITE.LANDING_ID_INDEX'
270 if (!empty($landing[
'FOLDER_ID']))
273 foreach ($breadCrumbs as $crumb)
275 if ($crumb[
'DELETED'] ===
'Y')
282 if (
$id && isset($landing) && is_array($landing))
289 self::$siteCode = $landing[
'SITE_TYPE'];
290 $this->title = $landing[
'TITLE'];
291 $this->code = $landing[
'CODE'];
292 $this->xmlId = $landing[
'XML_ID'];
293 $this->
id = (int)$landing[
'ID'];
294 $this->version = (int)$landing[
'VERSION'];
295 $this->siteId = (int)$landing[
'SITE_ID'];
296 $this->siteTitle = $landing[
'SITE_TITLE'];
297 $this->domainId = (int)$landing[
'DOMAIN_ID'];
298 $this->folderId = (int)$landing[
'FOLDER_ID'];
299 $this->active = $landing[
'ACTIVE'] ==
'Y';
300 if ($this->checkPermissions)
307 'TPL_ID' => $landing[
'SITE_TPL_ID'],
308 'LANDING_ID_INDEX' => $landing[
'SITE_LANDING_ID_INDEX']
310 $this->tplId = $landing[
'TPL_ID'] > 0
313 $landing[
'SITE_TPL_ID'] > 0
314 ? $landing[
'SITE_TPL_ID']
317 if (isset($params[
'is_area']) && $params[
'is_area'])
319 $this->mainInstance =
false;
321 if ($landing[
'SITE_TPL_ID'] > 0 && !$landing[
'TPL_ID'])
323 $this->tplType =
'site';
328 Block::cloneForEdit($this);
334 !isset($params[
'skip_blocks']) ||
335 $params[
'skip_blocks'] !==
true
340 isset($params[
'blocks_limit']) ? $params[
'blocks_limit'] : 0,
342 'id' => isset($params[
'blocks_id']) ? $params[
'blocks_id'] : 0,
343 'deleted' => isset($params[
'deleted']) && $params[
'deleted'] === true
348 foreach (self::META_KEYS as $key)
350 $this->metaData[$key] = $landing[$key];
356 $this->error->addError(
371 foreach ($metaData as $key => $value)
373 if (in_array($key, self::META_KEYS_MODIFIABLE,
true))
375 $this->metaData[$key] = $value;
386 public static function ping($id, $deleted =
false)
388 $returnCheckDelete =
false;
395 if (self::$checkDelete)
397 $returnCheckDelete =
true;
398 self::$checkDelete =
false;
400 $filter[
'=DELETED'] = [
'Y',
'N'];
403 $check = self::getList([
410 if ($returnCheckDelete)
412 self::$checkDelete =
true;
415 return (
boolean) $check->fetch();
425 self::$editMode = (boolean) $mode;
434 return self::$editMode;
444 self::$previewMode = (boolean) $mode;
453 return self::$previewMode;
462 return self::$checkDelete;
471 self::$checkDelete =
false;
480 self::$checkDelete =
true;
489 self::$enabledUpdate =
false;
498 self::$enabledUpdate =
true;
507 return self::$checkUniqueAddress;
516 self::$checkUniqueAddress =
false;
525 self::$checkUniqueAddress =
true;
536 return new self(
$id, $params);
548 $result = new \Bitrix\Main\Result;
552 'UNABLE_DELETE_INCLUDE'
558 $event =
new Event(
'landing',
'onBeforeLandingRecycle', array(
564 foreach ($event->getResults() as $result)
566 if ($result->getType() == EventResult::ERROR)
568 $return = new \Bitrix\Main\Result;
569 foreach ($result->getErrors() as
$error)
579 if (($currentScope =
Site\Type::getCurrentScopeId()))
584 $landing = self::createInstance($id, [
'skip_blocks' =>
true]);
586 $res = parent::update($id, array(
590 if ($res->isSuccess())
592 $landing->clearFolderIndex();
608 $event =
new Event(
'landing',
'onBeforeLandingRecycle', array(
614 foreach ($event->getResults() as $result)
616 if ($result->getType() == EventResult::ERROR)
618 $return = new \Bitrix\Main\Result;
619 foreach ($result->getErrors() as
$error)
629 return parent::update(
$id, array(
642 $result = new \Bitrix\Main\Entity\DeleteResult();
647 $params[
'force_deleted'] =
true;
653 foreach ([
'draft',
'public'] as
$code)
655 self::setEditMode($code ==
'draft');
656 $landing = self::createInstance(
$id, $params);
657 if ($landing->exist())
659 foreach ($landing->getBlocks() as $block)
661 if ($block->getAccess() < $block::ACCESS_X)
675 if (!$landing->getError()->isEmpty())
678 $landing->getError()->getErrors()[0]
687 $params[
'skip_blocks'] =
true;
688 foreach (array(
'draft',
'public') as
$code)
690 self::setEditMode($code ==
'draft');
691 $landing = self::createInstance(
$id, $params);
692 if ($landing->exist())
694 Block::deleteAll(
$id);
700 $res = parent::delete(
$id);
701 if ($res->isSuccess())
703 $landing->clearFolderIndex();
734 foreach (self::getHooks(
$id) as $hook)
736 $fields += $hook->getPageFields();
751 $fields = self::getAdditionalFields($landingId);
753 foreach ($fields as $key => $field)
755 $fields[$key] = $field->getValue();
757 if ($skipEmpty && !$fields[$key])
759 unset($fields[$key]);
763 if (in_array($key, $hookFiles))
765 $fields[
'~' . $key] = $fields[$key];
766 if (intval($fields[$key]) > 0)
795 foreach ($vars as
$code => $val)
797 self::$variables[
$code] = $val;
807 return self::$variables;
818 self::$dynamicFilterId = $filterId;
819 self::$dynamicElementId = $elementId;
828 static $filter =
null;
829 if ($filter ===
null)
831 $filter = Source\FilterEntity::getFilter(
832 self::$dynamicFilterId
844 return self::$dynamicElementId;
853 return self::$dynamicFilterId && self::$dynamicElementId;
863 public function getPreview(?
int $id =
null,
bool $skipCloud =
false, ?
string $publicUrl =
null): ?string
875 return rtrim($publicUrl,
'/') .
'/preview.jpg';
878 static $hookPics =
null;
880 if ($hookPics ===
null)
882 $hookPics = Hook\Page\MetaOg::getAllImages();
890 if (isset($hookPics[
$id]))
892 $pic = $hookPics[$id];
893 if (intval($pic) > 0)
911 public function getPublicUrl($id =
false, $absolute =
true, $createPubPath =
false, &$fullUrl = [])
918 $previewMode = self::$previewMode && !$this->disableLinkPreview;
919 $siteKeyCode = Site\Type::getKeyCode();
923 $bitrix24originalVar = $bitrix24;
925 $domainDefault =
null;
934 'SITE_ID_INDEX' =>
'SITE.LANDING_ID_INDEX',
935 'SITE_PROTOCOL' =>
'SITE.DOMAIN.PROTOCOL',
936 'SITE_DOMAIN' =>
'SITE.DOMAIN.DOMAIN',
937 'SITE_CODE' =>
'SITE.CODE',
938 'SITE_TYPE' =>
'SITE.TYPE',
939 'SITE_SMN_ID' =>
'SITE.SMN_SITE_ID'
943 '=DELETED' => [
'Y',
'N'],
944 'CHECK_PERMISSIONS' =>
'N'
947 while ($row = $res->fetch())
949 if ($row[
'SITE_TYPE'] ==
'SMN')
955 $bitrix24 = $bitrix24originalVar;
957 $domainReplace =
false;
958 $row[
'SITE_ID_ORIG'] = $row[
'SITE_ID'];
960 if (!$row[
'SITE_DOMAIN'])
964 $domainDefault = Domain::getList(array(
970 if (isset($domainDefault[
'PROTOCOL']))
972 $row[
'SITE_PROTOCOL'] = $domainDefault[
'PROTOCOL'];
974 if (isset($domainDefault[
'DOMAIN']))
976 $row[
'SITE_DOMAIN'] = $domainDefault[
'DOMAIN'];
978 $domainReplace =
true;
983 $row[
'SITE_PROTOCOL'] =
'https';
985 if ($domainReplace || !$bitrix24 || $disableCloud)
989 $row[
'SITE_SMN_ID'] ? $row[
'SITE_SMN_ID'] :
$siteId,
992 $pubPath = rtrim($pubPath,
'/');
995 if (!ModuleManager::isModuleInstalled(
'bitrix24'))
999 $row[
'SITE_SMN_ID'] ? $row[
'SITE_SMN_ID'] :
$siteId,
1003 if (isset($row[
'SITE_ID']))
1005 if ($siteKeyCode ==
'CODE')
1007 $row[
'SITE_ID'] = $row[
'SITE_CODE'];
1011 $row[
'SITE_ID'] =
'/' . $row[
'SITE_ID'] .
'/';
1017 if ($siteKeyCode ==
'CODE')
1028 $row[
'CODE'] .=
'/';
1032 $lastFolderItem = [];
1033 $fullUrl[$row[
'ID']] = ($absolute ? $hostUrl :
'') .
1035 ($bitrix24 ? $row[
'SITE_ID'] :
'/') .
1037 ($row[
'FOLDER_ID'] ? ltrim(
Folder::getFullPath($row[
'FOLDER_ID'], $row[
'SITE_ID_ORIG'], $lastFolderItem),
'/') :
'');
1038 $folderIndex = $row[
'ID'] == ($lastFolderItem[
'INDEX_ID'] ?? 0)
1040 !($lastFolderItem[
'INDEX_ID'] ?? 0)
1041 && ($row[
'CODE'] ??
null)
1042 && ($lastFolderItem[
'CODE'] ??
null)
1043 && trim($row[
'CODE'],
'/') === $lastFolderItem[
'CODE']
1045 $data[$row[
'ID']] = $fullUrl[$row[
'ID']] .
1046 (($row[
'ID'] == $row[
'SITE_ID_INDEX'] || $folderIndex || $row[
'RULE']) ?
'' : $row[
'CODE']);
1049 $fullUrl[$row[
'ID']] .= $row[
'CODE'];
1054 $lastFolderItem = [];
1055 $fullUrl[$row[
'ID']] = (
1058 $row[
'SITE_PROTOCOL'] .
'://' .
1063 (($domainReplace || !$bitrix24) ? $pubPath :
'') .
1064 ((
$previewMode && !$bitrix24) ?
'/preview/' . $publicHash :
'') .
1065 (($domainReplace && $bitrix24) ? $row[
'SITE_ID'] :
'/') .
1066 ((
$previewMode && $bitrix24) ?
'preview/' . $publicHash .
'/' :
'') .
1067 ($row[
'FOLDER_ID'] ? ltrim(
Folder::getFullPath($row[
'FOLDER_ID'], $row[
'SITE_ID_ORIG'], $lastFolderItem),
'/') :
'');
1068 $folderIndex = $row[
'ID'] == $lastFolderItem[
'INDEX_ID'] || !$lastFolderItem[
'INDEX_ID'] && trim($row[
'CODE'],
'/') === $lastFolderItem[
'CODE'];
1069 $data[$row[
'ID']] = $fullUrl[$row[
'ID']] .
1070 (($row[
'ID'] == $row[
'SITE_ID_INDEX'] || $folderIndex || $row[
'RULE']) ?
'' : $row[
'CODE']);
1073 $fullUrl[$row[
'ID']] .= $row[
'CODE'];
1082 elseif (!empty($data))
1084 return array_pop($data);
1103 $componentName =
'bitrix:landing.pub';
1104 $className = \CBitrixComponent::includeComponentClass($componentName);
1105 $demoCmp =
new $className;
1106 $demoCmp->initComponent($componentName);
1107 $demoCmp->arParams = [
1108 'PATH' => mb_substr($landingUrl, mb_strlen($publicationPath)),
1109 'DRAFT_MODE' =>
'Y',
1110 'SITE_ID' => $siteId,
1111 'SITE_TYPE' => self::getSiteType(),
1112 'CHECK_PERMISSIONS' =>
'N',
1113 'NOT_CHECK_DOMAIN' =>
'Y',
1114 'NOT_SEND_HTTP_STATUS' =>
'Y',
1117 return $demoCmp->detectPage() ?:
null;
1125 public function view(array $params = array())
1128 $editMode = $this->mainInstance && $blockEditMode;
1130 if (!isset($params[
'parse_link']))
1132 $params[
'parse_link'] =
true;
1135 if (!isset($params[
'apply_template']))
1137 $params[
'apply_template'] =
true;
1140 if (!isset($params[
'check_permissions']))
1142 $params[
'check_permissions'] =
true;
1145 if (!$params[
'check_permissions'])
1151 if ($this->mainInstance)
1154 \htmlspecialcharsbx($this->title)
1159 if ($this->mainInstance)
1161 if ($this->folderId)
1164 foreach ($chains as $chain)
1168 $chain[
'INDEX_ID'] ?
'#landing' . $chain[
'INDEX_ID'] :
'#'
1172 else if (($this->siteRow[
'LANDING_ID_INDEX'] ?? 0) != $this->id)
1176 '#landing' . $this->
id
1185 'site_id' => $this->siteId,
1186 'server_name' => $_SERVER[
'SERVER_NAME'],
1187 'xml_id' => $this->xmlId,
1188 'blocks' => Block::getRepository(),
1189 'style' => Block::getStyle(),
1190 'attrs' => Block::getAttrs(),
1192 'saveOriginalFileName' => Option::get(
'main',
'save_original_file_name') ===
'Y'
1196 $event =
new Event(
'landing',
'onLandingView', array(
1197 'options' => $options
1200 foreach ($event->getResults() as $result)
1202 if ($result->getResultType() != EventResult::ERROR)
1204 if (($modified = $result->getModified()))
1206 if (isset($modified[
'options']) && is_array($modified[
'options']))
1208 $options = array_merge($options, $modified[
'options']);
1214 Asset::getInstance()->addString(
1215 '<script type="text/javascript">' .
1216 'BX.ready(function(){'
1217 .
'if (typeof BX.Landing.Main !== "undefined")'
1219 .
'BX.Landing.Env.createInstance(' . \CUtil::phpToJSObject($options,
false,
false,
true) .
');'
1220 .
'BX.Landing.Main.createInstance(' . $this->
id .
');'
1230 if ($params[
'apply_template'] && $this->mainInstance)
1238 $content =
'<div class="landing-main"' .
1239 ' data-site="' . $this->siteId .
'"' .
1240 ' data-landing="' . $this->
id .
'">' .
1248 Landing\Seo::beforeLandingView();
1249 foreach ($this->blocks as $block)
1251 $block->view($blockEditMode, $this);
1253 Landing\Seo::afterLandingView();
1254 if ($this->mainInstance)
1258 $contentMain = ob_get_contents();
1265 $content = $contentMain;
1268 if (mb_strpos($content,
'#CONTENT#') !==
false)
1270 $replace[
'#CONTENT#'] =
'<a id="workarea"></a>' . $contentMain;
1273 if (mb_strpos($content . $contentMain,
'#crm') !==
false)
1280 $content = str_replace(
1281 array_keys($replace),
1282 array_values($replace),
1288 if (!$blockEditMode && $this->mainInstance)
1292 false, 0,
false,
true
1294 $breadcrumb = ob_get_contents();
1296 $content = str_replace(
1310 if ($params[
'parse_link'] ===
true && !$blockEditMode)
1319 if (!$params[
'check_permissions'])
1331 if ($this->tplType ==
'site')
1350 $template = Template::getList(array(
1352 'ID' => $this->tplId
1358 if ($template[
'XML_ID'] ==
'empty')
1360 $template[
'CONTENT'] =
'<div class="landing-main">' .
1361 $template[
'CONTENT'] .
1367 '>#CONTENT#<' =>
' data-site="' . $this->siteId .
1368 '" data-landing="' . $this->
id .
1370 '#CONTENT#' => $content ? $content :
'#CONTENT#'
1376 '#CONTENT#' => $content ? $content :
'#CONTENT#'
1380 if ($template[
'AREA_COUNT'] > 0)
1382 foreach ($this->
getAreas() as $area => $lid)
1385 $landing = self::createInstance($lid, array(
1387 'check_permissions' =>
false,
1388 'disable_link_preview' => $this->disableLinkPreview
1390 if ($landing->exist())
1397 $replace[
'>#AREA_' . $area .
'#<'] =
' data-site="' . $landing->getSiteId() .
1398 '" data-landing="' . $lid .
1399 '" data-rights="' . implode(
',',
$rights) .
1400 '">#AREA_' . $area .
'#<';
1402 $replace[
'#AREA_' . $area .
'#'] = ob_get_contents();
1406 $content = str_replace(
1407 array_keys($replace),
1408 array_values($replace),
1409 $template[
'CONTENT']
1417 $content =
'#CONTENT#';
1419 $content =
'<div class="landing-main" ' .
1420 'data-site="' . $this->siteId .
'" ' .
1421 'data-landing="' . $this->
id .
'">' .
1436 $pattern =
'/([",\'\;]{1})(page:|block:|user:)?#(landing|block|dynamic|user)([\d\_]+)\@{0,1}([^\'"]*)([",\'\&]{1})/is';
1437 $patternWithoutUser =
'/([",\'\;]{1})(page:|block:)?#(landing|block|dynamic)([\d\_]+)\@{0,1}([^\'"]*)([",\'\&]{1})/is';
1438 static $isIframe =
null;
1440 if (!self::$editMode && $content)
1442 $content = Subtype\Form::prepareFormsToView(
1447 if ($isIframe ===
null)
1450 $isIframe = $request->get(
'IFRAME') ==
'Y';
1454 if (self::$previewMode)
1456 $content = preg_replace_callback(
1457 '/href\="(product:)?#catalog(Element|Section)([\d]+)"/i',
1460 return 'href="' . PublicAction\Utils::getIblockURL(
1462 mb_strtolower($href[2])
1473 $replace[
'</form>'] =
'<input type="hidden" name="IFRAME" value="Y" /></form>';
1477 if ($this->siteRow[
'LANDING_ID_INDEX'] > 0)
1479 $replace[
'#system_mainpage'] =
'#landing' . $this->siteRow[
'LANDING_ID_INDEX'];
1484 $content = str_replace(
1485 array_keys($replace),
1486 array_values($replace),
1492 if (preg_match_all($pattern, $content, $matches))
1495 'LANDING' => array(),
1498 'DYNAMIC' => array()
1500 for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
1502 if (mb_strtoupper($matches[3][$i]) ==
'LANDING')
1504 $urls[
'LANDING'][] = $matches[4][$i];
1506 else if (mb_strtoupper($matches[3][$i]) ==
'DYNAMIC')
1508 [$dynamicId, ] = explode(
'_', $matches[4][$i]);
1509 $urls[
'DYNAMIC'][] = $dynamicId;
1511 else if (mb_strtoupper($matches[3][$i]) ==
'USER')
1513 $urls[
'USER'][] = $matches[4][$i];
1517 $urls[
'BLOCK'][] = $matches[4][$i];
1522 $anchorsId = array();
1523 $anchorsPublicId = array();
1524 if (!empty($urls[
'BLOCK']))
1526 $urls[
'BLOCK'] = Block::getRowByBlockId(
1529 'ID',
'LID',
'PARENT_ID',
'ANCHOR'
1532 foreach ($urls[
'BLOCK'] as $bid => &$bidRow)
1535 !self::$previewMode &&
1536 $bidRow[
'PARENT_ID']
1539 $anchorsPublicId[$bid] = $bidRow[
'PARENT_ID'];
1543 $anchorsId[$bid] = $bidRow[
'ANCHOR']
1544 ? \htmlspecialcharsbx($bidRow[
'ANCHOR'])
1545 : Block::getAnchor($bidRow[
'ID']);
1547 $bidRow = $bidRow[
'LID'];
1550 $urls[
'LANDING'] = array_unique(array_merge(
1555 $urls[
'LANDING'] = array_unique(array_merge(
1560 if ($anchorsPublicId)
1562 $anchorsPublicIdTmp = Block::getRowByBlockId(
1565 'ID',
'LID',
'PARENT_ID',
'ANCHOR'
1568 foreach ($anchorsPublicId as $bid => $bidParent)
1570 if (!isset($anchorsPublicIdTmp[$bidParent]))
1574 $bidParent = $anchorsPublicIdTmp[$bidParent];
1575 $anchorsPublicId[$bid] = $bidParent[
'ANCHOR']
1576 ? \htmlspecialcharsbx($bidParent[
'ANCHOR'])
1577 : Block::getAnchor($bidParent[
'ID']);
1580 $anchorsPublicId += $anchorsId;
1584 if (!empty($urls[
'LANDING']))
1592 foreach ($urls[
'LANDING'] as $lid => &$url)
1594 $lidEncoded[] = $lid;
1595 $url = \htmlspecialcharsbx($url);
1598 $url .=
'?IFRAME=Y';
1603 if (!empty($urls[
'BLOCK']))
1605 foreach ($urls[
'BLOCK'] as $bid => $lid)
1607 if (isset($urls[
'LANDING'][$lid]))
1609 if (!in_array($lid, $lidEncoded))
1611 $urls[
'LANDING'][$lid] = \htmlspecialcharsbx($urls[
'LANDING'][$lid]);
1613 $urls[
'LANDING'][$lid] .= ($isIframe ?
'?IFRAME=Y' :
'');
1614 $urls[
'BLOCK'][$bid] = $urls[
'LANDING'][$lid] .
'#' . $anchorsPublicId[$bid];
1618 unset($urls[
'BLOCK'][$bid]);
1623 if (!empty($urls[
'LANDING']))
1625 krsort($urls[
'LANDING']);
1626 $content = preg_replace_callback(
1627 $patternWithoutUser,
1628 function($matches) use($urls, $landingFull, $isIframe)
1631 $matches[3] = mb_strtoupper($matches[3]);
1632 if ($matches[3] ==
'DYNAMIC')
1634 $matches[3] =
'LANDING';
1635 if (($underPos = mb_strpos($matches[4],
'_')) !==
false)
1637 $dynamicPart = mb_substr($matches[4], $underPos);
1638 $matches[4] = mb_substr($matches[4], 0, $underPos);
1640 [$dynamicId, ] = explode(
'_', $matches[4]);
1641 $matches[4] = $dynamicId;
1643 if (isset($urls[$matches[3]][$matches[4]]))
1647 $landingUrl = $urls[$matches[3]][$matches[4]];
1648 if (isset($landingFull[$matches[4]]))
1650 $landingUrl = $landingFull[$matches[4]];
1652 $url = mb_substr($landingUrl, 0, mb_strlen($landingUrl) - 1);
1653 $url .= $dynamicPart . ($isIframe ?
'/?IFRAME=Y' :
'/');
1657 $url = $urls[$matches[3]][$matches[4]];
1659 return $matches[1] .
1660 $url . $matches[5] .
1665 return $matches[1] .
1666 '#landing' . $matches[4] . $matches[5] . $dynamicPart .
1672 $landingUrls = array();
1673 foreach ($urls[
'LANDING'] as $lid => $url)
1675 $landingUrls[
'@#landing' . $lid.
'@'] = $url;
1679 if (!empty($urls[
'USER']))
1681 $patternForPseudoUrlUser =
'/data-pseudo-url="{\S*(user:)?#user([\d\_]+)\S*}"/is';
1682 $content = preg_replace_callback(
1683 $patternForPseudoUrlUser,
1687 return 'onClick="BX.SidePanel.Instance.open('. $url .
')" ';
1691 $patternForUser =
'/(user:)?#(user)([\d\_]+)/is';
1692 $content = preg_replace_callback(
1712 $hooksExec = array();
1716 if ($hook->enabled())
1719 $hooksExec[$hook->getCode()] = $hook;
1725 if ($hook->enabled())
1727 $hooksExec[$hook->getCode()] = $hook;
1731 foreach ($hooksExec as $hook)
1735 $hook->enabledInEditMode()
1745 if ($hook->getCode() ===
'GMAP')
1747 $hook->setSiteId($this->siteId);
1759 return $this->
id > 0;
1768 return $this->active;
1786 return $this->xmlId;
1795 return $this->title;
1813 return $this->metaData;
1822 if (!$this->checkPermissions)
1835 if (!$this->checkPermissions)
1848 if (!$this->checkPermissions)
1861 return $this->folderId;
1870 return $this->siteId;
1879 return $this->siteTitle;
1888 return $this->domainId;
1897 return self::$siteCode;
1908 $res = Site::getList(array(
1913 'ID' => $this->siteId
1916 if ($row = $res->fetch())
1918 return $row[
'SMN_SITE_ID'];
1931 return $this->blocks;
1942 return isset($this->blocks[
$id])
1943 ? $this->blocks[$id]
1954 if ($block->exist())
1956 $this->blocks[$block->getId()] = $block;
1966 return $this->error;
1977 $error = $this->error->getFirstError();
1978 return new \Bitrix\Main\Error(
1992 static $touched = [];
1994 if (isset($touched[$this->
id]))
1999 $touched[$this->id] =
true;
2001 if (self::update($this->
id, [
'PUBLIC' =>
'N'])->isSuccess())
2013 $needUpdate =
false;
2015 if ($this->version <= 1)
2032 if ($this->version <= 2)
2036 Assets\PreProcessing\Icon::processingLanding($this->
id);
2037 Assets\Manager::rebuildWebpackForLanding($this->
id);
2039 if ($this->version <= 3)
2043 Assets\PreProcessing\Font::processingLanding($this->
id);
2045 if ($this->version <= 4)
2049 Hook\Page\ThemeFonts::migrateFromTypoThemes($this->
id, $this->siteId);
2051 if ($this->version <= 5)
2056 Assets\PreProcessing\Icon::processingLanding($this->
id);
2057 Assets\Manager::rebuildWebpackForLanding($this->
id);
2059 if ($this->version <= 6)
2062 Update\Block\Buttons::updateLanding($this->
id);
2063 Update\Block\FontWeight::updateLanding($this->
id);
2066 if ($this->version <= 7)
2069 Assets\PreProcessing\Icon::processingLanding($this->
id);
2070 Assets\Manager::rebuildWebpackForLanding($this->
id);
2073 if ($this->version <= 9)
2077 Subtype\Form::updateLandingToEmbedForms($this->
id);
2078 Assets\Manager::rebuildWebpackForLanding($this->
id);
2079 $this->version = 10;
2081 if ($this->version <= 10)
2084 Update\Block\DuplicateImages::updateLanding($this->
id);
2086 $this->version = 11;
2091 self::update($this->
id, [
2092 'VERSION' => $this->version,
2093 'DATE_MODIFY' =>
false,
2094 'MODIFIED_BY_ID' =>
false
2133 static $siteUpdated = [];
2135 $res = parent::update($this->
id, array(
2138 'DATE_MODIFY' =>
false
2140 if ($res->isSuccess())
2143 !in_array($this->siteId, $siteUpdated) &&
2147 $siteUpdated[] = $this->siteId;
2148 Site::update($this->siteId, array());
2151 $event =
new Event(
'landing',
'onLandingAfterUnPublication', array(
2152 'id' => $this->
getId()
2159 $this->error->addFromResult($res);
2171 public function addBlock(
string $code, array $data = array(),
bool $saveInLastUsed =
false)
2175 $this->error->addError(
2182 if (!isset($data[
'PUBLIC']))
2184 $data[
'PUBLIC'] = $this::$editMode ?
'N' :
'Y';
2187 $block = Block::createFromRepository($this, $code, $data);
2191 if ($saveInLastUsed)
2193 Block::markAsUsed($code);
2202 $history->push(
'ADD_BLOCK', [
'block' => $block]);
2205 return $block->getId();
2219 if (isset($this->blocks[
$id]))
2221 $result = $this->blocks[$id]->unlink();
2222 $this->error->copyError(
2227 unset($this->blocks[$id]);
2234 $this->error->addError(
2251 if (!isset($this->blocks[
$id]))
2253 $this->blocks[$id] =
new Block($id);
2257 isset($this->blocks[$id]) &&
2258 $this->blocks[$id]->
exist() &&
2259 $this->blocks[$id]->getLandingId() == $this->
getId()
2262 if ($this->blocks[$id]->getAccess() >= $this->blocks[$id]::ACCESS_X)
2264 $this->blocks[$id]->markDeleted($mark);
2267 Assets\PreProcessing::blockUndeleteProcessing(
2271 if ($this->blocks[$id]->save())
2278 $history->push(
'REMOVE_BLOCK', [
'block' => $this->blocks[$id]]);
2281 unset($this->blocks[$id]);
2294 $this->error->copyError(
2301 $this->error->addError(
2310 $this->error->addError(
2329 if (isset($this->blocks[
$id]))
2331 $result = $this->blocks[$id]->changeLanding($lid);
2332 $this->error->copyError($this->blocks[$id]->
getError());
2335 unset($this->blocks[$id]);
2341 $this->error->addError(
2355 uasort($this->blocks,
function($a, $b)
2357 if ($a->getSort() == $b->getSort())
2359 return ($a->getId() < $b->getId()) ? -1 : 1;
2361 return ($a->getSort() < $b->getSort()) ? -1 : 1;
2364 foreach ($this->blocks as
$id => $block)
2366 $block->saveSort($sort);
2380 if (isset($this->blocks[$id]))
2382 $blocks = array_keys($this->blocks);
2383 for ($i = 0, $c = count(
$blocks); $i < $c; $i++)
2388 $targetKey = $i + ($action ===
'up' ? -1 : 1);
2389 if (isset(
$blocks[$targetKey]))
2391 $thisBlock = $this->blocks[$id];
2392 $targetBlock = $this->blocks[
$blocks[$targetKey]];
2393 $thisBlockSort = $thisBlock->getSort();
2394 $targetBlockSort = $targetBlock->getSort();
2396 $thisBlock->setSort($targetBlockSort);
2397 $targetBlock->setSort($thisBlockSort);
2398 $res1 = $thisBlock->save();
2399 $res2 = $targetBlock->save();
2401 $this->error->copyError($thisBlock->getError());
2402 $this->error->copyError($targetBlock->getError());
2409 return $res1 && $res2;
2412 $this->error->addError(
2423 $this->error->addError(
2444 $history->push(
'SORT_BLOCK', [
2446 'lid' => $this->
getId(),
2469 $history->push(
'SORT_BLOCK', [
2471 'lid' => $this->
getId(),
2491 if (isset($this->blocks[
$id]))
2493 if ($this->blocks[$id]->setActive($action ==
'show'))
2495 if ($res = $this->blocks[$id]->save())
2500 $this->error->copyError($this->blocks[$id]->
getError());
2505 $this->error->addError(
2541 $bewBlockId = $this->
copyBlock($id, $id);
2543 if ($bewBlockId > 0)
2546 $this->blocks[$bewBlockId]->changeLanding(0) &&
2547 $this->blocks[$bewBlockId]->changeFavoriteMeta($meta)
2550 Block::markAsUsed($this->blocks[$bewBlockId]->
getCode() .
'@' . $bewBlockId);
2551 \Bitrix\Landing\Block::clearRepositoryCache();
2552 if ($meta[
'preview'] ??
null)
2559 $this->error->copyError($this->blocks[$bewBlockId]->
getError());
2574 $block =
new Block($blockId);
2575 if (!$block || empty($block->getMeta()[
'FAVORITE_META']))
2577 $this->error->addError(
2585 $block->getAccess() < Block::ACCESS_X
2589 $this->error->addError(
2596 if (BlockTable::delete($blockId)->isSuccess())
2599 Block::removeAsUsed($block->getCode() .
'@' . $block->getId());
2600 Block::clearRepositoryCache();
2615 $block = intval($block);
2616 $move = isset($params[
'MOVE']) && $params[
'MOVE'];
2617 $afterId = isset($params[
'AFTER_ID']) ? (int)$params[
'AFTER_ID'] : 0;
2618 $fromLandingRow = Block::getRowByBlockId($block, [
'ID',
'LID',
'SITE_TYPE' =>
'LANDING.SITE.TYPE']);
2619 $fromLandingId = $fromLandingRow[
'LID'] ??
null;
2620 $currentScopeId = Site\Type::getCurrentScopeId();
2621 $same = $this->
id == $fromLandingId;
2623 if ($currentScopeId !== $fromLandingRow[
'SITE_TYPE'])
2625 Site\Type::setScope($fromLandingRow[
'SITE_TYPE']);
2630 $fromLanding = clone $this;
2634 $fromLanding = self::createInstance($fromLandingId);
2638 if ($this->
exist() && $fromLanding->exist())
2640 $fromLandingBlocks = $fromLanding->getBlocks();
2644 $res = $fromLanding->transferBlock($block, $this->
id);
2645 $this->error->copyError($fromLanding->getError());
2648 $newBlock = $fromLandingBlocks[$block];
2652 else if (isset($fromLandingBlocks[$block]))
2654 $srcBlock = $fromLandingBlocks[$block];
2655 $newBlock = Block::createFromRepository(
2657 $srcBlock->getCode(),
2659 'ACTIVE' => $srcBlock->isActive() ?
'Y' :
'N',
2660 'DESIGNED' => $srcBlock->isDesigned() ?
'Y' :
'N',
2661 'ACCESS' => $srcBlock->getAccess(),
2662 'SORT' => $srcBlock->getSort(),
2663 'CONTENT' => $srcBlock->getContent(),
2664 'SOURCE_PARAMS' => $srcBlock->getDynamicParams(),
2668 $newBlock->saveContent(
2669 $srcBlock->getContent()
2682 if (isset($newBlock) && $newBlock)
2684 if ($afterId > 0 && isset($this->blocks[$afterId]))
2686 $targetBlock = $this->blocks[$afterId];
2690 $blocksTmp = array_values($this->blocks);
2691 $targetBlock = array_pop($blocksTmp);
2695 $newBlock->setSort($targetBlock->getSort() + 1);
2703 if ($this->error->isEmpty())
2705 if ($move && !$same)
2707 $fromLanding->touch();
2712 $this->error->copyError($fromLanding->getError());
2714 if ($currentScopeId !== $fromLandingRow[
'SITE_TYPE'])
2716 Site\Type::setScope($currentScopeId);
2719 if ($this->error->isEmpty())
2724 return isset($newBlock) ? $newBlock->getId() :
null;
2737 'AFTER_ID' => $afterId
2741 $this->error->addError(
2756 public function copyAllBlocks($lid, $replaceLinks =
true, array &$references = [])
2758 $landing = self::createInstance($lid);
2760 if ($this->
exist() && $landing->exist())
2764 foreach ($landing->getBlocks() as $block)
2766 $newBlock = Block::createFromRepository(
2770 'ACTIVE' => $block->isActive() ?
'Y' :
'N',
2771 'DESIGNED' => $block->isDesigned() ?
'Y' :
'N',
2772 'PUBLIC' => $block->isPublic() ?
'Y' :
'N',
2773 'ACCESS' => $block->getAccess(),
2774 'SORT' => $block->getSort(),
2775 'CONTENT' => $block->getContent(),
2776 'SOURCE_PARAMS' => $block->getDynamicParams()
2780 $oldNew[$block->getId()] = $newBlock;
2781 $references[$block->getId()] = $newBlock->getId();
2788 $content = $block->getContent();
2789 foreach ($oldNew as $oldId => $newBlock)
2799 $content = str_replace(
2801 '#block' . $newBlock->getId(),
2804 $block->saveContent($content);
2812 $this->error->copyError($this->
getError());
2813 $this->error->copyError($landing->getError());
2822 if ($this->folderId)
2824 $resFolder = Folder::getList([
2829 'ID' => $this->folderId,
2830 'INDEX_ID' => $this->
id
2833 if ($resFolder->fetch())
2835 Folder::update($this->folderId, [
2847 private function canPublicAfterCopy(): bool
2849 $siteId = $this->getSiteId();
2850 $folderId = $this->getFolderId();
2853 if (!$this->canPublication())
2866 foreach ($crumbs as $crumb)
2869 if ($crumb[
'ACTIVE'] ===
'Y')
2875 $res = self::getList([
2881 'FOLDER_ID' => $crumb[
'ID'],
2892 $res = Folder::getList([
2898 'PARENT_ID' => $crumb[
'ID'],
2919 public function move(?
int $toSiteId =
null, ?
int $toFolderId =
null): bool
2921 if (!$this->
exist())
2934 $this->error->addError(
2943 $this->error->addError(
2944 'DELETE_ACCESS_DENIED',
2950 $result = self::update($this->
id, [
2953 'CODE' => $this->code,
2954 'SITE_ID' => $toSiteId,
2955 'FOLDER_ID' => $toFolderId
2958 if ($result->isSuccess())
2961 if ($this->active && $this->canPublicAfterCopy($toFolderId))
2967 $this->error->addFromResult($result);
2969 return $result->isSuccess();
2980 public function copy(?
int $toSiteId =
null, ?
int $toFolderId =
null,
bool $withoutBlocks =
false,
bool $skipSystem =
false): ?int
2994 if ($toFolderId !==
null)
3002 if (intval($folderRow[
'SITE_ID'] ??
null) !== $toSiteId)
3013 '=TITLE' => $landingRow[
'TITLE'],
3016 'SITE_ID' => $toSiteId,
3021 'CODE' => $landingRow[
'CODE'],
3024 'TITLE' => $addCopyMark
3026 : $landingRow[
'TITLE'],
3027 'SYS' => $skipSystem ?
'N' : $landingRow[
'SYS'],
3028 'XML_ID' => $landingRow[
'XML_ID'],
3029 'TPL_CODE' => $landingRow[
'TPL_CODE'],
3030 'INITIATOR_APP_CODE' => $landingRow[
'INITIATOR_APP_CODE'],
3031 'DESCRIPTION' => $landingRow[
'DESCRIPTION'],
3032 'TPL_ID' => $landingRow[
'TPL_ID'],
3033 'SITE_ID' => $toSiteId,
3034 'SITEMAP' => $landingRow[
'SITEMAP'],
3039 if ($res->isSuccess())
3043 if ($landingNew->exist())
3045 if (!$withoutBlocks)
3047 $landingNew->copyAllBlocks($this->
id);
3052 $landingNew->getId()
3057 $landingNew->getId()
3065 if ($landingRow[
'ACTIVE'] ===
'Y' && $landingNew->canPublicAfterCopy($toFolderId))
3067 $landingNew->publication();
3069 return $landingNew->getId();
3071 $this->error->copyError($landingNew->getError());
3075 $this->error->addFromResult($res);
3092 'AFTER_ID' => $afterId
3096 $this->error->addError(
3110 public static function update($id, $fields = array())
3112 if (self::$enabledUpdate)
3114 return parent::update(
$id, $fields);
3118 return new \Bitrix\Main\Result;
3129 public static function addByTemplate(
int $siteId,
string $code, array $fields = []): \
Bitrix\Main\
Entity\
AddResult
3131 $result = new \Bitrix\Main\Entity\AddResult;
3134 $res = Site::getList([
3142 if (!($site = $res->fetch()))
3152 if ($fields[
'ID'] ??
null)
3154 $res = self::getList([
3156 'ID',
'FOLDER_ID',
'FOLDER',
'ACTIVE'
3159 'SITE_ID' => $siteId,
3160 'ID' => $fields[
'ID']
3163 if (!($landing = $res->fetch()))
3165 $result->addError(
new \
Bitrix\Main\Error(
3171 if ($landing[
'FOLDER'] ===
'Y')
3173 $landing[
'FOLDER_ID'] = $landing[
'ID'];
3178 $componentName =
'bitrix:landing.demo';
3179 $className = \CBitrixComponent::includeComponentClass($componentName);
3181 $demoCmp =
new $className;
3182 $demoCmp->initComponent($componentName);
3183 $demoCmp->arParams = [
3184 'TYPE' => $fields[
'SITE_TYPE'] ?? (($site[
'TYPE'] ==
'STORE' || $site[
'TYPE'] ==
'SMN') ?
'PAGE' : $site[
'TYPE']),
3185 'SITE_ID' => $siteId,
3186 'SITE_WORK_MODE' =>
'N',
3187 'DISABLE_REDIRECT' =>
'Y',
3188 'DONT_LEAVE_FRAME' =>
'N',
3189 'FOLDER_ID' => $landing[
'FOLDER_ID'] ?? $fields[
'FOLDER_ID'] ?? 0,
3193 isset($fields[
'PREPARE_BLOCKS'], $fields[
'PREPARE_BLOCKS_DATA'])
3194 && $fields[
'PREPARE_BLOCKS'] ===
true
3195 && is_array($fields[
'PREPARE_BLOCKS_DATA'])
3198 $demoCmp->arParams[
'PREPARE_BLOCKS_DATA'] = $fields[
'PREPARE_BLOCKS_DATA'];
3202 $landingId = $demoCmp->createPage($siteId, $code);
3207 $result->setId($landingId);
3208 if (($landing[
'ACTIVE'] ??
'N') ===
'Y')
3215 foreach ($demoCmp->getErrors() as $code => $title)
3217 $result->addError(
new \
Bitrix\Main\
Error($code, $title));
static addUniqueAgent(string $funcName, array $params=[], int $time=7200, ?int $nextExecDelay=null)
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)
const ENTITY_TYPE_LANDING
static publicationSite($siteId)
static getForLanding($id)
static publicationLanding($lid)
static copyLanding($from, $to)
static setEditMode(bool $mode=true)
static saveForLanding(int $id, array $data)
__construct($id, $params=array())
static getDynamicFilter()
static disableCheckDeleted()
static setPreviewMode($mode=true)
static setVariables(array $vars)
setMetaData(array $metaData)
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)
static setEditMode($mode=true)
static getAdditionalFields($id)
static isDynamicDetailPage()
static getDynamicElementId()
static disableCheckUniqueAddress()
unFavoriteBlock(int $blockId)
view(array $params=array())
static markDelete(int $id)
sortBlock(int $id, string $action)
static isCheckUniqueAddress()
markDeletedBlock($id, $mark)
changeParentOfBlock($block, $params)
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=[])
publication($blockId=null)
static enableCheckUniqueAddress()
parseLocalUrl(string $content)
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, $_591201104=null, bool $_1981551946=false)
static hasAccessForLanding($landingId, $accessType)
static getOperationsForSite($siteId)
static getPublicHash($id, $domain=null)
static getFolder(int $folderId, string $accessLevel=Rights::ACCESS_TYPES['read'])
static getForLanding($id)
static landingIsArea($lid)
static setForLanding($id, array $data=array())
static loadMessages($file)
static getMessage($code, $replace=null, $language=null)
static getList(array $parameters=array())