em = $entityManager; } private function daysInMonth($month, $year) { return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31); } public function getCalendarWithPadding() { $calendar = null; $currentMonth = date('n'); $currentYear = date('Y'); $weekDays = ['So','Mo','Di','Mi','Do','Fr','Sa']; setlocale(LC_TIME, "german"); for($m = $currentMonth; $m < ($currentMonth + 12); $m++) { if($m < 13) { $actualMonth = $m; $actualCurrentYear = $currentYear; } else { $actualMonth = $m % 12; $actualCurrentYear = $currentYear + 1; } $date = getdate(mktime(0,0,0, $actualMonth, 1, $actualCurrentYear)); $weekDay = $weekDays[$date['wday']]; $numberDays = $this->daysInMonth($actualMonth, $actualCurrentYear); $data = null; $actualStartingWeekDay = $date['wday']; if($actualStartingWeekDay == 0) { $actualStartingWeekDay = 7; } for($fwd = 0; $fwd < $actualStartingWeekDay - 1; $fwd++) { $day = new CalendarDayState(); $day->setDay(0); $day->setIsBookable(false); $day->setIsInSeason(false); $day->setIsReserved(false); $day->setIsReservationBegin(false); $day->setIsReservationEnd(false); $data[] = $day; } for($d = 1; $d <= $numberDays; $d++) { $day = new CalendarDayState(); $day->setDay($d); $day->setIsBookable(false); $day->setIsInSeason(false); $day->setIsReserved(false); $day->setIsReservationBegin(false); $day->setIsReservationEnd(false); $data[] = $day; } $startIndex = count($data); for($lwd = $startIndex; $lwd < 42; $lwd++) { $day = new CalendarDayState(); $day->setDay(0); $day->setIsBookable(false); $day->setIsInSeason(false); $day->setIsReserved(false); $day->setIsReservationBegin(false); $day->setIsReservationEnd(false); $data[] = $day; } $calendar[] = [ 'numberDays' => $numberDays, 'monthNumber' => $actualMonth, 'monthName' => utf8_encode(strftime("%B", mktime(0, 0, 0, $actualMonth, 1, $actualCurrentYear))), 'year' => $actualCurrentYear, 'startWeekDay' => $weekDay, 'data' => $data, 'marked' => 0 ]; } return $calendar; } public function getCalendar() { $calendar = null; $currentMonth = date('n'); $currentYear = date('Y'); $weekDays = ['So','Mo','Di','Mi','Do','Fr','Sa']; setlocale(LC_TIME, "german"); for($m = $currentMonth; $m < ($currentMonth + 12); $m++) { if($m < 13) { $actualMonth = $m; $actualCurrentYear = $currentYear; } else { $actualMonth = $m % 12; $actualCurrentYear = $currentYear + 1; } $date = getdate(mktime(0,0,0, $actualMonth, 1, $actualCurrentYear)); $weekDay = $weekDays[$date['wday']]; $numberDays = $this->daysInMonth($actualMonth, $actualCurrentYear); /** @var CalendarDayState[] $data */ $data = null; // alle Wochentage for($d = 1; $d <= $numberDays; $d++) { // standard-vorbelegung $day = new CalendarDayState(); $day->setDay($d); $day->setIsBookable(false); $day->setIsInSeason(false); $day->setIsReserved(false); $day->setIsReservationBegin(false); $day->setIsReservationEnd(false); $datetime = new \DateTime(); $datetime->setTimestamp(mktime(0,0,0, $actualMonth, $d, $actualCurrentYear)); $day->setDate($datetime); $data[] = $day; } $calendar[] = [ 'numberDays' => $numberDays, 'monthNumber' => $actualMonth, 'monthName' => utf8_encode(strftime("%B", mktime(0, 0, 0, $actualMonth, 1, $actualCurrentYear))), 'year' => $actualCurrentYear, 'startWeekDay' => $weekDay, 'data' => $data, 'marked' => 0 ]; } return $calendar; } /** * @param FewoLodging $lodging * @return array|null */ public function getReservations(FewoLodging $lodging) { $reservations = $lodging->getReservations(); $ret = null; for($i = 0; $i < count($reservations); $i++) { $fromDate = $reservations[$i]->getFromDate(); $toDate = $reservations[$i]->getToDate(); $ret[] = [ 'startDay' => $fromDate->format('j'), 'startMonth' => $fromDate->format('n'), 'startYear' => $fromDate->format('Y'), 'endDay' => $toDate->format('j'), 'endMonth' => $toDate->format('n'), 'endYear' => $toDate->format('Y') ]; } return $ret; } private function getMonthIndex($calendar, $month) { $result = 0; for($i = 0; $i < count($calendar); $i++) { if($calendar[$i]['monthNumber'] == $month) { $result = $i; break; } } return $result; } /** * @param $calendar * @param \DateTime $fromDate * @param \DateTime $toDate * @param $appendix * @return mixed */ private function markCalendarDays($calendar, \DateTime $fromDate, \DateTime $toDate, $reservationMode = false, FewoPrice $price = null, FewoReservation $reservation = null) { $startDay = $fromDate->format('j'); $startMonth = $fromDate->format('n'); $startYear = $fromDate->format('Y'); $endDay = $toDate->format('j'); $endMonth = $toDate->format('n'); $endYear = $toDate->format('Y'); $today = new \DateTime(); $todayDay = $today->format('j'); $todayMonth = $today->format('n'); $todayYear = $today->format('Y'); if($startMonth < $todayMonth && $startYear == $todayYear) { $startDay = 1; $startMonth = $today->format('n'); $startYear = $today->format('Y'); } $startCalendarIndex = $this->getMonthIndex($calendar, $startMonth); $endCalendarIndex = $this->getMonthIndex($calendar, $endMonth); // anfang und ende innerhalb eines monats if($startCalendarIndex == $endCalendarIndex) { /** @var CalendarDayState[] $data */ $data = $calendar[$startCalendarIndex]['data']; $calendar[$startCalendarIndex]['marked'] = 1; $startIndex = $startDay - 1; $endIndex = $endDay - 1; for ($i = $startIndex; $i <= $endIndex; $i++) { if ($reservationMode) { if ($i == $startIndex) { $data[$i]->setIsReserved(true); $data[$i]->setIsReservationBegin(true); $data[$i]->setReservation($reservation); $data[$i]->setIsInSeason(true); $data[$i]->setIsBookable(false); } elseif ($i == $endIndex) { $data[$i]->setIsReserved(true); $data[$i]->setIsReservationEnd(true); $data[$i]->setReservation($reservation); $data[$i]->setIsInSeason(true); $data[$i]->setIsBookable(false); //$data[$i]->setIsBookable(true); } else { $data[$i]->setIsReserved(true); $data[$i]->setReservation($reservation); $data[$i]->setIsInSeason(true); $data[$i]->setIsBookable(false); } } else { $data[$i]->setIsReserved(false); $data[$i]->setPrice($price); $data[$i]->setIsInSeason(true); $data[$i]->setIsBookable(false); } } $calendar[$startCalendarIndex]['data'] = $data; } else { // erster monat /** @var CalendarDayState[] $data */ $data = $calendar[$startCalendarIndex]['data']; $calendar[$startCalendarIndex]['marked'] = 1; $startIndex = $startDay - 1; $endIndex = count($data) - 1; for($i = $startIndex; $i <= $endIndex; $i++) { if ($reservationMode) { if ($i == $startIndex) { $data[$i]->setIsReserved(true); $data[$i]->setIsReservationBegin(true); $data[$i]->setReservation($reservation); $data[$i]->setIsInSeason(true); $data[$i]->setIsBookable(false); } else { $data[$i]->setIsReserved(true); $data[$i]->setReservation($reservation); $data[$i]->setIsInSeason(true); $data[$i]->setIsBookable(false); } } else { $data[$i]->setIsReserved(false); $data[$i]->setPrice($price); $data[$i]->setIsInSeason(true); $data[$i]->setIsBookable(false); } } $calendar[$startCalendarIndex]['data'] = $data; // letzter monat /** @var CalendarDayState[] $data */ $data = $calendar[$endCalendarIndex]['data']; $calendar[$endCalendarIndex]['marked'] = 1; $startIndex = 0; $endIndex = $endDay - 1; for($i = $startIndex; $i <= $endIndex; $i++) { if ($reservationMode) { if ($i == $endIndex) { $data[$i]->setIsReserved(true); $data[$i]->setIsReservationEnd(true); $data[$i]->setReservation($reservation); $data[$i]->setIsInSeason(true); $data[$i]->setIsBookable(false); //$data[$i]->setIsBookable(true); } else { $data[$i]->setIsReserved(true); $data[$i]->setReservation($reservation); $data[$i]->setIsInSeason(true); $data[$i]->setIsBookable(false); } } else { $data[$i]->setIsReserved(false); $data[$i]->setPrice($price); $data[$i]->setIsInSeason(true); $data[$i]->setIsBookable(false); } } $calendar[$endCalendarIndex]['data'] = $data; // alle monate dazwischen for($i = $startCalendarIndex + 1; $i < $endCalendarIndex; $i++) { /** @var CalendarDayState[] $data */ $data = $calendar[$i]['data']; $calendar[$i]['marked'] = 1; $startIndex = 0; $endIndex = count($data) - 1; for($j = $startIndex; $j <= $endIndex; $j++) { if ($reservationMode) { $data[$j]->setIsReserved(true); $data[$j]->setReservation($reservation); $data[$j]->setIsInSeason(true); $data[$j]->setIsBookable(false); } else { $data[$j]->setIsReserved(false); $data[$j]->setPrice($price); $data[$j]->setIsInSeason(true); $data[$j]->setIsBookable(false); } } $calendar[$i]['data'] = $data; } } return $calendar; } private function mergeCalendars($calendar, $extensionCalendar, $withFromTo = false) { for($i = 0; $i < 12; $i++) { /** @var CalendarDayState[] $calendarData */ $calendarData = $calendar[$i]['data']; /** @var CalendarDayState[] $extensionCalendarData */ $extensionCalendarData = $extensionCalendar[$i]['data']; $endIndex = count($calendarData); for($j = 0; $j < $endIndex; $j++) { if ($withFromTo) { if ($extensionCalendarData[$j]->getIsInSeason()) { //$calendarData[$j] = $extensionCalendarData[$j]; $price = $extensionCalendarData[$j]->getPrice(); $calendarData[$j]->setIsInSeason(true); $calendarData[$j]->setPrice($price); } } if ($extensionCalendarData[$j]->getIsReserved()) { // braucht man das überhaupt noch? if ($withFromTo) { // zweite runde $actuallyReservableDaysCalendar merge mit $reservationsCalendar if (!($calendarData[$j]->getIsBookable() && $extensionCalendarData[$j]->getIsReservationEnd())) { //$calendarData[$j] = $extensionCalendarData[$j]; $price = $calendarData[$j]->getPrice(); //$calendarData[$j] = $extensionCalendarData[$j];// todo $calendarData[$j]->setIsBookable(false); $calendarData[$j]->setIsReserved(true); $calendarData[$j]->setReservation($extensionCalendarData[$j]->getReservation()); $calendarData[$j]->setIsReservationBegin($extensionCalendarData[$j]->getIsReservationBegin()); $calendarData[$j]->setIsReservationEnd($extensionCalendarData[$j]->getIsReservationEnd()); if ($calendarData[$j]->getIsReservationEnd() && $extensionCalendarData[$j]->getIsReservationBegin()) { $calendarData[$j]->setIsReservationBegin(false); $calendarData[$j]->setIsReservationEnd(false); } $calendarData[$j]->setIsInSeason(true); $calendarData[$j]->setPrice($price); } } else { // erste runde $pricesCalendar merge mit $reservationsCalendar $price = $calendarData[$j]->getPrice(); $isInSeason = $calendarData[$j]->getIsInSeason(); $reservation = $calendarData[$j]->getReservation(); $calendarData[$j] = $extensionCalendarData[$j]; if ($calendarData[$j]->getIsReservationEnd() && $extensionCalendarData[$j]->getIsReservationBegin()) { $calendarData[$j]->setReservation($reservation); $calendarData[$j]->setIsReservationBegin(false); $calendarData[$j]->setIsReservationEnd(false); } /** @var FewoPrice $price */ $calendarData[$j]->setIsInSeason(true); $calendarData[$j]->setPrice($price); } } } $calendar[$i]['data'] = $calendarData; } return $calendar; } /** @var CalendarDayState[] $calendarMonth */ private function findCalendarDayIndexInMonth($dayNumber, $calendarMonth) { $result = 0; for ($i = 0; $i < count($calendarMonth); $i++) { if ($calendarMonth[$i]->getDay() == $dayNumber) { $result = $i; break; } } return $result; } public function mergeWithPaddedCalendar($calendar, $paddedCalendar) { for($i = 0; $i < count($paddedCalendar); $i++) { $calendarDataCurrMonth = $calendar[$i]['data']; $paddedCalendarDataCurrMonth = $paddedCalendar[$i]['data']; $startIndex = $this->findCalendarDayIndexInMonth(1, $paddedCalendarDataCurrMonth); //$startIndex = array_search(1, $paddedCalendarDataCurrMonth); for($j = 0; $j < count($calendarDataCurrMonth); $j++, $startIndex++) { $paddedCalendarDataCurrMonth[$startIndex] = $calendarDataCurrMonth[$j]; } $paddedCalendar[$i]['data'] = $paddedCalendarDataCurrMonth; } return $paddedCalendar; } private function isNextDay($current, $next) { $result = false; $calculatedNextDate = date('d.m.Y', strtotime($current." + 1 day")); if($calculatedNextDate == $next) { $result = true; } return $result; } private function getMonthFromCalendar($calendar, $monthNumber) { $result = []; for($i = 0; $i < count($calendar); $i++) { if($calendar[$i]['monthNumber'] == $monthNumber) { $result = $calendar[$i]; } } return $result; } /** * @param FewoLodging $lodging * @param $calendar * @return array|null calendars */ private function filterReservableDays(FewoLodging $lodging, $calendar) { $potentiallyReservableDays = []; $priceId = 0; /** @var FewoPrice $lastReservablePrice */ $lastReservablePrice = null; for ($currMonthIndex = 0; $currMonthIndex < count($calendar); $currMonthIndex++) { $currMonth = $calendar[$currMonthIndex]; /** @var CalendarDayState[] $data */ $data = $currMonth['data']; for ($currDayIndex = 0; $currDayIndex < count($data); $currDayIndex++) { $currDay = $data[$currDayIndex]; if ($currDay->getPrice() !== $lastReservablePrice && !$currDay->getIsInSeason()) { $actuallyReservableDays = $this->processPotentiallyReservableDays($potentiallyReservableDays, $lastReservablePrice->getSeason()->getMinimumStay()); $this->processRest($actuallyReservableDays, $lastReservablePrice, $calendar); $potentiallyReservableDays = []; } if ($currDay->getIsInSeason() && (!$currDay->getIsReserved() || $currDay->getIsReservationBegin() || $currDay->getIsReservationEnd())) { $currentDayDate = date("d.m.Y", strtotime($currMonth['year']."-". $currMonth['monthNumber']."-".$currDay->getDay())); $potentiallyReservableDays[] = $currentDayDate; } $lastReservablePrice = $currDay->getIsInSeason() ? $currDay->getPrice() : null; } } if ($lastReservablePrice !== null) { $actuallyReservableDays = $this->processPotentiallyReservableDays($potentiallyReservableDays, $lastReservablePrice->getSeason()->getMinimumStay()); $this->processRest($actuallyReservableDays, $lastReservablePrice, $calendar); } return $calendar; } private function processPotentiallyReservableDays($potentiallyReservableDays, $minimumStay) { $coherentDays = []; $actuallyReservableDays = []; //$coherentDays[] = $potentiallyReservableDays[0]; for($i = 1; $i < count($potentiallyReservableDays); $i++) { if($this->isNextDay($potentiallyReservableDays[$i - 1], $potentiallyReservableDays[$i])) { if(count($coherentDays) == 0) { $coherentDays[] = $potentiallyReservableDays[$i - 1]; } $coherentDays[] = $potentiallyReservableDays[$i]; } else { if(count($coherentDays) < $minimumStay) { $coherentDays = []; $coherentDays[] = $potentiallyReservableDays[$i]; } else { $coherentDaysCount = count($coherentDays); $offset = $coherentDaysCount - ($minimumStay - 1); $coherentDays = array_splice($coherentDays, 0, $offset); for($j = 0; $j < count($coherentDays); $j++) { $actuallyReservableDays[] = $coherentDays[$j]; } $coherentDays = []; } } } if(count($coherentDays) > 0) { $coherentDaysCount = count($coherentDays); $offset = $coherentDaysCount - ($minimumStay - 1); $coherentDays = array_splice($coherentDays, 0, $offset); for($j = 0; $j < count($coherentDays); $j++) { $actuallyReservableDays[] = $coherentDays[$j]; } } return $actuallyReservableDays; } private function processRest($actuallyReservableDays, FewoPrice $price, &$cleanCalendar) { for($currMonthIndex = 0; $currMonthIndex < count($cleanCalendar); $currMonthIndex++) { $currMonth = $cleanCalendar[$currMonthIndex]; /** @var CalendarDayState[] $data */ $data = $currMonth['data']; for($currDayIndex = 0; $currDayIndex < count($data); $currDayIndex++) { $currDay = $data[$currDayIndex]; $currentDate = date("d.m.Y", strtotime($currMonth['year']."-".$currMonth['monthNumber']."-".$currDay->getDay())); if (in_array($currentDate, $actuallyReservableDays)) { //$data[$currDayIndex]->setIsInSeason(true); //$data[$currDayIndex]->setIsReserved(false); // todo ? $data[$currDayIndex]->setIsBookable(true); //$data[$currDayIndex]->setIsReservationBegin(false); //$data[$currDayIndex]->setIsReservationEnd(false); // todo ? //$data[$currDayIndex]->setPrice($price); $currMonth['marked'] = 1; } } $currMonth['data'] = $data; $cleanCalendar[$currMonthIndex] = $currMonth; } } /** * @param FewoLodging $lodging * @param $calendar * @return mixed */ public function getCalendarWithReservations(FewoLodging $lodging) { $today = new \DateTime(); $pricesCalendar = $this->getCalendar(); $reservationsCalendar = $this->getCalendar(); $reservations = $lodging->getReservations(); $prices = $lodging->getPrices(); $lodgingId = $lodging->getId(); foreach ($prices as $price) { /** @var FewoSeason $season */ $season = $price->getSeason(); $pricesCalendar = $this->markCalendarDays($pricesCalendar, $season->getFromDate(), $season->getToDate(), false, $price); } foreach($reservations as $reservation) { $reservationId = $reservation->getId(); $appendix = ','.$reservationId; $fromDate = $reservation->getFromDate(); $toDate = $reservation->getToDate(); $reservationsCalendar = $this->markCalendarDays($reservationsCalendar, $fromDate, $toDate, true, null, $reservation); //TODO fast fertig } $mergedPricesAndReservationsCalendar = $this->mergeCalendars($pricesCalendar, $reservationsCalendar, false); $actuallyReservableDaysCalendar = $this->filterReservableDays($lodging, $mergedPricesAndReservationsCalendar); //$resultCalendar = $this->mergeCalendars($actuallyReservableDaysCalendar, $reservationsCalendar, true); return $actuallyReservableDaysCalendar; //return $resultCalendar; } public function convertDate($date) { $result = substr($date, 0, 2).'.'.substr($date, 2, 2).'.'.substr($date, 4, 4); return $result; } }