style: apply php-cs-fixer formatting (PSR-12)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2026-03-09 20:46:59 +01:00
parent dae215dd3d
commit 7506a7a3c1
234 changed files with 447 additions and 370 deletions

View File

@@ -14,5 +14,6 @@ readonly class TestScraperConfiguration
public ?string $imageSelector = null,
public ?string $nextPageSelector = null,
public ?string $chapterSelector = null,
) {}
) {
}
}

View File

@@ -117,7 +117,7 @@ readonly class ScrapeChapterHandler
$chapter->volumeNumber,
$chapter->chapterNumber,
$tempDir,
array_map(fn($r) => $r->getLocalPath(), $downloadResults)
array_map(fn ($r) => $r->getLocalPath(), $downloadResults)
);
$cbzPath = $this->cbzGenerator->generate($cbzRequest);

View File

@@ -12,7 +12,8 @@ readonly class TestScraperConfigurationHandler
{
public function __construct(
private ScraperFactoryInterface $scraperFactory
) {}
) {
}
public function handle(TestScraperConfiguration $command): TestScraperConfigurationResponse
{

View File

@@ -11,7 +11,8 @@ readonly class TestScraperConfigurationResponse
public string $testedUrl,
public string $scrapingType,
public array $errors = [],
) {}
) {
}
public static function success(array $imageUrls, string $testedUrl, string $scrapingType): self
{

View File

@@ -18,4 +18,4 @@ class CbzGenerationException extends \RuntimeException
{
return new self(sprintf('Impossible d\'ajouter le fichier à l\'archive : %s', $filePath));
}
}
}

View File

@@ -10,5 +10,6 @@ class Chapter
public readonly float $chapterNumber,
public readonly ?int $volumeNumber,
public ?string $cbzPath,
) {}
) {
}
}

View File

@@ -77,5 +77,6 @@ class GetMangaPreferredSourcesResource
{
public function __construct(
public string $id
) {}
) {
}
}

View File

@@ -50,5 +50,6 @@ class SetMangaPreferredSourcesResource
new Assert\Type('string')
])]
public array $sourceIds = []
) {}
) {
}
}

View File

