Your IP : 3.149.247.78


Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/rest/lib/configuration/
Upload File :
Current File : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/rest/lib/configuration/structure.php

<?php

namespace Bitrix\Rest\Configuration;

use Bitrix\Main\Application;
use Bitrix\Main\Loader;
use Bitrix\Main\Type\DateTime;
use Bitrix\Main\Web\Json;
use Bitrix\Main\IO\File;
use Bitrix\Disk\Driver;
use Bitrix\Rest\Configuration\Core\StorageTable;
use Bitrix\Disk\Internals\ObjectTable;
use CTempFile;
use CFile;

class Structure
{
	public const CODE_CONFIGURATION_FILES_LIST = 'CONFIGURATION_FILES_LIST';
	public const CODE_FILES_LIST = 'FILES_LIST';
	public const CODE_FILES_SMALL_LIST = 'FILES_SMALL_LIST';
	public const CODE_UNPACK_FILE_PREFIX = 'UNPACK_FILE_';
	public const CODE_CUSTOM_FILE = 'CUSTOM_FILE_';
	private static $maxAgentTime = 10;
	private static $fileDescriptionDelete = 'configuration_delete';
	private $context;
	private $setting;
	private $zipMimeType = [
		'application/zip',
		'application/x-zip-compressed'
	];
	/**
	 * @param $context string
	 */
	public function __construct($context)
	{
		$this->context = $context;
		$this->setting = new Setting($context);
		$this->setting->addMultipleCode(self::CODE_CONFIGURATION_FILES_LIST);
		$this->setting->addMultipleCode(self::CODE_FILES_LIST);
		$this->setting->addMultipleCode(self::CODE_FILES_SMALL_LIST);
	}

	/**
	 * Create and/or return absolute path to temp folder
	 *
	 * @return string|boolean
	 */
	public function getFolder()
	{
		$folder = $this->setting->get('FOLDER');
		if (empty($folder))
		{
			$folder = CTempFile::GetDirectoryName(
				4,
				[
					'rest',
					uniqid($this->context, true)
				]
			);
			if (CheckDirPath($folder))
			{
				$this->setting->set('FOLDER', $folder);
			}
			else
			{
				$folder = false;
			}
		}

		return $folder ?: false;
	}

	/**
	 * Save content to temp folder
	 * @param $type string
	 * @param $code string
	 * @param $content array|string
	 *
	 * @return boolean
	 */
	public function saveContent($type, $code, $content)
	{
		$return = false;

		try
		{
			if (is_array($content))
			{
				$content = Json::encode($content);
			}
			elseif (!is_string($content))
			{
				return $return;
			}

			$path = ($type === false ? '' : $type . '/') . $code . Helper::CONFIGURATION_FILE_EXTENSION;

			$id = CFile::SaveFile(
				[
					'name' => $path,
					'MODULE_ID' => 'rest',
					'content' => $content,
					'description' => self::$fileDescriptionDelete
				],
				'configuration/export'
			);

			if ($id > 0)
			{
				$return = $this->saveConfigurationFile($id, $path);
			}
		}
		catch (\Exception $e)
		{
		}

		return $return;
	}

	/**
	 * @param $id integer file id from b_file
	 * @param $name string file name with path in folder
	 *
	 * @return boolean
	 */
	private function saveConfigurationFile($id, $name)
	{
		$id = (int) $id;
		$file = [
			'ID' => $id,
			'NAME' => $name
		];

		return $this->setting->set(self::CODE_CONFIGURATION_FILES_LIST, $file);
	}

	/**
	 * All files in current context
	 * @return array|null
	 */
	public function getConfigurationFileList()
	{
		return $this->setting->get(self::CODE_CONFIGURATION_FILES_LIST);
	}

	/**
	 * @param $id integer file id from b_file
	 * @param $additionalData array any short data save with file
	 *
	 * @return boolean
	 */
	public function saveFile($id, $additionalData = [])
	{
		$additionalData['ID'] = (int) $id;
		return $this->setting->set(self::CODE_FILES_LIST, $additionalData);
	}

	/**
	 * All files in current context
	 * @return array|null
	 */
	public function getFileList()
	{
		return $this->setting->get(self::CODE_FILES_LIST);
	}

