30 private const SALT_FILE_ID =
'previewfile';
33 private array $rendererList = [];
34 private static bool $disableCatchingViewByUser =
false;
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');
72 foreach ($event->getResults() as $result)
74 if ($result->getType() != EventResult::SUCCESS)
78 $result = $result->getParameters();
79 if (!\is_array($result))
81 throw new SystemException(
'Wrong event result. Must be array.');
84 foreach ($result as $class)
86 if (!\is_string($class) || !class_exists($class))
88 throw new SystemException(
'Wrong event result. There is not a class.');
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))
198 if (($response instanceof
Response\
BFile) && isset($options[
'cache_time']))
200 $response->setCacheTime($options[
'cache_time']);
203 if ($response instanceof Main\
Response)
208 $APPLICATION->RestartBuffer();
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)
228 return Response\BFile::createByFileId(
229 $filePreview[
'PREVIEW_ID'],
230 $file[
'ORIGINAL_NAME']
236 if (!\is_array($options))
240 $options[
'force_download'] =
false;
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),
286 return new Response\AjaxJson([
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'],
317 if ($generatePreview instanceof Main\
Result)
319 if ($generatePreview->isSuccess())
321 return Response\AjaxJson::createSuccess($generatePreview->getData());
324 return Response\AjaxJson::createError($generatePreview->getErrorCollection());
327 return Response\AjaxJson::createError();
333 return Response\AjaxJson::createSuccess([
334 'html' => $render->render(),
335 'data' => $render->getData(),
339 return Response\AjaxJson::createError();
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,
485 $options[
'contentType'] = $contentType;
487 'contentType' => $contentType,
488 'originalName' => $originalName,
491 $reflectionClass = new \ReflectionClass($rendererClass);
493 return $reflectionClass->newInstance($originalName, $sourceUri, $options);
498 $contentType = $file[
'contentType'];
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;
556 protected function getFileData(
int $fileId,
bool $cacheCleaned =
false): ?array
558 $fileData = \CFile::GetFileArray($fileId);
559 if ($fileData ===
false && !$cacheCleaned)
562 $strSql =
"SELECT ID FROM b_file WHERE ID={$fileId}";
563 $dbResult = $DB->Query($strSql);
564 if ($dbResult->Fetch())
566 \CFile::CleanCache($fileId);
572 return $fileData ?:
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)