• Модуль: translate
  • Путь к файлу: ~/bitrix/modules/translate/lib/controller/export/exportpath.php
  • Класс: BitrixTranslateControllerExportExportPath
  • Вызов: ExportPath::runExporting
private function runExporting(): array
{
	$csvFile = new TranslateIOCsvFile($this->exportFilePath);
	$this->configureExportCsvFile($csvFile);
	$csvFile->openWrite( MainIOFileStreamOpenMode::APPEND);

	if ($this->appendSamples)
	{
		$samplesFile = new TranslateIOCsvFile($this->samplesFilePath);
		$this->configureExportCsvFile($samplesFile);
		$samplesFile->openWrite( MainIOFileStreamOpenMode::APPEND);
	}

	$processedItemCount = 0;

	$filterCodeList = $this->codeList ?: [];
	$fileCodeList = [];
	foreach ($filterCodeList as $pathCode)
	{
		[$path, $code] = explode('::', $pathCode);
		if ($path && $code)
		{
			$langFilePath = TranslateIOPath::replaceLangId($path, '#LANG_ID#');
			if (!isset($fileCodeList[$langFilePath]))
			{
				$fileCodeList[$langFilePath] = [];
			}
			$fileCodeList[$langFilePath][] = $code;
		}
	}

	$currentLangId = Loc::getCurrentLang();

	for ($pos = ($this->seekOffset > 0 ? $this->seekOffset : 0), $total = count($this->pathList); $pos < $total; $pos ++)
	{
		$exportingPath = $this->pathList[$pos];

		// file
		if (TranslateIOPath::isPhpFile($exportingPath))
		{
			$langFilePath = TranslateIOPath::replaceLangId($exportingPath, '#LANG_ID#');
			if (!empty($this->seekLangFilePath))
			{
				if ($langFilePath == $this->seekLangFilePath)
				{
					$this->seekLangFilePath = '';
				}
				else
				{
					continue;
				}
			}

			$fullPaths = [];
			foreach ($this->languages as $langId)
			{
				$langRelPath = TranslateIOPath::replaceLangId($exportingPath, $langId);
				$langFullPath = TranslateIOPath::tidy(self::$documentRoot.'/'.$langRelPath);

				if (self::$useTranslationRepository && in_array($langId, self::$translationRepositoryLanguages))
				{
					$langFullPath = MainLocalizationTranslation::convertLangPath($langFullPath, $langId);
				}

				$fullPaths[$langId] = $langFullPath;
			}

			$rows = $this->mergeLangFiles($langFilePath, $fullPaths, $this->collectUntranslated, $fileCodeList[$langFilePath] ?? []);
			foreach ($rows as $code => $row)
			{
				if (!empty($this->seekPhraseCode))
				{
					if ($code == $this->seekPhraseCode)
					{
						$this->seekPhraseCode = '';
					}
					continue;
				}

				$csvFile->put(array_values($row));

				if (
					$this->appendSamples
					&& !empty($row[$currentLangId])
					&& mb_strlen($row[$currentLangId]) < $this->maxSampleSourceLength
				)
				{
					$samples = $this->findSamples(
						$row[$currentLangId],
						$currentLangId,
						$langFilePath,
						$this->samplesCount,
						$this->samplesRestriction
					);
					foreach ($samples as $sample)
					{
						$samplesFile->put(array_values($sample));
						$this->exportedSamplesCount ++;
					}
				}

				$this->exportedPhraseCount ++;

				if ($this->instanceTimer()->hasTimeLimitReached())
				{
					$this->seekPhraseCode = $code;
				}
				else
				{
					$this->seekPhraseCode = '';
				}
			}

			if ($this->instanceTimer()->hasTimeLimitReached())
			{
				$this->seekLangFilePath = $langFilePath;
				break;
			}
			else
			{
				$this->seekLangFilePath = '';
			}
		}

		// folder
		else
		{
			$exportingPath = TranslateIOPath::tidy($exportingPath. '/');
			if (preg_match("#(.+/lang)(/?w*)#", $exportingPath, $matches))
			{
				$lookForLangPath = $matches[1];
				$lookForLangSubPath = '';
				if (preg_match("#(.+/lang/[^/]+/?)(.*)$#", $exportingPath, $subMatches))
				{
					$lookForLangSubPath = $subMatches[2];
				}
			}
			else
			{
				$lookForLangPath = $exportingPath;
				$lookForLangSubPath = '';
			}
			unset($matches, $subMatches);


			// now let's find lang files
			$pathFilter = [
				'=%PATH' => $lookForLangPath.'%'
			];
			if ($this->seekPathLangId > 0)
			{
				$pathFilter['>=ID'] = $this->seekPathLangId;
			}

			$cachePathLangRes = TranslateIndexInternalsPathLangTable::getList([
				'filter' => $pathFilter,
				'order' => ['ID' => 'ASC'],
				'select' => ['ID', 'PATH'],
			]);
			while ($pathLang = $cachePathLangRes->fetch())
			{
				$lookThroughPath = $pathLang['PATH']. '/#LANG_ID#';
				if (!empty($lookForLangSubPath))
				{
					$lookThroughPath .= '/'. trim($lookForLangSubPath, '/');
				}
				foreach ($this->lookThroughLangFolder($lookThroughPath) as $filePaths)
				{
					foreach ($filePaths as $langFilePath => $fullPaths)
					{
						if (!empty($this->seekLangFilePath))
						{
							if ($langFilePath == $this->seekLangFilePath)
							{
								$this->seekLangFilePath = '';
							}
							else
							{
								continue;
							}
						}

						$rows = $this->mergeLangFiles($langFilePath, $fullPaths, $this->collectUntranslated, $fileCodeList[$langFilePath] ?? []);
						foreach ($rows as $code => $row)
						{
							if (!empty($this->seekPhraseCode))
							{
								if ($code == $this->seekPhraseCode)
								{
									$this->seekPhraseCode = '';
								}
								continue;
							}

							$csvFile->put(array_values($row));

							if (
								$this->appendSamples
								&& !empty($row[$currentLangId])
								&& mb_strlen($row[$currentLangId]) < $this->maxSampleSourceLength
							)
							{
								$samples = $this->findSamples(
									$row[$currentLangId],
									$currentLangId,
									$langFilePath,
									$this->samplesCount,
									$this->samplesRestriction
								);
								foreach ($samples as $sample)
								{
									$samplesFile->put(array_values($sample));
									$this->exportedSamplesCount ++;
								}
							}

							$this->exportedPhraseCount ++;

							if ($this->instanceTimer()->hasTimeLimitReached())
							{
								$this->seekPhraseCode = $code;
								break;
							}
							else
							{
								$this->seekPhraseCode = '';
							}
						}

						if ($this->instanceTimer()->hasTimeLimitReached())
						{
							$this->seekLangFilePath = $langFilePath;
							break;
						}
						else
						{
							$this->seekLangFilePath = '';
						}
					}
				}

				if ($this->instanceTimer()->hasTimeLimitReached())
				{
					$this->seekPathLangId = (int)$pathLang['ID'];
					break 2;
				}
				else
				{
					$this->seekPathLangId = 0;
				}
			}
		}

		$processedItemCount ++;

		if (isset($this->pathList[$pos + 1]))
		{
			$this->seekOffset = $pos + 1;//next
		}
		else
		{
			$this->seekOffset = 0;
			$this->declareAccomplishment();
			$this->clearProgressParameters();
		}

		if ($this->instanceTimer()->hasTimeLimitReached())
		{
			break;
		}
	}

	$this->exportFileSize = $csvFile->getSize();

	$csvFile->close();
	if ($this->appendSamples)
	{
		$this->samplesFileSize = $samplesFile->getSize();
		$samplesFile->close();
	}

	$this->processedItems += $processedItemCount;

	if ($this->instanceTimer()->hasTimeLimitReached() !== true)
	{
		$this->declareAccomplishment();
		$this->clearProgressParameters();
	}

	$result = [
		'PROCESSED_ITEMS' => $this->processedItems,
		'TOTAL_ITEMS' => $this->totalItems,
		'TOTAL_PHRASES' => $this->exportedPhraseCount,
		'TOTAL_SAMPLES' => $this->exportedSamplesCount,
	];

	if ($csvFile->hasErrors())
	{
		$errors = $csvFile->getErrors();
		foreach ($errors as $err)
		{
			if ($err->getCode() == TranslateIOCsvFile::ERROR_32K_FIELD_LENGTH)
			{
				$result['WARNING'] = Loc::getMessage('TR_EXPORT_ERROR_32K_LENGTH');
			}
			else
			{
				$this->addError($err);
			}
		}
	}

	return $result;
}