Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion backend/config/packages/liip_imagine.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
liip_imagine:
twig:
mode: lazy
driver: gd
driver: imagick
resolvers:
default:
web_path:
Expand All @@ -14,6 +14,7 @@ liip_imagine:
filter_sets:
avatar_thumb:
quality: 85
format: webp
filters:
thumbnail:
size: [200, 200]
Expand All @@ -22,6 +23,7 @@ liip_imagine:
~
avatar_full:
quality: 90
format: webp
filters:
thumbnail:
size: [400, 400]
Expand Down
2 changes: 1 addition & 1 deletion backend/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ services:
arguments:
$resolvers: !tagged_iterator app.contact_resolver

App\Command\MigratePicturesCommand:
App\Command\DeployResetCommand:
arguments:
$projectDir: '%kernel.project_dir%'

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
88 changes: 88 additions & 0 deletions backend/src/Command/DeployResetCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

namespace App\Command;

use App\Repository\PersonRepository;
use App\Service\AvatarCacheService;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Finder\Finder;

#[AsCommand(
name: 'app:deploy-reset',
description: 'Post-déploiement : vide les sessions et régénère le cache des avatars en WebP.',
)]
final class DeployResetCommand extends Command
{
public function __construct(
private readonly PersonRepository $personRepository,
private readonly AvatarCacheService $avatarCacheService,
private readonly string $projectDir,
) {
parent::__construct();
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);

// ── 1. Vider les sessions ─────────────────────────────────────────────
$io->section('Invalidation des sessions');

$sessionDir = $this->projectDir . '/var/sessions';
$cleared = 0;

if (is_dir($sessionDir)) {
$finder = new Finder();
$finder->files()->in($sessionDir);

foreach ($finder as $file) {
$path = $file->getRealPath();

if ($path !== false && is_file($path) && unlink($path)) {
++$cleared;
}
}
Comment thread
LukaMrt marked this conversation as resolved.
}

$io->writeln(sprintf(' <info>✓</info> %d session(s) supprimée(s)', $cleared));

// ── 2. Régénérer le cache des avatars ────────────────────────────────
$io->section('Régénération du cache avatars (WebP)');

$persons = $this->personRepository->findAll();
$warmed = 0;
$skipped = 0;

foreach ($persons as $person) {
$picture = $person->getPicture();

if ($picture === null) {
++$skipped;
continue;
}

try {
$this->avatarCacheService->warmUp($picture);
$io->writeln(sprintf(' <info>✓</info> %s', $person->getFullName()));
++$warmed;
} catch (\Throwable $e) {
$io->warning(sprintf('%s — %s', $person->getFullName(), $e->getMessage()));
}
}

$io->success(sprintf(
'%d avatar(s) régénéré(s), %d sans image, %d session(s) invalidée(s).',
$warmed,
$skipped,
$cleared,
));

return Command::SUCCESS;
}
}
98 changes: 0 additions & 98 deletions backend/src/Command/MigratePicturesCommand.php

This file was deleted.

28 changes: 24 additions & 4 deletions backend/src/Controller/Api/PersonApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use App\Entity\Person\Role;
use App\Entity\Person\User;
use App\Security\Voter\PersonVoter;
use App\Service\AvatarCacheService;
use App\Service\PersonService;
use App\Service\UserService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
Expand All @@ -33,6 +34,7 @@ public function __construct(
private readonly PersonService $personService,
private readonly UserService $userService,
private readonly ValidatorInterface $validator,
private readonly AvatarCacheService $avatarCacheService,
) {
}

Expand All @@ -48,7 +50,15 @@ public function list(Request $request): JsonResponse
];
$orderByParam = $request->query->getString('orderBy', 'id');
$orderBy = in_array($orderByParam, $allowedOrderBy, true) ? $orderByParam : 'id';
$people = $this->personService->getAll($orderBy);

$q = trim($request->query->getString('q', ''));
$limit = $request->query->getInt('limit', 20);

