mirror of
https://github.com/werkraum-media/events.git
synced 2025-03-26 17:03:47 +01:00
Refactor date factory
Use a dedicated object to represent the incoming data. That way the factory can ask the data/date questions and fetch data. We do not need to expose the internals to the factory.
This commit is contained in:
parent
d1f8b253e4
commit
7b551547b6
3 changed files with 148 additions and 72 deletions
Classes
117
Classes/Domain/DestinationData/Date.php
Normal file
117
Classes/Domain/DestinationData/Date.php
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WerkraumMedia\Events\Domain\DestinationData;
|
||||||
|
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use DateTimeZone;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
final class Date
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly array $data
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isSingle(): bool
|
||||||
|
{
|
||||||
|
$frequency = $this->data['freq'] ?? '';
|
||||||
|
$start = $this->data['start'] ?? '';
|
||||||
|
|
||||||
|
return $frequency === ''
|
||||||
|
&& $start !== '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isInterval(): bool
|
||||||
|
{
|
||||||
|
return $this->isDaily()
|
||||||
|
|| $this->isWeekly();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isDaily(): bool
|
||||||
|
{
|
||||||
|
return $this->getFrequency() == 'Daily' && empty($this->data['weekdays']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isWeekly(): bool
|
||||||
|
{
|
||||||
|
return $this->getFrequency() == 'Weekly' && !empty($this->data['weekdays']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isAfter(DateTimeImmutable $comparison): bool
|
||||||
|
{
|
||||||
|
return new DateTimeImmutable($this->data['start']) > $comparison;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasKnownRepeat(): bool
|
||||||
|
{
|
||||||
|
return empty($this->data['repeatUntil']) === false
|
||||||
|
|| empty($this->data['repeatCount']) === false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withRepeatUntil(string $repeatUntil): self
|
||||||
|
{
|
||||||
|
$data = $this->data;
|
||||||
|
$data['repeatUntil'] = $repeatUntil;
|
||||||
|
|
||||||
|
return new self($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStart(): DateTimeImmutable
|
||||||
|
{
|
||||||
|
return new DateTimeImmutable(
|
||||||
|
$this->data['start'],
|
||||||
|
new DateTimeZone($this->data['tz'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEnd(): DateTimeImmutable
|
||||||
|
{
|
||||||
|
return new DateTimeImmutable(
|
||||||
|
$this->data['end'],
|
||||||
|
new DateTimeZone($this->data['tz'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTimeZone(): DateTimeZone
|
||||||
|
{
|
||||||
|
return new DateTimeZone($this->data['tz']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getWeekdays(): array
|
||||||
|
{
|
||||||
|
return $this->data['weekdays'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRepeatUntil(): DateTimeImmutable
|
||||||
|
{
|
||||||
|
if (array_key_exists('repeatUntil', $this->data)) {
|
||||||
|
return new DateTimeImmutable($this->data['repeatUntil'], $this->getTimezone());
|
||||||
|
}
|
||||||
|
|
||||||
|
$repeatCountUnit = '';
|
||||||
|
if ($this->isDaily()) {
|
||||||
|
$repeatCountUnit = 'days';
|
||||||
|
} elseif ($this->isWeekly()) {
|
||||||
|
$repeatCountUnit = 'weeks';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($repeatCountUnit === '') {
|
||||||
|
throw new RuntimeException('The current date can not repeat.', 1739279561);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getStart()->modify(
|
||||||
|
'+' . ((int)$this->data['repeatCount']) . ' ' . $repeatCountUnit
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getFrequency(): string
|
||||||
|
{
|
||||||
|
return $this->data['freq'] ?? '';
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,8 +6,8 @@ namespace WerkraumMedia\Events\Domain\Model;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use DateTimeZone;
|
|
||||||
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
|
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
|
||||||
|
use WerkraumMedia\Events\Domain\DestinationData\Date as DestinationDataDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Date
|
* Date
|
||||||
|
@ -126,12 +126,12 @@ class Date extends AbstractEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function createFromDestinationDataDate(
|
public static function createFromDestinationDataDate(
|
||||||
array $date,
|
DestinationDataDate $date,
|
||||||
bool $canceled
|
bool $canceled
|
||||||
): self {
|
): self {
|
||||||
return self::createFromDestinationData(
|
return self::createFromDestinationData(
|
||||||
new DateTimeImmutable($date['start'], new DateTimeZone($date['tz'])),
|
$date->getStart(),
|
||||||
new DateTimeImmutable($date['end'], new DateTimeZone($date['tz'])),
|
$date->getEnd(),
|
||||||
$canceled
|
$canceled
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,11 @@ namespace WerkraumMedia\Events\Service\DestinationDataImportService;
|
||||||
use DateInterval;
|
use DateInterval;
|
||||||
use DatePeriod;
|
use DatePeriod;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use DateTimeZone;
|
|
||||||
use Generator;
|
use Generator;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use TYPO3\CMS\Core\Context\Context;
|
use TYPO3\CMS\Core\Context\Context;
|
||||||
use TYPO3\CMS\Core\Log\LogManager;
|
use TYPO3\CMS\Core\Log\LogManager;
|
||||||
|
use WerkraumMedia\Events\Domain\DestinationData\Date as DestinationDataDate;
|
||||||
use WerkraumMedia\Events\Domain\Model\Date;
|
use WerkraumMedia\Events\Domain\Model\Date;
|
||||||
use WerkraumMedia\Events\Domain\Model\Import;
|
use WerkraumMedia\Events\Domain\Model\Import;
|
||||||
|
|
||||||
|
@ -54,12 +54,14 @@ final class DatesFactory
|
||||||
array $date,
|
array $date,
|
||||||
bool $canceled
|
bool $canceled
|
||||||
): ?Generator {
|
): ?Generator {
|
||||||
if ($this->isDateSingleDate($date)) {
|
$date = new DestinationDataDate($date);
|
||||||
|
|
||||||
|
if ($date->isSingle()) {
|
||||||
$this->logger->info('Is single date', ['date' => $date]);
|
$this->logger->info('Is single date', ['date' => $date]);
|
||||||
return $this->createSingleDate($date, $canceled);
|
return $this->createSingleDate($date, $canceled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->isDateInterval($date)) {
|
if ($date->isInterval()) {
|
||||||
$this->logger->info('Is interval date', ['date' => $date]);
|
$this->logger->info('Is interval date', ['date' => $date]);
|
||||||
return $this->createDateFromInterval($import, $date, $canceled);
|
return $this->createDateFromInterval($import, $date, $canceled);
|
||||||
}
|
}
|
||||||
|
@ -67,38 +69,14 @@ final class DatesFactory
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isDateSingleDate(array $date): bool
|
|
||||||
{
|
|
||||||
$frequency = $date['freq'] ?? '';
|
|
||||||
$start = $date['start'] ?? '';
|
|
||||||
|
|
||||||
return $frequency === ''
|
|
||||||
&& $start !== '';
|
|
||||||
}
|
|
||||||
|
|
||||||
private function isDateInterval(array $date): bool
|
|
||||||
{
|
|
||||||
$frequency = $date['freq'] ?? '';
|
|
||||||
|
|
||||||
if ($frequency == 'Daily' && empty($date['weekdays'])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($frequency == 'Weekly' && !empty($date['weekdays'])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Generator<Date>
|
* @return Generator<Date>
|
||||||
*/
|
*/
|
||||||
private function createSingleDate(
|
private function createSingleDate(
|
||||||
array $date,
|
DestinationDataDate $date,
|
||||||
bool $canceled
|
bool $canceled
|
||||||
): Generator {
|
): Generator {
|
||||||
if (new DateTimeImmutable($date['start']) > $this->getToday()) {
|
if ($date->isAfter($this->getToday())) {
|
||||||
yield Date::createFromDestinationDataDate($date, $canceled);
|
yield Date::createFromDestinationDataDate($date, $canceled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,16 +86,16 @@ final class DatesFactory
|
||||||
*/
|
*/
|
||||||
private function createDateFromInterval(
|
private function createDateFromInterval(
|
||||||
Import $import,
|
Import $import,
|
||||||
array $date,
|
DestinationDataDate $date,
|
||||||
bool $canceled
|
bool $canceled
|
||||||
): ?Generator {
|
): ?Generator {
|
||||||
$date = $this->ensureRepeatUntil($import, $date);
|
$date = $this->ensureRepeatUntil($import, $date);
|
||||||
|
|
||||||
if ($date['freq'] == 'Daily') {
|
if ($date->isDaily()) {
|
||||||
return $this->createDailyDates($date, $canceled);
|
return $this->createDailyDates($date, $canceled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($date['freq'] == 'Weekly') {
|
if ($date->isWeekly()) {
|
||||||
return $this->createWeeklyDates($date, $canceled);
|
return $this->createWeeklyDates($date, $canceled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,35 +104,31 @@ final class DatesFactory
|
||||||
|
|
||||||
private function ensureRepeatUntil(
|
private function ensureRepeatUntil(
|
||||||
Import $import,
|
Import $import,
|
||||||
array $date
|
DestinationDataDate $date
|
||||||
): array {
|
): DestinationDataDate {
|
||||||
if (empty($date['repeatUntil']) === false) {
|
if ($date->hasKnownRepeat()) {
|
||||||
return $date;
|
|
||||||
}
|
|
||||||
if (empty($date['repeatCount']) === false) {
|
|
||||||
return $date;
|
return $date;
|
||||||
}
|
}
|
||||||
|
|
||||||
$date['repeatUntil'] = $this->getToday()->modify($import->getRepeatUntil())->format('c');
|
$repeatUntil = $this->getToday()->modify($import->getRepeatUntil())->format('c');
|
||||||
$this->logger->info('Interval did not provide repeatUntil.', ['newRepeat' => $date['repeatUntil']]);
|
$this->logger->info('Interval did not provide repeatUntil.', ['newRepeat' => $repeatUntil]);
|
||||||
|
|
||||||
return $date;
|
return $date->withRepeatUntil($repeatUntil);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Generator<Date>
|
* @return Generator<Date>
|
||||||
*/
|
*/
|
||||||
private function createDailyDates(
|
private function createDailyDates(
|
||||||
array $date,
|
DestinationDataDate $date,
|
||||||
bool $canceled
|
bool $canceled
|
||||||
): Generator {
|
): Generator {
|
||||||
$today = $this->getToday();
|
$today = $this->getToday();
|
||||||
$timeZone = new DateTimeZone($date['tz']);
|
$timeZone = $date->getTimeZone();
|
||||||
$start = new DateTimeImmutable($date['start'], $timeZone);
|
$start = $date->getStart();
|
||||||
$end = new DateTimeImmutable($date['end'], $timeZone);
|
$end = $date->getEnd();
|
||||||
$until = $this->createUntil($start, $date, 'days');
|
|
||||||
|
|
||||||
$period = new DatePeriod($start, new DateInterval('P1D'), $until);
|
$period = new DatePeriod($start, new DateInterval('P1D'), $date->getRepeatUntil());
|
||||||
foreach ($period as $day) {
|
foreach ($period as $day) {
|
||||||
$day = $day->setTimezone($timeZone);
|
$day = $day->setTimezone($timeZone);
|
||||||
if ($day < $today) {
|
if ($day < $today) {
|
||||||
|
@ -175,16 +149,16 @@ final class DatesFactory
|
||||||
* @return Generator<Date>
|
* @return Generator<Date>
|
||||||
*/
|
*/
|
||||||
private function createWeeklyDates(
|
private function createWeeklyDates(
|
||||||
array $date,
|
DestinationDataDate $date,
|
||||||
bool $canceled
|
bool $canceled
|
||||||
): Generator {
|
): Generator {
|
||||||
$today = $this->getToday();
|
$today = $this->getToday();
|
||||||
$timeZone = new DateTimeZone($date['tz']);
|
$timeZone = $date->getTimeZone();
|
||||||
$start = new DateTimeImmutable($date['start'], $timeZone);
|
$start = $date->getStart();
|
||||||
$end = new DateTimeImmutable($date['end'], $timeZone);
|
$end = $date->getEnd();
|
||||||
$until = $this->createUntil($start, $date, 'weeks');
|
$until = $date->getRepeatUntil();
|
||||||
|
|
||||||
foreach ($date['weekdays'] as $day) {
|
foreach ($date->getWeekdays() as $day) {
|
||||||
$dateToUse = $start->modify($day);
|
$dateToUse = $start->modify($day);
|
||||||
$dateToUse = $dateToUse->setTime((int)$start->format('H'), (int)$start->format('i'));
|
$dateToUse = $dateToUse->setTime((int)$start->format('H'), (int)$start->format('i'));
|
||||||
|
|
||||||
|
@ -219,21 +193,6 @@ final class DatesFactory
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $repeatCountUnit E.g. weeks or days
|
|
||||||
*/
|
|
||||||
private function createUntil(
|
|
||||||
DateTimeImmutable $start,
|
|
||||||
array $date,
|
|
||||||
string $repeatCountUnit,
|
|
||||||
): DateTimeImmutable {
|
|
||||||
if (array_key_exists('repeatUntil', $date)) {
|
|
||||||
return new DateTimeImmutable($date['repeatUntil'], $start->getTimezone());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $start->modify('+' . ((int)$date['repeatCount']) . ' ' . $repeatCountUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getToday(): DateTimeImmutable
|
private function getToday(): DateTimeImmutable
|
||||||
{
|
{
|
||||||
$today = $this->context->getPropertyFromAspect('date', 'full', new DateTimeImmutable());
|
$today = $this->context->getPropertyFromAspect('date', 'full', new DateTimeImmutable());
|
||||||
|
|
Loading…
Add table
Reference in a new issue