feat: analyse import + all tests fixed
This commit is contained in:
parent
fbe9619224
commit
3170a7c60e
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\Manga\Infrastructure\ApiPlatform\Dto;
|
||||
|
||||
readonly class FilenameMatchCollection
|
||||
{
|
||||
/**
|
||||
* @param FilenameMatchItem[] $matches
|
||||
* @param string[] $possibleTitles
|
||||
*/
|
||||
public function __construct(
|
||||
public array $matches,
|
||||
public ?float $chapterNumber,
|
||||
public ?int $volumeNumber,
|
||||
public array $possibleTitles
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\Manga\Infrastructure\ApiPlatform\Dto;
|
||||
|
||||
readonly class FilenameMatchItem
|
||||
{
|
||||
public function __construct(
|
||||
public string $id,
|
||||
public string $title,
|
||||
public string $slug,
|
||||
public array $alternativeSlugs,
|
||||
public ?string $thumbnailUrl,
|
||||
public int $matchScore,
|
||||
public ?float $chapterNumber,
|
||||
public ?float $volumeNumber
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\Manga\Infrastructure\ApiPlatform\Resource;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use App\Domain\Manga\Infrastructure\ApiPlatform\Dto\FilenameMatchCollection;
|
||||
use App\Domain\Manga\Infrastructure\ApiPlatform\State\Provider\FindMangaMatchByFilenameStateProvider;
|
||||
|
||||
#[ApiResource(
|
||||
shortName: 'MangaMatch',
|
||||
operations: [
|
||||
new Get(
|
||||
uriTemplate: '/manga-matches',
|
||||
provider: FindMangaMatchByFilenameStateProvider::class,
|
||||
openapiContext: [
|
||||
'summary' => 'Trouve des correspondances de manga à partir d\'un nom de fichier',
|
||||
'description' => 'Analyse un nom de fichier (cbz/cbr) et trouve les mangas correspondants dans la base de données. Extrait automatiquement le titre, le numéro de chapitre et le numéro de volume du nom de fichier.',
|
||||
'parameters' => [
|
||||
[
|
||||
'name' => 'filename',
|
||||
'in' => 'query',
|
||||
'required' => true,
|
||||
'schema' => [
|
||||
'type' => 'string',
|
||||
'example' => 'one-piece_vol108_ch1094.cbz'
|
||||
],
|
||||
'description' => 'Nom du fichier à analyser (avec ou sans extension .cbz/.cbr)'
|
||||
]
|
||||
],
|
||||
'responses' => [
|
||||
'200' => [
|
||||
'description' => 'Correspondances trouvées',
|
||||
'content' => [
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'matches' => [
|
||||
'type' => 'array',
|
||||
'description' => 'Liste des mangas correspondants triés par score de pertinence',
|
||||
'items' => [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'id' => ['type' => 'string', 'description' => 'Identifiant du manga'],
|
||||
'title' => ['type' => 'string', 'description' => 'Titre du manga'],
|
||||
'slug' => ['type' => 'string', 'description' => 'Slug du manga'],
|
||||
'alternativeSlugs' => [
|
||||
'type' => 'array',
|
||||
'items' => ['type' => 'string'],
|
||||
'description' => 'Slugs alternatifs'
|
||||
],
|
||||
'thumbnailUrl' => ['type' => 'string', 'nullable' => true, 'description' => 'URL de la miniature'],
|
||||
'matchScore' => ['type' => 'integer', 'description' => 'Score de correspondance (plus élevé = meilleure correspondance)'],
|
||||
'chapterNumber' => ['type' => 'number', 'nullable' => true, 'description' => 'Numéro de chapitre extrait'],
|
||||
'volumeNumber' => ['type' => 'number', 'nullable' => true, 'description' => 'Numéro de volume extrait']
|
||||
]
|
||||
]
|
||||
],
|
||||
'chapterNumber' => [
|
||||
'type' => 'number',
|
||||
'nullable' => true,
|
||||
'description' => 'Numéro de chapitre extrait du nom de fichier'
|
||||
],
|
||||
'volumeNumber' => [
|
||||
'type' => 'number',
|
||||
'nullable' => true,
|
||||
'description' => 'Numéro de volume extrait du nom de fichier'
|
||||
],
|
||||
'possibleTitles' => [
|
||||
'type' => 'array',
|
||||
'items' => ['type' => 'string'],
|
||||
'description' => 'Variantes de titres générées à partir du nom de fichier'
|
||||
]
|
||||
]
|
||||
],
|
||||
'example' => [
|
||||
'matches' => [
|
||||
[
|
||||
'id' => '123',
|
||||
'title' => 'One Piece',
|
||||
'slug' => 'one-piece',
|
||||
'alternativeSlugs' => [],
|
||||
'thumbnailUrl' => 'https://example.com/thumb.jpg',
|
||||
'matchScore' => 100,
|
||||
'chapterNumber' => 1094.0,
|
||||
'volumeNumber' => 108
|
||||
]
|
||||
],
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
'400' => [
|
||||
'description' => 'Nom de fichier manquant ou invalide'
|
||||
]
|
||||
]
|
||||
]
|
||||
)
|
||||
]
|
||||
)]
|
||||
class FindMangaMatchByFilenameResource
|
||||
{
|
||||
public function __construct(
|
||||
public readonly array $matches = [],
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
namespace App\Domain\Manga\Infrastructure\ApiPlatform\Resource;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use App\Domain\Manga\Infrastructure\ApiPlatform\Dto\MangaSearchCollection;
|
||||
use App\Domain\Manga\Infrastructure\ApiPlatform\State\Provider\SearchLocalMangaStateProvider;
|
||||
|
||||
#[ApiResource(
|
||||
shortName: 'Manga',
|
||||
shortName: 'MangaSearch',
|
||||
operations: [
|
||||
new Get(
|
||||
uriTemplate: '/mangas/search',
|
||||
new GetCollection(
|
||||
uriTemplate: '/manga-search',
|
||||
provider: SearchLocalMangaStateProvider::class,
|
||||
output: MangaSearchCollection::class,
|
||||
status: 200,
|
||||
@@ -82,4 +82,4 @@ use App\Domain\Manga\Infrastructure\ApiPlatform\State\Provider\SearchLocalMangaS
|
||||
)]
|
||||
class SearchLocalMangaResource
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\Manga\Infrastructure\ApiPlatform\State\Provider;
|
||||
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\State\ProviderInterface;
|
||||
use App\Domain\Manga\Application\Query\FindMangaMatchByFilename;
|
||||
use App\Domain\Manga\Application\QueryHandler\FindMangaMatchByFilenameHandler;
|
||||
use App\Domain\Manga\Infrastructure\ApiPlatform\Dto\FilenameMatchItem;
|
||||
use App\Domain\Manga\Infrastructure\ApiPlatform\Resource\FindMangaMatchByFilenameResource;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
readonly class FindMangaMatchByFilenameStateProvider implements ProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private FindMangaMatchByFilenameHandler $handler
|
||||
) {
|
||||
}
|
||||
|
||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): FindMangaMatchByFilenameResource
|
||||
{
|
||||
$filename = $context['filters']['filename'] ?? '';
|
||||
|
||||
if (empty($filename)) {
|
||||
throw new BadRequestHttpException('Le nom de fichier est requis');
|
||||
}
|
||||
|
||||
$query = new FindMangaMatchByFilename($filename);
|
||||
$response = $this->handler->handle($query);
|
||||
|
||||
// Pour Get, on retourne directement la resource
|
||||
return new FindMangaMatchByFilenameResource(
|
||||
matches: array_map(
|
||||
fn($match) => new FilenameMatchItem(
|
||||
id: $match->id,
|
||||
title: $match->title,
|
||||
slug: $match->slug,
|
||||
alternativeSlugs: $match->alternativeSlugs,
|
||||
thumbnailUrl: $match->thumbnailUrl,
|
||||
matchScore: $match->matchScore,
|
||||
chapterNumber: $match->chapterNumber,
|
||||
volumeNumber: $match->volumeNumber
|
||||
),
|
||||
$response->matches
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ readonly class GetMangaBySlugStateProvider implements ProviderInterface
|
||||
id: $response->id,
|
||||
title: $response->title,
|
||||
slug: $response->slug,
|
||||
alternativeSlugs: $response->alternativeSlugs,
|
||||
description: $response->description,
|
||||
author: $response->author,
|
||||
publicationYear: $response->publicationYear,
|
||||
@@ -31,7 +32,8 @@ readonly class GetMangaBySlugStateProvider implements ProviderInterface
|
||||
externalId: $response->externalId,
|
||||
imageUrl: $response->imageUrl,
|
||||
thumbnailUrl: $response->thumbnailUrl,
|
||||
rating: $response->rating
|
||||
rating: $response->rating,
|
||||
monitored: $response->monitored
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user