@@ -305,7 +305,6 @@ readonly class TestScraperConfigurationRequest
#[Assert\NotBlank(message: 'L\'URL de base est obligatoire')]
#[Assert\Url(message: 'L\'URL de base doit être une URL valide')]
public string $baseUrl,
#[ApiProperty(
description: 'Format d\'URL pour accéder aux chapitres. Utilisez {slug} pour le nom du manga et {chapter} pour le numéro de chapitre',
example: 'https://mangasite.example.com/manga/{slug}/chapter/{chapter}',
@@ -313,7 +312,6 @@ readonly class TestScraperConfigurationRequest
)]
#[Assert\NotBlank(message: 'Le format d\'URL de chapitre est obligatoire')]
public string $chapterUrlFormat,
#[ApiProperty(
description: 'Type de scraping à utiliser. "html" pour les sites statiques, "javascript" pour les sites avec contenu dynamique',
example: 'html',
@@ -322,7 +320,6 @@ readonly class TestScraperConfigurationRequest
#[Assert\NotBlank(message: 'Le type de scraping est obligatoire')]
#[Assert\Choice(choices: ['html', 'javascript'], message: 'Le type de scraping doit être html ou javascript')]
public string $scrapingType,
#[ApiProperty(
description: 'URL complète d\'un chapitre existant à utiliser pour tester la configuration. Cette URL doit être accessible et contenir des images',
example: 'https://mangasite.example.com/manga/one-piece/chapter/1',
@@ -331,7 +328,6 @@ readonly class TestScraperConfigurationRequest
#[Assert\NotBlank(message: 'L\'URL de test est obligatoire')]
#[Assert\Url(message: 'L\'URL de test doit être une URL valide')]
public string $testUrl,
#[ApiProperty(
description: 'Identifiant du manga utilisé dans les URLs (slug). Sera utilisé pour remplacer {slug} dans le format d\'URL',
example: 'one-piece',
@@ -339,7 +335,6 @@ readonly class TestScraperConfigurationRequest
)]
#[Assert\NotBlank(message: 'Le slug du manga est obligatoire')]
public string $mangaSlug,
#[ApiProperty(
description: 'Numéro du chapitre à tester. Peut être décimal pour les chapitres spéciaux (ex: 1.5)',
example: 1.0,
@@ -349,7 +344,6 @@ readonly class TestScraperConfigurationRequest
#[Assert\Type(type: 'numeric', message: 'Le numéro de chapitre doit être numérique')]
#[Assert\Positive(message: 'Le numéro de chapitre doit être positif')]
public float $chapterNumber,
#[ApiProperty(
description: 'Sélecteur CSS pour identifier les images du manga sur la page. Exemples: "img.manga-page", ".chapter img", "#reader img"',
example: 'img.manga-page, .chapter-image img',
@@ -357,7 +351,6 @@ readonly class TestScraperConfigurationRequest
)]
#[Assert\Length(min: 1, max: 500, minMessage: 'Le sélecteur d\'image ne peut pas être vide', maxMessage: 'Le sélecteur d\'image est trop long')]
public ?string $imageSelector = null,
#[ApiProperty(
description: 'Sélecteur CSS pour le lien vers la page suivante (requis pour les lecteurs horizontaux). Exemples: "a.next", ".navigation .next-page"',
example: 'a.next-page, .navigation .next',
@@ -365,7 +358,6 @@ readonly class TestScraperConfigurationRequest
)]
#[Assert\Length(max: 500, maxMessage: 'Le sélecteur de page suivante est trop long')]
public ?string $nextPageSelector = null,
#[ApiProperty(
description: 'Sélecteur CSS pour délimiter la zone contenant le chapitre (optionnel). Utile pour cibler une zone spécifique de la page',
example: '.chapter-content, #manga-reader',
@@ -373,5 +365,6 @@ readonly class TestScraperConfigurationRequest
)]
#[Assert\Length(max: 500, maxMessage: 'Le sélecteur de chapitre est trop long')]
public ?string $chapterSelector = null,
) {}
) {
}
}

View File

@@ -13,7 +13,6 @@ readonly class TestScraperConfigurationResource
schema: ['type' => 'boolean']
)]
public bool $success,
#[ApiProperty(
description: 'Liste des URLs d\'images trouvées lors du scraping. Vide en cas d\'échec.',
example: [
@@ -29,28 +28,24 @@ readonly class TestScraperConfigurationResource
]
)]
public array $imageUrls,
#[ApiProperty(
description: 'Nombre total d\'images trouvées',
example: 2,
schema: ['type' => 'integer', 'minimum' => 0]
)]
public int $totalImages,
#[ApiProperty(
description: 'URL qui a été testée',
example: 'https://mangasite.example.com/manga/one-piece/chapter/1',
schema: ['type' => 'string', 'format' => 'uri']
)]
public string $testedUrl,
#[ApiProperty(
description: 'Type de scraping qui a été utilisé pour le test',
example: 'html',
schema: ['type' => 'string', 'enum' => ['html', 'javascript']]
)]
public string $scrapingType,
#[ApiProperty(
description: 'Liste des erreurs détaillées en cas d\'échec. Vide en cas de succès. Chaque erreur contient un type, le champ concerné, un message et une suggestion.',
example: [
@@ -89,5 +84,6 @@ readonly class TestScraperConfigurationResource
]
)]
public array $errors = [],
) {}
) {
}
}

View File

@@ -13,7 +13,8 @@ readonly class TestScraperConfigurationStateProcessor implements ProcessorInterf
{
public function __construct(
private TestScraperConfigurationHandler $handler
) {}
) {
}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): TestScraperConfigurationResource
{

View File

@@ -15,7 +15,8 @@ class AutoScrapingListener
private readonly ScrapeChapterHandler $scrapeChapterHandler,
private readonly ChapterRepositoryInterface $chapterRepository,
private readonly MangaRepositoryInterface $mangaRepository,
) {}
) {
}
#[AsMessageHandler]
public function onChapterReadyForScraping(ChapterReadyForScraping $event): void