	/**
	 * Unzip the archive to a temporary folder
	 * @param $fileInfo array === $_FILES
	 *
	 * @return boolean
	 */
	public function unpack($fileInfo)
	{
		$result = false;
		$fileContent = File::getFileContents($fileInfo["tmp_name"]);
		if ($fileContent)
		{
			$type = (in_array($fileInfo["type"], $this->zipMimeType)) ? 'ZIP' : 'TAR.GZ';
			$folder = $this->getFolder();
			$filePath = $folder.'archive_tmp';

			File::putFileContents($filePath, $fileContent);
			$archive = \CBXArchive::GetArchive($filePath, $type);
			$res = $archive->Unpack($folder);
			if ($res)
			{
				$this->initUnpackFilesList();
				$result = true;
			}
			File::deleteFile($filePath);
		}

		return $result;
	}

	/**
	 * @param $content
	 * @return bool
	 */
	public function unpackSmallFiles($content): bool
	{
		$result = true;
		try
		{
			$files = Json::decode($content);
			if (is_array($files))
			{
				$folder = $this->getFolder();
				foreach ($files as $file)
				{
					if (!empty($file['CONTENT']))
					{
						$id = (int)$file['ID'];
						if ($id > 0)
						{
							File::putFileContents(
								$folder . Helper::STRUCTURE_FILES_NAME . '/' . $id,
								base64_decode($file['CONTENT'])
							);
							unset($file['CONTENT']);
							if (File::isFileExists($folder . Helper::STRUCTURE_FILES_NAME . '/' . $id))
							{
								$file['PATH'] = $folder . Helper::STRUCTURE_FILES_NAME . '/' . $id;
								$this->setting->set(self::CODE_UNPACK_FILE_PREFIX . $id, $file);
							}
						}
					}
				}
			}
		}
		catch (\Exception $e)
		{
			$result = false;
		}

		return $result;
	}

	private function initUnpackFilesList()
	{
		$folder = $this->getFolder();
		if (File::isFileExists($folder . Helper::STRUCTURE_SMALL_FILES_NAME . Helper::CONFIGURATION_FILE_EXTENSION))
		{
			$content = File::getFileContents(
				$folder
				. Helper::STRUCTURE_SMALL_FILES_NAME
				. Helper::CONFIGURATION_FILE_EXTENSION
			);
			$this->unpackSmallFiles($content);
		}

		if (File::isFileExists($folder.Helper::STRUCTURE_FILES_NAME.Helper::CONFIGURATION_FILE_EXTENSION))
		{
			$content = File::getFileContents($folder.Helper::STRUCTURE_FILES_NAME.Helper::CONFIGURATION_FILE_EXTENSION);
			try
			{
				$files = Json::decode($content);
				if (is_array($files))
				{
					foreach ($files as $file)
					{
						$id = (int) $file['ID'];
						if ($id > 0 && File::isFileExists($folder . Helper::STRUCTURE_FILES_NAME . '/' . $id))
						{
							$file['PATH'] = $folder . Helper::STRUCTURE_FILES_NAME . '/' . $id;
							$this->setting->set(self::CODE_UNPACK_FILE_PREFIX . $id, $file);
						}
					}
				}
			}
			catch (\Exception $e)
			{
			}
		}
	}

	/**
	 * Adds files list to current context
	 * @param array $filesInfo
	 * @param array $files
	 *
	 * @return bool
	 */
	public function addFileList(array $filesInfo, array $files): bool
	{
		foreach ($filesInfo as $file)
		{
			$id = (int) $file['ID'];
			if ($id > 0 && $files[$id])
			{
				$file['PATH'] = $files[$id];
				$this->setting->set(self::CODE_UNPACK_FILE_PREFIX . $id, $file);
			}
		}

		return true;
	}

