• Модуль: landing
  • Путь к файлу: ~/bitrix/modules/landing/lib/landing.php
  • Класс: BitrixLandingLanding
  • Вызов: Landing::parseLocalUrl
protected function parseLocalUrl(string $content): string
{
	$pattern = '/([",';]{1})(page:|block:|user:)?#(landing|block|dynamic|user)([d_]+)@{0,1}([^'"]*)([",'&]{1})/is';
	$patternWithoutUser = '/([",';]{1})(page:|block:)?#(landing|block|dynamic)([d_]+)@{0,1}([^'"]*)([",'&]{1})/is';
	static $isIframe = null;

	if (!self::$editMode && $content)
	{
		$content = SubtypeForm::prepareFormsToView(
			$content
		);
	}

	if ($isIframe === null)
	{
		$request = Application::getInstance()->getContext()->getRequest();
		$isIframe = $request->get('IFRAME') == 'Y';
	}

	// replace catalog links in preview mode
	if (self::$previewMode)
	{
		$content = preg_replace_callback(
			'/href="(product:)?#catalog(Element|Section)([d]+)"/i',
			function($href)
			{
				return 'href="' . PublicActionUtils::getIblockURL(
						$href[3],
						mb_strtolower($href[2])
					) . '"';
			},
			$content);
	}

	$replace = [];

	// for form in frames we should insert hidden tag
	if ($isIframe)
	{
		$replace[''] = '';
	}

	// fix breadcrumb navigation
	if ($this->siteRow['LANDING_ID_INDEX'] > 0)
	{
		$replace['#system_mainpage'] = '#landing' . $this->siteRow['LANDING_ID_INDEX'];
	}

	if ($replace)
	{
		$content = str_replace(
			array_keys($replace),
			array_values($replace),
			$content
		);
	}

	// replace in content
	if (preg_match_all($pattern, $content, $matches))
	{
		$urls = array(
			'LANDING' => array(),
			'BLOCK' => array(),
			'USER' => array(),
			'DYNAMIC' => array()
		);
		for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
		{
			if (mb_strtoupper($matches[3][$i]) == 'LANDING')
			{
				$urls['LANDING'][] = $matches[4][$i];
			}
			else if (mb_strtoupper($matches[3][$i]) == 'DYNAMIC')
			{
				[$dynamicId, ] = explode('_', $matches[4][$i]);
				$urls['DYNAMIC'][] = $dynamicId;
			}
			else if (mb_strtoupper($matches[3][$i]) == 'USER')
			{
				$urls['USER'][] = $matches[4][$i];
			}
			else
			{
				$urls['BLOCK'][] = $matches[4][$i];
			}
		}
		// get parent landings for blocks
		// and public version of blocks too
		$anchorsId = array();
		$anchorsPublicId = array();
		if (!empty($urls['BLOCK']))
		{
			$urls['BLOCK'] = Block::getRowByBlockId(
				$urls['BLOCK'],
				array(
					'ID', 'LID', 'PARENT_ID', 'ANCHOR'
				)
			);
			foreach ($urls['BLOCK'] as $bid => &$bidRow)
			{
				if (
					!self::$previewMode &&
					$bidRow['PARENT_ID']
				)
				{
					$anchorsPublicId[$bid] = $bidRow['PARENT_ID'];
				}
				else
				{
					$anchorsId[$bid] = $bidRow['ANCHOR']
										? htmlspecialcharsbx($bidRow['ANCHOR'])
										: Block::getAnchor($bidRow['ID']);
				}
				$bidRow = $bidRow['LID'];
			}
			unset($bidRow);
			$urls['LANDING'] = array_unique(array_merge(
				$urls['LANDING'],
				$urls['BLOCK']
			));
		}
		$urls['LANDING'] = array_unique(array_merge(
			$urls['LANDING'],
			$urls['DYNAMIC']
		));
		// get anchors for public version
		if ($anchorsPublicId)
		{
			$anchorsPublicIdTmp = Block::getRowByBlockId(
				$anchorsPublicId,
				array(
					'ID', 'LID', 'PARENT_ID', 'ANCHOR'
				)
			);
			foreach ($anchorsPublicId as $bid => $bidParent)
			{
				if (!isset($anchorsPublicIdTmp[$bidParent]))
				{
					continue;
				}
				$bidParent = $anchorsPublicIdTmp[$bidParent];
				$anchorsPublicId[$bid] = $bidParent['ANCHOR']
										? htmlspecialcharsbx($bidParent['ANCHOR'])
										: Block::getAnchor($bidParent['ID']);
			}
		}
		$anchorsPublicId += $anchorsId;
		$landingFull = [];
		$lidEncoded = [];
		// get landing and blocks urls
		if (!empty($urls['LANDING']))
		{
			$urls['LANDING'] = $this->getPublicUrl(
				$urls['LANDING'],
				!ConnectorMobile::isMobileHit(),
				false,
				$landingFull
			);
			foreach ($urls['LANDING'] as $lid => &$url)
			{
				$lidEncoded[] = $lid;
				$url = htmlspecialcharsbx($url);
				if ($isIframe)
				{
					$url .= '?IFRAME=Y';
				}
			}
			unset($url);
		}
		if (!empty($urls['BLOCK']))
		{
			foreach ($urls['BLOCK'] as $bid => $lid)
			{
				if (isset($urls['LANDING'][$lid]))
				{
					if (!in_array($lid, $lidEncoded))
					{
						$urls['LANDING'][$lid] = htmlspecialcharsbx($urls['LANDING'][$lid]);
					}
					$urls['LANDING'][$lid] .= ($isIframe ? '?IFRAME=Y' : '');
					$urls['BLOCK'][$bid] = $urls['LANDING'][$lid] . '#' . $anchorsPublicId[$bid];
				}
				else
				{
					unset($urls['BLOCK'][$bid]);
				}
			}
		}
		// replace urls
		if (!empty($urls['LANDING']))
		{
			krsort($urls['LANDING']);
			$content = preg_replace_callback(
				$patternWithoutUser,
				function($matches) use($urls, $landingFull, $isIframe)
				{
					$dynamicPart = '';
					$matches[3] = mb_strtoupper($matches[3]);
					if ($matches[3] == 'DYNAMIC')
					{
						$matches[3] = 'LANDING';
						if (($underPos = mb_strpos($matches[4], '_')) !== false)
						{
							$dynamicPart = mb_substr($matches[4], $underPos);
							$matches[4] = mb_substr($matches[4], 0, $underPos);
						}
						[$dynamicId, ] = explode('_', $matches[4]);
						$matches[4] = $dynamicId;
					}
					if (isset($urls[$matches[3]][$matches[4]]))
					{
						if ($dynamicPart)
						{
							$landingUrl = $urls[$matches[3]][$matches[4]];
							if (isset($landingFull[$matches[4]]))
							{
								$landingUrl = $landingFull[$matches[4]];
							}
							$url = mb_substr($landingUrl, 0, mb_strlen($landingUrl) - 1);
							$url .= $dynamicPart . ($isIframe ? '/?IFRAME=Y' : '/');
						}
						else
						{
							$url = $urls[$matches[3]][$matches[4]];
						}
						return $matches[1] .
							   		$url . $matches[5] .
								$matches[6];
					}
					else
					{
						return $matches[1] .
									'#landing' . $matches[4] . $matches[5] . $dynamicPart .
								$matches[6];
					}
				},
				$content
			);
			$landingUrls = array();
			foreach ($urls['LANDING'] as $lid => $url)
			{
				$landingUrls['@#landing' . $lid.'@'] = $url;
			}
		}
		// replace user urls
		if (!empty($urls['USER']))
		{
			$patternForPseudoUrlUser = '/data-pseudo-url="{S*(user:)?#user([d_]+)S*}"/is';
			$content = preg_replace_callback(
				$patternForPseudoUrlUser,
				function($matches)
				{
					$url = "'" . Domain::getHostUrl() . '/company/personal/user/' . $matches[2] . "/'";
					return 'onClick="BX.SidePanel.Instance.open('. $url . ')" ';
				},
				$content
			);
			$patternForUser = '/(user:)?#(user)([d_]+)/is';
			$content = preg_replace_callback(
				$patternForUser,
				function($matches)
				{
					return Domain::getHostUrl() . '/company/personal/user/' . $matches[3] . '/';
				},
				$content
			);
		}
	}

	return $content;
}