Your IP : 3.144.82.70


Current Path : /home/bitrix/ext_www/crm.klimatlend.ua/bitrix/modules/disk/lib/document/
Upload File :
Current File : /home/bitrix/ext_www/crm.klimatlend.ua/bitrix/modules/disk/lib/document/documenthandler.php

<?php

namespace Bitrix\Disk\Document;

use Bitrix\Disk\Internals\Error\Error;
use Bitrix\Disk\Internals\Error\ErrorCollection;
use Bitrix\Disk\Internals\Error\IErrorable;
use Bitrix\Disk\SpecificFolder;
use Bitrix\Disk\TypeFile;
use Bitrix\Main\Application;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\NotImplementedException;
use Bitrix\Main\Text\Encoding;
use Bitrix\Main\Web\HttpClient;

Loc::loadMessages(__FILE__);

abstract class DocumentHandler implements IErrorable
{
	const SPECIFIC_FOLDER_CODE            = SpecificFolder::CODE_FOR_UPLOADED_FILES;

	const ERROR_INVALID_RESPONSE_STATUS   = 'DISK_DOC_HANDLER_22002';
	const ERROR_REQUIRED_PARAMETER        = 'DISK_DOC_HANDLER_22003';

	const ERROR_CODE_INSUFFICIENT_SCOPE   = 'DISK_DOC_HANDLER_220022';
	const ERROR_CODE_INVALID_CREDENTIALS  = 'DISK_DOC_HANDLER_220023';
	const ERROR_CODE_NOT_INSTALLED_APP    = 'DISK_DOC_HANDLER_220024';
	const ERROR_CODE_NOT_GRANTED_APP      = 'DISK_DOC_HANDLER_220025';
	const ERROR_CODE_INVALID_ACCESS_LEVEL = 'DISK_DOC_HANDLER_220026';
	const ERROR_CODE_APP_NOT_CONFIGURED   = 'DISK_DOC_HANDLER_220027';
	const ERROR_CODE_APP_IN_BLACKLIST     = 'DISK_DOC_HANDLER_220028';
	const ERROR_CODE_UNKNOWN              = 'DISK_DOC_HANDLER_220029';
	const ERROR_CODE_NOT_FOUND            = 'DISK_DOC_HANDLER_220030';
	const ERROR_CODE_NOT_FOUND_ETAG       = 'DISK_DOC_HANDLER_220031';


	/** @var  string */
	protected $accessToken;
	/** @var int */
	protected $userId;

	/** @var  ErrorCollection */
	protected $errorCollection;

	public function __construct($userId)
	{
		$this->errorCollection = new ErrorCollection;
		$this->userId = $userId;
	}

	/**
	 * @return string the fully qualified name of this class.
	 */
	public static function className()
	{
		return get_called_class();
	}

	/**
	 * Returns user id.
	 *
	 * @return int
	 */
	public function getUserId()
	{
		return $this->userId;
	}

	/**
	 * Sets user id.
	 *
	 * @param $userId
	 * @return int
	 */
	public function setUserId($userId)
	{
		$this->userId = $userId;

		return $this;
	}

	/**
	 * Detect by extension editable or not
	 * @param $extension
	 * @return bool
	 */
	public static function isEditable($extension)
	{
		static $allowedFormat = array(
			'doc' => 'doc',
			'.doc' => '.doc',
			'docx' => 'docx',
			'.docx' => '.docx',
			'xls' => 'xls',
			'.xls' => '.xls',
			'xlsx' => 'xlsx',
			'.xlsx' => '.xlsx',
			'ppt' => 'ppt',
			'.ppt' => '.ppt',
			'pptx' => 'pptx',
			'.pptx' => '.pptx',
			'.xodt' => '.xodt',
			'xodt' => 'xodt',
		);

		return isset($allowedFormat[$extension]) || isset($allowedFormat[mb_strtolower($extension)]);
	}

	/**
	 * Detect by extension needle or not convert?
	 * We work with latest office
	 * @param $extension
	 * @return bool
	 */
	public static function isNeedConvertExtension($extension)
	{
		static $convertFormat = array(
			'doc' => 'docx',
			'.doc' => '.docx',
			'xls' => 'xlsx',
			'.xls' => '.xlsx',
			'ppt' => 'pptx',
			'.ppt' => '.pptx',
		);

		return isset($convertFormat[$extension]) || isset($convertFormat[mb_strtolower($extension)]);
	}

