feat: implement attachement preview

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-08-29 16:20:52 -04:00
parent 0bfb0c6aaf
commit 59838af3db
6 changed files with 123 additions and 9 deletions
+36
View File
@@ -180,6 +180,7 @@ class DefaultController extends ControllerAbstract {
'entity.copy' => throw new InvalidArgumentException('Operation not implemented: ' . $operation),
'entity.submit' => $this->entitySubmit($tenantId, $userId, $data),
'entity.download' => $this->entityDownload($tenantId, $userId, $data),
'entity.preview' => $this->entityPreview($tenantId, $userId, $data),
'entity.blobs' => $this->entityBlobs($tenantId, $userId, $data),
default => throw new InvalidArgumentException(self::ERR_INVALID_OPERATION . $operation)
@@ -968,4 +969,39 @@ class DefaultController extends ControllerAbstract {
return $results;
}
private function entityPreview(string $tenantId, string $userId, array $data): Response {
if (!isset($data['target']) || !is_string($data['target'])) {
throw new InvalidArgumentException(self::ERR_MISSING_TARGET);
}
if (!isset($data['part']) || !is_array($data['part'])) {
throw new InvalidArgumentException('Attachment preview requires a part');
}
$target = ResourceIdentifier::fromString($data['target']);
if (!$target instanceof EntityIdentifier) {
throw new InvalidArgumentException(self::ERR_INVALID_IDENTIFIER);
}
$preview = $this->manager->entityPreview(
$tenantId,
$userId,
$target,
$data['part'],
isset($data['variant']) && is_string($data['variant']) ? $data['variant'] : 'popover',
);
if ($preview === null) {
return new JsonResponse([
'status' => 'error',
'error' => ['code' => 404, 'message' => 'Preview unavailable'],
], Response::HTTP_NOT_FOUND);
}
return new StreamedResponse($preview->result->resource->stream(), Response::HTTP_OK, [
'Content-Type' => $preview->result->resource->mimeType(),
'Content-Length' => (string) $preview->blob->size,
'ETag' => '"' . trim($preview->blob->etag, '"') . '"',
'Cache-Control' => 'private, max-age=3600',
'X-Content-Type-Options' => 'nosniff',
]);
}
}