feat: migrer vers Symfony 8, PHP 8.4 et les dépendances majeures associées
- PHP 8.3 → 8.4 (Dockerfile + composer.json) - Symfony 7.0 → 8.0 (tous les composants symfony/*) - API Platform 3.x → 4.x : migration openapiContext → openapi: new Operation(...) - Doctrine DBAL 3 → 4 : suppression use_savepoints, replace prepare/executeQuery - Doctrine ORM 2.x → 3.x : ClassMetadataInfo → ClassMetadata, setParameters → setParameter - Doctrine Bundle 2.x → 3.x, Fixtures Bundle 3.x → 4.x - zenstruck/foundry 1.x → 2.x : ModelFactory → PersistentObjectFactory, getDefaults → defaults - phpmd/phpmd 2.x → 3.x-dev (seule version supportant Symfony 8) - phparkitect 0.3 → 0.8 : NotDependsOnTheseNamespaces prend un array - symfony/mercure-bundle 0.3 → 0.4, symfony/monolog-bundle 3 → 4 - Suppression de runtime/frankenphp-symfony (intégré nativement dans symfony/runtime 8) - worker.Caddyfile : suppression de APP_RUNTIME (détection automatique Symfony 8) - Routes errors.xml/wdt.xml/profiler.xml → .php (Symfony 8 supprime le XML) - Types::ARRAY → Types::JSON dans Entity/Manga.php (DBAL 4 retire array type) - Suppression de src/Schedule.php (doublon vide avec MonitoringSchedule) - Tests : hydra:Collection → Collection, hydra:member → member (API Platform 4)
This commit is contained in:
parent
5a0888eb28
commit
5ed303612a
@@ -7,9 +7,10 @@ namespace App\Domain\Reader\Application\Query;
|
||||
final class GetChapterContext
|
||||
{
|
||||
public function __construct(
|
||||
private readonly string $chapterId
|
||||
private readonly string $chapterId,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getChapterId(): string
|
||||
{
|
||||
return $this->chapterId;
|
||||
|
||||
@@ -8,8 +8,8 @@ final readonly class GetChapterPages
|
||||
{
|
||||
public function __construct(
|
||||
private string $chapterId,
|
||||
private int $page = 1,
|
||||
private int $itemsPerPage = 20
|
||||
private int $page = 1,
|
||||
private int $itemsPerPage = 20,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ use App\Domain\Reader\Domain\ValueObject\ChapterId;
|
||||
final readonly class GetChapterContextHandler
|
||||
{
|
||||
public function __construct(
|
||||
private ChapterRepositoryInterface $chapterRepository
|
||||
private ChapterRepositoryInterface $chapterRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use App\Domain\Reader\Domain\ValueObject\ChapterId;
|
||||
final readonly class GetChapterPagesHandler
|
||||
{
|
||||
public function __construct(
|
||||
private ChapterRepositoryInterface $chapterRepository
|
||||
private ChapterRepositoryInterface $chapterRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ final readonly class GetChapterPagesHandler
|
||||
|
||||
$totalItems = $this->chapterRepository->getTotalPagesForChapter($chapterId);
|
||||
|
||||
if ($totalItems === 0) {
|
||||
if (0 === $totalItems) {
|
||||
throw ChapterNotFoundException::forChapter($chapterId);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,13 +7,13 @@ namespace App\Domain\Reader\Application\Response;
|
||||
final readonly class ChapterContextResponse
|
||||
{
|
||||
public function __construct(
|
||||
private string $id,
|
||||
private string $mangaId,
|
||||
private string $title,
|
||||
private float $number,
|
||||
private int $totalPages,
|
||||
private string $id,
|
||||
private string $mangaId,
|
||||
private string $title,
|
||||
private float $number,
|
||||
private int $totalPages,
|
||||
private ?string $previousChapterId,
|
||||
private ?string $nextChapterId
|
||||
private ?string $nextChapterId,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class Page
|
||||
private readonly PageNumber $pageNumber,
|
||||
private readonly string $url,
|
||||
private readonly int $width,
|
||||
private readonly int $height
|
||||
private readonly int $height,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace App\Domain\Reader\Domain\ValueObject;
|
||||
readonly class ChapterId
|
||||
{
|
||||
public function __construct(
|
||||
private string $value
|
||||
private string $value,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\Reader\Domain\ValueObject;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class PageNumber
|
||||
{
|
||||
private int $value;
|
||||
@@ -13,7 +11,7 @@ final class PageNumber
|
||||
public function __construct(int $value)
|
||||
{
|
||||
if ($value < 1) {
|
||||
throw new InvalidArgumentException('Le numéro de page doit être supérieur à 0');
|
||||
throw new \InvalidArgumentException('Le numéro de page doit être supérieur à 0');
|
||||
}
|
||||
|
||||
$this->value = $value;
|
||||
|
||||
@@ -6,26 +6,27 @@ namespace App\Domain\Reader\Infrastructure\ApiPlatform\Resource;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\OpenApi\Model\Operation;
|
||||
use ApiPlatform\OpenApi\Model\Parameter;
|
||||
use App\Domain\Reader\Infrastructure\ApiPlatform\State\Provider\ChapterContextProvider;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
#[ApiResource(
|
||||
shortName: 'Reader',
|
||||
operations: [
|
||||
new Get(
|
||||
uriTemplate: '/reader/chapter/{chapterId}',
|
||||
openapiContext: [
|
||||
'summary' => 'Récupère le contexte d\'un chapitre',
|
||||
'description' => 'Retourne les métadonnées du chapitre et sa navigation',
|
||||
'parameters' => [
|
||||
[
|
||||
'name' => 'chapterId',
|
||||
'in' => 'path',
|
||||
'required' => true,
|
||||
'schema' => ['type' => 'string'],
|
||||
],
|
||||
openapi: new Operation(
|
||||
summary: 'Récupère le contexte d\'un chapitre',
|
||||
description: 'Retourne les métadonnées du chapitre et sa navigation',
|
||||
parameters: [
|
||||
new Parameter(
|
||||
name: 'chapterId',
|
||||
in: 'path',
|
||||
required: true,
|
||||
schema: ['type' => 'string']
|
||||
),
|
||||
],
|
||||
'responses' => [
|
||||
responses: [
|
||||
'200' => [
|
||||
'description' => 'Contexte du chapitre',
|
||||
'content' => [
|
||||
@@ -40,8 +41,8 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'id' => ['type' => 'string'],
|
||||
'title' => ['type' => 'string']
|
||||
]
|
||||
'title' => ['type' => 'string'],
|
||||
],
|
||||
],
|
||||
'navigation' => [
|
||||
'type' => 'object',
|
||||
@@ -51,29 +52,29 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
||||
'nullable' => true,
|
||||
'properties' => [
|
||||
'id' => ['type' => 'string'],
|
||||
'number' => ['type' => 'string']
|
||||
]
|
||||
'number' => ['type' => 'string'],
|
||||
],
|
||||
],
|
||||
'next' => [
|
||||
'type' => 'object',
|
||||
'nullable' => true,
|
||||
'properties' => [
|
||||
'id' => ['type' => 'string'],
|
||||
'number' => ['type' => 'string']
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
'number' => ['type' => 'string'],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'404' => [
|
||||
'description' => 'Chapitre non trouvé'
|
||||
]
|
||||
'description' => 'Chapitre non trouvé',
|
||||
],
|
||||
]
|
||||
],
|
||||
),
|
||||
provider: ChapterContextProvider::class
|
||||
),
|
||||
],
|
||||
|
||||
@@ -6,38 +6,39 @@ namespace App\Domain\Reader\Infrastructure\ApiPlatform\Resource;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\OpenApi\Model\Operation;
|
||||
use ApiPlatform\OpenApi\Model\Parameter;
|
||||
use App\Domain\Reader\Infrastructure\ApiPlatform\State\Provider\ChapterPagesProvider;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
#[ApiResource(
|
||||
shortName: 'Reader',
|
||||
operations: [
|
||||
new Get(
|
||||
uriTemplate: '/reader/chapter/{chapterId}/pages',
|
||||
openapiContext: [
|
||||
'summary' => 'Récupère les pages d\'un chapitre',
|
||||
'description' => 'Retourne une collection paginée des pages du chapitre',
|
||||
'parameters' => [
|
||||
[
|
||||
'name' => 'chapterId',
|
||||
'in' => 'path',
|
||||
'required' => true,
|
||||
'schema' => ['type' => 'string'],
|
||||
],
|
||||
[
|
||||
'name' => 'page',
|
||||
'in' => 'query',
|
||||
'required' => false,
|
||||
'schema' => ['type' => 'integer', 'default' => 1],
|
||||
],
|
||||
[
|
||||
'name' => 'itemsPerPage',
|
||||
'in' => 'query',
|
||||
'required' => false,
|
||||
'schema' => ['type' => 'integer', 'default' => 20],
|
||||
],
|
||||
openapi: new Operation(
|
||||
summary: 'Récupère les pages d\'un chapitre',
|
||||
description: 'Retourne une collection paginée des pages du chapitre',
|
||||
parameters: [
|
||||
new Parameter(
|
||||
name: 'chapterId',
|
||||
in: 'path',
|
||||
required: true,
|
||||
schema: ['type' => 'string']
|
||||
),
|
||||
new Parameter(
|
||||
name: 'page',
|
||||
in: 'query',
|
||||
required: false,
|
||||
schema: ['type' => 'integer', 'default' => 1]
|
||||
),
|
||||
new Parameter(
|
||||
name: 'itemsPerPage',
|
||||
in: 'query',
|
||||
required: false,
|
||||
schema: ['type' => 'integer', 'default' => 20]
|
||||
),
|
||||
],
|
||||
'responses' => [
|
||||
responses: [
|
||||
'200' => [
|
||||
'description' => 'Collection paginée des pages du chapitre',
|
||||
'content' => [
|
||||
@@ -55,26 +56,26 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'width' => ['type' => 'integer'],
|
||||
'height' => ['type' => 'integer']
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
'height' => ['type' => 'integer'],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'totalItems' => ['type' => 'integer'],
|
||||
'currentPage' => ['type' => 'integer'],
|
||||
'itemsPerPage' => ['type' => 'integer'],
|
||||
'totalPages' => ['type' => 'integer']
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
'totalPages' => ['type' => 'integer'],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'404' => [
|
||||
'description' => 'Chapitre non trouvé'
|
||||
]
|
||||
'description' => 'Chapitre non trouvé',
|
||||
],
|
||||
]
|
||||
],
|
||||
),
|
||||
provider: ChapterPagesProvider::class
|
||||
),
|
||||
],
|
||||
|
||||
@@ -13,7 +13,7 @@ use App\Domain\Reader\Application\Response\ChapterContextResponse;
|
||||
final readonly class ChapterContextProvider implements ProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private GetChapterContextHandler $handler
|
||||
private GetChapterContextHandler $handler,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use App\Domain\Reader\Application\Response\ChapterPagesResponse;
|
||||
final readonly class ChapterPagesProvider implements ProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private GetChapterPagesHandler $handler
|
||||
private GetChapterPagesHandler $handler,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -16,14 +16,14 @@ use Doctrine\ORM\EntityManagerInterface;
|
||||
readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManagerInterface $entityManager
|
||||
private EntityManagerInterface $entityManager,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getPagesForChapter(ChapterId $chapterId, int $page = 1, int $itemsPerPage = 20): array
|
||||
{
|
||||
$chapter = $this->entityManager->getRepository(ChapterEntity::class)->findOneBy([
|
||||
'id' => $chapterId->getValue()
|
||||
'id' => $chapterId->getValue(),
|
||||
]);
|
||||
|
||||
$pagesDirectory = $chapter->getPagesDirectory();
|
||||
@@ -38,7 +38,7 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
{
|
||||
/** @var ChapterEntity $chapter */
|
||||
$chapter = $this->entityManager->getRepository(ChapterEntity::class)->findOneBy([
|
||||
'id' => $chapterId->getValue()
|
||||
'id' => $chapterId->getValue(),
|
||||
]);
|
||||
|
||||
if (!$chapter) {
|
||||
@@ -65,7 +65,7 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
public function getTotalPagesForChapter(ChapterId $chapterId): int
|
||||
{
|
||||
$chapter = $this->entityManager->getRepository(ChapterEntity::class)->findOneBy([
|
||||
'id' => $chapterId->getValue()
|
||||
'id' => $chapterId->getValue(),
|
||||
]);
|
||||
|
||||
if (!$chapter) {
|
||||
@@ -83,7 +83,7 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
public function getPreviousChapterId(ChapterId $chapterId): ?ChapterId
|
||||
{
|
||||
$currentChapter = $this->entityManager->getRepository(ChapterEntity::class)->findOneBy([
|
||||
'id' => $chapterId->getValue()
|
||||
'id' => $chapterId->getValue(),
|
||||
]);
|
||||
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
@@ -95,10 +95,8 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
->andWhere('c.pagesDirectory IS NOT NULL OR c.cbzPath IS NOT NULL')
|
||||
->orderBy('c.number', 'DESC')
|
||||
->setMaxResults(1)
|
||||
->setParameters([
|
||||
'manga' => $currentChapter->getManga(),
|
||||
'number' => $currentChapter->getNumber()
|
||||
]);
|
||||
->setParameter('manga', $currentChapter->getManga())
|
||||
->setParameter('number', $currentChapter->getNumber());
|
||||
|
||||
$previousChapter = $qb->getQuery()->getOneOrNullResult();
|
||||
|
||||
@@ -108,7 +106,7 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
public function getNextChapterId(ChapterId $chapterId): ?ChapterId
|
||||
{
|
||||
$currentChapter = $this->entityManager->getRepository(ChapterEntity::class)->findOneBy([
|
||||
'id' => $chapterId->getValue()
|
||||
'id' => $chapterId->getValue(),
|
||||
]);
|
||||
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
@@ -120,10 +118,8 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
->andWhere('c.pagesDirectory IS NOT NULL OR c.cbzPath IS NOT NULL')
|
||||
->orderBy('c.number', 'ASC')
|
||||
->setMaxResults(1)
|
||||
->setParameters([
|
||||
'manga' => $currentChapter->getManga(),
|
||||
'number' => $currentChapter->getNumber()
|
||||
]);
|
||||
->setParameter('manga', $currentChapter->getManga())
|
||||
->setParameter('number', $currentChapter->getNumber());
|
||||
|
||||
$nextChapter = $qb->getQuery()->getOneOrNullResult();
|
||||
|
||||
@@ -132,7 +128,7 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
|
||||
private function getImageFiles(string $pagesDirectory): array
|
||||
{
|
||||
$files = glob($pagesDirectory . '/*.{jpg,jpeg,png,webp,gif}', GLOB_BRACE) ?: [];
|
||||
$files = glob($pagesDirectory.'/*.{jpg,jpeg,png,webp,gif}', GLOB_BRACE) ?: [];
|
||||
sort($files);
|
||||
|
||||
return $files;
|
||||
@@ -145,9 +141,9 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
||||
$end = min($start + $itemsPerPage, count($files));
|
||||
$pages = [];
|
||||
|
||||
for ($i = $start; $i < $end; $i++) {
|
||||
for ($i = $start; $i < $end; ++$i) {
|
||||
$imageSize = @getimagesize($files[$i]);
|
||||
if ($imageSize === false) {
|
||||
if (false === $imageSize) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user