	public static function getConvertExtension($extension)
	{
		static $convertFormat = array(
			'doc' => 'docx',
			'.doc' => '.docx',
			'xls' => 'xlsx',
			'.xls' => '.xlsx',
			'ppt' => 'pptx',
			'.ppt' => '.pptx',
		);
		if(isset($convertFormat[$extension]))
		{
			return $convertFormat[$extension];
		}
		if(isset($convertFormat[mb_strtolower($extension)]))
		{
			return $convertFormat[mb_strtolower($extension)];
		}
		return null;
	}

	/**
	 * Internal code. Identificate document handler
	 *
	 * Max length is 10 chars
	 * @throws \Bitrix\Main\NotImplementedException
	 * @return string
	 */
	public static function getCode()
	{
		throw new NotImplementedException;
	}

	/**
	 * Public name document handler. May show in user interface.
	 * @throws \Bitrix\Main\NotImplementedException
	 * @return string
	 */
	public static function getName()
	{
		throw new NotImplementedException;
	}

	/**
	 * Public name storage of documents. May show in user interface.
	 * @throws \Bitrix\Main\NotImplementedException
	 * @return string
	 */
	public static function getStorageName()
	{
		throw new NotImplementedException;
	}

	/**
	 * Create new blank file in cloud service.
	 * It is not necessary set shared rights on file.
	 * @param FileData $fileData
	 * @return FileData|null
	 */
	abstract public function createBlankFile(FileData $fileData);

	/**
	 * Create file in cloud service by upload from us server.
	 * Necessary set shared rights on file for common work.
	 *
	 * @param FileData $fileData
	 * @return FileData|null
	 */
	abstract public function createFile(FileData $fileData);

	/**
	 * Gets a file's metadata by ID.
	 *
	 * @param FileData $fileData
	 * @return array|null Describes file (id, title, size)
	 */
	abstract public function getFileMetadata(FileData $fileData);

	/**
	 * Download file from cloud service by FileData::id, put contents in FileData::src
	 * @param FileData $fileData
	 * @return FileData|null
	 */
	abstract public function downloadFile(FileData $fileData);

	/**
	 * Download part of file from cloud service by FileData::id, put contents in FileData::src
	 * @param FileData $fileData
	 * @param          $startRange
	 * @param          $chunkSize
	 * @return FileData|null
	 */
	abstract public function downloadPartFile(FileData $fileData, $startRange, $chunkSize);

	/**
	 * Delete file from cloud service by FileData::id
	 * @param FileData $fileData
	 * @return bool
	 */
	abstract public function deleteFile(FileData $fileData);

	/**
	 * Get data for showing preview file.
	 * Array must be contains keys: id, viewUrl, neededDelete, neededCheckView
	 * @param FileData $fileData
	 * @return array|null
	 */
	abstract public function getDataForViewFile(FileData $fileData);

	/**
	 * Tells if file in cloud service was changed. For example, the method compares created date and modified date.
	 *
	 * @param array $currentMetadata Metadata (@see \Bitrix\Disk\Document::getFileMetadata());
	 * @param array $oldMetadata Old metadata.
	 * @return bool
	 */
	public function wasChangedAfterCreation(array $currentMetadata, array $oldMetadata = array())
	{
		if(isset($currentMetadata['etag'], $oldMetadata['etag']))
		{
			return $currentMetadata['etag'] !== $oldMetadata['etag'];
		}

		$this->errorCollection[] = new Error('Could not get etag', self::ERROR_CODE_NOT_FOUND_ETAG);

		return false;
	}

	/**
	 * Check success view file in service.
	 * @param FileData $fileData
	 * @return bool|null
	 */
	public function checkViewFile(FileData $fileData)
	{
		return true;
	}

	/**
	 * Lists folder contents
	 * @param $path
	 * @param $folderId
	 * @return mixed
	 */
	abstract public function listFolder($path, $folderId);

	/**
	 * Execute this method for check potential possibility get access token.
	 * @return bool
	 */
	abstract public function checkAccessibleTokenService();

	/**
	 * Return link for authorize user in external service.
	 * @param string $mode
	 * @return string
	 */
	abstract public function getUrlForAuthorizeInTokenService($mode = 'modal');

	/**
	 * Request and store access token (self::accessToken) for self::userId
	 * @return $this
	 */
	abstract public function queryAccessToken();

	/**
	 * @return string
	 */
	public function getAccessToken()
	{
		return $this->accessToken;
	}

	/**
	 * @return bool
	 */
	public function hasAccessToken()
	{
		return !empty($this->accessToken);
	}

	public function getErrorContainer()
	{
		return $this->errorCollection;
	}

