diff --git a/Classes/Domain/Model/Dto/DateDemand.php b/Classes/Domain/Model/Dto/DateDemand.php index 0e4ed65..98942e4 100644 --- a/Classes/Domain/Model/Dto/DateDemand.php +++ b/Classes/Domain/Model/Dto/DateDemand.php @@ -77,10 +77,19 @@ class DateDemand protected $endObject = null; /** + * Use midnight as "start". + * * @var bool */ protected $useMidnight = true; + /** + * Only show dates that have not started yet. + * + * @var bool + */ + protected $upcoming = false; + /** * @var string */ @@ -361,13 +370,25 @@ class DateDemand public function setUseMidnight(bool $useMidnight): void { $this->useMidnight = $useMidnight; + $this->upcoming = false; + } + + public function setUpcoming(bool $upcoming): void + { + $this->startObject = null; + $this->endObject = null; + $this->useMidnight = false; + + $this->upcoming = $upcoming; } public function shouldShowFromNow(): bool { return $this->getStartObject() === null && $this->getEndObject() === null - && $this->useMidnight === false; + && $this->useMidnight === false + && $this->upcoming === false + ; } public function shouldShowFromMidnight(): bool @@ -377,6 +398,11 @@ class DateDemand && $this->useMidnight === true; } + public function shouldShowUpcoming(): bool + { + return $this->upcoming === true; + } + public function getConsiderDate(): bool { return $this->considerDate; diff --git a/Classes/Domain/Model/Dto/DateDemandFactory.php b/Classes/Domain/Model/Dto/DateDemandFactory.php index c73a2bf..fa34516 100644 --- a/Classes/Domain/Model/Dto/DateDemandFactory.php +++ b/Classes/Domain/Model/Dto/DateDemandFactory.php @@ -99,6 +99,9 @@ class DateDemandFactory if (isset($settings['useMidnight'])) { $demand->setUseMidnight((bool)$settings['useMidnight']); } + if (isset($settings['upcoming'])) { + $demand->setUpcoming((bool)$settings['upcoming']); + } if (!empty($settings['limit'])) { $demand->setLimit($settings['limit']); } diff --git a/Classes/Domain/Repository/DateRepository.php b/Classes/Domain/Repository/DateRepository.php index 4a190d7..aab0437 100644 --- a/Classes/Domain/Repository/DateRepository.php +++ b/Classes/Domain/Repository/DateRepository.php @@ -2,6 +2,8 @@ namespace Wrm\Events\Domain\Repository; +use DateTimeImmutable; +use DateTimeZone; use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -10,6 +12,7 @@ use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult; use TYPO3\CMS\Extbase\Persistence\QueryInterface; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Persistence\Repository; +use UnexpectedValueException; use Wrm\Events\Domain\Model\Dto\DateDemand; use Wrm\Events\Service\CategoryService; @@ -87,19 +90,7 @@ class DateRepository extends Repository } if ($demand->shouldShowFromNow() || $demand->shouldShowFromMidnight()) { - $now = $this->context->getPropertyFromAspect( - 'date', - 'full', - new \DateTimeImmutable() - ); - if (!$now instanceof \DateTimeImmutable) { - throw new \UnexpectedValueException( - 'Could not retrieve now as DateTimeImmutable, got "' . gettype($now) . '".', - 1639382648 - ); - } - - $now = $now->setTimezone(new \DateTimeZone(date_default_timezone_get())); + $now = $this->getNow(); if ($demand->shouldShowFromMidnight()) { $now = $now->modify('midnight'); @@ -109,6 +100,16 @@ class DateRepository extends Repository $query->greaterThanOrEqual('start', $now), $query->greaterThanOrEqual('end', $now) ]); + } elseif ($demand->shouldShowUpcoming()) { + $now = $this->getNow(); + + $constraints['future'] = $query->logicalAnd([ + $query->greaterThan('start', $now), + $query->logicalOr([ + $query->equals('end', 0), + $query->greaterThan('end', $now) + ]) + ]); } if ($demand->getLimit() !== '') { @@ -283,4 +284,24 @@ class DateRepository extends Repository $query->logicalNot($query->equals('event.uid', null)) ); } + + private function getNow(): DateTimeImmutable + { + $now = $this->context->getPropertyFromAspect( + 'date', + 'full', + new DateTimeImmutable() + ); + + if (!$now instanceof DateTimeImmutable) { + throw new UnexpectedValueException( + 'Could not retrieve now as DateTimeImmutable, got "' . gettype($now) . '".', + 1639382648 + ); + } + + $now = $now->setTimezone(new DateTimeZone(date_default_timezone_get())); + + return $now; + } } diff --git a/Documentation/Changelog/3.4.0.rst b/Documentation/Changelog/3.4.0.rst index 8e9241b..532b0ac 100644 --- a/Documentation/Changelog/3.4.0.rst +++ b/Documentation/Changelog/3.4.0.rst @@ -17,6 +17,13 @@ Features That allows visitors to always see the next dates. +* Add ``upcoming`` setting for dates. + + The option can be set to ``0`` (default) or ``1``. + ``0`` behaves the same way as in the past. + ``1`` turns off the option ``useMidnight``, ``start`` and ``end``. + Only dates with a start date in the future will be shown. + Fixes ----- diff --git a/Documentation/Settings.rst b/Documentation/Settings.rst index df9daef..1dbb78e 100644 --- a/Documentation/Settings.rst +++ b/Documentation/Settings.rst @@ -3,6 +3,28 @@ Settings ======== +Frontend +-------- + +The frontend can be configured via TYPO3 Extbase defaults. + +``stdWrap`` is applied to all options. + +.. option:: settings.useMidnight + + Can be set to ``1`` (default) or ``0``. + + | ``0`` will show dates starting from now. + | ``1`` will use midnight of configured start date. + +.. option:: settings.upcoming + + Can be set to ``0`` (default) or ``1``. + + | ``0`` does not alter the behaviour. + | ``1`` turns off the option ``useMidnight``, ``start`` and ``end``. + | Only dates with a start date in the future will be shown. + Import ------ diff --git a/Tests/Functional/Frontend/DatesTest.php b/Tests/Functional/Frontend/DatesTest.php index 76ae42e..041d768 100644 --- a/Tests/Functional/Frontend/DatesTest.php +++ b/Tests/Functional/Frontend/DatesTest.php @@ -172,4 +172,34 @@ class DatesTest extends AbstractTestCase self::assertStringContainsString('Event 8', $html); self::assertStringContainsString('Event 9', $html); } + + /** + * @test + */ + public function returnsUpcomingDates(): void + { + $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsUpcomingDates.php'); + + $request = new InternalRequest(); + $request = $request->withPageId(1); + $request = $request->withInstructions([ + $this->getTypoScriptInstruction() + ->withTypoScript([ + 'plugin.' => [ + 'tx_events.' => [ + 'settings.' => [ + 'upcoming' => '1', + ], + ], + ], + ]) + ]); + $response = $this->executeFrontendRequest($request); + + self::assertSame(200, $response->getStatusCode()); + $html = (string) $response->getBody(); + + self::assertStringNotContainsString('Event 1', $html); + self::assertStringContainsString('Event 2', $html); + } } diff --git a/Tests/Functional/Frontend/DatesTestFixtures/ReturnsUpcomingDates.php b/Tests/Functional/Frontend/DatesTestFixtures/ReturnsUpcomingDates.php new file mode 100644 index 0000000..2cd7aeb --- /dev/null +++ b/Tests/Functional/Frontend/DatesTestFixtures/ReturnsUpcomingDates.php @@ -0,0 +1,43 @@ + [ + [ + 'uid' => 1, + 'pid' => 1, + 'CType' => 'list', + 'list_type' => 'events_datelist', + 'header' => 'Upcoming Dates', + ], + ], + 'tx_events_domain_model_event' => [ + [ + 'uid' => 1, + 'pid' => 2, + 'title' => 'Event 1', + ], + [ + 'uid' => 2, + 'pid' => 2, + 'title' => 'Event 2', + ], + ], + 'tx_events_domain_model_date' => [ + [ + 'uid' => 1, + 'pid' => 2, + 'event' => 1, + 'start' => (new DateTimeImmutable())->modify('-5 minutes')->format('U'), + 'end' => (new DateTimeImmutable())->modify('+5 minutes')->format('U'), + ], + [ + 'uid' => 2, + 'pid' => 2, + 'event' => 2, + 'start' => (new DateTimeImmutable())->modify('+5 minutes')->format('U'), + 'end' => (new DateTimeImmutable())->modify('+15 minutes')->format('U'), + ], + ], +];