if ($q === '') {
return ApiResponse::success([]);
}

$people = $this->personService->getAll($orderBy, $q, $limit);

/** @var PersonResponseDto[] $dtos */
$dtos = array_map(
Expand Down Expand Up @@ -124,8 +134,8 @@ public function uploadPicture(Person $person, Request $request): JsonResponse
'image/webp',
'image/gif',
],
maxWidth: 4096,
maxHeight: 4096,
maxWidth: 2000,
maxHeight: 2000,
detectCorrupted: true,
),
]);
Expand All @@ -137,10 +147,20 @@ public function uploadPicture(Person $person, Request $request): JsonResponse
);
}

$oldPicture = $person->getPicture();
if ($oldPicture !== null) {
$this->avatarCacheService->bust($oldPicture);
}

$this->personService->update($person);
$person->setPictureFile(null);

return ApiResponse::success(['picture' => $person->getPicture()]);
$newPicture = $person->getPicture();
if ($newPicture !== null) {
$this->avatarCacheService->warmUp($newPicture);
}

return ApiResponse::success(['picture' => $newPicture]);
}

#[Route('/api/persons/{id}/account', name: 'api_persons_get_account', methods: ['GET'])]
Expand Down
4 changes: 2 additions & 2 deletions backend/src/Entity/Person/Person.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ class Person implements \Stringable
'image/webp',
'image/gif',
],
maxWidth: 4096,
maxHeight: 4096,
maxWidth: 2000,
maxHeight: 2000,
detectCorrupted: true,
)]
private ?File $pictureFile = null;
Expand Down
26 changes: 26 additions & 0 deletions backend/src/Entity/Person/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,30 @@ public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}

/**
* @return array<string, mixed>
*/
public function __serialize(): array
{
return [
'id' => $this->id,
'email' => $this->email,
'password' => $this->password,
'roles' => $this->roles,
'isValidated' => $this->isValidated,
];
}

/**
* @param array{id?: int|null, email?: string|null, password?: string|null, roles?: string[], isValidated?: bool} $data
*/
public function __unserialize(array $data): void
{
$this->id = $data['id'] ?? null;
$this->email = $data['email'] ?? null;
$this->password = $data['password'] ?? null;
$this->roles = $data['roles'] ?? [Role::USER->value];
$this->isValidated = $data['isValidated'] ?? false;
}
Comment thread
LukaMrt marked this conversation as resolved.
}
19 changes: 13 additions & 6 deletions backend/src/Repository/PersonRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function __construct(ManagerRegistry $managerRegistry)
/**
* @return Person[]
*/
public function getAll(string $orderBy = 'id'): array
public function getAll(string $orderBy = 'id', ?string $q = null, int $limit = 20): array
{
$allowedColumns = [
'id',
Expand All @@ -39,16 +39,23 @@ public function getAll(string $orderBy = 'id'): array
);
}

/** @var Person[] $result */
$result = $this->createQueryBuilder('p')
$qb = $this->createQueryBuilder('p')
->leftJoin('p.filieres', 'pf')->addSelect('pf')
->leftJoin('pf.filiere', 'f')->addSelect('f')
->leftJoin('pf.school', 's')->addSelect('s')
->leftJoin('p.associations', 'pa')->addSelect('pa')
->leftJoin('pa.association', 'assoc')->addSelect('assoc')
->orderBy('p.' . $orderBy, 'ASC')
->getQuery()
->getResult();
->orderBy('p.' . $orderBy, 'ASC');

if ($q !== null && trim($q) !== '') {
$escaped = addcslashes(trim($q), '%_\\');
$qb->andWhere('LOWER(p.firstName) LIKE LOWER(:q) OR LOWER(p.lastName) LIKE LOWER(:q)')
->setParameter('q', '%' . $escaped . '%')
->setMaxResults(max(1, min($limit, 100)));
}

/** @var Person[] $result */
$result = $qb->getQuery()->getResult();
return $result;
}

Expand Down
Loading
Loading