Provide configurable repeatUntil fallback

This commit is contained in:
Daniel Siepmann 2023-01-05 09:01:13 +00:00
parent 6570ec5ca9
commit f68da60842
15 changed files with 601 additions and 43 deletions

View file

@ -3,6 +3,9 @@
namespace Wrm\Events\Service\DestinationDataImportService; namespace Wrm\Events\Service\DestinationDataImportService;
use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Log\Logger;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use Wrm\Events\Domain\Model\Date; use Wrm\Events\Domain\Model\Date;
class DatesFactory class DatesFactory
@ -12,10 +15,24 @@ class DatesFactory
*/ */
private $context; private $context;
/**
* @var ConfigurationManager
*/
private $configurationManager;
/**
* @var Logger
*/
private $logger;
public function __construct( public function __construct(
Context $context Context $context,
ConfigurationManager $configurationManager,
LogManager $logManager
) { ) {
$this->context = $context; $this->context = $context;
$this->configurationManager = $configurationManager;
$this->logger = $logManager->getLogger(__CLASS__);
} }
/** /**
@ -45,10 +62,12 @@ class DatesFactory
bool $canceled bool $canceled
): ?\Generator { ): ?\Generator {
if ($this->isDateSingleDate($date)) { if ($this->isDateSingleDate($date)) {
$this->logger->info('Is single date', ['date' => $date]);
return $this->createSingleDate($date, $canceled); return $this->createSingleDate($date, $canceled);
} }
if ($this->isDateInterval($date)) { if ($this->isDateInterval($date)) {
$this->logger->info('Is interval date', ['date' => $date]);
return $this->createDateFromInterval($date, $canceled); return $this->createDateFromInterval($date, $canceled);
} }
@ -66,10 +85,6 @@ class DatesFactory
private function isDateInterval(array $date): bool private function isDateInterval(array $date): bool
{ {
if (empty($date['repeatUntil'])) {
return false;
}
$frequency = $date['freq'] ?? ''; $frequency = $date['freq'] ?? '';
if ($frequency == 'Daily' && empty($date['weekdays'])) { if ($frequency == 'Daily' && empty($date['weekdays'])) {
@ -102,6 +117,8 @@ class DatesFactory
array $date, array $date,
bool $canceled bool $canceled
): ?\Generator { ): ?\Generator {
$date = $this->ensureRepeatUntil($date);
if ($date['freq'] == 'Daily') { if ($date['freq'] == 'Daily') {
return $this->createDailyDates($date, $canceled); return $this->createDailyDates($date, $canceled);
} }
@ -113,6 +130,24 @@ class DatesFactory
return null; return null;
} }
private function ensureRepeatUntil(array $date): array
{
if (empty($date['repeatUntil']) === false) {
return $date;
}
$settings = $this->configurationManager->getConfiguration(
ConfigurationManager::CONFIGURATION_TYPE_SETTINGS,
'Events',
'Import'
);
$configuredModification = $settings['repeatUntil'] ?? '+60 days';
$date['repeatUntil'] = $this->getToday()->modify($configuredModification)->format('c');
$this->logger->info('Interval did not provide repeatUntil.', ['newRepeat' => $date['repeatUntil']]);
return $date;
}
/** /**
* @return \Generator<Date> * @return \Generator<Date>
*/ */
@ -130,6 +165,7 @@ class DatesFactory
foreach ($period as $day) { foreach ($period as $day) {
$day = $day->setTimezone($timeZone); $day = $day->setTimezone($timeZone);
if ($day < $today) { if ($day < $today) {
$this->logger->debug('Date was in the past.', ['day' => $day]);
continue; continue;
} }
@ -163,6 +199,7 @@ class DatesFactory
foreach ($period as $day) { foreach ($period as $day) {
$day = $day->setTimezone($timeZone); $day = $day->setTimezone($timeZone);
if ($day < $today) { if ($day < $today) {
$this->logger->debug('Date was in the past.', ['day' => $day]);
continue; continue;
} }

View file

@ -18,16 +18,20 @@ plugin.tx_events {
} }
} }
} }
persistence { persistence {
storagePid = {$plugin.tx_events.persistence.storagePid} storagePid = {$plugin.tx_events.persistence.storagePid}
recursive = 1 recursive = 1
} }
features { features {
skipDefaultArguments = 1 skipDefaultArguments = 1
} }
mvc { mvc {
callDefaultActionIfActionCantBeResolved = 1 callDefaultActionIfActionCantBeResolved = 1
} }
settings { settings {
defaulDetailEventsPid = defaulDetailEventsPid =
@ -52,6 +56,7 @@ plugin.tx_events {
categoriesPid = {$plugin.tx_events.settings.destinationData.categoriesPid} categoriesPid = {$plugin.tx_events.settings.destinationData.categoriesPid}
categoryParentUid = {$plugin.tx_events.settings.destinationData.categoryParentUid} categoryParentUid = {$plugin.tx_events.settings.destinationData.categoryParentUid}
} }
dataProcessing { dataProcessing {
Wrm\Events\Domain\Model\Event { Wrm\Events\Domain\Model\Event {
10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor 10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
@ -67,6 +72,7 @@ plugin.tx_events {
} }
} }
} }
} }
} }
@ -74,3 +80,9 @@ plugin.tx_events_datelist.view.pluginNamespace = events_search
plugin.tx_events_datesearch.view.pluginNamespace = events_search plugin.tx_events_datesearch.view.pluginNamespace = events_search
module.tx_events < plugin.tx_events module.tx_events < plugin.tx_events
module.tx_events_import {
settings {
repeatUntil = +60 days
}
}