	/**
	 * @return Error[]
	 */
	public function getErrors()
	{
		return $this->errorCollection->toArray();
	}

	/**
	 * @inheritdoc
	 */
	public function getErrorsByCode($code)
	{
		return $this->errorCollection->getErrorsByCode($code);
	}

	/**
	 * @inheritdoc
	 */
	public function getErrorByCode($code)
	{
		return $this->errorCollection->getErrorByCode($code);
	}

	/**
	 * Need re-run oauth authorization?
	 * @return bool
	 */
	public function isRequiredAuthorization()
	{
		if(!$this->errorCollection->hasErrors())
		{
			return false;
		}

		return
			(bool)$this->errorCollection->getErrorByCode(self::ERROR_CODE_INSUFFICIENT_SCOPE) ||
			(bool)$this->errorCollection->getErrorByCode(self::ERROR_CODE_INVALID_CREDENTIALS)
		;
	}

	/**
	 * @param HttpClient $http
	 * @return bool
	 */
	public function checkHttpResponse(HttpClient $http)
	{
		$status = (int)$http->getStatus();

		if($status === 401)
		{
			$this->errorCollection->add(array(
				new Error('Invalid credentials (401)', self::ERROR_CODE_INVALID_CREDENTIALS)
			));
			return false;
		}
		elseif($status === 403)
		{
			$headers = $http->getHeaders();

			$headerAuthenticate = $headers->get('WWW-Authenticate');
			if(is_string($headerAuthenticate) && mb_strpos($headerAuthenticate, 'insufficient') !== false)
			{
				$this->errorCollection->add(array(
					new Error('Insufficient scope (403)', self::ERROR_CODE_INSUFFICIENT_SCOPE)
				));
			}
			else
			{
				$this->errorCollection->add(array(
					new Error("Unknown error ({$status})", self::ERROR_CODE_UNKNOWN)
				));
			}

			return false;
		}
		elseif($status === 404)
		{
			$this->errorCollection->add(array(
				new Error('The resource could not be found (404)', self::ERROR_CODE_NOT_FOUND)
			));
			return false;
		}
		elseif( !($status >= 200 && $status < 300) )
		{
			$this->errorCollection->add(array(
				new Error("Invalid response status code ({$status})", self::ERROR_INVALID_RESPONSE_STATUS)
			));
			return false;
		}

		return true;
	}

	protected function recoverExtensionInName(&$fileName, $mimeType)
	{
		$originalExtension = TypeFile::getExtensionByMimeType($mimeType);
		$newExtension = mb_strtolower(trim(getFileExtension($fileName), '.'));
		if ($originalExtension != $newExtension)
		{
			$fileName = getFileNameWithoutExtension($fileName) . '.' . $originalExtension;

			return true;
		}

		return false;
	}

	/**
	 * @param array $inputParams
	 * @param array $required
	 * @return bool
	 */
	protected function checkRequiredInputParams(array $inputParams, array $required)
	{
		foreach ($required as $item)
		{
			if(
				!isset($inputParams[$item]) ||
				(
					!$inputParams[$item] &&
					!(is_string($inputParams[$item]) && $inputParams[$item] !== '') &&
					!($inputParams[$item] === 0)
				)
			)
			{
				$this->errorCollection->add(array(new Error(Loc::getMessage('DISK_DOC_HANDLER_ERROR_REQUIRED_PARAMETER', array('#PARAM#' => $item)), self::ERROR_REQUIRED_PARAMETER)));
				return false;
			}
		}

		return true;
	}

	protected function convertToUtf8($data)
	{
		if (Application::getInstance()->isUtfMode())
		{
			return $data;
		}
		return Encoding::convertEncodingArray($data, SITE_CHARSET, 'UTF-8');
	}

	protected function retryMethod($method, array $args, $numberOfTimesToRetry = 2)
	{
		if($numberOfTimesToRetry <= 0)
		{
			$numberOfTimesToRetry = 1;
		}

		$reflectionMethod = new \ReflectionMethod($this, $method);
		$reflectionMethod->setAccessible(true);

		do
		{
			$numberOfTimesToRetry--;
			$result = $reflectionMethod->invokeArgs($this, $args);
		}
		while($numberOfTimesToRetry > 0 && $result === null);

		return $result;
	}

	/**
	 * Returns normalized metadata.
	 *
	 * @param array $metaData
	 * @return array
	 */
	protected function normalizeMetadata($metaData)
	{
		//todo create class which will describe metaData.
		return $metaData;
	}
}