diff --git a/modules/opd_presentations/opd_presentations.services.yml b/modules/opd_presentations/opd_presentations.services.yml index e6b2fbe6c..bacc8f79c 100644 --- a/modules/opd_presentations/opd_presentations.services.yml +++ b/modules/opd_presentations/opd_presentations.services.yml @@ -1,2 +1,3 @@ services: - Drupal\opd_presentations\PresentationCounter: {} + Drupal\opd_presentations\PresentationCounter: + autowire: true diff --git a/modules/opd_presentations/src/Events.php b/modules/opd_presentations/src/Events.php index fba17a01d..4e60a9ad1 100644 --- a/modules/opd_presentations/src/Events.php +++ b/modules/opd_presentations/src/Events.php @@ -9,7 +9,11 @@ use Webmozart\Assert\Assert; /** * @implements \IteratorAggregate */ -readonly final class Events implements \IteratorAggregate { +readonly final class Events implements \Countable, \IteratorAggregate { + + public function count(): int { + return count($this->events); + } public function filter(\Closure $callback): self { return new self(array_filter( diff --git a/modules/opd_presentations/src/Presentation.php b/modules/opd_presentations/src/Presentation.php index 876866a5e..300104aae 100644 --- a/modules/opd_presentations/src/Presentation.php +++ b/modules/opd_presentations/src/Presentation.php @@ -11,9 +11,8 @@ final class Presentation extends Node implements NodeInterface { public const NODE_TYPE = 'presentation'; - public function getPastEvents(): Events { - return Events::fromEvents($this->get('field_events')->referencedEntities()) - ->getPast(); + public function getEvents(): Events { + return Events::fromEvents($this->get('field_events')->referencedEntities()); } } diff --git a/modules/opd_presentations/src/PresentationCounter.php b/modules/opd_presentations/src/PresentationCounter.php new file mode 100644 index 000000000..263032e6e --- /dev/null +++ b/modules/opd_presentations/src/PresentationCounter.php @@ -0,0 +1,37 @@ +entityTypeManager->getStorage('node'); + + $query = $nodeStorage->getQuery(); + $query->condition('status', NodeInterface::PUBLISHED); + $query->condition('type', Presentation::NODE_TYPE); + $query->accessCheck(); + + $nodeIds = $query->execute(); + + $presentations = $nodeStorage->loadMultiple($nodeIds); + + return array_reduce( + array: $presentations, + callback: fn (int $count, Presentation $presentation) + => $count + $presentation->getEvents()->getPast()->count(), + initial: 0, + ); + } + +} diff --git a/modules/opd_presentations/tests/src/Functional/PresentationCounterTest.php b/modules/opd_presentations/tests/src/Functional/PresentationCounterTest.php new file mode 100644 index 000000000..1e938a808 --- /dev/null +++ b/modules/opd_presentations/tests/src/Functional/PresentationCounterTest.php @@ -0,0 +1,95 @@ +container->get(PresentationCounter::class); + assert($counter instanceof PresentationCounter); + + $this->createPresentation( + events: [ + $this->createEvent( + eventDate: Date::fromString('yesterday'), + eventName: $this->randomString(), + ), + ], + ); + + $this->assertGreaterThanOrEqual( + actual: $counter->getPastCount(), + expected: 1, + ); + } + + public function test_it_only_counts_published_events(): void { + $counter = $this->container->get(PresentationCounter::class); + assert($counter instanceof PresentationCounter); + + $count = $counter->getPastCount(); + + $this->createPresentation( + events: [ + $this->createEvent( + eventDate: Date::fromString('yesterday'), + eventName: $this->randomString(), + ), + ], + isPublished: FALSE, + ); + + $this->assertSame( + actual: $counter->getPastCount(), + expected: $count, + ); + } + + public function test_it_only_counts_past_events(): void { + $counter = $this->container->get(PresentationCounter::class); + assert($counter instanceof PresentationCounter); + + // Get the existing presentation count (including existing nodes). + $originalCount = $counter->getPastCount(); + + $this->assertGreaterThanOrEqual( + actual: $originalCount, + expected: 0, + ); + + $this->createPresentation( + events: [ + $this->createEvent( + eventDate: Date::fromString('tomorrow'), + eventName: $this->randomString(), + ), + + $this->createEvent( + eventDate: Date::fromString('yesterday'), + eventName: $this->randomString(), + ), + ], + ); + + $counter = $this->container->get(PresentationCounter::class); + + // Ensure the count has only increased by one, even though a future and past event were created. + $this->assertSame( + actual: $counter->getPastCount(), + expected: $originalCount + 1, + ); + } + +} diff --git a/modules/opd_presentations/tests/src/Traits/PresentationCreationTrait.php b/modules/opd_presentations/tests/src/Traits/PresentationCreationTrait.php index 16530e5ab..d165fe6e5 100644 --- a/modules/opd_presentations/tests/src/Traits/PresentationCreationTrait.php +++ b/modules/opd_presentations/tests/src/Traits/PresentationCreationTrait.php @@ -19,9 +19,10 @@ trait PresentationCreationTrait { /** * @param Event[] $events */ - private function createPresentation(array $events): Presentation { + private function createPresentation(array $events, bool $isPublished = TRUE): Presentation { $presentation = $this->createNode([ 'field_events' => $events, + 'status' => $isPublished, 'type' => Presentation::NODE_TYPE, ]);