• Модуль: landing
  • Путь к файлу: ~/bitrix/modules/landing/lib/block.php
  • Класс: BitrixLandingBlock
  • Вызов: Block::setDynamic
protected function setDynamic($edit)
{
	static $sourceList = null;
	static $isDetailDynamic = null;
	static $dynamicElementId = null;
	static $dynamicFilter = null;

	$data = $this->dynamicParams;
	$caching = false;
	$cache = null;

	// check if is true dynamic
	if (!$this->active || !$this->content)
	{
		return;
	}
	if (!is_array($data) || empty($data))
	{
		return;
	}

	// check feature
	$availableFeature = RestrictionManager::isAllowed(
		'limit_sites_dynamic_blocks',
		['targetBlockId' => $this->id]
	);
	if (!$availableFeature)
	{
		$hackContent = preg_replace(
			'/^<([a-z]+)s/',
			'<$1 style="display: none;" ',
			$this->content
		);

		$this->saveContent(
			$hackContent .
			$this::getMessageBlock([
				'HEADER' => Loc::getMessage('LANDING_BLOCK_MESSAGE_ERROR_DYNAMIC_LIMIT_TITLE'),
				'MESSAGE' => RestrictionManager::getSystemErrorMessage('limit_sites_dynamic_blocks'),
				'BUTTON' => Loc::getMessage('LANDING_BLOCK_MESSAGE_ERROR_LIMIT_BUTTON'),
				'LINK' => Manager::BUY_LICENSE_PATH
	  	    ], 'locked')
		);
		return;
	}

	// if is detail page
	if ($isDetailDynamic === null)
	{
		$isDetailDynamic = Landing::isDynamicDetailPage();
	}
	if ($dynamicElementId === null)
	{
		$dynamicElementId = Landing::getDynamicElementId();
	}
	if ($dynamicFilter === null)
	{
		$dynamicFilter = Landing::getDynamicFilter();
	}

	if (!$edit && Cache::isCaching())
	{
		$cache = new CPHPCache();
		$cacheTime = 3600;
		$cacheId = 'block_' . $this->id . '_' . $dynamicElementId . '_';
		$cacheId .= md5(serialize($dynamicFilter));
		$cachePath = '/landing/dynamic/' . $this->id;
		if ($cache->initCache($cacheTime, $cacheId, $cachePath))
		{
			$result = $cache->getVars();
			if ($result['title'])
			{
				Manager::setPageTitle($result['title'], true);
				LandingSeo::changeValue('title', $result['title']);
			}
			$rememberAccess = $this->access;
			$this->access = $this::ACCESS_W;
			$this->saveContent($result['content']);
			$this->access = $rememberAccess;
			header('X-Bitrix24-Page: dynamic');
			return;
		}
		else
		{
			$caching = true;
			$cache->startDataCache($cacheTime, $cacheId, $cachePath);
			Manager::getCacheManager()->startTagCache($cachePath);
			Cache::register($this->id);
		}
	}

	$updated = false;
	// @todo: remove after refactoring
	$manifest = $this->getManifest();

	// build sources list
	if ($sourceList === null)
	{
		$sourceList = new SourceSelector();
	}

	// @todo: remove after refactoring
	$getDetailPage = function(array $detailPage, $filterId = 0, $elemId = 0)
	{
		$filterId = intval($filterId);
		$elemId = intval($elemId);
		$query = [];

		if (isset($detailPage['query']))
		{
			$query = (array) $detailPage['query'];
			unset($detailPage['query']);
		}

		// normalize the array
		$detailPage = array_merge(
			array_fill_keys(['text', 'href', 'target'], ''),
			$detailPage
		);
		trimArr($detailPage, true);

		if ($filterId && $elemId && $detailPage['href'])
		{
			$detailPage['href'] = str_replace(
				'#landing',
				'#dynamic',
				$detailPage['href']
			);
			$detailPage['href'] .= '_' . $filterId;
			$detailPage['href'] .= '_' . $elemId;
		}
		else if ($filterId && $elemId)
		{
			$detailPage['href'] = '#';
		}

		if ($detailPage['href'] && $query)
		{
			$detailPage['query'] = http_build_query($query);
		}

		return $detailPage;
	};

	// apply for each selector dynamic data from source
	$disableUpdate = false;
	$pageTitle = '';
	foreach ($data as $cardSelector => $item)
	{
		$update = [];
		$itemDetail = $cardSelector == 'wrapper';
		if (
			!isset($item['source']) ||
			!isset($item['settings']) ||
			!isset($item['references'])
		)
		{
			continue;
		}
		// build start params
		$sourceId = $item['source'];
		$settings = $item['settings'];
		$references = (array)$item['references'];
		$filterId = isset($item['filterId'])
					? intval($item['filterId'])
					: 0;
		$detailPage = isset($settings['detailPage'])
					? (array)$settings['detailPage']
					: [];
		$pagesCount = (
						isset($settings['pagesCount']) &&
						$settings['pagesCount'] > 0
					)
					? (int)$settings['pagesCount']
					: 10;
		$filter = isset($settings['source']['filter'])
					? (array)$settings['source']['filter']
					: [];
		$order = isset($settings['source']['sort'])
					? (array)$settings['source']['sort']
					: [];
		$additional = isset($settings['source']['additional'])
					? (array)$settings['source']['additional']
					: [];
		$stubs = isset($item['stubs'])
					? (array)$item['stubs']
					: [];
		// load external filter, if we on detail
		if (
			$isDetailDynamic && $itemDetail &&
			$dynamicFilter['SOURCE_ID'] == $sourceId
		)
		{
			$filter = $dynamicFilter['FILTER'];
		}
		$sourceParameters = [
			'select' => array_values($references),
			'filter' => $filter,
			'order' => $order,
			'limit' => $pagesCount,
			'additional' => $additional
		];
		// gets list or singleton data
		$sourceData = [];
		$source = $sourceList->getDataLoader(
			$sourceId,
			$sourceParameters,
			[
				'context_filter' => [
					'SITE_ID' => $this->siteId,
					'LANDING_ID' => $this->lid,
					'LANDING_ACTIVE' => $this->landingActive ? 'Y' : ['Y', 'N']
				],
				'cache' => $cache,
				'block' => $this
			]
		);
		if (is_object($source))
		{
			// detail page
			if ($isDetailDynamic && $itemDetail)
			{
				$sourceData = $source->getElementData($dynamicElementId);
				if (!$sourceData)
				{
					$disableUpdate = true;
					continue;
				}
				$pageTitle = $source->getSeoTitle();
				Manager::setPageTitle($pageTitle, true);
				LandingSeo::changeValue('title', $pageTitle);
			}
			// element list
			else
			{
				$sourceData = $source->getElementListData();
				$pagesCount = max(1, count($sourceData));
			}
		}
		// apply getting data in block
		if (!empty($sourceData) && is_array($sourceData))
		{
			// collect array for update html
			foreach ($references as $selector => $field)
			{
				if (empty($field) || !is_array($field))
				{
					continue;
				}
				if (empty($field['id']))
				{
					continue;
				}
				if (mb_strpos($selector, '@') !== false)
				{
					[$selector,] = explode('@', $selector);
				}
				if (!isset($update[$selector]))
				{
					$update[$selector] = [];
				}
				$fieldCode = $field['id'];
				$fieldType = isset($manifest['nodes'][$selector]['type'])
							? $manifest['nodes'][$selector]['type']
							: NodeType::TEXT;
				// fill ever selector with data, if data exist
				$detailPageData = [];
				foreach ($sourceData as $dataItem)
				{
					// set link to the card
					// @todo: need refactoring
					if (
						$fieldType == NodeType::LINK &&
						isset($field['action'])
					)
					{
						switch ($field['action'])
						{
							case 'detail':
								{
									$detailPage['text'] = isset($field['text'])
														? $field['text']
														: '';
									$update[$selector][] = $detailPageData[$selector][] = $getDetailPage(
										$detailPage,
										$filterId,
										$dataItem['ID']
									);
									break;
								}
							case 'link':
								{
									if (isset($field['link']))
									{
										$field['link'] = (array) $field['link'];
										if (isset($field['text']))
										{
											$field['link']['text'] = $field['text'];
										}
										$update[$selector][] = $getDetailPage(
											$field['link']
										);
									}
									break;
								}
							case 'landing':
								{
									if (isset($dataItem['LINK']))
									{
										$update[$selector][] = $detailPageData[$selector][] = $getDetailPage([
											'text' => isset($field['text'])
													? $field['text']
													: '',
											'href' => $dataItem['LINK'],
											'target' => '_self',
											'query' => isset($dataItem['_GET']) ? $dataItem['_GET'] : []
										]);
									}
								}
						}
					}
					else// if ($fieldType != NodeType::LINK)
					{
						$value = isset($dataItem[$fieldCode])
							? $dataItem[$fieldCode]
							: '';
						$update[$selector][] = $value;
						if ($detailPage)
						{
							$detailPageData[$selector][] = $getDetailPage(
								$detailPage,
								$filterId,
								$dataItem['ID']
							);;
						}
						else if (isset($dataItem['LINK']))
						{
							$detailPageData[$selector][] = $getDetailPage([
								'text' => isset($field['text'])
									? $field['text']
									: '',
								'href' => $dataItem['LINK'],
								'target' => '_self',
								'query' => isset($dataItem['_GET']) ? $dataItem['_GET'] : []
							]);
						}
					}
				}
				// not touch the selector, if there is no data
				if (!$update[$selector])
				{
					unset($update[$selector]);
				}
				// set detail url for nodes
				// @todo: refactor
				else if (
					isset($field['link']) &&
					(
						$fieldType == NodeType::IMAGE ||
						$fieldType == NodeType::TEXT
					)
				)
				{
					if (!isset($detailPageData[$selector]))
					{
						continue;
					}
					foreach ($update[$selector] as $i => &$value)
					{
						if ($fieldType == NodeType::IMAGE)
						{
							$value = (array) $value;
						}
						else
						{
							$value = [
								'text' => (string) $value
							];
						}
						if (
							$detailPageData[$selector][$i] &&
							UtilsAction::isTrue($field['link'])
						)
						{
							$detailPageData[$selector][$i]['enabled'] = true;
						}
						else
						{
							$detailPageData[$selector][$i]['enabled'] = false;
						}
						if ($detailPageData[$selector][$i]['enabled'])
						{
							$value['url'] = $detailPageData[$selector][$i];
						}
					}
					unset($value);
				}
			}
			if (!$itemDetail)
			{
				$rememberAccess = $this->access;
				$this->access = $this::ACCESS_W;
				$this->adjustCards(
					$cardSelector,
					$pagesCount
				);
				$this->access = $rememberAccess;
			}
		}

		// stubs (common content)
		if ($stubs)
		{
			foreach ($stubs as $selector => $stub)
			{
				if (mb_strpos($selector, '@') !== false)
				{
					[$selector,] = explode('@', $selector);
				}
				$update[$selector] = array_fill(0, $pagesCount, $stub);
			}
		}

		// update dynamic
		if ($update)
		{
			$updated = true;
			$rememberAccess = $this->access;
			$this->access = $this::ACCESS_W;
			$this->updateNodes(
				$update,
				[
					'sanitize' => false,
					'skipCheckAffected' => true
				]
			);
			if(!$edit)
			{
				AssetsPreProcessing::blockSetDynamicProcessing($this);
			}
			$this->access = $rememberAccess;

			header('X-Bitrix24-Page: dynamic');
			if ($caching)
			{
				$cache->endDataCache([
					'title' => $pageTitle,
					'content' => $this->content
 					]);
				Manager::getCacheManager()->endTagCache();
			}
		}
		else if (false)
		{
			$this->runtimeRequiredUserAction = [
				'header' => Loc::getMessage('LANDING_BLOCK_MESSAGE_ERROR_NO_DATA_TITLE'),
				'description' => Loc::getMessage('LANDING_BLOCK_MESSAGE_ERROR_NO_DATA_TEXT')
			];
		}
	}

	if (
		$disableUpdate ||
		(!$updated && !Landing::getEditMode())
	)
	{
		if ($cache)
		{
			$cache->abortDataCache();
		}
		$this->deleted = true;
	}
}