Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 0 additions & 42 deletions phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -3973,18 +3973,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',
Expand Down Expand Up @@ -7471,36 +7459,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',
Expand Down
7 changes: 5 additions & 2 deletions sources/AppBundle/Controller/Api/Antennes/GetOneAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -70,14 +70,17 @@ private function createLink(string $prefix, ?string $suffix): ?string
return $prefix . $suffix;
}

/**
* @return array<string, mixed>
*/
private function transformMeetup(Antenne $antenne, Meetup $meetup): array
{
return [
'title' => $meetup->titre,
'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,
];
}
Expand Down
10 changes: 7 additions & 3 deletions sources/AppBundle/Event/Entity/Repository/MeetupRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function findNextForAntenne(Antenne $antenne): ?Meetup
->setParameter('codeAntenne', $antenne->code)
->andWhere($qb->expr()->gt('m.date', ':after'))
->setParameter('after', $this->now()->modify('midnight'))
->orderBy('m.date', 'DESC')
->orderBy('m.date', 'ASC')
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
Expand All @@ -55,8 +55,12 @@ public function findAllForAntenne(Antenne $antenne): array
*/
public function findNextEvents(int $quantity): array
{
return $this->createQueryBuilder('m')
->orderBy('m.date', 'DESC')
$qb = $this->createQueryBuilder('m');

return $qb
->where($qb->expr()->gte('m.date', ':now'))
->setParameter('now', $this->now())
->orderBy('m.date', 'ASC')
->setMaxResults($quantity)
->getQuery()
->getResult();
Expand Down
6 changes: 5 additions & 1 deletion sources/AppBundle/Indexation/Meetups/Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function run(): void

protected function initIndex(): SearchIndex
{
/** @var SearchIndex $index */
$index = $this->algoliaClient->initIndex('afup_meetups');

$index->setSettings([
Expand All @@ -61,6 +62,9 @@ protected function initIndex(): SearchIndex
return $index;
}

/**
* @return list<array<string, mixed>>
*/
private function getTransformedMeetupsFromDatabase(): array
{
$meetupsCollection = $this->meetupRepository->findAll();
Expand All @@ -70,7 +74,7 @@ private function getTransformedMeetupsFromDatabase(): array

/**
* @param array<Meetup> $meetupsCollection
* @return list<array>
* @return list<array<string, mixed>>
*/
public function transformMeetupsForIndexation(array $meetupsCollection): array
{
Expand Down
9 changes: 7 additions & 2 deletions sources/AppBundle/Indexation/Meetups/Transformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Transformer
public function __construct(private readonly AntenneRepository $antennesCollection) {}

/**
* @return array
* @return array<string, mixed>
*/
public function transform(Meetup $meetup): array
{
Expand Down Expand Up @@ -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;
}
}
6 changes: 4 additions & 2 deletions tests/behat/features/PublicSite/Home.feature
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ Feature: Site Public - Home

@reloadDbWithTestData
Scenario: Sur la home on a bien un lien vers le dernier article affiché
Given I am on the homepage
Given the current date is "2026-01-01"
And I am on the homepage

# Article à la une
Then I should see "Un article en Markdown"
Expand All @@ -27,7 +28,8 @@ Feature: Site Public - Home

@reloadDbWithTestData
Scenario: Affichage des derniers meetups
Given I am on the homepage
Given the current date is "2025-11-01"
And I am on the homepage
Then I should see "Le super meetup"
And I should see "Lyon"
And I should see "08/11"
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

declare(strict_types=1);

namespace AppBundle\IntegrationTests\Event\Entity\Repository;

use Afup\Tests\Support\IntegrationTestCase;
use AppBundle\Antennes\AntenneRepository;
use AppBundle\Event\Entity\Meetup;
use AppBundle\Event\Entity\Repository\MeetupRepository;

final class MeetupRepositoryTest extends IntegrationTestCase
{
public function testFindSaveAndQueries(): void
{
$meetupRepository = self::getContainer()->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);

// Deuxième meetup futur pour lyon : permet de vérifier que findNextForAntenne()
// renvoie bien le meetup le plus proche et non le plus lointain
$plusLointain = new Meetup();
$plusLointain->id = 4;
$plusLointain->date = new \DateTimeImmutable('+4 days');
$plusLointain->titre = 'Meetup futur lointain';
$plusLointain->lieu = 'Lyon';
$plusLointain->description = 'Meetup à Lyon';
$plusLointain->codeAntenne = $antenne->code;
$plusLointain->photoUrl = null;
$meetupRepository->save($plusLointain);

$next = $meetupRepository->findNextForAntenne($antenne);
self::assertNotNull($next);
self::assertSame(2, $next->id);

$all = $meetupRepository->findAllForAntenne($antenne);
self::assertCount(3, $all);
$titres = array_map(static fn(Meetup $meetup): string => $meetup->titre, $all);
sort($titres);
self::assertSame(['Meetup futur', 'Meetup futur lointain', 'Meetup passé'], $titres);

// Tri chronologique croissant, meetup passé exclu
self::assertSame([2, 3], array_map(
static fn(Meetup $meetup): int => $meetup->id,
$meetupRepository->findNextEvents(2),
));
self::assertSame([2, 3, 4], array_map(
static fn(Meetup $meetup): int => $meetup->id,
$meetupRepository->findNextEvents(42),
));

// 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);
}
}
Loading