Skip to content

Commit

Permalink
manage and documentation for file #3525
Browse files Browse the repository at this point in the history
  • Loading branch information
sfinx13 committed Jan 15, 2025
1 parent 8765bb1 commit 43a1085
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 52 deletions.
Binary file added public/img/sample_resize.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/sample_thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 7 additions & 28 deletions src/Controller/FileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

namespace App\Controller;

use App\Entity\Enum\DocumentType;
use App\Entity\File;
use App\Service\ImageManipulationHandler;
use League\Flysystem\FilesystemOperator;
use App\Service\Files\ImageVariantProvider;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
Expand All @@ -21,36 +19,17 @@ public function showFile(
File $file,
Request $request,
LoggerInterface $logger,
FilesystemOperator $fileStorage,
ImageVariantProvider $imageVariantProvider,
): BinaryFileResponse {
try {
$variant = $request->query->get('variant');
$filename = $file->getFilename();
$documentType = $file->getDocumentType();
$variantNames = ImageManipulationHandler::getVariantNames($filename);
$file = $imageVariantProvider->getFileVariant($filename, $variant);

if ('thumb' == $variant && $fileStorage->fileExists($variantNames[ImageManipulationHandler::SUFFIX_THUMB])) {
$filename = $variantNames[ImageManipulationHandler::SUFFIX_THUMB];
} elseif ($fileStorage->fileExists($variantNames[ImageManipulationHandler::SUFFIX_RESIZE])) {
$filename = $variantNames[ImageManipulationHandler::SUFFIX_RESIZE];
}
if (!$fileStorage->fileExists($filename)) {
throw new \Exception('File "'.$filename.'" not found');
}
$tmpFilepath = $this->getParameter('uploads_tmp_dir').$filename;
$bucketFilepath = $this->getParameter('url_bucket').'/'.$filename;
$content = file_get_contents($bucketFilepath);
file_put_contents($tmpFilepath, $content);
$file = new SymfonyFile($tmpFilepath);

if (DocumentType::EXPORT === $documentType) {
return (new BinaryFileResponse($file))->setContentDisposition(
ResponseHeaderBag::DISPOSITION_INLINE,
$file->getFilename()
);
}

return new BinaryFileResponse($file);
return (new BinaryFileResponse($file))->setContentDisposition(
ResponseHeaderBag::DISPOSITION_INLINE,
$file->getFilename()
);
} catch (\Throwable $exception) {
$logger->error($exception->getMessage());
}
Expand Down
30 changes: 12 additions & 18 deletions src/Controller/Security/SecurityController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

namespace App\Controller\Security;

use App\Controller\FileController;
use App\Entity\Signalement;
use App\Entity\User;
use App\Service\ImageManipulationHandler;
use League\Flysystem\FilesystemOperator;
use App\Service\Files\ImageVariantProvider;
use Nelmio\ApiDocBundle\Attribute\Security;
use OpenApi\Attributes as OA;
use Psr\Log\LoggerInterface;
Expand All @@ -23,6 +23,10 @@

class SecurityController extends AbstractController
{
public function __construct(private readonly ImageVariantProvider $imageVariantProvider)
{
}

#[When('dev')]
#[When('test')]
#[Route('/api/login', name: 'api_login', methods: ['POST'])]
Expand Down Expand Up @@ -100,10 +104,14 @@ public function login(AuthenticationUtils $authenticationUtils): Response
return $this->render('security/login.html.twig', ['title' => $title, 'last_username' => $lastUsername, 'error' => $error]);
}

/**
* Use only for exporting pdf signalement and using in old description suivi
* Use @see FileController::showFile() instead.
*/
#[Route('/_up/{filename}/{uuid:signalement?}', name: 'show_uploaded_file')]
public function showUploadedFile(
LoggerInterface $logger,
FilesystemOperator $fileStorage,
ImageVariantProvider $imageVariantProvider,
string $filename,
?Signalement $signalement = null,
): BinaryFileResponse|RedirectResponse {
Expand All @@ -114,21 +122,7 @@ public function showUploadedFile(
}
try {
$variant = $request->query->get('variant');
$variantNames = ImageManipulationHandler::getVariantNames($filename);

if ('thumb' == $variant && $fileStorage->fileExists($variantNames[ImageManipulationHandler::SUFFIX_THUMB])) {
$filename = $variantNames[ImageManipulationHandler::SUFFIX_THUMB];
} elseif ($fileStorage->fileExists($variantNames[ImageManipulationHandler::SUFFIX_RESIZE])) {
$filename = $variantNames[ImageManipulationHandler::SUFFIX_RESIZE];
}
if (!$fileStorage->fileExists($filename)) {
throw new \Exception('File "'.$filename.'" not found');
}
$tmpFilepath = $this->getParameter('uploads_tmp_dir').$filename;
$bucketFilepath = $this->getParameter('url_bucket').'/'.$filename;
$content = file_get_contents($bucketFilepath);
file_put_contents($tmpFilepath, $content);
$file = new File($tmpFilepath);
$file = $imageVariantProvider->getFileVariant($filename, $variant);

return new BinaryFileResponse($file);
} catch (\Throwable $exception) {
Expand Down
33 changes: 33 additions & 0 deletions src/Dto/Api/Model/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,40 @@
)]
class File
{
#[OA\Property(
description: 'Titre du fichier',
example: 'sample.png',
)]
public string $titre;
#[OA\Property(
description: 'Type de document<br>
<ul>
<li>`AUTRE_PROCEDURE`</li>
<li>`AUTRE`</li>
<li>`SITUATION_FOYER_DPE`</li>
<li>`SITUATION_FOYER_ETAT_DES_LIEUX`</li>
<li>`PROCEDURE_RAPPORT_DE_VISITE`</li>
<li>`SITUATION_FOYER_BAIL`</li>
<li>`PHOTO_SITUATION`</li>
<li>`PHOTO_VISITE`</li>
<li>`SITUATION_DIAGNOSTIC_PLOMB_AMIANTE`</li>
<li>`PROCEDURE_MISE_EN_DEMEURE`</li>
<li>`PROCEDURE_ARRETE_PREFECTORAL`</li>
<li>`BAILLEUR_REPONSE_BAILLEUR`</li>
<li>`PROCEDURE_ARRETE_MUNICIPAL`</li>
<li>`PROCEDURE_SAISINE`</li>
<li>`BAILLEUR_DEVIS_POUR_TRAVAUX`</li>
<li>`EXPORT`</li>
</ul>
',
example: 'PHOTO_VISITE'
)]
public string $documentType;
#[OA\Property(
description: 'URL du fichier<br>
Le nom du fichier peut être récupéré avec les informations du header HTTP de la ressource `Content-Disposition` indiquant son nom et son extension.
<br> Exemple : `Content-Disposition: inline; filename=sample_demo_resize.png`',
example: 'https://histologe-staging.osc-fr1.scalingo.io/show/5ca99705-5ef6-11ef-ba0f-0242ac110034'
)]
public string $url;
}
14 changes: 13 additions & 1 deletion src/Dto/Api/Response/SignalementResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -825,9 +825,21 @@ enum: [
)]
public array $interventions = [];
#[OA\Property(
description: 'Liste des fichiers joints au signalement',
description: 'Liste des fichiers joints au signalement.',
type: 'array',
items: new OA\Items(ref: new Model(type: File::class)),
example: [
[
'titre' => 'Capture d’écran du 2025-01-13 09-48-11.png',
'documentType' => 'PHOTO_VISITE',
'url' => 'https://histologe-staging.osc-fr1.scalingo.io/show/5ca99705-5ef6-11ef-ba0f-0242ac110034',
],
[
'titre' => '9c2fef07-f2a9-4505-914a-523cbfb911df.png',
'documentType' => 'AUTRE',
'url' => 'https://histologe-staging.osc-fr1.scalingo.io/show/5ca99705-5ef6-11ef-ba0f-0242ac110034',
],
]
)]
public array $files = [];