View File

@@ -7,11 +7,13 @@ use App\Domain\Scraping\Domain\Exception\ChapterNotFoundException;
use App\Domain\Scraping\Domain\Model\Chapter;
use App\Entity\Chapter as EntityChapter;
use Doctrine\ORM\EntityManagerInterface;
readonly class LegacyChapterRepository implements ChapterRepositoryInterface
{
public function __construct(
private EntityManagerInterface $entityManager,
) {}
) {
}
/**
* Récupère un chapitre par son identifiant

View File

@@ -71,7 +71,7 @@ readonly class LegacyMangaRepository implements MangaRepositoryInterface
} else {
// Valider que toutes les sources existent avant de les sauvegarder
$sources = $this->entityManager->getRepository(ContentSource::class)->findBy(['id' => $sourceIds]);
$existingSourceIds = array_map(fn($source) => (string) $source->getId(), $sources);
$existingSourceIds = array_map(fn ($source) => (string) $source->getId(), $sources);
// Garder uniquement les sources qui existent et maintenir l'ordre
$validSourceIds = array_values(array_intersect($sourceIds, $existingSourceIds));

View File

@@ -89,7 +89,7 @@ class AdvancedHtmlScraper implements ScraperInterface
return $this->cleanImageUrl($src);
});
return array_filter($images, fn($url) => !empty($url));
return array_filter($images, fn ($url) => !empty($url));
}
private function scrapeHorizontalReader(ScrapingRequest $request): array
@@ -143,7 +143,7 @@ class AdvancedHtmlScraper implements ScraperInterface
sleep(1);
}
return array_filter($pages, fn($url) => !empty($url));
return array_filter($pages, fn ($url) => !empty($url));
}
private function fetchHtmlWithRetry(string $url): string

View File

@@ -16,7 +16,8 @@ class JavaScriptScraper implements ScraperInterface
public function __construct(
private readonly string $projectDir
) {}
) {
}
public function scrape(ScrapingRequest $request): ScrapingResult
{
@@ -44,7 +45,7 @@ class JavaScriptScraper implements ScraperInterface
return 'javascript' === $sourceType;
}
private function scrapeVerticalReader(ScrapingRequest $request, string $scriptPath): array
private function scrapeVerticalReader(ScrapingRequest $request, string $scriptPath): array
{
$params = $request->getScrapingParameters();
$processArgs = [
@@ -70,7 +71,7 @@ class JavaScriptScraper implements ScraperInterface
return $this->executeProcess($process);
}
private function scrapeHorizontalReader(ScrapingRequest $request, string $scriptPath): array
private function scrapeHorizontalReader(ScrapingRequest $request, string $scriptPath): array
{
$params = $request->getScrapingParameters();
@@ -143,10 +144,10 @@ class JavaScriptScraper implements ScraperInterface
{
return array_filter(
array_map(
fn($url) => $this->cleanImageUrl($url),
fn ($url) => $this->cleanImageUrl($url),
$urls
),
fn($url) => !empty($url) && filter_var($url, FILTER_VALIDATE_URL)
fn ($url) => !empty($url) && filter_var($url, FILTER_VALIDATE_URL)
);
}

View File

@@ -54,7 +54,7 @@ class ScraperFactory implements ScraperFactoryInterface
public function getBestScraper(): ScraperInterface
{
$sortedTypes = array_keys(self::SCRAPER_PRIORITIES);
usort($sortedTypes, fn($a, $b) => self::SCRAPER_PRIORITIES[$a] <=> self::SCRAPER_PRIORITIES[$b]);
usort($sortedTypes, fn ($a, $b) => self::SCRAPER_PRIORITIES[$a] <=> self::SCRAPER_PRIORITIES[$b]);
return $this->scrapers[$sortedTypes[0]];
}