3namespace Bitrix\Main\UI\Viewer;
5use Bitrix\Main\Application;
7use Bitrix\Main\Context;
9use Bitrix\Main\EventResult;
10use Bitrix\Main\HttpRequest;
11use Bitrix\Main\Loader;
12use Bitrix\Main\SystemException;
13use Bitrix\Main\Type\DateTime;
14use Bitrix\Main\UI\Viewer\Transformation\TransformerManager;
15use Bitrix\Main\Web\MimeType;
16use Bitrix\Main\Web\Uri;
17use Bitrix\Main\Security;
18use Bitrix\Main\Engine\Response;
30 private const SALT_FILE_ID =
'previewfile';
33 private array $rendererList = [];
34 private static bool $disableCatchingViewByUser =
false;
43 $this->httpRequest = $httpRequest? : Context::getCurrent()->getRequest();
44 $this->transformer = $this->buildTransformer();
45 $this->buildViewRendererList();
55 return new TransformerManager();
58 private function buildViewRendererList(): void
62 Renderer\Video::class,
63 Renderer\Audio::class,
64 Renderer\Image::class,
68 $event =
new Event(
'main',
'onPreviewRendererBuildList');
74 if (
$result->getType() != EventResult::SUCCESS)
81 throw new SystemException(
'Wrong event result. Must be array.');
86 if (!\is_string($class) || !class_exists($class))
88 throw new SystemException(
'Wrong event result. There is not a class.');
91 if (!is_subclass_of($class, Renderer\Renderer::class,
true))
93 throw new SystemException(
"Wrong event result. {$class} is not a subclass of " . Renderer\Renderer::class);
96 $additionalList[] = $class;
100 $this->rendererList = array_merge($additionalList, $default);
105 self::$disableCatchingViewByUser =
true;
110 self::$disableCatchingViewByUser =
false;
115 return self::$disableCatchingViewByUser;
120 if (self::isDisabledCatchingViewByUser())
125 if (!\is_array($file) || empty($file[
'ID']))
130 if (!empty(
$options[
'prevent_work_with_preview']))
135 if ($this->httpRequest->get(self::GET_KEY_TO_SEND_PREVIEW_CONTENT))
140 if ($this->httpRequest->get(self::GET_KEY_TO_SHOW_IMAGE))
145 if ($this->httpRequest->getHeader(self::HEADER_TO_SEND_PREVIEW))
150 if ($this->httpRequest->getHeader(self::HEADER_TO_RUN_FORCE_TRANSFORMATION))
155 if ($this->httpRequest->getHeader(self::HEADER_TO_CHECK_TRANSFORMATION))
160 if ($this->httpRequest->getHeader(self::HEADER_TO_RESIZE_IMAGE))
173 if ($this->httpRequest->get(self::GET_KEY_TO_SEND_PREVIEW_CONTENT))
177 elseif ($this->httpRequest->get(self::GET_KEY_TO_SHOW_IMAGE))
181 elseif ($this->httpRequest->getHeader(self::HEADER_TO_RUN_FORCE_TRANSFORMATION))
185 elseif ($this->httpRequest->getHeader(self::HEADER_TO_CHECK_TRANSFORMATION))
189 elseif ($this->httpRequest->getHeader(self::HEADER_TO_SEND_PREVIEW))
193 elseif ($this->httpRequest->getHeader(self::HEADER_TO_RESIZE_IMAGE))
216 $possiblePreviewFileId = $this->
unsignFileId($this->httpRequest->get(self::GET_KEY_TO_SEND_PREVIEW_CONTENT));
218 if (!$filePreview || empty($filePreview[
'PREVIEW_ID']) || $filePreview[
'PREVIEW_ID'] != $possiblePreviewFileId)
229 $filePreview[
'PREVIEW_ID'],
230 $file[
'ORIGINAL_NAME']
241 $options[
'prevent_work_with_preview'] =
true;
242 \CFile::viewByUser($file,
$options);
249 return $fileView?->render();
254 $getContentType =
function() use ($file){
256 if (!$filePreviewData)
261 return $filePreviewData[
'CONTENT_TYPE'];
264 $getSourceUri =
function() use ($file){
266 if (!$filePreviewData)
272 self::GET_KEY_TO_SEND_PREVIEW_CONTENT => $this->
signFileId($filePreviewData[
'ID']),
278 'contentType' => $getContentType->bindTo($this, $this),
279 'sourceUri' => $getSourceUri->bindTo($this, $this),
294 $file[
'ORIGINAL_NAME'],
295 $file[
'CONTENT_TYPE'],
299 if ($render instanceof
Renderer\Stub || $forceTransformation)
302 if ($filePreviewData)
305 self::GET_KEY_TO_SEND_PREVIEW_CONTENT => $this->
signFileId($filePreviewData[
'ID']),
309 $filePreviewData[
'ORIGINAL_NAME'],
310 $filePreviewData[
'CONTENT_TYPE'],
319 if ($generatePreview->isSuccess())
334 'html' => $render->render(),
335 'data' => $render->getData(),
344 $updatedFields = array_filter([
345 'PREVIEW_IMAGE_ID' => $previewImageId,
346 'PREVIEW_ID' => $previewId,
349 if (empty($updatedFields))
355 if (isset($alreadyPreview[
'ID']))
361 $addedFields = $updatedFields;
362 $addedFields[
'FILE_ID'] = $fileId;
377 if (!$this->transformer)
384 return $this->transformer->transform($fileId);
389 $sourceSrc = $this->httpRequest->getHeader(self::HEADER_TO_GET_SOURCE);
392 $sourceSrc = $this->httpRequest->getRequestUri();
395 return new Uri($sourceSrc);
402 return $signer->sign(
403 base64_encode(serialize($fileId)),
412 $unsignedParameters = $signer->unsign(
417 return unserialize(base64_decode($unsignedParameters), [
'allowed_classes' =>
false]);
429 $fileData[
'ORIGINAL_NAME'],
430 $fileData[
'CONTENT_TYPE'],
433 'originalImage' => $fileData,
436 if (!($renderer instanceof
Renderer\Image))
448 if (empty($fileData[
'ID']))
453 if (isset($cache[$fileData[
'ID']]) || \array_key_exists($fileData[
'ID'], $cache))
455 return $cache[$fileData[
'ID']];
459 if (!$filePreview || empty($filePreview[
'PREVIEW_ID']))
461 $cache[$fileData[
'ID']] =
null;
466 $cache[$fileData[
'ID']] = $this->
getFileData($filePreview[
'PREVIEW_ID']);
468 return $cache[$fileData[
'ID']];
475 '=FILE_ID' => $fileId,
488 'originalName' => $originalName,
491 $reflectionClass = new \ReflectionClass($rendererClass);
493 return $reflectionClass->newInstance($originalName, $sourceUri,
$options);
499 $originalName = $file[
'originalName'];
500 $rendererClass = $this->findRenderClassByContentType(
$contentType);
504 $rendererClass = $this->findRenderClassByContentType($contentTypeByName);
507 $rendererClass = $rendererClass? : Renderer\Stub::class;
509 if ($this->shouldRestrictBySize($file, $rendererClass))
511 return Renderer\RestrictedBySize::class;
514 return $rendererClass;
517 private function shouldRestrictBySize(
array $file, $rendererClass): bool
519 if (!isset($file[
'size']))
524 $size = $file[
'size'];
525 $restriction = $rendererClass::getSizeRestriction();
526 if ($restriction !==
null && $size > $restriction)
534 private function findRenderClassByContentType(
$contentType)
536 foreach ($this->rendererList as $rendererClass)
539 if (\in_array(
$contentType, $rendererClass::getAllowedContentTypes(),
true))
541 return $rendererClass;
558 $fileData = \CFile::GetFileArray($fileId);
559 if ($fileData ===
false && !$cacheCleaned)
562 $strSql =
"SELECT ID FROM b_file WHERE ID={$fileId}";
566 \CFile::CleanCache($fileId);
572 return $fileData ?:
null;
static createSuccess($data=null)
static createError(ErrorCollection $errorCollection=null, $data=null)
static createByFileId($fileId, $name=null)
static includeModule($moduleName)
static getList(array $parameters=array())
static update($primary, array $data)
getViewFileData(array $fileData)
__construct(HttpRequest $httpRequest=null)
getFilePreviewEntryByFileId(int $fileId)
static enableCatchingViewByUser()
const HEADER_TO_CHECK_TRANSFORMATION
sendPreviewContent($file, $options)
const HEADER_TO_GET_SOURCE
prepareRenderParameters($file)
setPreviewImageId(int $fileId, int $previewImageId)
getFileData(int $fileId, bool $cacheCleaned=false)
unsignFileId($signedString)
const GET_KEY_TO_SEND_PREVIEW_CONTENT
buildRenderByFile($originalName, $contentType, Uri $sourceUri, array $options=[])
attachPreviewToFileId(int $fileId, ?int $previewId, ?int $previewImageId)
const HEADER_TO_RUN_FORCE_TRANSFORMATION
isInternalRequest($file, $options)
showImage($file, $options)
sendPreview($file, bool $forceTransformation=false)
getByImage($fileId, Uri $sourceUri)
getRenderClassByFile(array $file)
const HEADER_TO_SEND_PREVIEW
const HEADER_TO_RESIZE_IMAGE
static disableCatchingViewByUser()
const GET_KEY_TO_SHOW_IMAGE
checkTransformation($file)
processViewByUserRequest($file, $options)
static isDisabledCatchingViewByUser()
static getByFilename($filename)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)