Skip to content

Commit

Permalink
Merge remote-tracking branch 'ezsystems/ezplatform-kernel/1.3' into 4.5
Browse files Browse the repository at this point in the history
  • Loading branch information
glye committed Nov 3, 2023
2 parents c649c39 + affa252 commit 704f221
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/bundle/Core/Resources/config/routing/internal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ ibexa.content.download:

ibexa.content.download.field_id:
path: /content/download/{contentId}/{fieldId}
defaults: { _controller: Ibexa\Core\MVC\Symfony\Controller\Content\DownloadRedirectionController:redirectToContentDownloadAction }
defaults: { _controller: Ibexa\Core\MVC\Symfony\Controller\Content\DownloadController:downloadBinaryFileByIdAction }
requirements:
contentId: '\d+'
fieldId: '\d+'
59 changes: 47 additions & 12 deletions src/lib/MVC/Symfony/Controller/Content/DownloadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@

use Ibexa\Bundle\IO\BinaryStreamResponse;
use Ibexa\Contracts\Core\Repository\ContentService;
use Ibexa\Contracts\Core\Repository\Values\Content\Content;
use Ibexa\Contracts\Core\Repository\Values\Content\Field;
use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
use Ibexa\Core\Base\Exceptions\NotFoundException;
use Ibexa\Core\Helper\TranslationHelper;
use Ibexa\Core\IO\IOServiceInterface;
use Ibexa\Core\MVC\Symfony\Controller\Controller;
use InvalidArgumentException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

Expand All @@ -36,18 +37,51 @@ public function __construct(ContentService $contentService, IOServiceInterface $
}

/**
* @param mixed $contentId ID of a valid Content
* @param string $fieldIdentifier Field Definition identifier of the Field the file must be downloaded from
* @param string $filename
* @param \Symfony\Component\HttpFoundation\Request $request
* Download binary file identified by field ID.
*
* @return \Ibexa\Bundle\IO\BinaryStreamResponse
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException If the field $fieldId can't be found, or the translation can't be found.
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException If the content is trashed, or can't be found.
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException If the user has no access to read content and in case of un-published content: read versions.
*/
public function downloadBinaryFileByIdAction(Request $request, int $contentId, int $fieldId): BinaryStreamResponse
{
$content = $this->contentService->loadContent($contentId);
try {
$field = $this->findFieldInContent($fieldId, $content);
} catch (InvalidArgumentException $e) {
throw new NotFoundException('File', $fieldId);
}

return $this->downloadBinaryFileAction($contentId, $field->fieldDefIdentifier, $field->value->fileName, $request);
}

/**
* Finds the field with id $fieldId in $content.
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException If the field $fieldId can't be found, or the translation can't be found.
*/
protected function findFieldInContent(int $fieldId, Content $content): Field
{
foreach ($content->getFields() as $field) {
if ($field->getId() === $fieldId) {
return $field;
}
}

throw new InvalidArgumentException(
'$fieldId',
"Field with id $fieldId not found in Content with id {$content->id}"
);
}

/**
* Download binary file identified by field identifier.
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException If the field can't be found, or the translation can't be found.
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException If the content is trashed, or can't be found.
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException If the user has no access to read content and in case of un-published content: read versions.
*/
public function downloadBinaryFileAction($contentId, $fieldIdentifier, $filename, Request $request)
public function downloadBinaryFileAction(int $contentId, string $fieldIdentifier, string $filename, Request $request): BinaryStreamResponse
{
if ($request->query->has('version')) {
$version = (int) $request->query->get('version');
Expand All @@ -70,14 +104,15 @@ public function downloadBinaryFileAction($contentId, $fieldIdentifier, $filename
);
if (!$field instanceof Field) {
throw new InvalidArgumentException(
"'{$fieldIdentifier}' Field does not exist in Content item {$content->contentInfo->id} '{$content->contentInfo->name}'"
'$fieldIdentifier',
"'{$fieldIdentifier}' field not present on content #{$content->contentInfo->id} '{$content->contentInfo->name}'"
);
}

$response = new BinaryStreamResponse($this->ioService->loadBinaryFile($field->value->id), $this->ioService);
$response->setContentDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
$filename,
$field->value->fileName,
bin2hex(random_bytes(8))
);

Expand Down

0 comments on commit 704f221

Please sign in to comment.