Created
September 14, 2025 10:02
-
-
Save juanwilde/1a999f3ebc7241c8273b0e63c913cbb1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // EventImport | |
| <?php | |
| declare(strict_types=1); | |
| namespace App\Application\UseCase; | |
| use App\Application\Service\EventProviderInterface; | |
| use App\Domain\Repository\EventRepository; | |
| use Psr\Log\LoggerInterface; | |
| use Symfony\Component\DependencyInjection\Attribute\AutowireIterator; | |
| use Throwable; | |
| use function iterator_count; | |
| use function sprintf; | |
| final readonly class EventImport | |
| { | |
| /** | |
| * @param iterable<EventProviderInterface> $providers | |
| */ | |
| public function __construct( | |
| #[AutowireIterator('app.event.provider')] | |
| private iterable $providers, | |
| private EventRepository $eventRepository, | |
| private LoggerInterface $logger, | |
| ) {} | |
| public function execute(): void | |
| { | |
| $this->logger->info(sprintf('Providers: %s', iterator_count($this->providers))); | |
| foreach ($this->providers as $provider) { | |
| try { | |
| $events = iterator_to_array($provider->fetchEvents()); | |
| if (!empty($events)) { | |
| $this->eventRepository->bulkUpsert($events); | |
| } | |
| } catch (Throwable $e) { | |
| $this->logger->error(sprintf('Provider %s failed with error <%s>', $provider->getName(), $e->getMessage())); | |
| continue; | |
| } | |
| } | |
| } | |
| } | |
| // EventRepository | |
| <?php | |
| declare(strict_types=1); | |
| namespace App\Domain\Repository; | |
| use App\Domain\DTO\EventDTO; | |
| use App\Domain\Entity\Event; | |
| interface EventRepository | |
| { | |
| public function findOneByProviderAndExternalId(string $provider, string $externalId): ?Event; | |
| /** | |
| * @return array<int, Event> | |
| */ | |
| public function findByDateRange(int $startTimestamp, int $endTimestamp): array; | |
| public function persist(Event $event): void; | |
| public function flush(): void; | |
| /** | |
| * @param array<EventDTO> $eventDTOs | |
| */ | |
| public function bulkUpsert(array $eventDTOs): void; | |
| } | |
| // DoctrineEvent Repository | |
| <?php | |
| declare(strict_types=1); | |
| namespace App\Adapter\Persistence\Doctrine; | |
| use App\Domain\DTO\EventDTO; | |
| use App\Domain\Entity\Event; | |
| use App\Domain\Repository\EventRepository; | |
| use DateTimeImmutable; | |
| use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; | |
| use Doctrine\Common\Collections\ArrayCollection; | |
| use Doctrine\DBAL\Connection; | |
| use Doctrine\ORM\Query\Parameter; | |
| use Doctrine\ORM\Query\ResultSetMappingBuilder; | |
| use Doctrine\Persistence\ManagerRegistry; | |
| use Ramsey\Uuid\Uuid; | |
| /** | |
| * @extends ServiceEntityRepository<Event> | |
| */ | |
| final class DoctrineEventRepository extends ServiceEntityRepository implements EventRepository | |
| { | |
| public function __construct(ManagerRegistry $registry) | |
| { | |
| parent::__construct($registry, Event::class); | |
| } | |
| // ...existing code... | |
| /** | |
| * @param array<EventDTO> $eventDTOs | |
| */ | |
| public function bulkUpsert(array $eventDTOs): void | |
| { | |
| if (empty($eventDTOs)) { | |
| return; | |
| } | |
| $connection = $this->getEntityManager()->getConnection(); | |
| $sql = <<<'SQL' | |
| INSERT INTO events ( | |
| id, external_id, event_provider, title, starts_at, ends_at, | |
| min_price, max_price, sell_mode, ever_online | |
| ) VALUES %s | |
| ON CONFLICT (event_provider, external_id) | |
| DO UPDATE SET | |
| title = EXCLUDED.title, | |
| starts_at = EXCLUDED.starts_at, | |
| ends_at = EXCLUDED.ends_at, | |
| min_price = EXCLUDED.min_price, | |
| max_price = EXCLUDED.max_price, | |
| sell_mode = EXCLUDED.sell_mode, | |
| ever_online = events.ever_online OR (EXCLUDED.sell_mode = 'online') | |
| SQL; | |
| $values = []; | |
| $params = []; | |
| $types = []; | |
| foreach ($eventDTOs as $i => $dto) { | |
| $values[] = sprintf( | |
| '($%d, $%d, $%d, $%d, $%d, $%d, $%d, $%d, $%d, $%d)', | |
| $i * 10 + 1, $i * 10 + 2, $i * 10 + 3, $i * 10 + 4, $i * 10 + 5, | |
| $i * 10 + 6, $i * 10 + 7, $i * 10 + 8, $i * 10 + 9, $i * 10 + 10 | |
| ); | |
| $params = array_merge($params, [ | |
| Uuid::uuid4()->toString(), | |
| $dto->externalId, | |
| $dto->eventProvider->value, | |
| $dto->title, | |
| $dto->startsAt, | |
| $dto->endsAt, | |
| $dto->minPrice, | |
| $dto->maxPrice, | |
| $dto->sellMode, | |
| $dto->sellMode === 'online' | |
| ]); | |
| $types = array_merge($types, [ | |
| 'string', 'string', 'string', 'string', 'datetimetz_immutable', | |
| 'datetimetz_immutable', 'decimal', 'decimal', 'string', 'boolean' | |
| ]); | |
| } | |
| $finalSql = sprintf($sql, implode(', ', $values)); | |
| $connection->executeStatement($finalSql, $params, $types); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment