diff --git a/phpstan-baseline.php b/phpstan-baseline.php index f85ead6d8..9de35b79c 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -4183,18 +4183,6 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/TechLetter/PreviewAction.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Cannot access property \\$urlName on AppBundle\\\\Antennes\\\\Meetup\\|null\\.$#', - 'identifier' => 'property.nonObject', - 'count' => 2, - 'path' => __DIR__ . '/sources/AppBundle/Controller/Api/Antennes/GetOneAction.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Controller\\\\Api\\\\Antennes\\\\GetOneAction\\:\\:transformMeetup\\(\\) return type has no value type specified in iterable type array\\.$#', - 'identifier' => 'missingType.iterableValue', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Controller/Api/Antennes/GetOneAction.php', -]; $ignoreErrors[] = [ 'message' => '#^Cannot access offset \'email\' on mixed\\.$#', 'identifier' => 'offsetAccess.nonOffsetAccessible', @@ -7909,36 +7897,6 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Github/Exception/UnableToGetGithubUserInfosException.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Cannot call method setSettings\\(\\) on mixed\\.$#', - 'identifier' => 'method.nonObject', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Indexation/Meetups/Runner.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Indexation\\\\Meetups\\\\Runner\\:\\:getTransformedMeetupsFromDatabase\\(\\) return type has no value type specified in iterable type array\\.$#', - 'identifier' => 'missingType.iterableValue', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Indexation/Meetups/Runner.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Indexation\\\\Meetups\\\\Runner\\:\\:initIndex\\(\\) should return Algolia\\\\AlgoliaSearch\\\\SearchIndex but returns mixed\\.$#', - 'identifier' => 'return.type', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Indexation/Meetups/Runner.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Cannot access property \\$urlName on AppBundle\\\\Antennes\\\\Meetup\\|null\\.$#', - 'identifier' => 'property.nonObject', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Indexation/Meetups/Transformer.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Indexation\\\\Meetups\\\\Transformer\\:\\:transform\\(\\) return type has no value type specified in iterable type array\\.$#', - 'identifier' => 'missingType.iterableValue', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Indexation/Meetups/Transformer.php', -]; $ignoreErrors[] = [ 'message' => '#^Cannot call method setSettings\\(\\) on mixed\\.$#', 'identifier' => 'method.nonObject', diff --git a/sources/AppBundle/Controller/Api/Antennes/GetOneAction.php b/sources/AppBundle/Controller/Api/Antennes/GetOneAction.php index c084c91c5..41dfb3fba 100644 --- a/sources/AppBundle/Controller/Api/Antennes/GetOneAction.php +++ b/sources/AppBundle/Controller/Api/Antennes/GetOneAction.php @@ -37,7 +37,7 @@ public function __invoke(string $code): JsonResponse 'simple' => 'https://afup.org' . $antenne->logoUrl, ], 'links' => [ - 'meetup' => $this->createLink('https://www.meetup.com/fr-FR/', $antenne->meetup->urlName), + 'meetup' => $this->createLink('https://www.meetup.com/fr-FR/', $antenne->meetup?->urlName), 'linkedin' => $this->createLink('https://www.linkedin.com/company/', $antenne->socials->linkedin), 'bluesky' => $this->createLink('https://bsky.app/profile/', $antenne->socials->bluesky), 'cfp' => $antenne->socials->cfp, @@ -70,6 +70,9 @@ private function createLink(string $prefix, ?string $suffix): ?string return $prefix . $suffix; } + /** + * @return array + */ private function transformMeetup(Antenne $antenne, Meetup $meetup): array { return [ @@ -77,7 +80,7 @@ private function transformMeetup(Antenne $antenne, Meetup $meetup): array 'date' => $meetup->date->format('Y-m-d H:i:s'), 'location' => $meetup->lieu, 'description' => $meetup->description, - 'url' => 'https://www.meetup.com/fr-FR/' . $antenne->meetup->urlName . '/events/' . $meetup->id, + 'url' => $antenne->meetup === null ? null : 'https://www.meetup.com/fr-FR/' . $antenne->meetup->urlName . '/events/' . $meetup->id, 'photo' => $meetup->photoUrl, ]; } diff --git a/sources/AppBundle/Indexation/Meetups/Runner.php b/sources/AppBundle/Indexation/Meetups/Runner.php index 8b67d530f..e06f3a0e0 100644 --- a/sources/AppBundle/Indexation/Meetups/Runner.php +++ b/sources/AppBundle/Indexation/Meetups/Runner.php @@ -40,6 +40,7 @@ public function run(): void protected function initIndex(): SearchIndex { + /** @var SearchIndex $index */ $index = $this->algoliaClient->initIndex('afup_meetups'); $index->setSettings([ @@ -61,6 +62,9 @@ protected function initIndex(): SearchIndex return $index; } + /** + * @return list> + */ private function getTransformedMeetupsFromDatabase(): array { $meetupsCollection = $this->meetupRepository->findAll(); @@ -70,7 +74,7 @@ private function getTransformedMeetupsFromDatabase(): array /** * @param array $meetupsCollection - * @return list + * @return list> */ public function transformMeetupsForIndexation(array $meetupsCollection): array { diff --git a/sources/AppBundle/Indexation/Meetups/Transformer.php b/sources/AppBundle/Indexation/Meetups/Transformer.php index c76032cd8..904fd5fe6 100644 --- a/sources/AppBundle/Indexation/Meetups/Transformer.php +++ b/sources/AppBundle/Indexation/Meetups/Transformer.php @@ -15,7 +15,7 @@ class Transformer public function __construct(private readonly AntenneRepository $antennesCollection) {} /** - * @return array + * @return array */ public function transform(Meetup $meetup): array { @@ -55,6 +55,11 @@ public function transform(Meetup $meetup): array private function getEventUrl(Antenne $antenne, Meetup $meetup): string { - return self::MEETUP_URL . $antenne->meetup->urlName . '/events/' . $meetup->id; + $antenneMeetup = $antenne->meetup; + if ($antenneMeetup === null) { + return self::MEETUP_URL . '/events/' . $meetup->id; + } + + return self::MEETUP_URL . $antenneMeetup->urlName . '/events/' . $meetup->id; } } diff --git a/tests/integration/AppBundle/Event/Entity/Repository/MeetupRepositoryTest.php b/tests/integration/AppBundle/Event/Entity/Repository/MeetupRepositoryTest.php new file mode 100644 index 000000000..5aae0af1a --- /dev/null +++ b/tests/integration/AppBundle/Event/Entity/Repository/MeetupRepositoryTest.php @@ -0,0 +1,77 @@ +get(MeetupRepository::class); + $antennesCollection = self::getContainer()->get(AntenneRepository::class); + $antenne = $antennesCollection->findByCode('lyon'); + + self::assertSame([], $meetupRepository->findAllForAntenne($antenne)); + self::assertNull($meetupRepository->findNextForAntenne($antenne)); + self::assertSame([], $meetupRepository->findNextEvents(3)); + + $passe = new Meetup(); + $passe->id = 1; + $passe->date = new \DateTimeImmutable('yesterday'); + $passe->titre = 'Meetup passé'; + $passe->lieu = 'Lyon'; + $passe->description = 'Meetup à Lyon'; + $passe->codeAntenne = $antenne->code; + $passe->photoUrl = null; + $meetupRepository->save($passe); + + $futur = new Meetup(); + $futur->id = 2; + $futur->date = new \DateTimeImmutable('tomorrow'); + $futur->titre = 'Meetup futur'; + $futur->lieu = 'Lyon'; + $futur->description = 'Meetup à Lyon'; + $futur->codeAntenne = $antenne->code; + $futur->photoUrl = 'https://example.com/photo.png'; + $meetupRepository->save($futur); + + $autreAntenne = new Meetup(); + $autreAntenne->id = 3; + $autreAntenne->date = new \DateTimeImmutable('+2 days'); + $autreAntenne->titre = 'Meetup autre antenne'; + $autreAntenne->lieu = 'Paris'; + $autreAntenne->description = 'Meetup à Paris'; + $autreAntenne->codeAntenne = 'paris'; + $autreAntenne->photoUrl = null; + $meetupRepository->save($autreAntenne); + + $next = $meetupRepository->findNextForAntenne($antenne); + self::assertNotNull($next); + self::assertSame(2, $next->id); + + $all = $meetupRepository->findAllForAntenne($antenne); + self::assertCount(2, $all); + self::assertSame(['Meetup passé', 'Meetup futur'], array_map( + static fn(Meetup $meetup): string => $meetup->titre, + $all, + )); + + self::assertSame([3, 2], array_map( + static fn(Meetup $meetup): int => $meetup->id, + $meetupRepository->findNextEvents(2), + )); + + // Mise à jour d'une entité existante proche du comportement de ScrappingMeetupEventsCommand + $existing = $meetupRepository->find(2); + self::assertNotNull($existing); + $existing->titre = 'Meetup futur mis à jour'; + $meetupRepository->save($existing); + self::assertSame('Meetup futur mis à jour', $meetupRepository->find(2)?->titre); + } +}