team = $team; $this->entityManager = $entityManager; $this->config = $config; $this->timezone = new DateTimeZone($config->get('timeZone')); $this->init(); if (!$this->workingTimeCalendar) { $this->initDefault(); } if ($this->workingTimeCalendar) { $this->util = new CalendarUtil($this->workingTimeCalendar); $this->timezone = $this->workingTimeCalendar->getTimeZone() ?? $this->timezone; } } private function init(): void { $workingTimeCalendarLink = $this->team->getWorkingTimeCalendar(); if (!$workingTimeCalendarLink) { return; } $this->workingTimeCalendar = $this->entityManager ->getRepositoryByClass(WorkingTimeCalendar::class) ->getById($workingTimeCalendarLink->getId()); } private function initDefault(): void { $id = $this->config->get('workingTimeCalendarId'); if (!$id) { return; } $this->workingTimeCalendar = $this->entityManager->getEntityById(WorkingTimeCalendar::ENTITY_TYPE, $id); } public function isAvailable(): bool { return $this->workingTimeCalendar !== null; } public function getTimezone(): DateTimeZone { return $this->timezone; } /** * @return WorkingWeekday[] */ public function getWorkingWeekdays(): array { if ($this->workingTimeCalendar === null) { return []; } return $this->workingTimeCalendar->getWorkingWeekdays(); } /** * @return WorkingDate[] */ public function getNonWorkingDates(Date $from, Date $to): array { if ($this->workingTimeCalendar === null) { return []; } return $this->getDates($from, $to)[0]; } /** * @return WorkingDate[] */ public function getWorkingDates(Date $from, Date $to): array { if ($this->workingTimeCalendar === null) { return []; } return $this->getDates($from, $to)[1]; } /** * @return array{WorkingDate[], WorkingDate[]} */ private function getDates(Date $from, Date $to): array { $cacheKey = $from->toString() . '-' . $to->toString(); if ($this->cacheKey === $cacheKey) { assert($this->cache !== null); return $this->cache; } $notWorkingList = []; $workingList = []; $list = $this->fetchRanges($from, $to); foreach ($list as $range) { $dates = $this->rangeToDates($range); if ($range->getType() === WorkingTimeRange::TYPE_NON_WORKING) { $notWorkingList = array_merge($notWorkingList, $dates); continue; } $workingList = array_merge($workingList, $dates); } $this->cacheKey = $cacheKey; $this->cache = [$notWorkingList, $workingList]; return $this->cache; } /** * @param WorkingTimeRange $range * @return WorkingDate[] */ private function rangeToDates(WorkingTimeRange $range): array { if (!$this->util) { return []; } return $this->util->rangeToDates($range); } /** * @return WorkingTimeRange[] */ private function fetchRanges(Date $from, Date $to): array { if ($this->workingTimeCalendar === null) { return []; } $list = []; $collection = $this->entityManager ->getRDBRepositoryByClass(WorkingTimeRange::class) ->leftJoin('calendars') ->where( Condition::equal( Expression::column('calendars.id'), $this->workingTimeCalendar->getId() ) ) ->where( OrGroup::create( Condition::greaterOrEqual( Expression::column('dateEnd'), $from->toString() ), Condition::lessOrEqual( Expression::column('dateStart'), $to->toString() ), ) ) ->find(); foreach ($collection as $entity) { $list[] = $entity; } return $list; } }