chore: reorganizing
This commit is contained in:
52
src/Import/ActorSyncer.php
Normal file
52
src/Import/ActorSyncer.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Import;
|
||||
|
||||
use App\Entity\Actor;
|
||||
use App\Entity\Movie;
|
||||
use App\Entity\MovieRole;
|
||||
use App\Exception\GatewayException;
|
||||
use App\Gateway\TMDBGateway;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
readonly class ActorSyncer
|
||||
{
|
||||
public function __construct(
|
||||
private TMDBGateway $tmdbGateway,
|
||||
private EntityManagerInterface $em,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Fetch credits from TMDB for the given movie and create missing Actor/MovieRole entries.
|
||||
*
|
||||
* @throws GatewayException
|
||||
*/
|
||||
public function syncActorsForMovie(Movie $movie): void
|
||||
{
|
||||
$creditsContext = $this->tmdbGateway->getMovieCredits($movie->getTmdbId());
|
||||
|
||||
foreach ($creditsContext->cast as $actorModel) {
|
||||
$actor = $this->em->getRepository(Actor::class)->findOneBy(['tmdbId' => $actorModel->id]);
|
||||
if (!$actor instanceof Actor) {
|
||||
$actor = new Actor()
|
||||
->setPopularity($actorModel->popularity)
|
||||
->setName($actorModel->name)
|
||||
->setTmdbId($actorModel->id);
|
||||
|
||||
$this->em->persist($actor);
|
||||
}
|
||||
|
||||
$existingRole = $this->em->getRepository(MovieRole::class)->count(['actor' => $actor, 'movie' => $movie]);
|
||||
if (0 === $existingRole) {
|
||||
$role = new MovieRole()
|
||||
->setMovie($movie)
|
||||
->setActor($actor)
|
||||
->setCharacter($actorModel->character);
|
||||
|
||||
$this->em->persist($role);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
89
src/Import/AwardImporter.php
Normal file
89
src/Import/AwardImporter.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Import;
|
||||
|
||||
use App\Entity\Actor;
|
||||
use App\Entity\Award;
|
||||
use App\Entity\AwardType;
|
||||
use App\Gateway\WikidataGateway;
|
||||
use App\Repository\AwardTypeRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
readonly class AwardImporter
|
||||
{
|
||||
public function __construct(
|
||||
private WikidataGateway $wikidataGateway,
|
||||
private AwardTypeRepository $awardTypeRepository,
|
||||
private EntityManagerInterface $em,
|
||||
private ?LoggerInterface $logger = null,
|
||||
) {}
|
||||
|
||||
public function importForActor(Actor $actor): void
|
||||
{
|
||||
if ($actor->isAwardsImported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$wikidataAwards = $this->wikidataGateway->getAwards($actor);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger?->warning('Failed to fetch awards from Wikidata', [
|
||||
'actor' => $actor->getName(),
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$knownTypes = $this->awardTypeRepository->findAll();
|
||||
|
||||
foreach ($wikidataAwards as $wikidataAward) {
|
||||
$awardType = $this->resolveAwardType($wikidataAward['name'], $knownTypes);
|
||||
|
||||
$award = new Award();
|
||||
$award->setName($wikidataAward['name']);
|
||||
$award->setYear($wikidataAward['year']);
|
||||
$award->setActor($actor);
|
||||
$award->setAwardType($awardType);
|
||||
|
||||
$this->em->persist($award);
|
||||
}
|
||||
|
||||
$actor->setAwardsImported(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<AwardType> $knownTypes
|
||||
*/
|
||||
private function resolveAwardType(string $awardName, array &$knownTypes): AwardType
|
||||
{
|
||||
foreach ($knownTypes as $type) {
|
||||
if (str_contains($awardName, $type->getPattern())) {
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
|
||||
$newType = new AwardType();
|
||||
$prefix = $this->extractPrefix($awardName);
|
||||
$newType->setName($prefix);
|
||||
$newType->setPattern($prefix);
|
||||
|
||||
$this->em->persist($newType);
|
||||
$knownTypes[] = $newType;
|
||||
|
||||
return $newType;
|
||||
}
|
||||
|
||||
private function extractPrefix(string $awardName): string
|
||||
{
|
||||
// Extract text before " for " or " pour " (common patterns in award names)
|
||||
if (preg_match('/^(.+?)\s+(?:for|pour)\s+/i', $awardName, $matches)) {
|
||||
return trim($matches[1]);
|
||||
}
|
||||
|
||||
return $awardName;
|
||||
}
|
||||
}
|
||||
48
src/Import/FilmImporter.php
Normal file
48
src/Import/FilmImporter.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Import;
|
||||
|
||||
use App\Entity\Movie;
|
||||
use App\Exception\GatewayException;
|
||||
use App\Gateway\TMDBGateway;
|
||||
use App\Model\Ltbxd\LtbxdMovie;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
readonly class FilmImporter
|
||||
{
|
||||
public function __construct(
|
||||
private TMDBGateway $tmdbGateway,
|
||||
private EntityManagerInterface $em,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Find an existing Movie by ltbxdRef or create a new one via TMDB.
|
||||
* Returns null if the movie is not found on TMDB.
|
||||
*
|
||||
* @throws GatewayException
|
||||
*/
|
||||
public function importFromLtbxdMovie(LtbxdMovie $ltbxdMovie): ?Movie
|
||||
{
|
||||
$existing = $this->em->getRepository(Movie::class)->findOneBy(['ltbxdRef' => $ltbxdMovie->getLtbxdRef()]);
|
||||
if ($existing) {
|
||||
return $existing;
|
||||
}
|
||||
|
||||
$tmdbMovie = $this->tmdbGateway->searchMovie($ltbxdMovie->getName());
|
||||
if (!$tmdbMovie) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$movie = new Movie()
|
||||
->setLtbxdRef($ltbxdMovie->getLtbxdRef())
|
||||
->setTitle($ltbxdMovie->getName())
|
||||
->setTmdbId($tmdbMovie->getId())
|
||||
->setYear($ltbxdMovie->getYear());
|
||||
|
||||
$this->em->persist($movie);
|
||||
|
||||
return $movie;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user