• Модуль: seo
  • Путь к файлу: ~/bitrix/modules/seo/lib/Sitemap/Generator.php
  • Класс: BitrixSeoSitemapGenerator
  • Вызов: Generator::runIblock
protected function runIblock(): bool
{
	$result = true;

	$timeFinish = self::getTimeFinish();
	$isFinished = false;
	$bCheckFinished = false;
	$runtimeIblock = false;
	$currentIBlock = false;
	$sitemapFile = null;
	$iblockId = 0;

	$dbOldIblockResult = null;
	$dbIblockResult = null;

	if (isset($_SESSION["SEO_SITEMAP_" . $this->sitemapId]))
	{
		$this->state['IBLOCK_MAP'] = $_SESSION["SEO_SITEMAP_" . $this->sitemapId];
		unset($_SESSION["SEO_SITEMAP_" . $this->sitemapId]);
	}

	while (!$isFinished && microtime(true) <= $timeFinish && Loader::includeModule('iblock'))
	{
		if (!$runtimeIblock)
		{
			$dbRes = RuntimeTable::getList([
				'order' => ['ID' => 'ASC'],
				'filter' => [
					'PID' => $this->sitemapId,
					'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_IBLOCK,
					'PROCESSED' => RuntimeTable::UNPROCESSED,
				],
				'limit' => 1,
			]);
			$runtimeIblock = $dbRes->fetch();

			if ($runtimeIblock)
			{
				$iblockId = intval($runtimeIblock['ITEM_ID']);

				$dbIBlock = CIBlock::GetByID($iblockId);
				$currentIBlock = $dbIBlock->Fetch();

				if (!$currentIBlock)
				{
					RuntimeTable::update($runtimeIblock['ID'], [
						'PROCESSED' => RuntimeTable::PROCESSED,
					]);

					$this->state['LEFT_MARGIN'] = 0;
					$this->state['IBLOCK_LASTMOD'] = 0;
					$this->state['LAST_ELEMENT_ID'] = 0;
					unset($this->state['CURRENT_SECTION']);

					$this->statusMessage = Loc::getMessage(
						'SITEMAP_RUN_IBLOCK_NAME',
						['#IBLOCK_NAME#' => $currentIBlock['NAME']]
					);
				}
				else
				{
					if ($currentIBlock['LIST_PAGE_URL'] == '')
					{
						$this->sitemapData['SETTINGS']['IBLOCK_LIST'][$iblockId] = 'N';
					}
					if ($currentIBlock['SECTION_PAGE_URL'] == '')
					{
						$this->sitemapData['SETTINGS']['IBLOCK_SECTION'][$iblockId] = 'N';
					}
					if ($currentIBlock['DETAIL_PAGE_URL'] == '')
					{
						$this->sitemapData['SETTINGS']['IBLOCK_ELEMENT'][$iblockId] = 'N';
					}

					$this->state['IBLOCK_LASTMOD'] =
						max($this->state['IBLOCK_LASTMOD'], MakeTimeStamp($currentIBlock['TIMESTAMP_X']));

					if ($this->state['LEFT_MARGIN'] <= 0 && $this->sitemapData['SETTINGS']['IBLOCK_ELEMENT'][$iblockId] != 'N')
					{
						$this->state['CURRENT_SECTION'] = 0;
					}

					$fileName = str_replace(
						['#IBLOCK_ID#', '#IBLOCK_CODE#', '#IBLOCK_XML_ID#'],
						[$iblockId, $currentIBlock['CODE'], $currentIBlock['XML_ID']],
						$this->sitemapData['SETTINGS']['FILENAME_IBLOCK']
					);

					$sitemapFile =
						new FileRuntime(
						$this->sitemapId,
						$fileName,
						$this->getSitemapSettings()
					);
				}
			}
		}

		if (!$runtimeIblock || !$sitemapFile)
		{
			$isFinished = true;
		}
		elseif (is_array($currentIBlock))
		{
			if ($dbIblockResult == null)
			{
				if (isset($this->state['CURRENT_SECTION']))
				{
					$dbIblockResult = CIBlockElement::GetList(
						['ID' => 'ASC'],
						[
							'IBLOCK_ID' => $iblockId,
							'ACTIVE' => 'Y',
							'SECTION_ID' => intval($this->state['CURRENT_SECTION']),
							'>ID' => intval($this->state['LAST_ELEMENT_ID']),
							'SITE_ID' => $this->sitemapData['SITE_ID'],
							"ACTIVE_DATE" => "Y",
						],
						false,
						['nTopCount' => 1000],
						['ID', 'TIMESTAMP_X', 'DETAIL_PAGE_URL']
					);
				}
				else
				{
					$this->state['LAST_ELEMENT_ID'] = 0;
					$dbIblockResult = CIBlockSection::GetList(
						['LEFT_MARGIN' => 'ASC'],
						[
							'IBLOCK_ID' => $iblockId,
							'GLOBAL_ACTIVE' => 'Y',
							'>LEFT_BORDER' => intval($this->state['LEFT_MARGIN']),
						],
						false,
						['ID', 'TIMESTAMP_X', 'SECTION_PAGE_URL', 'LEFT_MARGIN', 'IBLOCK_SECTION_ID'],
						['nTopCount' => 100]
					);
				}
			}

			if (isset($this->state['CURRENT_SECTION']))
			{
				$arElement = $dbIblockResult->fetch();

				if ($arElement)
				{
					if (!is_array($this->state['IBLOCK_MAP'][$iblockId]))
					{
						$this->state['IBLOCK_MAP'][$iblockId] = [];
					}

					if (!array_key_exists($arElement['ID'], $this->state['IBLOCK_MAP'][$iblockId]))
					{
						$arElement['LANG_DIR'] = $this->sitemapData['SITE']['DIR'];

						$bCheckFinished = false;
						$elementLastmod = MakeTimeStamp($arElement['TIMESTAMP_X']);
						$this->state['IBLOCK_LASTMOD'] = max($this->state['IBLOCK_LASTMOD'], $elementLastmod);
						$this->state['LAST_ELEMENT_ID'] = $arElement['ID'];

						$this->state['IBLOCK'][$iblockId]['E']++;
						$this->state['IBLOCK_MAP'][$iblockId][$arElement["ID"]] = 1;

						// remove or replace SERVER_NAME
						$url =
							SourceIblock::prepareUrlToReplace(
								$arElement['DETAIL_PAGE_URL'],
								$this->sitemapData['SITE_ID']
							);
						$url = CIBlock::ReplaceDetailUrl($url, $arElement, false, "E");

						$sitemapFile->addIBlockEntry($url, $elementLastmod);
					}
				}
				elseif (!$bCheckFinished)
				{
					$bCheckFinished = true;
					$dbIblockResult = null;
				}
				else
				{
					$bCheckFinished = false;
					unset($this->state['CURRENT_SECTION']);
					$this->state['LAST_ELEMENT_ID'] = 0;

					$dbIblockResult = null;
					if ($dbOldIblockResult)
					{
						$dbIblockResult = $dbOldIblockResult;
						$dbOldIblockResult = null;
					}
				}
			}
			else
			{
				$arSection = $dbIblockResult->fetch();

				if ($arSection)
				{
					$bCheckFinished = false;
					$sectionLastmod = MakeTimeStamp($arSection['TIMESTAMP_X']);
					$this->state['LEFT_MARGIN'] = $arSection['LEFT_MARGIN'];
					$this->state['IBLOCK_LASTMOD'] = max($this->state['IBLOCK_LASTMOD'], $sectionLastmod);

					$bActive = false;
					$bActiveElement = false;

					if (isset($this->sitemapData['SETTINGS']['IBLOCK_SECTION_SECTION'][$iblockId][$arSection['ID']]))
					{
						$bActive =
							$this->sitemapData['SETTINGS']['IBLOCK_SECTION_SECTION'][$iblockId][$arSection['ID']] == 'Y';
						$bActiveElement =
							$this->sitemapData['SETTINGS']['IBLOCK_SECTION_ELEMENT'][$iblockId][$arSection['ID']] == 'Y';
					}
					elseif ($arSection['IBLOCK_SECTION_ID'] > 0)
					{
						$dbRes = RuntimeTable::getList([
							'filter' => [
								'PID' => $this->sitemapId,
								'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_SECTION,
								'ITEM_ID' => $arSection['IBLOCK_SECTION_ID'],
								'PROCESSED' => RuntimeTable::PROCESSED,
							],
							'select' => ['ACTIVE', 'ACTIVE_ELEMENT'],
							'limit' => 1,
						]);

						$parentSection = $dbRes->fetch();
						if ($parentSection)
						{
							$bActive = $parentSection['ACTIVE'] == RuntimeTable::ACTIVE;
							$bActiveElement = $parentSection['ACTIVE_ELEMENT'] == RuntimeTable::ACTIVE;
						}
					}
					else
					{
						$bActive = $this->sitemapData['SETTINGS']['IBLOCK_SECTION'][$iblockId] == 'Y';
						$bActiveElement = $this->sitemapData['SETTINGS']['IBLOCK_ELEMENT'][$iblockId] == 'Y';
					}

					$arRuntimeData = [
						'PID' => $this->sitemapId,
						'ITEM_ID' => $arSection['ID'],
						'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_SECTION,
						'ACTIVE' => $bActive ? RuntimeTable::ACTIVE : RuntimeTable::INACTIVE,
						'ACTIVE_ELEMENT' => $bActiveElement ? RuntimeTable::ACTIVE : RuntimeTable::INACTIVE,
						'PROCESSED' => RuntimeTable::PROCESSED,
					];

					if ($bActive)
					{
						$this->state['IBLOCK'][$iblockId]['S']++;

						$arSection['LANG_DIR'] = $this->sitemapData['SITE']['DIR'];

						//							remove or replace SERVER_NAME
						$url =
							SourceIblock::prepareUrlToReplace(
								$arSection['SECTION_PAGE_URL'],
								$this->sitemapData['SITE_ID']
							);
						$url = CIBlock::ReplaceDetailUrl($url, $arSection, false, "S");

						$sitemapFile->addIBlockEntry($url, $sectionLastmod);
					}

					RuntimeTable::add($arRuntimeData);

					if ($bActiveElement)
					{
						$this->state['CURRENT_SECTION'] = $arSection['ID'];
						$this->state['LAST_ELEMENT_ID'] = 0;

						$dbOldIblockResult = $dbIblockResult;
						$dbIblockResult = null;
					}
				}
				elseif (!$bCheckFinished)
				{
					unset($this->state['CURRENT_SECTION']);
					$bCheckFinished = true;
					$dbIblockResult = null;
				}
				else
				{
					$bCheckFinished = false;
					// we have finished current iblock

					RuntimeTable::update($runtimeIblock['ID'], [
						'PROCESSED' => RuntimeTable::PROCESSED,
					]);

					if ($this->sitemapData['SETTINGS']['IBLOCK_LIST'][$iblockId] == 'Y'
						&& $currentIBlock['LIST_PAGE_URL']
						<> '')
					{
						$this->state['IBLOCK'][$iblockId]['I']++;

						$currentIBlock['IBLOCK_ID'] = $currentIBlock['ID'];
						$currentIBlock['LANG_DIR'] = $this->sitemapData['SITE']['DIR'];

						//							remove or replace SERVER_NAME
						$url =
							SourceIblock::prepareUrlToReplace(
								$currentIBlock['LIST_PAGE_URL'],
								$this->sitemapData['SITE_ID']
							);
						$url = CIBlock::ReplaceDetailUrl($url, $currentIBlock, false, "");

						$sitemapFile->addIBlockEntry($url, $this->state['IBLOCK_LASTMOD']);
					}

					if ($sitemapFile->isNotEmpty())
					{
						if ($sitemapFile->isCurrentPartNotEmpty())
						{
							$sitemapFile->finish();
						}
						else
						{
							$sitemapFile->delete();
						}

						if (!is_array($this->state['XML_FILES']))
						{
							$this->state['XML_FILES'] = [];
						}

						$xmlFiles = $sitemapFile->getNameList();
						$directory = $sitemapFile->getPathDirectory();
						foreach ($xmlFiles as &$xmlFile)
							$xmlFile = $directory . $xmlFile;
						$this->state['XML_FILES'] = array_unique(array_merge($this->state['XML_FILES'], $xmlFiles));
					}
					else
					{
						$sitemapFile->delete();
					}

					$runtimeIblock = false;
					$this->state['LEFT_MARGIN'] = 0;
					$this->state['IBLOCK_LASTMOD'] = 0;
					unset($this->state['CURRENT_SECTION']);
					$this->state['LAST_ELEMENT_ID'] = 0;
				}
			}
		}
	}
	if ($this->step < Step::STEPS[Step::STEP_IBLOCK] - 1)
	{
		$this->step++;
	}

	if ($isFinished)
	{
		$this->step = Step::STEPS[Step::STEP_IBLOCK];
		$this->statusMessage = Loc::getMessage('SITEMAP_RUN_FINALIZE');
	}

	return $result;
}