Expand Down
11 changes: 7 additions & 4 deletions src/Factory/Api/FileFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,23 @@
use App\Entity\File as FileEntity;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class FileFactory
readonly class FileFactory
{
public function __construct(
private readonly UrlGeneratorInterface $urlGenerator,
private UrlGeneratorInterface $urlGenerator,
) {
}

public function createFromSignalement(FileEntity $fileEntity): File
{
$file = new File();

$file->titre = $fileEntity->getTitle();
$file->documentType = $fileEntity->getDocumentType()->value;
$file->url = $this->urlGenerator->generate('show_file', ['uuid' => $fileEntity->getUuid()], UrlGeneratorInterface::ABSOLUTE_URL);
$file->url = $this->urlGenerator->generate(
'show_file',
['uuid' => $fileEntity->getUuid()],
UrlGeneratorInterface::ABSOLUTE_URL
);

return $file;
}
Expand Down
41 changes: 41 additions & 0 deletions src/Service/Files/ImageVariantProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace App\Service\Files;

use App\Service\ImageManipulationHandler;
use League\Flysystem\FilesystemException;
use League\Flysystem\FilesystemOperator;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\File\File;

readonly class ImageVariantProvider
{
public function __construct(
private FilesystemOperator $fileStorage,
private ParameterBagInterface $parameterBag,
) {
}

/**
* @throws FilesystemException
* @throws \Exception
*/
public function getFileVariant(string $filename, ?string $variant = null): File
{
$variantNames = ImageManipulationHandler::getVariantNames($filename);
if ('thumb' === $variant && $this->fileStorage->fileExists($variantNames[ImageManipulationHandler::SUFFIX_THUMB])) {
$filename = $variantNames[ImageManipulationHandler::SUFFIX_THUMB];
} elseif ($this->fileStorage->fileExists($variantNames[ImageManipulationHandler::SUFFIX_RESIZE])) {
$filename = $variantNames[ImageManipulationHandler::SUFFIX_RESIZE];
}
if (!$this->fileStorage->fileExists($filename)) {
throw new \Exception('File "'.$filename.'" not found');
}
$tmpFilepath = $this->parameterBag->get('uploads_tmp_dir').$filename;
$bucketFilepath = $this->parameterBag->get('url_bucket').'/'.$filename;
$content = file_get_contents($bucketFilepath);
file_put_contents($tmpFilepath, $content);

return new File($tmpFilepath);
}
}
48 changes: 48 additions & 0 deletions tests/Unit/Service/Files/ImageVariantProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace App\Tests\Unit\Service\Files;

use App\Service\Files\ImageVariantProvider;
use League\Flysystem\FilesystemException;
use League\Flysystem\FilesystemOperator;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class ImageVariantProviderTest extends KernelTestCase
{
private FilesystemOperator|MockObject $fileStorageMock;
private ImageVariantProvider|MockObject $imageVariantProvider;

protected function setUp(): void
{
$this->fileStorageMock = $this->createMock(FilesystemOperator::class);
$parameterBag = self::getContainer()->get(ParameterBagInterface::class);

$this->imageVariantProvider = new ImageVariantProvider(
$this->fileStorageMock,
$parameterBag
);
}

/**
* @throws FilesystemException
*
* @dataProvider provideImages
*/
public function testGetFileVariantSuccessfullyRetrievesThumb(string $variant): void
{
$this->fileStorageMock
->method('fileExists')
->willReturn(true);

$file = $this->imageVariantProvider->getFileVariant(__DIR__.'/../../../files/sample.png', $variant);
$this->assertStringContainsString($variant, $file->getFilename(), 'The filename should contain the variant');
}

public function provideImages(): \Generator
{
yield 'Sample for thumb' => ['thumb'];
yield 'Sample for resize' => ['resize'];
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace App\Tests\Unit\Service\File;
namespace App\Tests\Unit\Service\Files;

use App\Service\Files\ZipHelper;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
Expand Down

0 comments on commit 43a1085

Please sign in to comment.