View file

@ -1,4 +1,4 @@
3.0.1 3.1.0
===== =====
Breaking Breaking
@ -9,7 +9,9 @@ Nothing
Features Features
-------- --------
Nothing * Handles date intervals without given ``repeatUntil`` property.
A default of ``+60 days`` is hard coded.
The actual date span can be configured via TypoScript.
Fixes Fixes
----- -----

View file

@ -36,6 +36,7 @@ Table of Contents
:titlesonly: :titlesonly:
Commands Commands
Settings
Changelog Changelog
Maintenance Maintenance

View file

@ -0,0 +1,16 @@
.. _settings:
Settings
========
Import
------
The import can be configured via ``module.tx_events_import`` and offers the following
options:
.. option:: module.tx_events_import.settings.repeatUntil
Allows to define how long dates should be repeated if ``repeatUntil`` is missing in import data.
The value will be passed to https://www.php.net/manual/en/datetime.modify.php.
No stdWrap is applied.

View file

@ -45,12 +45,17 @@ abstract class AbstractTest extends FunctionalTestCase
parent::tearDown(); parent::tearDown();
} }
protected function setUpConfiguration(array $configuration): void protected function setUpConfiguration(
{ array $destinationDataSettings,
array $importSettings = []
): void {
$this->setUpFrontendRootPage(1, [], [ $this->setUpFrontendRootPage(1, [], [
'config' => implode(PHP_EOL, [ 'config' => implode(PHP_EOL, [
'module.tx_events_pi1.settings.destinationData {', 'module.tx_events_pi1.settings.destinationData {',
implode(PHP_EOL, $configuration), implode(PHP_EOL, $destinationDataSettings),
'}',
'module.tx_events_import.settings {',
implode(PHP_EOL, $importSettings),
'}', '}',
]), ]),
]); ]);

View file

@ -0,0 +1,15 @@
"tx_events_domain_model_event",,,,,
,"uid","pid","title","global_id","dates"
,"1","2","Kurzführung - Historische Altstadt","e_100354481",10
"tx_events_domain_model_date",,,,,
,"uid","pid","event","start","end"
,"1","2",1,1657720800,1657724400
,"2","2",1,1657807200,1657810800
,"3","2",1,1657893600,1657897200
,"4","2",1,1657980000,1657983600
,"5","2",1,1658066400,1658070000
,"6","2",1,1658152800,1658156400
,"7","2",1,1658239200,1658242800
,"8","2",1,1658325600,1658329200
,"9","2",1,1658412000,1658415600
,"10","2",1,1658498400,1658502000
1 tx_events_domain_model_event
2 uid pid title global_id dates
3 1 2 Kurzführung - Historische Altstadt e_100354481 10
4 tx_events_domain_model_date
5 uid pid event start end
6 1 2 1 1657720800 1657724400
7 2 2 1 1657807200 1657810800
8 3 2 1 1657893600 1657897200
9 4 2 1 1657980000 1657983600
10 5 2 1 1658066400 1658070000
11 6 2 1 1658152800 1658156400
12 7 2 1 1658239200 1658242800
13 8 2 1 1658325600 1658329200
14 9 2 1 1658412000 1658415600
15 10 2 1 1658498400 1658502000

View file

@ -0,0 +1,9 @@
"tx_events_domain_model_event",,,,,
,"uid","pid","title","global_id","dates"
,"1","2","Tüftlerzeit","e_100354481",4
"tx_events_domain_model_date",,,,,
,"uid","pid","event","start","end"
,"1","2",1,1657958400,1657980000
,"2","2",1,1658563200,1658584800
,"3","2",1,1659168000,1659189600
,"4","2",1,1659772800,1659794400
1 tx_events_domain_model_event
2 uid pid title global_id dates
3 1 2 Tüftlerzeit e_100354481 4
4 tx_events_domain_model_date
5 uid pid event start end
6 1 2 1 1657958400 1657980000
7 2 2 1 1658563200 1658584800
8 3 2 1 1659168000 1659189600
9 4 2 1 1659772800 1659794400

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<tx_events_domain_model_import>
<uid>1</uid>
<pid>2</pid>
<title>Example import configuration</title>
<storage_pid>2</storage_pid>
<rest_experience>beispielstadt</rest_experience>
</tx_events_domain_model_import>
</dataset>

View file

@ -0,0 +1,188 @@
{
"status": "OK",
"count": 3,
"overallcount": 50,
"channels": [],
"facetGroups": [],
"items": [
{
"global_id": "e_100354481",
"id": "100354481",
"title": "Tüftlerzeit",
"type": "Event",
"categories": [
"Kinder"
],
"texts": [
{
"rel": "details",
"type": "text/html",
"value": "Die Tüftlerzeit wird dieses Mal ein weihnachtliches Angebot bereithalten. Alle kleinen Tüftler dürfen gespannt sein.<br>Voranmeldung über: kinderbibliothek@rudolstadt.de oder 03672-486420<br><br>Bitte beachten Sie die derzeit geltenden Zugangsregeln."
},
{
"rel": "details",
"type": "text/plain",
"value": "Die Tüftlerzeit wird dieses Mal ein weihnachtliches Angebot bereithalten. Alle kleinen Tüftler dürfen gespannt sein.\nVoranmeldung über: kinderbibliothek@rudolstadt.de oder 03672-486420\n\nBitte beachten Sie die derzeit geltenden Zugangsregeln."
},
{
"rel": "teaser",
"type": "text/html"
},
{
"rel": "teaser",
"type": "text/plain"
}
],
"country": "Deutschland",
"areas": [
"Rudolstadt und Umgebung"
],
"city": "Rudolstadt",
"zip": "07407",
"street": "Schulplatz 13",
"phone": "0 36 72 - 48 64 20",
"fax": "0 36 72 - 48 64 30",
"web": "http://www.stadtbibliothek-rudolstadt.de/",
"email": "stadtbibliothek@rudolstadt.de",
"author": "support@hubermedia.de",
"geo": {
"main": {
"latitude": 50.720835175055917,
"longitude": 11.342568397521973
},
"entry": [],
"attributes": []
},
"ratings": [
{
"type": "eT4",
"value": 40.0
},
{
"type": "order",
"value": 99.0001
}
],
"cuisine_types": [],
"payment": [],
"media_objects": [
],
"keywords": [],
"timeIntervals": [
{
"weekdays": [],
"start": "2022-07-13T11:00:00+02:00",
"end": "2022-07-13T13:00:00+02:00",
"tz": "Europe/Berlin",
"freq": "Daily",
"interval": 1
}
],
"kitchenTimeIntervals": [],
"deliveryTimeIntervals": [],
"numbers": [],
"name": "Stadtbibliothek Rudolstadt",
"attributes": [
{
"key": "VO_Id",
"value": "100042570"
},
{
"key": "VO_CategoryName",
"value": "POI"
},
{
"key": "VA_Id",
"value": "100042570"
},
{
"key": "VA_CategoryName",
"value": "POI"
},
{
"key": "interval_first_match_start",
"value": "2099-12-16T15:00:00+01"
},
{
"key": "interval_first_match_end",
"value": "2099-12-16T16:30:00+01"
},
{
"key": "interval_match_count",
"value": "3"
},
{
"key": "interval_last_match_start",
"value": "2022-02-17T15:00:00+01"
},
{
"key": "interval_last_match_end",
"value": "2022-02-17T17:00:00+01"
}
],
"features": [
"vorhandenes Feature",
"Barrierefrei",
"Zielgruppe Jugendliche",
"neues Feature"
],
"addresses": [
{
"name": "Städtetourismus in Thüringen e.V.",
"city": "Weimar",
"zip": "99423",
"street": "UNESCO-Platz 1",
"phone": "+49 (3643) 745 314",
"web": "http://www.thueringer-staedte.de",
"email": "verein@thueringer-staedte.de",
"rel": "author"
},
{
"name": "Städtetourismus in Thüringen\" e.V.",
"web": "http://www.thueringer-staedte.de",
"email": "verein@thueringer-staedte.de",
"rel": "organisation"
},
{
"name": "Stadtbibliothek Rudolstadt",
"city": "Rudolstadt",
"zip": "07407",
"street": "Schulplatz 13",
"phone": "0 36 72 - 48 64 20",
"fax": "0 36 72 - 48 64 30",
"web": "http://www.stadtbibliothek-rudolstadt.de ",
"email": "stadtbibliothek@rudolstadt.de",
"rel": "organizer"
}
],
"created": "2099-11-10T23:02:00+00:00",
"changed": "2099-12-14T08:28:00+00:00",
"source": {
"url": "http://destination.one/",
"value": "destination.one"
},
"company": "",
"district": "",
"postoffice": "",
"phone2": "",
"seasons": [],
"subitems": [],
"texts": [
],
"timeIntervals": [
{
"end": "2022-04-30T17:00:00+02:00",
"freq": "Daily",
"interval": 1,
"start": "2022-07-13T16:00:00+02:00",
"tz": "Europe/Berlin",
"weekdays": []
}
],
"title": "Kurzf\u00fchrung - Historische Altstadt",
"type": "Event",
"web": "http://www.erfurt-tourismus.de/stadtfuehrung/individuell/kurzfuehrung-historische-altstadt/",
"zip": "99084"
}
]
}

View file

@ -0,0 +1,175 @@
{
"status": "OK",
"count": 3,
"overallcount": 50,
"channels": [],
"facetGroups": [],
"items": [
{
"global_id": "e_100354481",
"id": "100354481",
"title": "Tüftlerzeit",
"type": "Event",
"categories": [
"Kinder"
],
"texts": [
{
"rel": "details",
"type": "text/html",
"value": "Die Tüftlerzeit wird dieses Mal ein weihnachtliches Angebot bereithalten. Alle kleinen Tüftler dürfen gespannt sein.<br>Voranmeldung über: kinderbibliothek@rudolstadt.de oder 03672-486420<br><br>Bitte beachten Sie die derzeit geltenden Zugangsregeln."
},
{
"rel": "details",
"type": "text/plain",
"value": "Die Tüftlerzeit wird dieses Mal ein weihnachtliches Angebot bereithalten. Alle kleinen Tüftler dürfen gespannt sein.\nVoranmeldung über: kinderbibliothek@rudolstadt.de oder 03672-486420\n\nBitte beachten Sie die derzeit geltenden Zugangsregeln."
},
{
"rel": "teaser",
"type": "text/html"
},
{
"rel": "teaser",
"type": "text/plain"
}
],
"country": "Deutschland",
"areas": [
"Rudolstadt und Umgebung"
],
"city": "Rudolstadt",
"zip": "07407",
"street": "Schulplatz 13",
"phone": "0 36 72 - 48 64 20",
"fax": "0 36 72 - 48 64 30",
"web": "http://www.stadtbibliothek-rudolstadt.de/",
"email": "stadtbibliothek@rudolstadt.de",
"author": "support@hubermedia.de",
"geo": {
"main": {
"latitude": 50.720835175055917,
"longitude": 11.342568397521973
},
"entry": [],
"attributes": []
},
"ratings": [
{
"type": "eT4",
"value": 40.0
},
{
"type": "order",
"value": 99.0001
}
],
"cuisine_types": [],
"payment": [],
"media_objects": [
],
"keywords": [],
"timeIntervals": [
{
"end": "2022-07-10T16:00:00+02:00",
"freq": "Weekly",
"interval": 1,
"start": "2022-07-13T10:00:00+02:00",
"tz": "Europe/Berlin",
"weekdays": [
"Saturday"
]
}
],
"kitchenTimeIntervals": [],
"deliveryTimeIntervals": [],
"numbers": [],
"name": "Stadtbibliothek Rudolstadt",
"attributes": [
{
"key": "VO_Id",
"value": "100042570"
},
{
"key": "VO_CategoryName",
"value": "POI"
},
{
"key": "VA_Id",
"value": "100042570"
},
{
"key": "VA_CategoryName",
"value": "POI"
},
{
"key": "interval_first_match_start",
"value": "2099-12-16T15:00:00+01"
},
{
"key": "interval_first_match_end",
"value": "2099-12-16T16:30:00+01"
},
{
"key": "interval_match_count",
"value": "3"
},
{
"key": "interval_last_match_start",
"value": "2022-02-17T15:00:00+01"
},
{
"key": "interval_last_match_end",
"value": "2022-02-17T17:00:00+01"
}
],
"features": [
"vorhandenes Feature",
"Barrierefrei",
"Zielgruppe Jugendliche",
"neues Feature"
],
"addresses": [
{
"name": "Städtetourismus in Thüringen e.V.",
"city": "Weimar",
"zip": "99423",
"street": "UNESCO-Platz 1",
"phone": "+49 (3643) 745 314",
"web": "http://www.thueringer-staedte.de",
"email": "verein@thueringer-staedte.de",
"rel": "author"
},
{
"name": "Städtetourismus in Thüringen\" e.V.",
"web": "http://www.thueringer-staedte.de",
"email": "verein@thueringer-staedte.de",
"rel": "organisation"
},
{
"name": "Stadtbibliothek Rudolstadt",
"city": "Rudolstadt",
"zip": "07407",
"street": "Schulplatz 13",
"phone": "0 36 72 - 48 64 20",
"fax": "0 36 72 - 48 64 30",
"web": "http://www.stadtbibliothek-rudolstadt.de ",
"email": "stadtbibliothek@rudolstadt.de",
"rel": "organizer"
}
],
"created": "2099-11-10T23:02:00+00:00",
"changed": "2099-12-14T08:28:00+00:00",
"source": {
"url": "http://destination.one/",
"value": "destination.one"
},
"company": "",
"district": "",
"postoffice": "",
"phone2": "",
"seasons": [],
"subitems": [],
"hyperObjects": []
}
]
}

View file

@ -5,6 +5,7 @@
<uid>1</uid> <uid>1</uid>
<title>Root page</title> <title>Root page</title>
<slug>1</slug> <slug>1</slug>
<is_siteroot>1</is_siteroot>
</pages> </pages>
<pages> <pages>
<pid>1</pid> <pid>1</pid>
@ -13,4 +14,3 @@
<doktype>254</doktype> <doktype>254</doktype>
</pages> </pages>
</dataset> </dataset>

View file

@ -0,0 +1,64 @@
<?php
namespace Wrm\Events\Tests\Functional\Import\DestinationDataTest;
use GuzzleHttp\Psr7\Response;
use Wrm\Events\Command\ImportDestinationDataViaConfigruationCommand;
/**
* @testdox DestinationData import
*/
class ImportsWithConfiguredRepeatUntilTest extends AbstractTest
{
public function setUp(): void
{
parent::setUp();
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/MinimalImportConfiguration.xml');
$this->setDateAspect(new \DateTimeImmutable('2022-07-13', new \DateTimeZone('UTC')));
}
/**
* @test
*/
public function recurringWeekly(): void
{
$this->setUpConfiguration([
'restUrl = https://example.com/some-path/',
], [
'repeatUntil = +30 days',
]);
$this->setUpResponses([new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ResponseWithRecurringWeeklyWithoutRepeatUntil.json') ?: '')]);
$this->executeCommand();
$this->assertCSVDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsRecurringDatesWeeklyWithConfiguredRepeatUntil.csv');
self::assertFileEquals(
__DIR__ . '/Assertions/EmptyLogFile.txt',
$this->getInstancePath() . '/typo3temp/var/log/typo3_0493d91d8e.log',
'Logfile was not empty.'
);
}
/**
* @test
*/
public function recurringDaily(): void
{
$this->setUpConfiguration([
'restUrl = https://example.com/some-path/',
], [
'repeatUntil = +10 days',
]);
$this->setUpResponses([new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ResponseWithRecurringDailyWithoutRepeatUntil.json') ?: '')]);
$this->executeCommand();
$this->assertCSVDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsRecurringDatesDailyWithConfiguredRepeatUntil.csv');
self::assertFileEquals(
__DIR__ . '/Assertions/EmptyLogFile.txt',
$this->getInstancePath() . '/typo3temp/var/log/typo3_0493d91d8e.log',
'Logfile was not empty.'
);
}
}

View file

@ -4,9 +4,13 @@ declare(strict_types=1);
namespace Wrm\Events\Tests\Unit\Service\DestinationDataImportService; namespace Wrm\Events\Tests\Unit\Service\DestinationDataImportService;
use PHPUnit\Framework\MockObject\Stub;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Context\DateTimeAspect; use TYPO3\CMS\Core\Context\DateTimeAspect;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Log\Logger;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use Wrm\Events\Domain\Model\Date; use Wrm\Events\Domain\Model\Date;
use Wrm\Events\Service\DestinationDataImportService\DatesFactory; use Wrm\Events\Service\DestinationDataImportService\DatesFactory;
@ -15,14 +19,25 @@ use Wrm\Events\Service\DestinationDataImportService\DatesFactory;
*/ */
class DatesFactoryTest extends TestCase class DatesFactoryTest extends TestCase
{ {
private function createTestSubject(
string $contextDate
): DatesFactory {
$logger = $this->createStub(Logger::class);
$logManager = $this->createStub(LogManager::class);
$logManager->method('getLogger')->willReturn($logger);
return new DatesFactory(
$this->createContext(new \DateTimeImmutable($contextDate)),
$this->createStub(ConfigurationManager::class),
$logManager
);
}
/** /**
* @test * @test
*/ */
public function canBeCreated(): void public function canBeCreated(): void
{ {
$subject = new DatesFactory( $subject = $this->createTestSubject('now');
$this->getContext(new \DateTimeImmutable('now'))
);
self::assertInstanceOf( self::assertInstanceOf(
DatesFactory::class, DatesFactory::class,
@ -36,9 +51,7 @@ class DatesFactoryTest extends TestCase
*/ */
public function returnsNoResultOnUnkownInput(array $unkownInput): void public function returnsNoResultOnUnkownInput(array $unkownInput): void
{ {
$subject = new DatesFactory( $subject = $this->createTestSubject('2022-01-01T13:17:24 Europe/Berlin');
$this->getContext(new \DateTimeImmutable('2022-01-01T13:17:24 Europe/Berlin'))
);
$result = $subject->createDates($unkownInput, false); $result = $subject->createDates($unkownInput, false);
@ -66,9 +79,7 @@ class DatesFactoryTest extends TestCase
*/ */
public function returnsSingleNotCanceledDate(): void public function returnsSingleNotCanceledDate(): void
{ {
$subject = new DatesFactory( $subject = $this->createTestSubject('2022-01-01T13:17:24 Europe/Berlin');
$this->getContext(new \DateTimeImmutable('2022-01-01T13:17:24 Europe/Berlin'))
);
$result = $subject->createDates([[ $result = $subject->createDates([[
'start' => '2022-04-01T16:00:00+02:00', 'start' => '2022-04-01T16:00:00+02:00',
@ -89,14 +100,37 @@ class DatesFactoryTest extends TestCase
self::assertSame('no', $firstEntry->getCanceled()); self::assertSame('no', $firstEntry->getCanceled());
} }
/**
* @test
*/
public function returnsWeeklyWithConfiguredRepeat(): void
{
$subject = $this->createTestSubject('2023-01-01T13:17:24 Europe/Berlin');
$result = $subject->createDates([[
'weekdays' => [
'Monday',
'Friday',
],
'start' => '2023-01-06T14:00:00+01:00',
'end' => '2023-01-06T15:00:00+01:00',
'tz' => 'Europe/Berlin',
'freq' => 'Weekly',
'interval' => 1
]], false);
self::assertInstanceOf(\Generator::class, $result);
$result = iterator_to_array($result);
self::assertCount(16, $result);
}
/** /**
* @test * @test
*/ */
public function returnsSingleCanceledDate(): void public function returnsSingleCanceledDate(): void
{ {
$subject = new DatesFactory( $subject = $this->createTestSubject('2022-01-01T13:17:24 Europe/Berlin');
$this->getContext(new \DateTimeImmutable('2022-01-01T13:17:24 Europe/Berlin'))
);
$result = $subject->createDates([[ $result = $subject->createDates([[
'start' => '2022-04-01T16:00:00+02:00', 'start' => '2022-04-01T16:00:00+02:00',
@ -122,9 +156,7 @@ class DatesFactoryTest extends TestCase
*/ */
public function returnsCanceledDatesOnDailyBasis(): void public function returnsCanceledDatesOnDailyBasis(): void
{ {
$subject = new DatesFactory( $subject = $this->createTestSubject('2022-01-01T13:17:24 Europe/Berlin');
$this->getContext(new \DateTimeImmutable('2022-01-01T13:17:24 Europe/Berlin'))
);
$result = $subject->createDates([[ $result = $subject->createDates([[
'start' => '2022-10-29T16:00:00+02:00', 'start' => '2022-10-29T16:00:00+02:00',
@ -155,9 +187,7 @@ class DatesFactoryTest extends TestCase
*/ */
public function returnsNotCanceledDatesOnDailyBasis(): void public function returnsNotCanceledDatesOnDailyBasis(): void
{ {
$subject = new DatesFactory( $subject = $this->createTestSubject('2022-08-29T13:17:24 Europe/Berlin');
$this->getContext(new \DateTimeImmutable('2022-08-29T13:17:24 Europe/Berlin'))
);
$result = $subject->createDates([[ $result = $subject->createDates([[
'start' => '2022-10-29T16:00:00+02:00', 'start' => '2022-10-29T16:00:00+02:00',
@ -188,9 +218,7 @@ class DatesFactoryTest extends TestCase
*/ */
public function returnsCanceledDatesOnWeeklyBasis(): void public function returnsCanceledDatesOnWeeklyBasis(): void
{ {
$subject = new DatesFactory( $subject = $this->createTestSubject('2022-08-29T13:17:24 Europe/Berlin');
$this->getContext(new \DateTimeImmutable('2022-08-29T13:17:24 Europe/Berlin'))
);
$result = $subject->createDates([[ $result = $subject->createDates([[
'weekdays' => [ 'weekdays' => [
@ -233,9 +261,7 @@ class DatesFactoryTest extends TestCase
*/ */
public function returnsNotCanceledDatesOnWeeklyBasis(): void public function returnsNotCanceledDatesOnWeeklyBasis(): void
{ {
$subject = new DatesFactory( $subject = $this->createTestSubject('2022-08-29T13:17:24 Europe/Berlin');
$this->getContext(new \DateTimeImmutable('2022-08-29T13:17:24 Europe/Berlin'))
);
$result = $subject->createDates([[ $result = $subject->createDates([[
'weekdays' => [ 'weekdays' => [
@ -278,9 +304,7 @@ class DatesFactoryTest extends TestCase
*/ */
public function returnsCanceledDatesOnMixedIntervals(): void public function returnsCanceledDatesOnMixedIntervals(): void
{ {
$subject = new DatesFactory( $subject = $this->createTestSubject('2022-01-01T13:17:24 Europe/Berlin');
$this->getContext(new \DateTimeImmutable('2022-01-01T13:17:24 Europe/Berlin'))
);
$result = $subject->createDates([ $result = $subject->createDates([
[ [
@ -327,9 +351,7 @@ class DatesFactoryTest extends TestCase
*/ */
public function returnsNotCanceledDatesOnMixedIntervals(): void public function returnsNotCanceledDatesOnMixedIntervals(): void
{ {
$subject = new DatesFactory( $subject = $this->createTestSubject('2022-01-01T13:17:24 Europe/Berlin');
$this->getContext(new \DateTimeImmutable('2022-01-01T13:17:24 Europe/Berlin'))
);
$result = $subject->createDates([ $result = $subject->createDates([
[ [
@ -371,7 +393,7 @@ class DatesFactoryTest extends TestCase
} }
} }
private function getContext(\DateTimeImmutable $dateTime): Context private function createContext(\DateTimeImmutable $dateTime): Context
{ {
$context = new Context(); $context = new Context();
$context->setAspect('date', new DateTimeAspect($dateTime)); $context->setAspect('date', new DateTimeAspect($dateTime));

View file

@ -9,7 +9,7 @@ $EM_CONF['events'] = [
'state' => 'alpha', 'state' => 'alpha',
'createDirs' => '', 'createDirs' => '',
'clearCacheOnLoad' => 0, 'clearCacheOnLoad' => 0,
'version' => '3.0.0', 'version' => '3.1.0',
'constraints' => [ 'constraints' => [
'depends' => [ 'depends' => [
'typo3' => '10.4.00-11.5.99', 'typo3' => '10.4.00-11.5.99',