context = $context; $this->configurationManager = $configurationManager; $this->logger = $logManager->getLogger(__CLASS__); } /** * @return \Generator */ public function createDates( array $timeIntervals, bool $canceled ): \Generator { foreach ($timeIntervals as $date) { $dates = $this->createDate($date, $canceled); if (!$dates instanceof \Generator) { return null; } foreach ($dates as $createdDate) { yield $createdDate; } } } /** * @return \Generator|null */ private function createDate( array $date, bool $canceled ): ?\Generator { if ($this->isDateSingleDate($date)) { $this->logger->info('Is single date', ['date' => $date]); return $this->createSingleDate($date, $canceled); } if ($this->isDateInterval($date)) { $this->logger->info('Is interval date', ['date' => $date]); return $this->createDateFromInterval($date, $canceled); } 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 */ private function createSingleDate( array $date, bool $canceled ): \Generator { if (new \DateTimeImmutable($date['start']) > $this->getToday()) { yield Date::createFromDestinationDataDate($date, $canceled); } } /** * @return \Generator|null */ private function createDateFromInterval( array $date, bool $canceled ): ?\Generator { $date = $this->ensureRepeatUntil($date); if ($date['freq'] == 'Daily') { return $this->createDailyDates($date, $canceled); } if ($date['freq'] == 'Weekly') { return $this->createWeeklyDates($date, $canceled); } 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 */ private function createDailyDates( array $date, bool $canceled ): \Generator { $today = $this->getToday(); $timeZone = new \DateTimeZone($date['tz']); $start = new \DateTimeImmutable($date['start'], $timeZone); $end = new \DateTimeImmutable($date['end'], $timeZone); $until = new \DateTimeImmutable($date['repeatUntil'], $timeZone); $period = new \DatePeriod($start, new \DateInterval('P1D'), $until); foreach ($period as $day) { $day = $day->setTimezone($timeZone); if ($day < $today) { $this->logger->debug('Date was in the past.', ['day' => $day]); continue; } yield $this->createDateFromStartAndEnd( $day, $start, $end, $canceled ); } } /** * @return \Generator */ private function createWeeklyDates( array $date, bool $canceled ): \Generator { $today = $this->getToday(); $timeZone = new \DateTimeZone($date['tz']); $start = new \DateTimeImmutable($date['start'], $timeZone); $end = new \DateTimeImmutable($date['end'], $timeZone); $until = new \DateTimeImmutable($date['repeatUntil'], $timeZone); foreach ($date['weekdays'] as $day) { $dateToUse = $start->modify($day); $dateToUse = $dateToUse->setTime((int)$start->format('H'), (int)$start->format('i')); $period = new \DatePeriod($dateToUse, new \DateInterval('P1W'), $until); foreach ($period as $day) { $day = $day->setTimezone($timeZone); if ($day < $today) { $this->logger->debug('Date was in the past.', ['day' => $day]); continue; } yield $this->createDateFromStartAndEnd( $day, $start, $end, $canceled ); } } } private function createDateFromStartAndEnd( \DateTimeImmutable $dateToUse, \DateTimeImmutable $start, \DateTimeImmutable $end, bool $canceled ): Date { return Date::createFromDestinationData( $dateToUse->setTime((int)$start->format('H'), (int)$start->format('i')), $dateToUse->setTime((int)$end->format('H'), (int)$end->format('i')), $canceled ); } private function getToday(): \DateTimeImmutable { $today = $this->context->getPropertyFromAspect('date', 'full', new \DateTimeImmutable()); if (!$today instanceof \DateTimeImmutable) { $today = new \DateTimeImmutable(); } return $today->modify('midnight'); } }