	/**
	 * Set Disk work folder with external files
	 * @param $folderId
	 * @param $storageParams
	 *
	 * @return bool
	 */
	public function setUnpackFilesFromDisk($folderId, $storageParams)
	{
		$result = false;
		if (Loader::includeModule('disk'))
		{
			try
			{
				$storage = Driver::getInstance()->addStorageIfNotExist(
					$storageParams
				);
				if ($storage)
				{
					$folder = $storage->getChild(
						[
							'=ID' => $folderId
						]
					);
					if ($folder)
					{
						$file = $folder->getChild(
							[
								'=NAME' => Helper::STRUCTURE_FILES_NAME . Helper::CONFIGURATION_FILE_EXTENSION
							]
						);
						if ($file && $file->getFileId() > 0)
						{
							$server = Application::getInstance()->getContext()->getServer();
							$documentRoot = $server->getDocumentRoot();
							$filePath = $documentRoot . CFile::GetPath($file->getFileId());
							if (File::isFileExists($filePath))
							{
								$content = File::getFileContents($filePath);
								$fileList = Json::decode($content);
								if ($fileList)
								{
									$subFolder = $folder->getChild(
										[
											'NAME' => Helper::STRUCTURE_FILES_NAME
										]
									);
									if ($subFolder)
									{
										$fileList = array_column($fileList, null, 'ID');
										$fakeSecurityContext = Driver::getInstance()->getFakeSecurityContext();
										$folderFiles = $subFolder->getChildren(
											$fakeSecurityContext,
											[
												'filter' => [
													'=TYPE' => ObjectTable::TYPE_FILE
												]
											]
										);

										foreach ($folderFiles as $file)
										{
											$id = $file->getOriginalName();
											if (!empty($fileList[$id]))
											{
												$path = $documentRoot . CFile::GetPath(
													$file->getFileId()
												);
												if (File::isFileExists($path))
												{
													$saveFile = $fileList[$id];
													$saveFile['PATH'] = $path;
													$this->setting->set(self::CODE_UNPACK_FILE_PREFIX . $file->getFileId(), $saveFile);
												}
											}
										}

										$result = true;
									}
								}
							}
						}
					}
				}
			}
			catch (\Exception $e)
			{
			}
		}
		return $result;
	}

	/**
	 * Get file from Disk work folder with external files
	 * @param $id
	 *
	 * @return bool|mixed
	 */
	public function getUnpackFile($id)
	{
		return $this->setting->get(self::CODE_UNPACK_FILE_PREFIX . (int) $id);
	}

	/**
	 * Saves smalls files on import.
	 * @param $info
	 * @param $content
	 */
	public function addSmallFile($info, $content)
	{
		$info['CONTENT'] = base64_encode($content);
		$this->setting->set(self::CODE_FILES_SMALL_LIST, $info);
	}

	/**
	 * @return array|mixed|null
	 */
	public function listSmallFile()
	{
		return $this->setting->get(self::CODE_FILES_SMALL_LIST);
	}

	/**
	 * Set export archive name
	 * @param $name string [a-zA-Z0-9_] new name archive
	 *
	 * @return bool result of set new name
	 */
	public function setArchiveName($name)
	{
		$result = false;
		$name = preg_replace('/[^a-zA-Z0-9_]/', '', $name);
		if (!empty($name))
		{
			$result = $this->setting->set(Setting::SETTING_EXPORT_ARCHIVE_NAME, $name);
		}

		return $result;
	}

	/**
	 * Return export name archive
	 * @return string
	 */
	public function getArchiveName()
	{
		$result = $this->setting->get(Setting::SETTING_EXPORT_ARCHIVE_NAME);

		return is_string($result) ? $result : '';
	}

	/**
	 * Agent delete old temp export files
	 * @return string
	 */
	public static function clearContentAgent()
	{
		$deleteDate = new DateTime();
		$deleteDate->add('-2 days');

		$res = StorageTable::getList(
			[
				'select' => ['ID', 'CODE'],
				'filter' => [
					'<CREATE_TIME' => $deleteDate
				],
				'limit' => 100,
			]
		);
		while ($item = $res->fetch())
		{
			if ($item['CODE'] === Structure::CODE_CONFIGURATION_FILES_LIST
				|| mb_strpos($item['CODE'], Structure::CODE_CUSTOM_FILE) !== false)
			{
				$row = StorageTable::getRowById($item['ID']);
				StorageTable::deleteFile($row);
			}

			StorageTable::delete($item['ID']);
		}

		return '\Bitrix\Rest\Configuration\Structure::clearContentAgent();';
	}
}