Your IP : 18.119.255.135


Current Path : /var/www/www-root/data/www/www.monolith-realty.ru/bitrix/modules/translate/lib/
Upload File :
Current File : /var/www/www-root/data/www/www.monolith-realty.ru/bitrix/modules/translate/lib/componentbase.php

<?php

namespace Bitrix\Translate;

use Bitrix\Main;
use Bitrix\Main\Error;
use Bitrix\Main\Localization;
use Bitrix\Main\Localization\Loc;
use Bitrix\Translate;


abstract class ComponentBase
	extends \CBitrixComponent
	implements Translate\IErrorable
{
	use Translate\Error;
	use Translate\Warning;

	const STATUS_SUCCESS = 'success';
	const STATUS_DENIED = 'denied';
	const STATUS_ERROR = 'error';

	const TEMPLATE_ERROR = 'error';

	/** @var string */
	protected $path = '';

	/** @var int Session tab counter. */
	protected $tabId = 0;


	/**
	 * @return boolean
	 */
	protected function checkModuleAvailability()
	{
		if (!Main\Loader::includeModule('translate'))
		{
			if ($this->isAjaxRequest())
			{
				$this->sendJsonResponse(new Error('Module "translate" is not installed.', self::STATUS_ERROR));
			}
			else
			{
				$this->addError(new Error('Module "translate" is not installed.', self::STATUS_ERROR));
				$this->includeComponentTemplate(self::TEMPLATE_ERROR);
			}

			return false;
		}

		return true;
	}

	/**
	 * Checks if user has permission to view language file.
	 * @param \CUser $user User to check permissions.
	 * @return boolean
	 */
	protected function hasUserPermissionView($user)
	{
		return Translate\Permission::canView($user);
	}

	/**
	 * Checks if user has permission to edit language file.
	 * @param \CUser $user User to check permissions.
	 * @return boolean
	 */
	protected function hasUserPermissionEdit($user)
	{
		return Translate\Permission::canEdit($user);
	}
	/**
	 * Checks if user has permission to edit source language file.
	 * @param \CUser $user User to check permissions.
	 * @return boolean
	 */
	protected function hasUserPermissionEditSource($user)
	{
		return Translate\Permission::canEditSource($user);
	}

	/**
	 * Checks if user has permission to view language file.
	 * @return boolean
	 */
	protected function checkPermissionView()
	{
		if (!$this->hasUserPermissionView($this->getUser()))
		{
			if ($this->isAjaxRequest())
			{
				$this->sendJsonResponse(new Error(Loc::getMessage('TRANSLATE_FILTER_ERROR_ACCESS_DENIED'), self::STATUS_DENIED));
			}
			else
			{
				$this->addError(new Error(Loc::getMessage('TRANSLATE_FILTER_ERROR_ACCESS_DENIED'), self::STATUS_DENIED));
				$this->includeComponentTemplate(self::TEMPLATE_ERROR);
			}

			return false;
		}

		return true;
	}

	/**
	 * Checks if user has permission to edit language file.
	 * @return boolean
	 */
	protected function checkPermissionEdit()
	{
		if (!$this->hasUserPermissionEdit($this->getUser()))
		{
			if ($this->isAjaxRequest())
			{
				$this->sendJsonResponse(new Error(Loc::getMessage('TRANSLATE_FILTER_ERROR_WRITING_RIGHTS'), self::STATUS_DENIED));
			}
			else
			{
				$this->addError(new Error(Loc::getMessage('TRANSLATE_FILTER_ERROR_WRITING_RIGHTS'), self::STATUS_DENIED));
				$this->includeComponentTemplate(self::TEMPLATE_ERROR);
			}

			return false;
		}

		return true;
	}

	/**
	 * Checks if user has permission to edit source language file.
	 * @return boolean
	 */
	protected function checkPermissionEditPhp()
	{
		if (!$this->hasUserPermissionEditSource($this->getUser()))
		{
			if ($this->isAjaxRequest())
			{
				$this->sendJsonResponse(new Error(Loc::getMessage('TRANSLATE_FILTER_ERROR_PHP_EDIT_RIGHTS'), self::STATUS_DENIED));
			}
			else
			{
				$this->addError(new Error(Loc::getMessage('TRANSLATE_FILTER_ERROR_PHP_EDIT_RIGHTS'), self::STATUS_DENIED));
				$this->includeComponentTemplate(self::TEMPLATE_ERROR);
			}

			return false;
		}

		return true;
	}

	/**
	 * Checks some mysql config variables.
	 * @return void
	 */
	protected function checkModuleStepper(): void
	{
		$stepper = \Bitrix\Main\Update\Stepper::getHtml('translate', Loc::getMessage('TRANSLATE_INDEX_STEPPER'));
		if (!empty($stepper))
		{
			$this->arResult['STEPPER'] = $stepper;
		}
	}

	/**
	 * Checks FTS if tables exists.
	 * @return void
	 */
	protected function checkFtsTables(): void
	{
		Translate\Index\Internals\PhraseFts::checkTables();
	}

	/**
	 * Checks some mysql config variables.
	 * @return void
	 */
	protected function checkMysqlConfig(): void
	{
		$majorVersion = (int)\mb_substr(\Bitrix\Main\Application::getConnection()->getVersion()[0], 0, 1);

		if ($majorVersion >= 8)
		{
			$conf = Main\Application::getConnection()->query("SHOW VARIABLES LIKE 'regexp_time_limit'")->fetch();
			if ($conf['Variable_name'] == 'regexp_time_limit')
			{
				if ((int)$conf['Value'] <= 0)
				{
					$this->addWarning(new Error(Loc::getMessage('TRANSLATE_MYSQL_CONFIG_ERROR_REGEXP_TIME_LIMIT'), self::STATUS_ERROR));
				}
			}
		}
	}

	/**
	 * @return void
	 */
	protected function prepareParams()
	{
		$params =& $this->getParams();
		if (empty($params['CURRENT_LANG']))
		{
			$params['CURRENT_LANG'] = Loc::getCurrentLang();
		}
		if (empty($params['LIST_PATH']))
		{
			$params['LIST_PATH'] = '/bitrix/admin/translate_list.php';
		}
		if (empty($params['EDIT_PATH']))
		{
			$params['EDIT_PATH'] = '/bitrix/admin/translate_edit.php';
		}
		if (empty($params['SHOW_SOURCE_PATH']))
		{
			$params['SHOW_SOURCE_PATH'] = '/bitrix/admin/translate_show_php.php';
		}
		if (empty($params['EDIT_SOURCE_PATH']))
		{
			$params['EDIT_SOURCE_PATH'] = '/bitrix/admin/translate_edit_php.php';
		}

		$params['SET_TITLE'] = isset($params['SET_TITLE']) ? $params['SET_TITLE'] === 'Y' : true;

		$this->arResult['IS_AJAX_REQUEST'] = $this->isAjaxRequest();

		$this->arResult['ALLOW_VIEW'] = $this->hasUserPermissionView($this->getUser());
		$this->arResult['ALLOW_EDIT'] = $this->hasUserPermissionEdit($this->getUser());
		$this->arResult['ALLOW_EDIT_SOURCE'] = $this->hasUserPermissionEditSource($this->getUser());
	}

	/**
	 * Moves current language to the first position.
	 *
	 * @param string[] $languageList
	 * @param string $currentLangId
	 *
	 * @return string[]
	 */
	protected function rearrangeLanguages($languageList, $currentLangId)
	{
		$inx = \array_search($currentLangId, $languageList, true);
		if ($inx !== false)
		{
			unset($languageList[$inx]);
		}

		\array_unshift($languageList, $currentLangId);

		return $languageList;
	}

	/**
	 * @return string[]
	 */
	protected function getLanguages()
	{
		static $languagesList;

		if (empty($languagesList))
		{
			$languagesList = Translate\Config::getEnabledLanguages();
		}

		return $languagesList;
	}

	/**
	 * Returns list of language names from the site settings.
	 *
	 * @param string[] $languageIds Languages list to get name.
	 *
	 * @return array
	 */
	protected function getLanguagesTitle($languageIds)
	{
		$titles = Translate\Config::getLanguagesTitle($languageIds);
		array_walk($titles, function(&$title, $langId) { $title = "{$title} ({$langId})"; });

		return $titles;
	}

	/**
	 * Return languages compatible by their encoding.
	 *
	 * @return string[]
	 */
	protected function getCompatibleLanguages()
	{
		static $languages = array();
		if (empty($languages))
		{
			$currentEncoding = Localization\Translation::getCurrentEncoding();
			$currentLang = Loc::getCurrentLang();
			$limitEncoding = !($currentEncoding == 'utf-8' || Localization\Translation::useTranslationRepository());

			$isEncodingCompatible = function ($langId) use ($limitEncoding, $currentEncoding, $currentLang)
			{
				$compatible = true;
				if ($limitEncoding)
				{
					$compatible = (
						$langId == $currentLang ||
						Translate\Config::getCultureEncoding($langId) == $currentEncoding ||
						$langId == 'en'
					);
				}

				return $compatible;
			};

			$enabledLanguages = $this->getLanguages();
			foreach ($enabledLanguages as $langId)
			{
				if ($limitEncoding && !$isEncodingCompatible($langId))
				{
					continue;
				}
				$languages[] = $langId;
			}
		}

		return $languages;
	}

	/**
	 * @return string
	 */
	protected function detectTabId()
	{
		$tabId = $this->request->get('tabId');
		if (!empty($tabId) && (int)$tabId > 0)
		{
			$this->tabId = (int)$tabId;
		}
		elseif ($this->isAjaxRequest())
		{
			$this->tabId = Translate\Filter::getTabId(false);
		}
		else
		{
			$this->tabId = Translate\Filter::getTabId();
		}

		return $this->tabId;
	}

	/**
	 * @return string
	 */
	protected function detectStartingPath(?string $path = ''): string
	{
		$home = Translate\Config::getDefaultPath();

		$initPaths = Translate\Config::getInitPath();
		if (count($initPaths) > 0)
		{
			$home = $initPaths[0];
			if (!empty($path))
			{
				foreach ($initPaths as $initPath)
				{
					if (\mb_strpos($path, $initPath) === 0)
					{
						$home = $initPath;
						break;
					}
				}
			}
		}

		return $home;
	}


	/**
	 * Returns component calling params by reference.
	 * @return array
	 */
	public function &getParams()
	{
		return $this->arParams;
	}

	/**
	 * Returns component resulting array by reference.
	 * @return array
	 */
	public function &getResult()
	{
		return $this->arResult;
	}


	/**
	 * @return \CUser
	 */
	protected function getUser()
	{
		/** @global \CUser $USER */
		global $USER;
		return $USER;
	}

	/**
	 * @return \CMain
	 */
	protected function getApplication()
	{
		/** @global \CMain $APPLICATION */
		global $APPLICATION;
		return $APPLICATION;
	}

	/**
	 * Returns whether this is an AJAX (XMLHttpRequest) request.
	 * @return boolean
	 */
	protected function isAjaxRequest()
	{
		return
			($this->request->isAjaxRequest() || $this->request->get('AJAX_CALL') !== null) &&
			$this->request->getRequestMethod() == 'POST';
	}

	/**
	 * Sends Json response to client.
	 *
	 * @param array|object|Main\Error $response Response to send.
	 *
	 * @throws Main\ArgumentException
	 * @return void
	 */
	protected function sendJsonResponse($response)
	{
		$this->getApplication()->restartBuffer();

		$answer = Main\Application::getInstance()->getContext()->getResponse();

		if ($response instanceof Main\Error)
		{
			$this->addError($response);
			$response = array();
		}

		$response['result'] = true;
		if ($this->hasErrors())
		{
			$answer->setStatus('500 Internal Server Error');

			$response['status'] = self::STATUS_ERROR;
			$errors = array();
			foreach ($this->getErrors() as $error)
			{
				/** @var Main\Error $error */
				$errors[] = array(
					'message' => $error->getMessage(),
					'code' => $error->getCode(),
				);
			}
			$response['result'] = false;
			$response['errors'] = $errors;
		}
		elseif (!isset($response['status']))
		{
			$response['status'] = self::STATUS_SUCCESS;
		}

		$answer->addHeader('Content-Type', 'application/x-javascript; charset=UTF-8');
		echo Main\Web\Json::encode($response);

		\CMain::finalActions();
	}

	/**
	 * Drops saved options.
	 * @param string $category Group option name.
	 * @param string $nameMask Option name mask.
	 * @return void
	 */
	protected function clearSavedOptions($category, $nameMask)
	{
		$res = \CUserOptions::getList(false,['CATEGORY' => $category, 'USER_ID' => $this->getUser()->getId(), 'NAME_MASK' => $nameMask]);
		while ($opt = $res->fetch())
		{
			\CUserOptions::deleteOption($category, $opt['NAME']);
		}
	}

	/**
	 * Finds way to get back.
	 *
	 * @param string $path Path to analise.
	 *
	 * @return string
	 */
	protected function detectPathBack($path)
	{
		static $pathBackCache = array();;
		if (!isset($pathBackCache[$path]))
		{
			$pathBack = \dirname($path);
			$slash = \explode('/', $pathBack);
			if (\is_array($slash))
			{
				$slashTmp = $slash;
				$langKey = \array_search('lang', $slash) + 1;
				unset($slashTmp[$langKey]);
				if ($langKey == \count($slash) - 1)
				{
					unset($slash[$langKey]);
					$pathBack = \implode('/', $slash);
				}
			}
			$pathBackCache[$path] = $pathBack;
		}

		return $pathBackCache[$path];
	}

	/**
	 * Get data for chain links.
	 *
	 * @param string $path Path to analise.
	 *
	 * @return array
	 */
	protected function generateChainLinks($path)
	{
		static $chainCache = [];
		if (!isset($chainCache[$path]))
		{
			$params =& $this->getParams();
			$chain = array();
			$slash = \explode('/', \dirname($path));
			if (\is_array($slash))
			{
				$langKey = \array_search('lang', $slash) + 1;
				$slash[$langKey] = $params['CURRENT_LANG'];
				if ($langKey == \count($slash) - 1)
				{
					unset($slash[$langKey]);
				}
				$i = 0;
				$pathList = array();
				foreach ($slash as $dir)
				{
					$i++;
					if ($i == 1)
					{
						$chain[] = array(
							'link' => $params['LIST_PATH'].
											'?lang='.$params['CURRENT_LANG'].
											'&tabId='.$this->tabId.
											'&path=/',
							'title' => '..'
						);
					}
					else
					{
						$pathList[] = \htmlspecialcharsbx($dir);
						$chain[] = array(
							'link' => $params['LIST_PATH'].
											'?lang='.$params['CURRENT_LANG'].
											'&tabId='.$this->tabId.
											'&path=/'.\implode('/', $pathList).'/',
							'title' => \htmlspecialcharsbx($dir)
						);
					}
				}
			}
			$chainCache[$path] = $chain;
		}

		return $chainCache[$path];
	}

	public function getTopIndexedFolders(int $depth = 2): array
	{
		static $list;
		if ($list === null)
		{
			$list = [0 => ''];
			$res = Index\Internals\PathIndexTable::getList([
				'select' => ['ID', 'PATH'],
				'filter' => [
					'=INDEXED' => 'Y',
					'=IS_DIR' => 'Y',
					'<=DEPTH_LEVEL' => $depth,
				],
				'order' => [
					'DEPTH_LEVEL' => 'ASC',
					'PATH' => 'ASC',
				]
			]);
			while ($row = $res->fetch())
			{
				$list[$row['ID']] = $row['PATH'];
			}
		}

		return $list;
	}
}