git-svn-id: http://78.47.251.156/svn/dev/sterntours-3@3356 f459cee4-fb09-11de-96c3-f9c5f16c3c76
This commit is contained in:
uli 2017-10-27 09:47:23 +00:00
parent 8240ce87f9
commit 3bb0bb53a7
11 changed files with 276 additions and 330 deletions

View file

@ -1,812 +0,0 @@
<?php
namespace AppBundle\Util;
use AppBundle\Entity\FewoLodging;
use AppBundle\Entity\FewoPrice;
use AppBundle\Entity\FewoReservation;
use AppBundle\Entity\FewoSeason;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\EntityManager;
use AppBundle\Util\CalendarDayState;
class LodgingCalendarUtil
{
private $em;
public function __construct(EntityManager $entityManager)
{
$this->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);
$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(true);
}
}
$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(true);
}
}
$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); // todo, hier evtl direkt true
//$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(true);
}
}
$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(true);
}
}
$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++)
{
//$mergedPricesAndReservationsCalendar = $this->mergeCalendarsNew($pricesCalendar, $reservationsCalendar, false);
//$actuallyReservableDaysCalendar = $this->filterReservableDays($lodging, $mergedPricesAndReservationsCalendar);
//$resultCalendar = $this->mergeCalendars($actuallyReservableDaysCalendar, $reservationsCalendar, true);
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();
$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
*/
private function filterReservableDays(FewoLodging $lodging, $calendar)
{
$priceRepo = $this->em->getRepository('AppBundle:FewoPrice');
$today = new \DateTime();
$seasons = $lodging->getSeasons();
$prices = $lodging->getPrices();
$cleanCalendar = $this->getCalendar();
$potentiallyReservableDays = [];
$actuallyReservableDays = [];
$lastReservablePriceId = 0;
$priceId = 0;
for($currMonthIndex = 0; $currMonthIndex < count($calendar); $currMonthIndex++)
{
$currMonth = $calendar[$currMonthIndex];
/** @var CalendarDayState[] $data */
$data = $currMonth['data'];
for($currDayIndex = 0; $currDayIndex < count($data); $currDayIndex++)
{
//$currDay = explode(',', $data[$currDayIndex]);
$currDay = $data[$currDayIndex];
if ($currDay->getIsBookable() || $currDay->getIsReserved())
{
if ($currDay->getIsBookable())
{
$price = $currDay->getPrice();
$priceId = $price->getId();
if ($lastReservablePriceId == 0)
{
$lastReservablePriceId = $priceId;
}
if($lastReservablePriceId != $priceId)
{
$lastPrice = $priceRepo->find($lastReservablePriceId);
/** @var FewoSeason $season */
$season = $lastPrice->getSeason();
$actuallyReservableDays = $this->processPotentiallyReservableDays($potentiallyReservableDays, $season->getMinimumStay());
$this->processRest($actuallyReservableDays, $lastPrice, $cleanCalendar); //todo
$lastReservablePriceId = $priceId;
$potentiallyReservableDays = [];
$actuallyReservableDays = [];
}
$currentDayDate = date("d.m.Y", strtotime($currMonth['year']."-".$currMonth['monthNumber']."-".$currDay->getDay()));
$potentiallyReservableDays[] = $currentDayDate;
}
elseif ($currDay->getIsReserved() && $currDay->getIsReservationBegin())
{
$currentDayDate = date("d.m.Y", strtotime($currMonth['year']."-".$currMonth['monthNumber']."-".$currDay->getDay()));
$potentiallyReservableDays[] = $currentDayDate;
}
}
else
{
if($lastReservablePriceId == $priceId && $lastReservablePriceId != 0)
{
$lastPrice = $priceRepo->find($lastReservablePriceId);
/** @var FewoSeason $season */
$season = $lastPrice->getSeason();
$actuallyReservableDays = $this->processPotentiallyReservableDays($potentiallyReservableDays, $season->getMinimumStay());
$this->processRest($actuallyReservableDays, $lastPrice, $cleanCalendar); //todo
$lastReservablePriceId = $priceId;
$potentiallyReservableDays = [];
$actuallyReservableDays = [];
}
}
}
}
return $cleanCalendar;
}
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 markCalendarDaysWithReservations(FewoLodging $lodging, $calendar)
{
$today = new \DateTime();
$pricesCalendar = $calendar;
$reservationsCalendar = $calendar;
$reservations = $lodging->getReservations();
$prices = $lodging->getPrices();
$lodgingId = $lodging->getId();
foreach($prices as $price)
{
/** @var FewoSeason $season */
$season = $price->getSeason();
$fromDate = $season->getFromDate();
$toDate = $season->getToDate();
if(!($toDate < $today))
{
$pricesCalendar = $this->markCalendarDays($pricesCalendar, $fromDate, $toDate, false, $price, null); //TODO fast fertig
}
}
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 $resultCalendar;
}
public function convertDate($date)
{
$result = substr($date, 0, 2).'.'.substr($date, 2, 2).'.'.substr($date, 4, 4);
return $result;
}
}