File manager - Edit - /home/premiey/www/wp-includes/images/media/Services.tar
Back
Entity/EntityService.php 0000666 00000021601 15165343622 0011341 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Entity; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Extra; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\SlotsEntities; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Booking\SlotsEntitiesFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Resource\AbstractResourceService; use AmeliaBooking\Domain\Services\User\ProviderService; use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue; use AmeliaBooking\Domain\ValueObjects\Duration; /** * Class EntityService * * @package AmeliaBooking\Domain\Services\Entity */ class EntityService { /** @var ProviderService */ private $providerService; /** @var AbstractResourceService */ private $resourceService; /** * EntityService constructor. * * @param ProviderService $providerService * @param AbstractResourceService $resourceService */ public function __construct( ProviderService $providerService, AbstractResourceService $resourceService ) { $this->providerService = $providerService; $this->resourceService = $resourceService; } /** * get filtered entities needed for slots calculation. * * @param array $settings * @param array $props * @param SlotsEntities $slotsEntities * * @return SlotsEntities * @throws InvalidArgumentException */ public function getFilteredSlotsEntities($settings, $props, $slotsEntities) { /** @var Collection $services */ $services = $slotsEntities->getServices() ?: new Collection(); /** @var Collection $providers */ $providers = $slotsEntities->getProviders() ?: new Collection(); /** @var Collection $locations */ $locations = $slotsEntities->getLocations() ?: new Collection(); /** @var Collection $filteredProviders */ $filteredProviders = new Collection(); /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { if ($provider->getServiceList()->keyExists($props['serviceId'])) { if ($settings['allowAdminBookAtAnyTime']) { $this->providerService->setProvidersAlwaysAvailable( $providers ); } $this->providerService->setProviderServices( $provider, $services, false ); /** @var Service $service */ foreach ($provider->getServiceList()->getItems() as $service) { $this->checkServiceTimes($service); } $filteredProviders->addItem($provider, $provider->getId()->getValue()); } } /** @var Service $service */ foreach ($services->getItems() as $service) { $this->checkServiceTimes($service); } /** @var Collection $serviceResources */ $serviceResources = $slotsEntities->getResources() ? $this->resourceService->getServiceResources( $slotsEntities->getResources(), $props['serviceId'] ) : new Collection(); $this->resourceService->setNonSharedResources( $serviceResources, [ 'service' => $services->keys(), 'location' => $locations->keys(), ] ); /** @var SlotsEntities $filteredSlotsEntities */ $filteredSlotsEntities = SlotsEntitiesFactory::create(); $filteredSlotsEntities->setServices($services); $filteredSlotsEntities->setProviders($filteredProviders); $filteredSlotsEntities->setLocations($locations); $filteredSlotsEntities->setResources($serviceResources); return $filteredSlotsEntities; } /** * Add 0 as duration for service time before or time after if it is null * * @param Service $service * * @throws InvalidArgumentException */ private function checkServiceTimes($service) { if (!$service->getTimeBefore()) { $service->setTimeBefore(new Duration(0)); } if (!$service->getTimeAfter()) { $service->setTimeAfter(new Duration(0)); } } /** * filter appointments required for slots calculation * * @param SlotsEntities $slotsEntities * @param Collection $appointments * @param array $props * * @return void * @throws InvalidArgumentException */ public function filterSlotsAppointments($slotsEntities, $appointments, $props) { /** @var Collection $services */ $services = $slotsEntities->getServices(); /** @var Collection $providers */ $providers = $slotsEntities->getProviders(); $providersIds = $providers->keys(); /** @var Appointment $appointment */ foreach ($appointments->getItems() as $index => $appointment) { if (!in_array($appointment->getProviderId()->getValue(), $providersIds) || ( $props['excludeAppointmentId'] && $index === $props['excludeAppointmentId'] ) ) { $appointments->deleteItem($index); } } $lastIndex = null; /** @var Appointment $appointment */ foreach ($appointments->getItems() as $index => $appointment) { /** @var Provider $provider */ $provider = $providers->getItem($appointment->getProviderId()->getValue()); /** @var Service $providerService */ $providerService = $provider->getServiceList()->keyExists($appointment->getServiceId()->getValue()) ? $provider->getServiceList()->getItem($appointment->getServiceId()->getValue()) : $services->getItem($appointment->getServiceId()->getValue()); $appointment->setService($providerService); if ($lastIndex) { /** @var Appointment $previousAppointment */ $previousAppointment = $appointments->getItem($lastIndex); if (( $previousAppointment->getLocationId() && $appointment->getLocationId() ? $previousAppointment->getLocationId()->getValue() === $appointment->getLocationId()->getValue() : true ) && $previousAppointment->getProviderId()->getValue() === $appointment->getProviderId()->getValue() && $previousAppointment->getServiceId()->getValue() === $appointment->getServiceId()->getValue() && $providerService->getMaxCapacity()->getValue() === 1 && $appointment->getBookingStart()->getValue()->format('H:i') !== '00:00' && $previousAppointment->getBookingEnd()->getValue()->format('Y-m-d H:i') === $appointment->getBookingStart()->getValue()->format('Y-m-d H:i') ) { $previousAppointment->setBookingEnd( new DateTimeValue( DateTimeService::getCustomDateTimeObject( $appointment->getBookingEnd()->getValue()->format('Y-m-d H:i:s') ) ) ); $appointments->deleteItem($index); } else { $lastIndex = $index; } } else { $lastIndex = $index; } } } /** * Return required time for the appointment in seconds by summing service duration, service time before and after * and each passed extra. * * @param Service $service * @param array $selectedExtras * * @return mixed * @throws InvalidArgumentException */ public function getAppointmentRequiredTime($service, $selectedExtras) { $requiredTime = $service->getTimeBefore()->getValue() + $service->getDuration()->getValue() + $service->getTimeAfter()->getValue(); $extraIds = array_column($selectedExtras, 'id'); /** @var Extra $extra */ foreach ($service->getExtras()->getItems() as $extra) { if (in_array($extra->getId()->getValue(), $extraIds, false)) { if (!$extra->getDuration()) { $extra->setDuration(new Duration(0)); } $requiredTime += ($extra->getDuration()->getValue() * array_column($selectedExtras, 'quantity', 'id')[$extra->getId()->getValue()]); } } return $requiredTime; } } Permissions/PermissionsService.php 0000666 00000011011 15165343622 0013431 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Permissions; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Admin; use AmeliaBooking\Infrastructure\Common\Container; /** * Class PermissionsService * * @package AmeliaBooking\Domain\Services\Permissions */ class PermissionsService { const READ_PERMISSIONS = 'read'; const READ_OTHERS_PERMISSIONS = 'read_others'; const WRITE_PERMISSIONS = 'write'; const DELETE_PERMISSIONS = 'delete'; const WRITE_STATUS_PERMISSIONS = 'write_status'; const WRITE_TIME_PERMISSIONS = 'write_time'; const WRITE_OTHERS_PERMISSIONS = 'write_others'; /** * @var AbstractUser */ private $currentUser; /** * @var PermissionsCheckerInterface */ private $permissionsChecker; /** * PermissionsService constructor. * * @param Container $container * @param PermissionsCheckerInterface $permissionsChecker * * @throws \Slim\Exception\ContainerValueNotFoundException * @throws \InvalidArgumentException * @throws \Interop\Container\Exception\ContainerException */ public function __construct(Container $container, PermissionsCheckerInterface $permissionsChecker) { // Inject dependencies if (!($permissionsChecker instanceof PermissionsCheckerInterface)) { throw new \InvalidArgumentException('Permissions checker must implement PermissionsCheckerInterface!'); } // Assign current user reference $this->currentUser = $container->get('logged.in.user'); $this->permissionsChecker = $permissionsChecker; } /** * @param $user * @param $object * @param $permission * * @return bool|mixed */ public function userCan($user, $object, $permission) { if ($user instanceof Admin) { return true; } return $this->permissionsChecker->checkPermissions($user, $object, $permission); } /** * Checks if a given user (AbstractUser) can read a given entity * * @param AbstractUser $user * @param $object * * @return bool */ public function userCanRead(AbstractUser $user, $object) { return $this->userCan($user, $object, self::READ_PERMISSIONS); } /** * Checks if a given user (AbstractUser) can write a given entity * * @param AbstractUser $user * @param $object * * @return bool */ public function userCanWrite(AbstractUser $user, $object) { return $this->userCan($user, $object, self::WRITE_PERMISSIONS); } /** * Checks if a given user (AbstractUser) can delete a given entity * * @param AbstractUser $user * @param $object * * @return bool */ public function userCanDelete(AbstractUser $user, $object) { return $this->userCan($user, $object, self::DELETE_PERMISSIONS); } /** * @param $object * * @return bool */ public function currentUserCanRead($object) { return $this->userCan($this->currentUser, $object, self::READ_PERMISSIONS); } /** * @param $object * * @return bool */ public function currentUserCanReadOthers($object) { return $this->userCan($this->currentUser, $object, self::READ_OTHERS_PERMISSIONS); } /** * @param $object * * @return bool */ public function currentUserCanWrite($object) { return $this->userCan($this->currentUser, $object, self::WRITE_PERMISSIONS); } /** * @param $object * * @return bool */ public function currentUserCanWriteOthers($object) { return $this->userCan($this->currentUser, $object, self::WRITE_OTHERS_PERMISSIONS); } /** * @param $object * * @return bool */ public function currentUserCanWriteStatus($object) { return $this->userCan($this->currentUser, $object, self::WRITE_STATUS_PERMISSIONS); } /** * @param $object * * @return bool */ public function currentUserCanWriteTime($object) { return $this->userCan($this->currentUser, $object, self::WRITE_TIME_PERMISSIONS); } /** * Checks if current user can delete an entity * * @param $object * * @return bool */ public function currentUserCanDelete($object) { return $this->userCan($this->currentUser, $object, self::DELETE_PERMISSIONS); } } Permissions/PermissionsCheckerInterface.php 0000666 00000000604 15165343622 0015224 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Permissions; /** * Interface PermissionsCheckerInterface * * @package AmeliaBooking\Domain\Services\Permissions */ interface PermissionsCheckerInterface { /** * @param $user * @param $object * @param $permission * * @return mixed */ public function checkPermissions($user, $object, $permission); } TimeSlot/TimeSlotService.php 0000666 00000131743 15165343622 0012122 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\TimeSlot; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\SlotsEntities; use AmeliaBooking\Domain\Entity\Schedule\DayOff; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Services\Entity\EntityService; use AmeliaBooking\Domain\Services\Interval\IntervalService; use AmeliaBooking\Domain\Services\Resource\AbstractResourceService; use AmeliaBooking\Domain\Services\Schedule\ScheduleService; use AmeliaBooking\Domain\Services\User\ProviderService; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\Status; use DateInterval; use DatePeriod; use DateTime; use DateTimeZone; use Exception; /** * Class TimeSlotService * * @package AmeliaBooking\Domain\Services\TimeSlot */ class TimeSlotService { /** @var IntervalService */ private $intervalService; /** @var ScheduleService */ private $scheduleService; /** @var ProviderService */ private $providerService; /** @var AbstractResourceService */ private $resourceService; /** @var EntityService */ private $entityService; /** * TimeSlotService constructor. * * @param IntervalService $intervalService * @param ScheduleService $scheduleService * @param ProviderService $providerService * @param AbstractResourceService $resourceService * @param EntityService $entityService */ public function __construct( IntervalService $intervalService, ScheduleService $scheduleService, ProviderService $providerService, AbstractResourceService $resourceService, EntityService $entityService ) { $this->intervalService = $intervalService; $this->scheduleService = $scheduleService; $this->providerService = $providerService; $this->resourceService = $resourceService; $this->entityService = $entityService; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * get appointment intervals for provider. * * @param array $weekDaysIntervals * @param array $intervals * @param string $dateString * @param int $start * @param int $end * @return array */ private function getModifiedEndInterval($weekDaysIntervals, &$intervals, $dateString, $start, $end) { $dayIndex = DateTimeService::getDayIndex($dateString); if (isset($weekDaysIntervals[$dayIndex]['busy'][$start]) && $weekDaysIntervals[$dayIndex]['busy'][$start][1] > $end ) { $end = $weekDaysIntervals[$dayIndex]['busy'][$start][1]; } if (isset($intervals[$dateString]['occupied'][$start]) && $intervals[$dateString]['occupied'][$start][1] > $end ) { $end = $intervals[$dateString]['occupied'][$start][1]; } return $end; } /** * Split start and end in array of dates. * * @param DateTime $start * @param DateTime $end * * @return array */ private function getPeriodDates($start, $end) { /** @var DatePeriod $period */ $period = new DatePeriod( $start->setTime(0, 0, 0), new DateInterval('P1D'), $end ); $periodDates = []; /** @var DateTime $date */ foreach ($period as $index => $date) { $periodDates[] = $date->format('Y-m-d'); } return $periodDates; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * get appointment intervals for provider. * * @param Provider $provider * @param Collection $locations * @param int $serviceId * @param int $locationId * @param int $personsCount * @param boolean $bookIfPending * @param array $weekDaysIntervals * @param array $specialDaysIntervals * @return array * @throws InvalidArgumentException */ private function getProviderAppointmentIntervals( $provider, $locations, $serviceId, $locationId, $personsCount, $bookIfPending, &$weekDaysIntervals, &$specialDaysIntervals ) { $intervals = []; $specialDays = []; foreach ($specialDaysIntervals as $specialDay) { $specialDays = array_merge($specialDays, $specialDay['dates']); } /** @var Appointment $app */ foreach ($provider->getAppointmentList()->getItems() as $app) { $occupiedStart = $provider->getTimeZone() ? DateTimeService::getDateTimeObjectInTimeZone( $app->getBookingStart()->getValue()->format('Y-m-d H:i'), $provider->getTimeZone()->getValue() ) : DateTimeService::getCustomDateTimeObject($app->getBookingStart()->getValue()->format('Y-m-d H:i')); $occupiedEnd = $provider->getTimeZone() ? DateTimeService::getDateTimeObjectInTimeZone( $app->getBookingEnd()->getValue()->format('Y-m-d H:i'), $provider->getTimeZone()->getValue() ) : DateTimeService::getCustomDateTimeObject($app->getBookingEnd()->getValue()->format('Y-m-d H:i')); if ($app->getServiceId()->getValue()) { $occupiedStart->modify('-' . ($app->getService()->getTimeBefore() ? $app->getService()->getTimeBefore()->getValue() : 0) . ' seconds'); $occupiedEnd->modify('+' . ($app->getService()->getTimeAfter() ? $app->getService()->getTimeAfter()->getValue() : 0) . ' seconds'); } $occupiedDateStart = $occupiedStart->format('Y-m-d'); $occupiedSecondsStart = $this->intervalService->getSeconds($occupiedStart->format('H:i') . ':00'); $occupiedSecondsEnd = $this->intervalService->getSeconds($occupiedEnd->format('H:i:s')); if ($occupiedDateStart === $occupiedEnd->format('Y-m-d')) { $intervals[$occupiedDateStart]['occupied'][$occupiedSecondsStart] = [ $occupiedSecondsStart, $this->getModifiedEndInterval( !array_key_exists($occupiedDateStart, $specialDays) ? $weekDaysIntervals : [], $intervals, $occupiedDateStart, $occupiedSecondsStart, $occupiedSecondsEnd ) ]; } else { $dates = $this->getPeriodDates($occupiedStart, $occupiedEnd); $datesCount = sizeof($dates); if ($datesCount === 1) { $intervals[$dates[0]]['occupied'][$occupiedSecondsStart] = [ $occupiedSecondsStart, $occupiedSecondsEnd === 0 ? 86400 : $occupiedSecondsEnd ]; } else { foreach ($dates as $index => $date) { if ($index === 0) { $intervals[$date]['occupied'][$occupiedSecondsStart] = [$occupiedSecondsStart, 86400]; } elseif ($index === $datesCount - 1) { $modifiedEnd = $this->getModifiedEndInterval( !array_key_exists($occupiedDateStart, $specialDays) ? $weekDaysIntervals : [], $intervals, $date, 0, $occupiedSecondsEnd ); $intervals[$date]['occupied'][0] = [ 0, $modifiedEnd === 0 ? 86400 : $modifiedEnd ]; } else { $intervals[$date]['occupied'][0] = [0, 86400]; } } } } $providerLocationId = $provider->getLocationId() ? $provider->getLocationId()->getValue() : null; if ($app->getServiceId()->getValue() === $serviceId) { $persons = 0; /** @var CustomerBooking $booking */ foreach ($app->getBookings()->getItems() as $booking) { $persons += $booking->getPersons()->getValue(); } $status = $app->getStatus()->getValue(); $appLocationId = $app->getLocationId() ? $app->getLocationId()->getValue() : null; $hasCapacity = $personsCount !== null && ($persons + $personsCount) <= $app->getService()->getMaxCapacity()->getValue() && !($app->isFull() ? $app->isFull()->getValue() : false); $hasLocation = !$locationId || ($app->getLocationId() && $app->getLocationId()->getValue() === $locationId) || (!$app->getLocationId() && $providerLocationId === $locationId) || ($appLocationId && $appLocationId === $locationId && $locations->getItem($appLocationId)->getStatus()->getValue() === Status::VISIBLE) || (!$appLocationId && $providerLocationId && $locations->getItem($providerLocationId)->getStatus()->getValue() === Status::VISIBLE); if (($hasLocation && $status === BookingStatus::APPROVED && $hasCapacity) || ($hasLocation && $status === BookingStatus::PENDING && ($bookIfPending || $hasCapacity)) ) { $endDateTime = $app->getBookingEnd()->getValue()->format('Y-m-d H:i:s'); $endDateTimeParts = explode(' ', $endDateTime); $intervals[$occupiedDateStart]['available'][$app->getBookingStart()->getValue()->format('H:i')] = [ 'locationId' => $app->getLocationId() ? $app->getLocationId()->getValue() : $providerLocationId, 'places' => $app->getService()->getMaxCapacity()->getValue() - $persons, 'endDate' => $endDateTimeParts[0], 'endTime' => $endDateTimeParts[1], 'serviceId' => $serviceId, ]; } else { $intervals[$occupiedDateStart]['full'][$app->getBookingStart()->getValue()->format('H:i')] = [ 'locationId' => $app->getLocationId() ? $app->getLocationId()->getValue() : $providerLocationId, 'places' => $app->getService()->getMaxCapacity()->getValue() - $persons, 'end' => $app->getBookingEnd()->getValue()->format('Y-m-d H:i:s'), 'serviceId' => $app->getServiceId()->getValue(), ]; } } elseif ($app->getServiceId()->getValue()) { $intervals[$occupiedDateStart]['full'][$app->getBookingStart()->getValue()->format('H:i')] = [ 'locationId' => $app->getLocationId() ? $app->getLocationId()->getValue() : $providerLocationId, 'places' => 0, 'end' => $app->getBookingEnd()->getValue()->format('Y-m-d H:i:s'), 'serviceId' => $app->getServiceId()->getValue(), ]; } } return $intervals; } /** * get provider day off dates. * * @param Provider $provider * * @return array * @throws Exception */ private function getProviderDayOffDates($provider) { $dates = []; /** @var DayOff $dayOff */ foreach ($provider->getDayOffList()->getItems() as $dayOff) { $endDateCopy = clone $dayOff->getEndDate()->getValue(); $dayOffPeriod = new DatePeriod( $dayOff->getStartDate()->getValue(), new DateInterval('P1D'), $endDateCopy->modify('+1 day') ); /** @var DateTime $date */ foreach ($dayOffPeriod as $date) { $dateFormatted = $dayOff->getRepeat()->getValue() ? $date->format('m-d') : $date->format('Y-m-d'); $dates[$dateFormatted] = $dateFormatted; } } return $dates; } /** * get available appointment intervals. * * @param array $availableIntervals * @param array $unavailableIntervals * * @return array */ private function getAvailableIntervals(&$availableIntervals, $unavailableIntervals) { $parsedAvailablePeriod = []; ksort($availableIntervals); ksort($unavailableIntervals); foreach ($availableIntervals as $available) { $parsedAvailablePeriod[] = $available; foreach ($unavailableIntervals as $unavailable) { if ($parsedAvailablePeriod) { $lastAvailablePeriod = $parsedAvailablePeriod[sizeof($parsedAvailablePeriod) - 1]; if ($unavailable[0] >= $lastAvailablePeriod[0] && $unavailable[1] <= $lastAvailablePeriod[1]) { // unavailable interval is inside available interval $fixedPeriod = array_pop($parsedAvailablePeriod); if ($fixedPeriod[0] !== $unavailable[0]) { $parsedAvailablePeriod[] = [$fixedPeriod[0], $unavailable[0], $fixedPeriod[2]]; } if ($unavailable[1] !== $fixedPeriod[1]) { $parsedAvailablePeriod[] = [$unavailable[1], $fixedPeriod[1], $fixedPeriod[2]]; } } elseif ($unavailable[0] <= $lastAvailablePeriod[0] && $unavailable[1] >= $lastAvailablePeriod[1]) { // available interval is inside unavailable interval array_pop($parsedAvailablePeriod); } elseif ($unavailable[0] <= $lastAvailablePeriod[0] && $unavailable[1] >= $lastAvailablePeriod[0] && $unavailable[1] <= $lastAvailablePeriod[1]) { // unavailable interval intersect start of available interval $fixedPeriod = array_pop($parsedAvailablePeriod); if ($unavailable[1] !== $fixedPeriod[1]) { $parsedAvailablePeriod[] = [$unavailable[1], $fixedPeriod[1], $fixedPeriod[2]]; } } elseif ($unavailable[0] >= $lastAvailablePeriod[0] && $unavailable[0] <= $lastAvailablePeriod[1] && $unavailable[1] >= $lastAvailablePeriod[1]) { // unavailable interval intersect end of available interval $fixedPeriod = array_pop($parsedAvailablePeriod); if ($fixedPeriod[0] !== $unavailable[0]) { $parsedAvailablePeriod[] = [$fixedPeriod[0], $unavailable[0], $fixedPeriod[2]]; } } } } } return $parsedAvailablePeriod; } /** * @param Service $service * @param Provider $provider * @param int $personsCount * * @return bool * * @throws Exception */ private function getOnlyAppointmentsSlots($service, $provider, $personsCount) { $getOnlyAppointmentsSlots = false; if ($provider->getServiceList()->keyExists($service->getId()->getValue())) { /** @var Service $providerService */ $providerService = $provider->getServiceList()->getItem($service->getId()->getValue()); if ($personsCount < $providerService->getMinCapacity()->getValue()) { $getOnlyAppointmentsSlots = true; } } return $getOnlyAppointmentsSlots; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Service $service * @param int $locationId * @param Collection $providers * @param Collection $locations * @param array $globalDaysOffDates * @param DateTime $startDateTime * @param DateTime $endDateTime * @param int $personsCount * @param boolean $bookIfPending * @param boolean $bookIfNotMin * @param boolean $bookAfterMin * * @return array * @throws Exception */ private function getFreeTime( Service $service, $locationId, Collection $locations, Collection $providers, array $globalDaysOffDates, DateTime $startDateTime, DateTime $endDateTime, $personsCount, $bookIfPending, $bookIfNotMin, $bookAfterMin ) { $weekDayIntervals = []; $appointmentIntervals = []; $daysOffDates = []; $specialDayIntervals = []; $getOnlyAppointmentsSlots = []; $serviceId = $service->getId()->getValue(); /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { $providerId = $provider->getId()->getValue(); $getOnlyAppointmentsSlots[$providerId] = $bookIfNotMin && $bookAfterMin ? $this->getOnlyAppointmentsSlots( $service, $provider, $personsCount ) : false; $daysOffDates[$providerId] = $this->getProviderDayOffDates($provider); $weekDayIntervals[$providerId] = $this->scheduleService->getProviderWeekDaysIntervals( $provider, $locations, $locationId, $serviceId ); $specialDayIntervals[$providerId] = $this->scheduleService->getProviderSpecialDayIntervals( $provider, $locations, $locationId, $serviceId ); $appointmentIntervals[$providerId] = $this->getProviderAppointmentIntervals( $provider, $locations, $serviceId, $locationId, $personsCount, $bookIfPending, $weekDayIntervals[$providerId], $specialDayIntervals[$providerId] ); } $freeDateIntervals = []; foreach ($appointmentIntervals as $providerKey => $providerDates) { foreach ((array)$providerDates as $dateKey => $dateIntervals) { $dayIndex = DateTimeService::getDayIndex($dateKey); $specialDayDateKey = null; foreach ((array)$specialDayIntervals[$providerKey] as $specialDayKey => $specialDays) { if (array_key_exists($dateKey, $specialDays['dates'])) { $specialDayDateKey = $specialDayKey; break; } } if ($specialDayDateKey !== null && isset($specialDayIntervals[$providerKey][$specialDayDateKey]['intervals']['free'])) { // get free intervals if it is special day $freeDateIntervals[$providerKey][$dateKey] = $this->getAvailableIntervals( $specialDayIntervals[$providerKey][$specialDayDateKey]['intervals']['free'], $dateIntervals['occupied'] ); } elseif (isset($weekDayIntervals[$providerKey][$dayIndex]['free']) && !isset($specialDayIntervals[$providerKey][$specialDayDateKey]['intervals'])) { // get free intervals if it is working day $unavailableIntervals = $weekDayIntervals[$providerKey][$dayIndex]['busy'] + $dateIntervals['occupied']; $intersectedTimes = array_intersect( array_keys($weekDayIntervals[$providerKey][$dayIndex]['busy']), array_keys($dateIntervals['occupied']) ); foreach ($intersectedTimes as $time) { $unavailableIntervals[$time] = $weekDayIntervals[$providerKey][$dayIndex]['busy'][$time] > $dateIntervals['occupied'][$time] ? $weekDayIntervals[$providerKey][$dayIndex]['busy'][$time] : $dateIntervals['occupied'][$time]; } $freeDateIntervals[$providerKey][$dateKey] = $this->getAvailableIntervals( $weekDayIntervals[$providerKey][$dayIndex]['free'], $unavailableIntervals ); } } } $startDateTime = clone $startDateTime; $startDateTime->setTime(0, 0); $endDateTime = clone $endDateTime; $endDateTime->modify('+1 day')->setTime(0, 0); // create calendar $period = new DatePeriod( $startDateTime, new DateInterval('P1D'), $endDateTime ); $calendar = []; /** @var DateTime $day */ foreach ($period as $day) { $currentDate = $day->format('Y-m-d'); $dayIndex = (int)$day->format('N'); $isGlobalDayOff = array_key_exists($currentDate, $globalDaysOffDates) || array_key_exists($day->format('m-d'), $globalDaysOffDates); if (!$isGlobalDayOff) { foreach ($weekDayIntervals as $providerKey => $providerWorkingHours) { $isProviderDayOff = array_key_exists($currentDate, $daysOffDates[$providerKey]) || array_key_exists($day->format('m-d'), $daysOffDates[$providerKey]); $specialDayDateKey = null; foreach ((array)$specialDayIntervals[$providerKey] as $specialDayKey => $specialDays) { if (array_key_exists($currentDate, $specialDays['dates'])) { $specialDayDateKey = $specialDayKey; break; } } if (!$isProviderDayOff) { if ($freeDateIntervals && isset($freeDateIntervals[$providerKey][$currentDate])) { // get date intervals if there are appointments (special or working day) $calendar[$currentDate][$providerKey] = [ 'slots' => $personsCount && $bookIfNotMin && isset($appointmentIntervals[$providerKey][$currentDate]['available']) ? $appointmentIntervals[$providerKey][$currentDate]['available'] : [], 'full' => isset($appointmentIntervals[$providerKey][$currentDate]['full']) ? $appointmentIntervals[$providerKey][$currentDate]['full'] : [], 'intervals' => $getOnlyAppointmentsSlots[$providerKey] ? [] : $freeDateIntervals[$providerKey][$currentDate], ]; } else { if ($specialDayDateKey !== null && isset($specialDayIntervals[$providerKey][$specialDayDateKey]['intervals']['free'])) { // get date intervals if it is special day with out appointments $calendar[$currentDate][$providerKey] = [ 'slots' => [], 'full' => [], 'intervals' => $getOnlyAppointmentsSlots[$providerKey] ? [] : $specialDayIntervals[$providerKey][$specialDayDateKey]['intervals']['free'] ]; } elseif (isset($weekDayIntervals[$providerKey][$dayIndex]) && !isset($specialDayIntervals[$providerKey][$specialDayDateKey]['intervals'])) { // get date intervals if it is working day without appointments $calendar[$currentDate][$providerKey] = [ 'slots' => [], 'full' => [], 'intervals' => $getOnlyAppointmentsSlots[$providerKey] ? [] : $weekDayIntervals[$providerKey][$dayIndex]['free'] ]; } } } } } } return $calendar; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Service $service * @param int $requiredTime * @param array $freeIntervals * @param array $resourcedIntervals * @param int $slotLength * @param DateTime $startDateTime * @param bool $serviceDurationAsSlot * @param bool $bufferTimeInSlot * @param bool $isFrontEndBooking * @param String $timeZone * * @return array */ private function getAppointmentFreeSlots( $service, $requiredTime, &$freeIntervals, $resourcedIntervals, $slotLength, $startDateTime, $serviceDurationAsSlot, $bufferTimeInSlot, $isFrontEndBooking, $timeZone ) { $availableResult = []; $occupiedResult = []; $realRequiredTime = $requiredTime - $service->getTimeBefore()->getValue() - $service->getTimeAfter()->getValue(); if ($serviceDurationAsSlot && !$bufferTimeInSlot) { $requiredTime = $requiredTime - $service->getTimeBefore()->getValue() - $service->getTimeAfter()->getValue(); } $currentDateTime = DateTimeService::getNowDateTimeObject(); $currentDateString = $currentDateTime->format('Y-m-d'); $currentTimeStringInSeconds = $this->intervalService->getSeconds($currentDateTime->format('H:i:s')); $currentTimeInSeconds = $this->intervalService->getSeconds($currentDateTime->format('H:i:s')); $currentDateFormatted = $currentDateTime->format('Y-m-d'); $startTimeInSeconds = $this->intervalService->getSeconds($startDateTime->format('H:i:s')); $startDateFormatted = $startDateTime->format('Y-m-d'); $bookingLength = $serviceDurationAsSlot && $isFrontEndBooking ? $requiredTime : $slotLength; foreach ($freeIntervals as $dateKey => $dateProviders) { foreach ((array)$dateProviders as $providerKey => $provider) { foreach ((array)$provider['intervals'] as $timePeriod) { if ($timePeriod[1] === 86400) { $nextDateString = DateTimeService::getDateTimeObjectInTimeZone( $dateKey . ' 00:00:00', $timeZone )->modify('+1 days')->format('Y-m-d'); if (isset($freeIntervals[$nextDateString][$providerKey]['intervals'][0]) && $freeIntervals[$nextDateString][$providerKey]['intervals'][0][0] === 0 ) { $nextDayInterval = $freeIntervals[$nextDateString][$providerKey]['intervals'][0][1]; $timePeriod[1] += ($realRequiredTime <= $nextDayInterval ? $realRequiredTime : $nextDayInterval); } } if (!$bufferTimeInSlot && $serviceDurationAsSlot) { $timePeriod[1] = $timePeriod[1] - $service->getTimeAfter()->getValue(); } $customerTimeStart = $timePeriod[0] + $service->getTimeBefore()->getValue(); $providerTimeStart = $customerTimeStart - $service->getTimeBefore()->getValue(); $numberOfSlots = (int)(floor(($timePeriod[1] - $providerTimeStart - $requiredTime) / $bookingLength) + 1); $inspectResourceIndexes = []; if (isset($resourcedIntervals[$dateKey])) { foreach ($resourcedIntervals[$dateKey] as $resourceIndex => $resourceData) { if (array_intersect( $timePeriod[2], $resourcedIntervals[$dateKey][$resourceIndex]['locationsIds'] )) { $inspectResourceIndexes[] = $resourceIndex; } } } $providerPeriodSlots = []; $achievedLength = 0; for ($i = 0; $i < $numberOfSlots; $i++) { $achievedLength += $bookingLength; $timeSlot = $customerTimeStart + $i * $bookingLength; if (($startDateFormatted !== $dateKey && ($serviceDurationAsSlot && !$bufferTimeInSlot ? $timeSlot <= $timePeriod[1] - $requiredTime : true)) || ($startDateFormatted === $dateKey && $startTimeInSeconds < $timeSlot) || ($startDateFormatted === $currentDateFormatted && $startDateFormatted === $dateKey && $startTimeInSeconds < $timeSlot && $currentTimeInSeconds < $timeSlot) ) { $timeSlotEnd = $timeSlot + $bookingLength; $filteredLocationsIds = $timePeriod[2]; foreach ($inspectResourceIndexes as $resourceIndex) { foreach ($resourcedIntervals[$dateKey][$resourceIndex]['intervals'] as $start => $end) { if (($start >= $timeSlot && $start < $timeSlotEnd) || ($end > $timeSlot && $end <= $timeSlotEnd) || ($start <= $timeSlot && $end >= $timeSlotEnd) || ($start >= $timeSlot && $start < $timeSlot + $requiredTime) ) { $filteredLocationsIds = array_diff( $filteredLocationsIds, $resourcedIntervals[$dateKey][$resourceIndex]['locationsIds'] ); if (!$filteredLocationsIds) { if ($achievedLength < $requiredTime) { $providerPeriodSlots = []; $achievedLength = 0; } continue 3; } $removedLocationsIds = array_diff( $resourcedIntervals[$dateKey][$resourceIndex]['locationsIds'], $filteredLocationsIds ); if ($removedLocationsIds && $achievedLength < $requiredTime) { $parsedPeriodSlots = []; foreach ($providerPeriodSlots as $previousTimeSlot => $periodSlotData) { if ($start >= $previousTimeSlot && $start < $previousTimeSlot + $requiredTime ) { foreach ($periodSlotData as $data) { if (!in_array($data[1], $removedLocationsIds)) { $parsedPeriodSlots[$previousTimeSlot][] = $data; } } } else { $parsedPeriodSlots[$previousTimeSlot] = $periodSlotData; } } $providerPeriodSlots = $parsedPeriodSlots; } } } } if (!$timePeriod[2]) { $providerPeriodSlots[$timeSlot][] = [$providerKey, null]; } else if ($filteredLocationsIds) { foreach ($filteredLocationsIds as $locationId) { $providerPeriodSlots[$timeSlot][] = [$providerKey, $locationId]; } } } } foreach ($providerPeriodSlots as $timeSlot => $data) { $time = sprintf('%02d', floor($timeSlot / 3600)) . ':' . sprintf('%02d', floor(($timeSlot / 60) % 60)); $availableResult[$dateKey][$time] = $data; } } foreach ($provider['slots'] as $appointmentTime => $appointmentData) { $startInSeconds = $this->intervalService->getSeconds($appointmentTime . ':00'); if ($currentDateString === $dateKey && ($currentTimeStringInSeconds > $startInSeconds || $startTimeInSeconds > $startInSeconds) ) { continue; } $endInSeconds = $this->intervalService->getSeconds($appointmentData['endTime']); $newEndInSeconds = $startInSeconds + $realRequiredTime; if ($newEndInSeconds > $endInSeconds) { if ($dateKey !== $appointmentData['endDate']) { $nextDateString = DateTimeService::getDateTimeObjectInTimeZone( $dateKey . ' 00:00:00', $timeZone )->modify('+1 days')->format('Y-m-d'); if (!isset($freeIntervals[$nextDateString][$providerKey]['intervals'][0]) || $freeIntervals[$nextDateString][$providerKey]['intervals'][0][0] != $endInSeconds || $freeIntervals[$nextDateString][$providerKey]['intervals'][0][1] < $newEndInSeconds - 86400 ) { continue; } } elseif ($newEndInSeconds > 86400) { $nextIntervalIsValid = false; foreach ($freeIntervals[$dateKey][$providerKey]['intervals'] as $interval) { if ($interval[0] === $endInSeconds && $interval[1] === 86400) { $nextIntervalIsValid = true; break; } } if (!$nextIntervalIsValid) { continue; } $nextDateString = DateTimeService::getDateTimeObjectInTimeZone( $dateKey . ' 00:00:00', $timeZone )->modify('+1 days')->format('Y-m-d'); if (!isset($freeIntervals[$nextDateString][$providerKey]['intervals'][0]) || $freeIntervals[$nextDateString][$providerKey]['intervals'][0][0] != 0 || $freeIntervals[$nextDateString][$providerKey]['intervals'][0][1] < $newEndInSeconds - 86400 ) { continue; } } else { $nextIntervalIsValid = false; foreach ($freeIntervals[$dateKey][$providerKey]['intervals'] as $interval) { if ($interval[0] === $endInSeconds && $interval[1] >= $newEndInSeconds) { $nextIntervalIsValid = true; break; } } if (!$nextIntervalIsValid) { continue; } } } $availableResult[$dateKey][$appointmentTime][] = [ $providerKey, $appointmentData['locationId'], $appointmentData['places'], $appointmentData['serviceId'] ]; } foreach ($provider['full'] as $appointmentTime => $appointmentData) { $occupiedResult[$dateKey][$appointmentTime][] = [ $providerKey, $appointmentData['locationId'], $appointmentData['places'], $appointmentData['serviceId'] ]; } } } return [ 'available' => $availableResult, 'occupied' => $occupiedResult, ]; } /** * @param array $slots * @param string $timeZone * * @return array * @throws Exception */ private function getSlotsInMainTimeZoneFromTimeZone($slots, $timeZone) { $convertedProviderSlots = []; foreach ($slots as $slotDate => $slotTimes) { foreach ($slots[$slotDate] as $slotTime => $slotTimesProviders) { $convertedSlotParts = explode( ' ', DateTimeService::getDateTimeObjectInTimeZone( $slotDate . ' ' . $slotTime, $timeZone )->setTimezone(new DateTimeZone(DateTimeService::getTimeZone()->getName()))->format('Y-m-d H:i') ); $convertedProviderSlots[$convertedSlotParts[0]][$convertedSlotParts[1]] = $slotTimesProviders; } } return $convertedProviderSlots; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param array $settings * @param array $props * @param SlotsEntities $slotsEntities * @param Collection $appointments * * @return array * @throws Exception */ public function getSlots($settings, $props, $slotsEntities, $appointments) { $resourcedLocationsIntervals = $slotsEntities->getResources()->length() ? $this->resourceService->manageResources( $slotsEntities->getResources(), $appointments, $slotsEntities->getLocations(), $slotsEntities->getServices()->getItem($props['serviceId']), $slotsEntities->getProviders(), $props['locationId'], $props['excludeAppointmentId'], array_key_exists('totalPersons', $props) ? $props['totalPersons'] : $props['personsCount'] ) : []; $this->entityService->filterSlotsAppointments($slotsEntities, $appointments, $props); $this->providerService->addAppointmentsToAppointmentList( $slotsEntities->getProviders(), $appointments, $settings['isGloballyBusySlot'] ); return $this->getCalculatedFreeSlots( $settings, $props, $slotsEntities, $resourcedLocationsIntervals ); } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param array $settings * @param array $props * @param SlotsEntities $slotsEntities * @param array $resourcedLocationsIntervals * * @return array * @throws Exception */ private function getCalculatedFreeSlots( $settings, $props, $slotsEntities, $resourcedLocationsIntervals ) { $freeProvidersSlots = []; /** @var DateTime $startDateTime */ $startDateTime = $props['startDateTime']; /** @var DateTime $endDateTime */ $endDateTime = $props['endDateTime']; /** @var Service $service */ $service = $slotsEntities->getServices()->getItem($props['serviceId']); /** @var Collection $providers */ $providers = $slotsEntities->getProviders(); /** @var Collection $locations */ $locations = $slotsEntities->getLocations(); $requiredTime = $this->entityService->getAppointmentRequiredTime( $service, $props['extras'] ); /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { $providerContainer = new Collection(); if ($provider->getTimeZone()) { $this->providerService->modifyProviderTimeZone( $provider, $settings['globalDaysOff'], $startDateTime, $endDateTime ); } $start = $provider->getTimeZone() ? DateTimeService::getCustomDateTimeObjectInTimeZone( $startDateTime->format('Y-m-d H:i'), $provider->getTimeZone()->getValue() ) : DateTimeService::getCustomDateTimeObject($startDateTime->format('Y-m-d H:i')); $end = $provider->getTimeZone() ? DateTimeService::getCustomDateTimeObjectInTimeZone( $endDateTime->format('Y-m-d H:i'), $provider->getTimeZone()->getValue() ) : DateTimeService::getCustomDateTimeObject($endDateTime->format('Y-m-d H:i')); $providerContainer->addItem($provider, $provider->getId()->getValue()); $freeIntervals = $this->getFreeTime( $service, $props['locationId'], $locations, $providerContainer, $settings['allowAdminBookAtAnyTime'] || $provider->getTimeZone() ? [] : $settings['globalDaysOff'], $start, $end, $props['personsCount'], $settings['allowBookingIfPending'], $settings['allowBookingIfNotMin'], $props['isFrontEndBooking'] ? $settings['openedBookingAfterMin'] : false ); $freeProvidersSlots[$provider->getId()->getValue()] = $this->getAppointmentFreeSlots( $service, $requiredTime, $freeIntervals, !empty($resourcedLocationsIntervals[$provider->getId()->getValue()]) ? $resourcedLocationsIntervals[$provider->getId()->getValue()] : [], $settings['timeSlotLength'] ?: $requiredTime, $start, $settings['serviceDurationAsSlot'], $settings['bufferTimeInSlot'], true, $provider->getTimeZone() ? $provider->getTimeZone()->getValue() : DateTimeService::getTimeZone()->getName() ); } $freeSlots = [ 'available' => [], 'occupied' => [], ]; foreach ($freeProvidersSlots as $providerKey => $providerSlots) { /** @var Provider $provider */ $provider = $providers->getItem($providerKey); foreach (['available', 'occupied'] as $type) { if ($provider->getTimeZone()) { $providerSlots[$type] = $this->getSlotsInMainTimeZoneFromTimeZone( $providerSlots[$type], $provider->getTimeZone()->getValue() ); } foreach ($providerSlots[$type] as $dateKey => $dateSlots) { foreach ($dateSlots as $timeKey => $slotData) { if (empty($freeSlots[$type][$dateKey][$timeKey])) { $freeSlots[$type][$dateKey][$timeKey] = []; } foreach ($slotData as $item) { $freeSlots[$type][$dateKey][$timeKey][] = $item; } if (isset($freeSlots[$type][$dateKey])) { if (!$freeSlots[$type][$dateKey]) { unset($freeSlots[$type][$dateKey]); } else { ksort($freeSlots[$type][$dateKey]); } } } } } } return $freeSlots; } } Settings/SettingsService.php 0000666 00000011747 15165343622 0012223 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Settings; use AmeliaBooking\Domain\Entity\Settings\Settings; use AmeliaBooking\Domain\Factory\Settings\SettingsFactory; use AmeliaBooking\Domain\ValueObjects\Json; /** * Class SettingsService * * @package AmeliaBooking\Domain\Services\Settings */ class SettingsService { const NUMBER_OF_DAYS_AVAILABLE_FOR_BOOKING = 365; /** @var SettingsStorageInterface */ private $settingsStorage; /** * SettingsService constructor. * * @param SettingsStorageInterface $settingsStorage */ public function __construct(SettingsStorageInterface $settingsStorage) { $this->settingsStorage = $settingsStorage; } /** * @param $settingCategoryKey * @param $settingKey * @param null $defaultValue * * @return mixed|null */ public function getSetting($settingCategoryKey, $settingKey, $defaultValue = null) { if (null !== $this->settingsStorage->getSetting($settingCategoryKey, $settingKey)) { return $this->settingsStorage->getSetting($settingCategoryKey, $settingKey); } return $defaultValue; } /** * @param $settingCategoryKey * * @return mixed|array */ public function getCategorySettings($settingCategoryKey) { return $this->settingsStorage->getCategorySettings($settingCategoryKey); } /** * Return array of all settings where keys are settings names and values are settings values * * @return mixed */ public function getAllSettings() { return $this->settingsStorage->getAllSettings(); } /** * Return array of arrays where keys are settings categories names and values are categories settings * * @return mixed */ public function getAllSettingsCategorized() { return $this->settingsStorage->getAllSettingsCategorized(); } /** * @return mixed */ public function getFrontendSettings() { return $this->settingsStorage->getFrontendSettings(); } /** * @param $settingCategoryKey * @param $settingKey * @param $settingValue * * @return mixed */ public function setSetting($settingCategoryKey, $settingKey, $settingValue) { return $this->settingsStorage->setSetting($settingCategoryKey, $settingKey, $settingValue); } /** * @param $settingCategoryKey * @param $settingValues * * @return mixed */ public function setCategorySettings($settingCategoryKey, $settingValues) { return $this->settingsStorage->setCategorySettings($settingCategoryKey, $settingValues); } /** * @param $settings * * @return mixed */ public function setAllSettings($settings) { return $this->settingsStorage->setAllSettings($settings); } /** * @param Json $entitySettingsJson * * @return Settings */ public function getEntitySettings($entitySettingsJson) { return SettingsFactory::create($entitySettingsJson, $this->getAllSettingsCategorized()); } /** * @param Json $entitySettingsJson * * @return Settings */ public function getSavedSettings($entitySettingsJson) { $data = $entitySettingsJson ? json_decode($entitySettingsJson->getValue(), true) : []; $isOldEntitySettings = !isset($data['activation']['version']); if ($isOldEntitySettings && isset($data['general']['minimumTimeRequirementPriorToCanceling'])) { $data['general']['minimumTimeRequirementPriorToRescheduling'] = $data['general']['minimumTimeRequirementPriorToCanceling']; } return $data; } /** * @param array $entities * * @return void */ public function setStashEntities($entities) { update_option('amelia_stash', json_encode($entities)); } /** * @return array */ public function getStashEntities() { $entitiesStash = get_option('amelia_stash'); return $entitiesStash ? json_decode($entitiesStash, true) : []; } /** * @param array $settings * * @return void */ public function fixCustomization(&$settings) { if (isset($settings['forms']) && $settings['forms']) { foreach ($settings['forms'] as $formName => &$form) { if (isset($form['confirmBookingForm'])) { foreach ($form['confirmBookingForm'] as $entityName => &$entity) { if (isset($entity['itemsStatic']['paymentMethodFormField']['switchPaymentMethodViewOptions'])) { array_splice( $settings['forms'][$formName]['confirmBookingForm'][$entityName]['itemsStatic']['paymentMethodFormField']['switchPaymentMethodViewOptions'], 2 ); } } } } } } } Settings/SettingsStorageInterface.php 0000666 00000002362 15165343622 0014041 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Settings; /** * Interface SettingsStorageInterface * * @package AmeliaBooking\Domain\Services\Settings */ interface SettingsStorageInterface { /** * @param $settingCategoryKey * @param $settingKey * * @return mixed */ public function getSetting($settingCategoryKey, $settingKey); /** * @param $settingCategoryKey * * @return mixed */ public function getCategorySettings($settingCategoryKey); /** * @return mixed */ public function getAllSettings(); /** * @return mixed */ public function getAllSettingsCategorized(); /** * @return mixed */ public function getFrontendSettings(); /** * @param $settingCategoryKey * @param $settingKey * @param $settingValue * * @return mixed */ public function setSetting($settingCategoryKey, $settingKey, $settingValue); /** * @param $settingCategoryKey * @param $settingValue * * @return mixed */ public function setCategorySettings($settingCategoryKey, $settingValue); /** * @param $settings * * @return mixed */ public function setAllSettings($settings); } Schedule/ScheduleService.php 0000666 00000021605 15165343622 0012105 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Schedule; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\Entity\Schedule\Period; use AmeliaBooking\Domain\Entity\Schedule\PeriodService; use AmeliaBooking\Domain\Entity\Schedule\SpecialDay; use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriod; use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriodService; use AmeliaBooking\Domain\Entity\Schedule\TimeOut; use AmeliaBooking\Domain\Entity\Schedule\WeekDay; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Services\Interval\IntervalService; use AmeliaBooking\Domain\Services\Location\LocationService; use AmeliaBooking\Domain\Services\User\ProviderService; use DateTime; use DateInterval; use DatePeriod; use Exception; /** * Class ScheduleService * * @package AmeliaBooking\Domain\Services\Schedule */ class ScheduleService { /** @var IntervalService */ private $intervalService; /** @var ProviderService */ private $providerService; /** @var ProviderService */ private $locationService; /** * ScheduleService constructor. * * @param IntervalService $intervalService * @param ProviderService $providerService * @param LocationService $locationService */ public function __construct( $intervalService, $providerService, $locationService ) { $this->intervalService = $intervalService; $this->providerService = $providerService; $this->locationService = $locationService; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * get special dates intervals for provider. * * @param Provider $provider * @param Collection $locations * @param int|null $locationId * @param int $serviceId * * @return array * @throws Exception * @throws InvalidArgumentException */ public function getProviderSpecialDayIntervals($provider, $locations, $locationId, $serviceId) { $intervals = []; $hasVisibleLocations = $this->locationService->hasVisibleLocations($locations); /** @var Location $providerLocation */ $providerLocation = $provider->getLocationId() && $locations->length() && $locations->keyExists($provider->getLocationId()->getValue()) ? $locations->getItem($provider->getLocationId()->getValue()) : null; /** @var SpecialDay $specialDay */ foreach ($provider->getSpecialDayList()->getItems() as $specialDay) { $specialDates = []; $endDateCopy = clone $specialDay->getEndDate()->getValue(); $specialDaysPeriod = new DatePeriod( $specialDay->getStartDate()->getValue(), new DateInterval('P1D'), $endDateCopy->modify('+1 day') ); /** @var DateTime $day */ foreach ($specialDaysPeriod as $day) { $specialDates[$day->format('Y-m-d')] = true; } $specialDatesIntervals = []; /** @var SpecialDayPeriod $period */ foreach ($specialDay->getPeriodList()->getItems() as $period) { /** @var Collection $availablePeriodLocations */ $availablePeriodLocations = $this->providerService->getProviderPeriodLocations( $period, $providerLocation, $locations, $hasVisibleLocations ); if (($hasVisibleLocations && !$availablePeriodLocations->length()) || ($hasVisibleLocations && $locationId && !$availablePeriodLocations->keyExists($locationId)) ) { continue; } $hasService = $period->getPeriodServiceList()->length() === 0; /** @var SpecialDayPeriodService $periodService */ foreach ($period->getPeriodServiceList()->getItems() as $periodService) { if ($periodService->getServiceId()->getValue() === $serviceId) { $hasService = true; } } $start = $this->intervalService->getSeconds($period->getStartTime()->getValue()->format('H:i:s')); $end = $this->intervalService->getSeconds($this->intervalService->getEndTimeString($period->getEndTime()->getValue()->format('H:i:s'))); if ($hasService) { $specialDatesIntervals['free'][$start] = [ $start, $end, $locationId ? [$locationId] : $availablePeriodLocations->keys(), ]; } } $intervals[] = [ 'dates' => $specialDates, 'intervals' => $specialDatesIntervals ]; } return array_reverse($intervals); } /** @noinspection MoreThanThreeArgumentsInspection */ /** * get week days intervals for provider. * * @param Provider $provider * @param Collection $locations * @param int $serviceId * @param int|null $locationId * * @return array * @throws InvalidArgumentException */ public function getProviderWeekDaysIntervals($provider, $locations, $locationId, $serviceId) { $intervals = []; $hasVisibleLocations = $this->locationService->hasVisibleLocations($locations); /** @var Location $providerLocation */ $providerLocation = $provider->getLocationId() && $locations->length() ? $locations->getItem($provider->getLocationId()->getValue()) : null; $providerLocationId = $providerLocation ? $providerLocation->getId()->getValue() : null; /** @var WeekDay $weekDay */ foreach ($provider->getWeekDayList()->getItems() as $weekDay) { $dayIndex = $weekDay->getDayIndex()->getValue(); $intervals[$dayIndex]['busy'] = []; $intervals[$dayIndex]['free'] = []; /** @var TimeOut $timeOut */ foreach ($weekDay->getTimeOutList()->getItems() as $timeOut) { $start = $this->intervalService->getSeconds($timeOut->getStartTime()->getValue()->format('H:i:s')); $intervals[$dayIndex]['busy'][$start] = [ $start, $this->intervalService->getSeconds($timeOut->getEndTime()->getValue()->format('H:i:s')) ]; } /** @var Period $period */ foreach ($weekDay->getPeriodList()->getItems() as $period) { /** @var Collection $availablePeriodLocations */ $availablePeriodLocations = $this->providerService->getProviderPeriodLocations( $period, $providerLocation, $locations, $hasVisibleLocations ); if (($hasVisibleLocations && !$availablePeriodLocations->length()) || ($hasVisibleLocations && $locationId && !$availablePeriodLocations->keyExists($locationId)) ) { continue; } $hasService = $period->getPeriodServiceList()->length() === 0; /** @var PeriodService $periodService */ foreach ($period->getPeriodServiceList()->getItems() as $periodService) { if ($periodService->getServiceId()->getValue() === $serviceId) { $hasService = true; } } $start = $this->intervalService->getSeconds($period->getStartTime()->getValue()->format('H:i:s')); $end = $this->intervalService->getSeconds($this->intervalService->getEndTimeString($period->getEndTime()->getValue()->format('H:i:s'))); if ($hasService) { $intervals[$dayIndex]['free'][$start] = [ $start, $end, $locationId ? [$locationId] : $availablePeriodLocations->keys(), ]; } } if ($weekDay->getPeriodList()->length() === 0) { $start = $this->intervalService->getSeconds($weekDay->getStartTime()->getValue()->format('H:i:s')); $end = $this->intervalService->getSeconds($this->intervalService->getEndTimeString($weekDay->getEndTime()->getValue()->format('H:i:s'))); $intervals[$dayIndex]['free'][$start] = [$start, $end, [$providerLocationId]]; } $intervals[$dayIndex]['free'] = $this->intervalService->getAvailableIntervals( $intervals[$dayIndex]['free'], isset($intervals[$dayIndex]['busy']) ? $intervals[$dayIndex]['busy'] : [] ); } return $intervals; } } Payment/PaymentServiceInterface.php 0000666 00000001351 15165343622 0013464 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Domain\Services\Payment; /** * Interface PaymentServiceInterface * * @package AmeliaBooking\Domain\Services\Payment */ interface PaymentServiceInterface { /** * @param array $data * * @return mixed */ public function execute($data); /** * @param array $data * * @return array */ public function getPaymentLink($data); /** * @param array $data * * @return array */ public function refund($data); /** * @param string $id * * @return mixed */ public function getTransactionAmount($id); } Payment/AbstractPaymentService.php 0000666 00000001262 15165343622 0013330 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Domain\Services\Payment; use AmeliaBooking\Domain\Services\Settings\SettingsService; /** * Class AbstractPaymentService * * @package AmeliaBooking\Domain\Services\Payment */ class AbstractPaymentService { /** * @var SettingsService $settingsService */ protected $settingsService; /** * PayPalService constructor. * * @param SettingsService $settingsService */ public function __construct( SettingsService $settingsService ) { $this->settingsService = $settingsService; } } Resource/AbstractResourceService.php 0000666 00000004022 15165343622 0013651 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Resource; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; /** * Class AbstractResourceService * * @package AmeliaBooking\Domain\Services\Resource */ abstract class AbstractResourceService { /** * set substitute resources instead of resources that are not shred between services/locations * * @param Collection $resources * @param array $entitiesIds * * @return void * @throws InvalidArgumentException */ abstract public function setNonSharedResources($resources, $entitiesIds); /** * get collection of resources for service * * @param Collection $resources * @param int $serviceId * * @return Collection * @throws InvalidArgumentException */ abstract public function getServiceResources($resources, $serviceId); /** * get providers id values for resources * * @param Collection $resources * * @return array */ abstract public function getResourcesProvidersIds($resources); /** @noinspection MoreThanThreeArgumentsInspection */ /** * set unavailable intervals (fake appointments) to providers in moments when resources are used up * return intervals of resources with locations that are used up * * @param Collection $resources * @param Collection $appointments * @param Collection $allLocations * @param Service $service * @param Collection $providers * @param int|null $locationId * @param int|null $excludeAppointmentId * @param int $personsCount * * @return array * @throws InvalidArgumentException */ abstract public function manageResources( $resources, $appointments, $allLocations, $service, $providers, $locationId, $excludeAppointmentId, $personsCount ); } Resource/BasicResourceService.php 0000666 00000004047 15165343622 0013136 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Resource; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; /** * Class BasicResourceService * * @package AmeliaBooking\Domain\Services\Resource */ class BasicResourceService extends AbstractResourceService { /** * set substitute resources instead of resources that are not shred between services/locations * * @param Collection $resources * @param array $entitiesIds * * @return void * @throws InvalidArgumentException */ public function setNonSharedResources($resources, $entitiesIds) { } /** * get collection of resources for service * * @param Collection $resources * @param int $serviceId * * @return Collection * @throws InvalidArgumentException */ public function getServiceResources($resources, $serviceId) { return new Collection(); } /** * get providers id values for resources * * @param Collection $resources * * @return array */ public function getResourcesProvidersIds($resources) { return []; } /** * set unavailable intervals (fake appointments) to providers in moments when resources are used up * return intervals of resources with locations that are used up * * @param Collection $resources * @param Collection $appointments * @param Collection $allLocations * @param Service $service * @param Collection $providers * @param int|null $locationId * @param int|null $excludeAppointmentId * @param int $personsCount * * @return array * @throws InvalidArgumentException */ public function manageResources( $resources, $appointments, $allLocations, $service, $providers, $locationId, $excludeAppointmentId, $personsCount ) { return []; } } Notification/MailServiceInterface.php 0000666 00000001132 15165343622 0013737 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Domain\Services\Notification; /** * Interface MailServiceInterface * * @package AmeliaBooking\Domain\Services\Notification */ interface MailServiceInterface { /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param $to * @param $subject * @param $body * @param bool $bcc * * @return mixed * @SuppressWarnings(PHPMD) */ public function send($to, $subject, $body, $bcc = false); } Notification/AbstractMailService.php 0000666 00000001161 15165343622 0013604 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Domain\Services\Notification; /** * Class AbstractMailService * * @package AmeliaBooking\Domain\Services\Notification */ class AbstractMailService { /** @var string */ protected $from; /** @var string */ protected $fromName; /** * AbstractMailService constructor. * * @param $from * @param $fromName */ public function __construct($from, $fromName) { $this->from = $from; $this->fromName = $fromName; } } Notification/SMSAPIServiceInterface.php 0000666 00000005760 15165343622 0014064 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Domain\Services\Notification; /** * Interface SMSAPIServiceInterface * * @package AmeliaBooking\Domain\Services\Notification */ interface SMSAPIServiceInterface { /** * @param $route * @param $authorize * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function sendRequest($route, $authorize, $data = null); /** * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function signUp($data); /** * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function signIn($data); /** * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function getUserInfo(); /** * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function forgotPassword($data); /** * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function resetPassword($data); /** * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function changePassword($data); /** * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function getCountryPriceList($data); /** * @param $data * * @return mixed * * @throws \AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException * @throws \AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function testNotification($data); /** * @param $to * @param $body * @param $callbackUrl * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function send($to, $body, $callbackUrl); /** * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function refreshSMSHistory($data); /** * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function paymentCheckout($data); /** * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function paymentComplete($data); /** * @param $data * * @return mixed * * @throws \Interop\Container\Exception\ContainerException */ public function getPaymentHistory($data); } DateTime/DateTimeService.php 0000666 00000015247 15165343622 0012012 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Domain\Services\DateTime; /** * Class DateTimeService * * @package AmeliaBooking\Domain\Services\DateTime */ class DateTimeService { /** @var \DateTimeZone */ private static $timeZone; /** * @param array $settings */ public static function setTimeZone($settings) { if (!self::$timeZone) { if ($settings['timeZoneString']) { self::$timeZone = new \DateTimeZone($settings['timeZoneString']); } elseif ($settings['gmtOffset']) { $hours = (int)$settings['gmtOffset']; $minutes = ($settings['gmtOffset'] - floor($settings['gmtOffset'])) * 60; self::$timeZone = new \DateTimeZone(sprintf('%+03d:%02d', $hours, $minutes)); } else { self::$timeZone = new \DateTimeZone('UTC'); } } } /** * @return \DateTimeZone */ public static function getTimeZone() { return self::$timeZone; } /** * Return now date and time object by timezone settings * * @return \DateTime */ public static function getNowDateTimeObject() { return new \DateTime('now', self::getTimeZone()); } /** * Return now date and time string by timezone settings * * @return string */ public static function getNowDateTime() { return self::getNowDateTimeObject()->format('Y-m-d H:i:s'); } /** * @param String $dateTimeString * * @return \DateTime */ public static function getCustomDateTimeObject($dateTimeString) { return new \DateTime($dateTimeString ? $dateTimeString : 'now', self::getTimeZone()); } /** * Return custom date and time string by timezone settings * * @param String $dateTimeString * * @return string */ public static function getCustomDateTime($dateTimeString) { return self::getCustomDateTimeObject($dateTimeString)->format('Y-m-d H:i:s'); } /** * @param String $dateTimeString * @param int $clientUtcOffset * * @return \DateTime */ public static function getClientUtcCustomDateTimeObject($dateTimeString, $clientUtcOffset) { $clientDateTime = new \DateTime($dateTimeString, new \DateTimeZone('UTC')); if ($clientUtcOffset > 0) { $clientDateTime->modify("+{$clientUtcOffset} minutes"); } elseif ($clientUtcOffset < 0) { $clientDateTime->modify("{$clientUtcOffset} minutes"); } return $clientDateTime; } /** * Return custom date and time string by utc offset * * @param String $dateTimeString * @param int $clientUtcOffset * * @return string */ public static function getClientUtcCustomDateTime($dateTimeString, $clientUtcOffset) { return self::getClientUtcCustomDateTimeObject($dateTimeString, $clientUtcOffset)->format('Y-m-d H:i:s'); } /** * Return now date and time object in UTC * * @return \DateTime */ public static function getNowDateTimeObjectInUtc() { return self::getNowDateTimeObject()->setTimezone(new \DateTimeZone('UTC')); } /** * Return now date and time string in UTC * * @return string */ public static function getNowDateTimeInUtc() { return self::getNowDateTimeObjectInUtc()->format('Y-m-d H:i:s'); } /** * Return custom date and time object in UTC * * @param $dateTimeString * * @return \DateTime */ public static function getCustomDateTimeObjectInUtc($dateTimeString) { return self::getCustomDateTimeObject($dateTimeString)->setTimezone(new \DateTimeZone('UTC')); } /** * Return custom date and time object in UTC * * @param $dateTimeString * @param $timezone * * @return \DateTime */ public static function getCustomDateTimeObjectInTimeZone($dateTimeString, $timezone) { return self::getCustomDateTimeObject($dateTimeString)->setTimezone(new \DateTimeZone($timezone)); } /** * Return custom date and time object in UTC * * @param $dateTimeString * @param $timezone * * @return \DateTime */ public static function getDateTimeObjectInTimeZone($dateTimeString, $timezone) { return (new \DateTime($dateTimeString, new \DateTimeZone($timezone))); } /** * Return custom date and time string in UTC * * @param $dateTimeString * * @return string */ public static function getCustomDateTimeInUtc($dateTimeString) { return self::getCustomDateTimeObjectInUtc($dateTimeString)->format('Y-m-d H:i:s'); } /** * Return custom date and time object from UTC * * @param $dateTimeString * * @return \DateTime */ public static function getCustomDateTimeObjectFromUtc($dateTimeString) { return (new \DateTime($dateTimeString, new \DateTimeZone('UTC')))->setTimezone(self::getTimeZone()); } /** * Return custom date and time string from UTC * * @param $dateTimeString * * @return string */ public static function getCustomDateTimeFromUtc($dateTimeString) { return self::getCustomDateTimeObjectFromUtc($dateTimeString)->format('Y-m-d H:i:s'); } /** * Return custom date and time RFC3339 from UTC * * @param string $dateTimeString * * @return string */ public static function getCustomDateTimeRFC3339($dateTimeString) { return self::getCustomDateTimeObjectInUtc($dateTimeString)->format(DATE_RFC3339); } /** * Return now date string by timezone settings * * @return string */ public static function getNowDate() { return self::getNowDateTimeObject()->format('Y-m-d'); } /** * Return now time string by timezone settings * * @return string */ public static function getNowTime() { return self::getNowDateTimeObject()->format('H:i:s'); } /** * Return current Unix timestamp * * @return false|int */ public static function getNowTimestamp() { return strtotime(self::getNowTime()); } /** * Return Day Index for passed date string in 'YYYY-MM-DD' format. * Monday index is 1, Sunday index is 7. * * @param $dateString * * @return int */ public static function getDayIndex($dateString) { return self::getCustomDateTimeObject($dateString)->format('N'); } } Booking/AppointmentDomainService.php 0000666 00000015343 15165343622 0013635 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Booking; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; /** * Class AppointmentDomainService * * @package AmeliaBooking\Domain\Services\Booking */ class AppointmentDomainService { /** * Returns an array with bookings statuses count for passed appointment * * @param Appointment $appointment * * @return array * @throws InvalidArgumentException */ public function getBookingsStatusesCount($appointment) { $approvedBookings = 0; $pendingBookings = 0; $canceledBookings = 0; $rejectedBookings = 0; $noShowBookings = 0; foreach ((array)$appointment->getBookings()->keys() as $customerBookingKey) { /** @var CustomerBooking $booking */ $booking = $appointment->getBookings()->getItem($customerBookingKey); switch ($booking->getStatus()->getValue()) { case BookingStatus::PENDING: $pendingBookings += $booking->getPersons()->getValue(); break; case BookingStatus::CANCELED: $canceledBookings += $booking->getPersons()->getValue(); break; case BookingStatus::REJECTED: $rejectedBookings += $booking->getPersons()->getValue(); break; case BookingStatus::NO_SHOW: $noShowBookings += $booking->getPersons()->getValue(); break; default: $approvedBookings += $booking->getPersons()->getValue(); break; } } return [ 'approvedBookings' => $approvedBookings, 'pendingBookings' => $pendingBookings, 'canceledBookings' => $canceledBookings, 'rejectedBookings' => $rejectedBookings, 'noShowBookings' => $noShowBookings ]; } /** * @param Service $service * @param array $bookingsCount * * @return string */ public function getAppointmentStatusWhenEditAppointment($service, $bookingsCount) { $totalBookings = array_sum($bookingsCount); if ($bookingsCount['canceledBookings'] === $totalBookings) { return BookingStatus::CANCELED; } if ($bookingsCount['noShowBookings'] === $totalBookings) { return BookingStatus::NO_SHOW; } if ($bookingsCount['rejectedBookings'] === $totalBookings) { return BookingStatus::REJECTED; } if ($bookingsCount['approvedBookings'] === 0 && $bookingsCount['pendingBookings'] === 0) { return BookingStatus::CANCELED; } return $bookingsCount['approvedBookings'] >= $service->getMinCapacity()->getValue() ? BookingStatus::APPROVED : BookingStatus::PENDING; } /** * When booking status is changed, find out appointment status. * * If there is no any more 'approved' and 'pending' bookings, set appointment status to 'canceled' or 'rejected'. * * If appointment status is 'approved' or 'pending' and minimum capacity condition is not satisfied, * set appointment status to 'pending'. * * @param Service $service * @param array $bookingsCount * @param string $requestedStatus * * @return string */ public function getAppointmentStatusWhenChangingBookingStatus($service, $bookingsCount, $requestedStatus) { if ($bookingsCount['approvedBookings'] === 0 && $bookingsCount['pendingBookings'] === 0) { return $requestedStatus; } return $bookingsCount['approvedBookings'] >= $service->getMinCapacity()->getValue() ? BookingStatus::APPROVED : BookingStatus::PENDING; } /** * sort and merge appointments by date-time * * @param Collection $appointments * * @return Collection * @throws InvalidArgumentException */ public function getSortedAndMergedAppointments($appointments) { $timeStampsData = []; /** @var Appointment $appointment */ foreach ($appointments->getItems() as $index => $appointment) { $timeStampStart = $appointment->getBookingStart()->getValue()->getTimestamp(); $timeStampEnd = $appointment->getBookingEnd()->getValue()->getTimestamp(); if (!isset($timeStampsData[$timeStampStart])) { $timeStampsData[$timeStampStart] = [$timeStampEnd, $index]; } else { /** @var Appointment $passedAppointment */ $passedAppointment = $appointments->getItem($timeStampsData[$timeStampStart][1]); if ($appointment->getBookingEnd()->getValue() > $passedAppointment->getBookingEnd()->getValue()) { $timeStampsData[$timeStampStart] = [$timeStampEnd, $index]; } } } ksort($timeStampsData); $mergedTimeStampsData = []; $previousInterval = null; foreach ($timeStampsData as $start => $currentInterval) { if ($previousInterval !== null && $start <= $previousInterval[1]) { if ($currentInterval[0] > $previousInterval[1]) { $mergedTimeStampsData[$previousInterval[0]][0] = $currentInterval[0]; } } else { $mergedTimeStampsData[$start] = $currentInterval; $previousInterval = [ $start, $currentInterval[0], $currentInterval[1] ]; } } /** @var Collection $sortedAndMergedAppointments */ $sortedAndMergedAppointments = new Collection(); foreach ($mergedTimeStampsData as $start => $interval) { /** @var Appointment $appointment */ $appointment = $appointments->getItem($interval[1]); $appointment->setBookingStart( new DateTimeValue(DateTimeService::getNowDateTimeObject()->setTimestamp($start)) ); $appointment->setBookingEnd( new DateTimeValue(DateTimeService::getNowDateTimeObject()->setTimestamp($interval[0])) ); $sortedAndMergedAppointments->addItem($appointment); } return $sortedAndMergedAppointments; } } Booking/EventDomainService.php 0000666 00000050717 15165343622 0012424 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Booking; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Event\EventPeriod; use AmeliaBooking\Domain\Entity\Booking\Event\EventTicket; use AmeliaBooking\Domain\Entity\Gallery\GalleryImage; use AmeliaBooking\Domain\Factory\Booking\Event\EventTicketFactory; use AmeliaBooking\Domain\Factory\Gallery\GalleryImageFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue; use AmeliaBooking\Domain\ValueObjects\Json; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\Number\Integer\IntegerValue; use AmeliaBooking\Domain\ValueObjects\Recurring; use AmeliaBooking\Domain\ValueObjects\String\Cycle; /** * Class EventDomainService * * @package AmeliaBooking\Domain\Services\Booking */ class EventDomainService { /** * @param Recurring $recurring * @param Collection $eventPeriods * * @return Collection * * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException */ public function getRecurringEventsPeriods($recurring, $eventPeriods) { $recurringPeriods = new Collection(); if (!($recurring && $recurring->getCycle() && $recurring->getUntil())) { return $recurringPeriods; } $dateNew = null; $modifyCycle = 'days'; $modifyBaseValue = $recurring->getCycleInterval()->getValue(); switch ($recurring->getCycle()->getValue()) { case (Cycle::DAILY): $modifyCycle = 'days'; break; case (Cycle::WEEKLY): $modifyCycle = 'days'; $modifyBaseValue = 7*$modifyBaseValue; break; case (Cycle::MONTHLY): if ($recurring->getMonthlyRepeat() === 'on') { $repeatPeriod = $recurring->getMonthlyOnRepeat() . ' ' . $recurring->getMonthlyOnDay(); } else { $dateNew = $recurring->getMonthDate(); } $modifyCycle = 'months'; break; case (Cycle::YEARLY): $modifyCycle = 'years'; break; } $hasMoreRecurringPeriods = true; $recurringOrder = 1; while ($hasMoreRecurringPeriods) { $periods = new Collection(); $modifyValue = $recurringOrder * $modifyBaseValue; $periodStartDate0 = DateTimeService::getCustomDateTimeObject($eventPeriods->getItem(0)->getPeriodStart()->getValue()->format('Y-m-d H:i:s')); $periodEndDate0 = DateTimeService::getCustomDateTimeObject($eventPeriods->getItem(0)->getPeriodEnd()->getValue()->format('Y-m-d H:i:s')); if (isset($repeatPeriod)) { $periodStart0 = $this->getNextPeriodStartDate($periodStartDate0, $modifyValue, $repeatPeriod); $dayDifference = $periodStartDate0->diff($periodStart0); } else if ($dateNew) { $periodStartNew = DateTimeService::getCustomDateTimeObject($dateNew->getValue()->format('Y-m-d H:i:s')); $dayDifference = $periodStartDate0->diff($periodStartNew); } for ($i = 0; $i < count($eventPeriods->getItems()); $i++) { $periodStartDate = DateTimeService::getCustomDateTimeObject($eventPeriods->getItem($i)->getPeriodStart()->getValue()->format('Y-m-d H:i:s')); $periodEndDate = DateTimeService::getCustomDateTimeObject($eventPeriods->getItem($i)->getPeriodEnd()->getValue()->format('Y-m-d H:i:s')); if (isset($repeatPeriod)) { if ($i === 0) { $periodStart = $periodStart0; $periodEnd = $periodEndDate0->add($dayDifference); } else { $periodStart = $periodStartDate->add($dayDifference); $periodEnd = $periodEndDate->add($dayDifference); } } else { $periodStart = $periodStartDate->modify("+{$modifyValue} {$modifyCycle}"); $periodEnd = $periodEndDate->modify("+{$modifyValue} {$modifyCycle}"); if ($dateNew) { $periodStart = $periodStart->add($dayDifference); $periodEnd = $periodEnd->add($dayDifference); } } $newEventPeriod = new EventPeriod(); $newEventPeriod->setPeriodStart(new DateTimeValue($periodStart)); $newEventPeriod->setPeriodEnd(new DateTimeValue($periodEnd)); $periods->addItem($newEventPeriod); if ($periodStart > $recurring->getUntil()->getValue()) { $hasMoreRecurringPeriods = false; } } if ($hasMoreRecurringPeriods) { $recurringPeriods->addItem($periods); $recurringOrder++; } } return $recurringPeriods; } /** * @param Collection $eventPeriods * @param bool $setId * * @return Collection * * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException */ public function getClonedEventPeriods($eventPeriods, $setId = false) { $clonedPeriods = new Collection(); /** @var EventPeriod $eventPeriod **/ foreach ($eventPeriods->getItems() as $eventPeriod) { $periodStart = DateTimeService::getCustomDateTimeObject( $eventPeriod->getPeriodStart()->getValue()->format('Y-m-d H:i:s') ); $periodEnd = DateTimeService::getCustomDateTimeObject( $eventPeriod->getPeriodEnd()->getValue()->format('Y-m-d H:i:s') ); $newEventPeriod = new EventPeriod(); $newEventPeriod->setPeriodStart(new DateTimeValue($periodStart)); $newEventPeriod->setPeriodEnd(new DateTimeValue($periodEnd)); if ($eventPeriod->getZoomMeeting()) { $newEventPeriod->setZoomMeeting($eventPeriod->getZoomMeeting()); } if ($setId) { $newEventPeriod->setId(new Id($eventPeriod->getId()->getValue())); } $clonedPeriods->addItem($newEventPeriod); } return $clonedPeriods; } /** * @param Collection $eventTickets * * @return Collection * * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException */ public function getClonedEventTickets($eventTickets) { $clonedTickets = new Collection(); /** @var EventTicket $eventTicket **/ foreach ($eventTickets->getItems() as $eventTicket) { $newEventTicket = EventTicketFactory::create($eventTicket->toArray()); $clonedTickets->addItem($newEventTicket); } return $clonedTickets; } /** * @param Event $followingEvent * @param Event $originEvent * @param Collection $clonedOriginEventPeriods * * @return void * * @throws \Slim\Exception\ContainerValueNotFoundException * @throws \Interop\Container\Exception\ContainerException * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException */ public function buildFollowingEvent($followingEvent, $originEvent, $clonedOriginEventPeriods) { $followingEvent->setName($originEvent->getName()); $followingEvent->setPrice($originEvent->getPrice()); $followingEvent->setMaxCapacity($originEvent->getMaxCapacity()); $followingEvent->setTags($originEvent->getTags()); $followingEvent->setProviders($originEvent->getProviders()); $followingEvent->setBringingAnyone($originEvent->getBringingAnyone()); $followingEvent->setBookMultipleTimes($originEvent->getBookMultipleTimes()); $followingEvent->setOrganizerId($originEvent->getOrganizerId()); $followingEvent->setCustomPricing($originEvent->getCustomPricing()); $followingEvent->setCloseAfterMin($originEvent->getCloseAfterMin()); $followingEvent->setMaxCustomCapacity($originEvent->getMaxCustomCapacity()); $followingEvent->setCloseAfterMinBookings($originEvent->getCloseAfterMinBookings()); $followingEvent->setAggregatedPrice($originEvent->getAggregatedPrice()); $followingEvent->setMaxExtraPeople($originEvent->getMaxExtraPeople()); $followingEvent->setNotifyParticipants($originEvent->isNotifyParticipants()); if ($originEvent->getCustomPricing() && $originEvent->getCustomPricing()->getValue() && $followingEvent->getBookings()->length() === 0) { $newEventTickets = new Collection(); /** @var EventTicket $eventTicket */ foreach ($originEvent->getCustomTickets()->getItems() as $ticketIndex => $eventTicket) { if (!empty($followingEvent->getCustomTickets()->toArray()[$ticketIndex])) { $editedTicket = EventTicketFactory::create($followingEvent->getCustomTickets()->toArray()[$ticketIndex]); $editedTicket->setName($eventTicket->getName()); $editedTicket->setEnabled($eventTicket->getEnabled()); $editedTicket->setPrice($eventTicket->getPrice()); if ($eventTicket->getTranslations()) { $editedTicket->setTranslations($eventTicket->getTranslations()); } $editedTicket->setSpots($eventTicket->getSpots()); $newEventTickets->addItem($editedTicket); } else { $newTicket = EventTicketFactory::create($eventTicket->toArray()); $newTicket->setId(new Id(0)); $newTicket->setEventId($followingEvent->getId() ? new Id($followingEvent->getId()->getValue()) : null); $newTicket->setSold(new IntegerValue(0)); $newTicket->setDateRanges(new Json('[]')); $newEventTickets->addItem($newTicket); } } $followingEvent->setCustomTickets($newEventTickets); } if ($originEvent->getTranslations()) { $followingEvent->setTranslations($originEvent->getTranslations()); } if ($originEvent->getDeposit()) { $followingEvent->setDeposit($originEvent->getDeposit()); } if ($originEvent->getDepositPayment()) { $followingEvent->setDepositPayment($originEvent->getDepositPayment()); } if ($originEvent->getDepositPerPerson()) { $followingEvent->setDepositPerPerson($originEvent->getDepositPerPerson()); } $followingEventGallery = new Collection(); /** @var GalleryImage $image **/ foreach ($originEvent->getGallery()->getItems() as $image) { $followingEventGallery->addItem( GalleryImageFactory::create( [ 'id' => null, 'entityId' => $followingEvent->getId() ? $followingEvent->getId()->getValue() : null, 'entityType' => $image->getEntityType()->getValue(), 'pictureFullPath' => $image->getPicture()->getFullPath(), 'pictureThumbPath' => $image->getPicture()->getThumbPath(), 'position' => $image->getPosition()->getValue(), ] ) ); } $followingEvent->setGallery($followingEventGallery); if ($originEvent->getSettings()) { $followingEvent->setSettings($originEvent->getSettings()); } $followingEvent->setBookingOpens($originEvent->getBookingOpens()); $followingEvent->setBookingCloses($originEvent->getBookingCloses()); $followingEvent->setBookingOpensRec($originEvent->getBookingOpensRec()); $followingEvent->setBookingClosesRec($originEvent->getBookingClosesRec()); if ($originEvent->getLocationId()) { $followingEvent->setLocationId($originEvent->getLocationId()); } if ($originEvent->getCustomLocation()) { $followingEvent->setCustomLocation($originEvent->getCustomLocation()); } if ($originEvent->getTags()) { $followingEvent->setTags($originEvent->getTags()); } if ($originEvent->getDescription()) { $followingEvent->setDescription($originEvent->getDescription()); } if ($originEvent->getColor()) { $followingEvent->setColor($originEvent->getColor()); } if ($originEvent->getShow()) { $followingEvent->setShow($originEvent->getShow()); } if ($originEvent->getZoomUserId()) { $followingEvent->setZoomUserId($originEvent->getZoomUserId()); } $modifyCycle = 'days'; $modifyBaseValue = $originEvent->getRecurring()->getCycleInterval()->getValue(); $dateNew = null; switch ($originEvent->getRecurring()->getCycle()->getValue()) { case (Cycle::DAILY): $modifyCycle = 'days'; break; case (Cycle::WEEKLY): $modifyCycle = 'days'; $modifyBaseValue = 7*$modifyBaseValue; break; case (Cycle::MONTHLY): if ($followingEvent->getRecurring()->getMonthlyRepeat() === 'on') { $repeatPeriod = $followingEvent->getRecurring()->getMonthlyOnRepeat() . ' ' . $followingEvent->getRecurring()->getMonthlyOnDay(); } else { $dateNew = $followingEvent->getRecurring()->getMonthDate(); } $modifyCycle = 'months'; break; case (Cycle::YEARLY): $modifyCycle = 'years'; break; } $modifyValue = $modifyBaseValue * ($followingEvent->getRecurring()->getOrder()->getValue() - 1); $periodStartDate0 = DateTimeService::getCustomDateTimeObject($clonedOriginEventPeriods->getItem(0)->getPeriodStart()->getValue()->format('Y-m-d H:i:s')); $periodEndDate0 = DateTimeService::getCustomDateTimeObject($clonedOriginEventPeriods->getItem(0)->getPeriodEnd()->getValue()->format('Y-m-d H:i:s')); if (isset($repeatPeriod)) { $periodStart0 = $this->getNextPeriodStartDate($periodStartDate0, $modifyValue, $repeatPeriod); $dayDifference = $periodStartDate0->diff($periodStart0); } else if ($dateNew) { $thisPeriodStart = DateTimeService::getCustomDateTimeObject($originEvent->getPeriods()->getItem(0)->getPeriodStart()->getValue()->format('Y-m-d H:i:s')); $periodStartNew = DateTimeService::getCustomDateTimeObject($dateNew->getValue()->format('Y-m-d H:i:s')); $dayDifference = $thisPeriodStart->diff($periodStartNew); } /** @var EventPeriod $followingEventPeriod */ foreach ($followingEvent->getPeriods()->getItems() as $key => $followingEventPeriod) { if ($clonedOriginEventPeriods->keyExists($key)) { /** @var EventPeriod $clonedOriginEventPeriod */ $clonedOriginEventPeriod = $clonedOriginEventPeriods->getItem($key); $periodStartDate = DateTimeService::getCustomDateTimeObject($clonedOriginEventPeriod->getPeriodStart()->getValue()->format('Y-m-d H:i:s')); $periodEndDate = DateTimeService::getCustomDateTimeObject($clonedOriginEventPeriod->getPeriodEnd()->getValue()->format('Y-m-d H:i:s')); if (isset($repeatPeriod)) { if ($key === 0) { $periodStart = $periodStart0; $periodEnd = $periodEndDate0->add($dayDifference); } else { $periodStart = $periodStartDate->add($dayDifference); $periodEnd = $periodEndDate->add($dayDifference); } } else { $periodStart = $periodStartDate->modify("+{$modifyValue} {$modifyCycle}"); $periodEnd = $periodEndDate->modify("+{$modifyValue} {$modifyCycle}"); $toEndTime = $periodStart->diff($periodEnd); if ($dateNew) { $periodStart = DateTimeService::getCustomDateTimeObject($periodStart->format('Y-m-'. $periodStartNew->format('d') .' H:i:s')); $periodStartClone = clone $periodStart; $periodEnd = $periodStartClone->add($toEndTime); } } $followingEventPeriod->setPeriodStart(new DateTimeValue($periodStart)); $followingEventPeriod->setPeriodEnd(new DateTimeValue($periodEnd)); } else { $followingEvent->getPeriods()->deleteItem($key); } } /** @var EventPeriod $originEventPeriod */ foreach ($originEvent->getPeriods()->getItems() as $key => $originEventPeriod) { if (!$followingEvent->getPeriods()->keyExists($key)) { /** @var EventPeriod $followingEventPeriod */ $newFollowingEventPeriod = new EventPeriod(); $newPeriodStart = DateTimeService::getCustomDateTimeObject( $originEventPeriod->getPeriodStart()->getValue()->format('Y-m-d H:i:s') ); $newPeriodEnd = DateTimeService::getCustomDateTimeObject( $originEventPeriod->getPeriodEnd()->getValue()->format('Y-m-d H:i:s') ); if (isset($repeatPeriod)) { $periodStart = $newPeriodStart->add($dayDifference); $periodEnd = $newPeriodEnd->add($dayDifference); } else { $periodStart = $newPeriodStart->modify("+{$modifyValue} {$modifyCycle}"); $periodEnd = $newPeriodEnd->modify("+{$modifyValue} {$modifyCycle}"); $toEndTime = $periodStart->diff($periodEnd); if ($dateNew && $dayDifference && $dayDifference->format('%a') !== '0') { $periodStart = $periodStart->add($dayDifference); $periodStartClone = clone $periodStart; $periodEnd = $periodStartClone->add($toEndTime); } } $newFollowingEventPeriod->setPeriodStart(new DateTimeValue($periodStart)); $newFollowingEventPeriod->setPeriodEnd(new DateTimeValue($periodEnd)); $newFollowingEventPeriod->setEventId(new Id($followingEvent->getId()->getValue())); $followingEvent->getPeriods()->addItem($newFollowingEventPeriod); } } } /** * @param Collection $eventPeriods * @param bool $setId * * @return Collection * * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException */ public function getShortcodeForEventList($container, $events) { /** @var SettingsService $settingsService */ $settingsService = $container->get('domain.settings.service'); $dateFormat = $settingsService->getSetting('wordpress', 'dateFormat'); for ($i=0; $i < count($events); $i++) { $dateString = explode(" ", $events[$i]['periods'][0]['periodStart'])[0]; $newDate = date_i18n($dateFormat, strtotime($dateString)); $events[$i]['formattedPeriodStart'] = $newDate; } return $events; } /** * @param \DateTime $periodStartDate0 * @param int $modifyValue * @param string $repeatPeriod * * @return \DateTime * * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException * @throws \Exception */ public function getNextPeriodStartDate($periodStartDate0, $modifyValue, $repeatPeriod) { $month = (int)$periodStartDate0->format('m') + $modifyValue; $year = (int)$periodStartDate0->format('Y'); $year += floor($month / 12); $month -= 12 * floor($month / 12); $time = (int)$periodStartDate0->format('H')*60 + (int)$periodStartDate0->format('i'); $periodStart0 = DateTimeService::getCustomDateTimeObject($repeatPeriod . " of $year-$month"); return $periodStart0->add(new \DateInterval('PT' . $time . 'M')); } } Interval/IntervalService.php 0000666 00000011371 15165343622 0012164 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Interval; /** * Class IntervalService * * @package AmeliaBooking\Domain\Services\Interval */ class IntervalService { /** * @param string $time * * @return int */ public function getSeconds($time) { $timeParts = explode(':', $time); return $timeParts[0] * 60 * 60 + $timeParts[1] * 60 + $timeParts[2]; } /** * @param string $endTime * * @return string */ public function getEndTimeString($endTime) { return $endTime === '00:00:00' ? '24:00:00' : $endTime; } /** * get available appointment intervals. * * @param array $availableIntervals * @param array $unavailableIntervals * * @return array */ public function getAvailableIntervals(&$availableIntervals, $unavailableIntervals) { $parsedAvailablePeriod = []; ksort($availableIntervals); ksort($unavailableIntervals); foreach ($availableIntervals as $available) { $parsedAvailablePeriod[] = $available; foreach ($unavailableIntervals as $unavailable) { if ($parsedAvailablePeriod) { $lastAvailablePeriod = $parsedAvailablePeriod[sizeof($parsedAvailablePeriod) - 1]; if ($unavailable[0] >= $lastAvailablePeriod[0] && $unavailable[1] <= $lastAvailablePeriod[1]) { // unavailable interval is inside available interval $fixedPeriod = array_pop($parsedAvailablePeriod); if ($fixedPeriod[0] !== $unavailable[0]) { $parsedAvailablePeriod[] = [$fixedPeriod[0], $unavailable[0], $fixedPeriod[2]]; } if ($unavailable[1] !== $fixedPeriod[1]) { $parsedAvailablePeriod[] = [$unavailable[1], $fixedPeriod[1], $fixedPeriod[2]]; } } elseif ($unavailable[0] <= $lastAvailablePeriod[0] && $unavailable[1] >= $lastAvailablePeriod[1]) { // available interval is inside unavailable interval array_pop($parsedAvailablePeriod); } elseif ($unavailable[0] <= $lastAvailablePeriod[0] && $unavailable[1] >= $lastAvailablePeriod[0] && $unavailable[1] <= $lastAvailablePeriod[1]) { // unavailable interval intersect start of available interval $fixedPeriod = array_pop($parsedAvailablePeriod); if ($unavailable[1] !== $fixedPeriod[1]) { $parsedAvailablePeriod[] = [$unavailable[1], $fixedPeriod[1], $fixedPeriod[2]]; } } elseif ($unavailable[0] >= $lastAvailablePeriod[0] && $unavailable[0] <= $lastAvailablePeriod[1] && $unavailable[1] >= $lastAvailablePeriod[1]) { // unavailable interval intersect end of available interval $fixedPeriod = array_pop($parsedAvailablePeriod); if ($fixedPeriod[0] !== $unavailable[0]) { $parsedAvailablePeriod[] = [$fixedPeriod[0], $unavailable[0], $fixedPeriod[2]]; } } } } } return $parsedAvailablePeriod; } /** * @param array $data * @param int $startTime * @param int $endTime * * @return array */ public function getFreeIntervals($data, $startTime, $endTime) { $result = []; ksort($data); $firstIntervalTime = true; $lastStartTime = $startTime; foreach ((array)$data as &$interval) { // Appointment is out of working hours if ($interval[0] >= $endTime || $interval[1] <= $startTime) { continue; } // Beginning or End of the Appointment is out of working hours if ($interval[0] < $startTime && $interval[1] <= $endTime) { $interval[0] = $startTime; } elseif ($interval[0] >= $startTime && $interval[1] > $endTime) { $interval[1] = $endTime; } if ($lastStartTime !== $interval[0] && ($lastStartTime !== $startTime || ($firstIntervalTime && $lastStartTime !== $interval[0]))) { $firstIntervalTime = false; $result[$lastStartTime] = [ $lastStartTime, $interval[0] ]; } $lastStartTime = $interval[1]; } if ($lastStartTime !== $endTime) { $result[$lastStartTime] = [ $lastStartTime, $endTime ]; } return $result; } } Location/CurrentLocationInterface.php 0000666 00000000654 15165343622 0014001 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Domain\Services\Location; /** * Interface CurrentLocationInterface * * @package AmeliaBooking\Domain\Services\Location */ interface CurrentLocationInterface { /** * @return string * @SuppressWarnings(PHPMD) */ public function getCurrentLocationCountryIso(); } Location/LocationService.php 0000666 00000001465 15165343622 0012137 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\Location; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\ValueObjects\String\Status; use Slim\Exception\ContainerValueNotFoundException; /** * Class LocationService * * @package AmeliaBooking\Domain\Services\Location */ class LocationService { /** * @param Collection $locations * * @return boolean * * @throws ContainerValueNotFoundException */ public function hasVisibleLocations($locations) { /** @var Location $location */ foreach ($locations->getItems() as $location) { if ($location->getStatus()->getValue() === Status::VISIBLE) { return true; } } return false; } } Reservation/ReservationServiceInterface.php 0000666 00000021065 15165343622 0015240 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Domain\Services\Reservation; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Domain\Common\Exceptions\BookingCancellationException; use AmeliaBooking\Domain\Common\Exceptions\BookingsLimitReachedException; use AmeliaBooking\Domain\Common\Exceptions\BookingUnavailableException; use AmeliaBooking\Domain\Common\Exceptions\CouponExpiredException; use AmeliaBooking\Domain\Common\Exceptions\CouponInvalidException; use AmeliaBooking\Domain\Common\Exceptions\CouponUnknownException; use AmeliaBooking\Domain\Common\Exceptions\CustomerBookedException; use AmeliaBooking\Domain\Common\Exceptions\EventBookingUnavailableException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Common\Exceptions\PackageBookingUnavailableException; use AmeliaBooking\Domain\Entity\Bookable\AbstractBookable; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Reservation; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\String\BookingType; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use DateTime; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Interface ReservationServiceInterface * * @package AmeliaBooking\Domain\Services\Reservation */ interface ReservationServiceInterface { /** * @param CustomerBooking $booking * @param string $requestedStatus * * @return array * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws NotFoundException * @throws BookingCancellationException */ public function updateStatus($booking, $requestedStatus); /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param int $bookingId * @param int $packageCustomerId * @param array $paymentData * @param float $amount * @param DateTime $dateTime * @param string $entityType * * @return Payment * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException */ public function addPayment($bookingId, $packageCustomerId, $paymentData, $amount, $dateTime, $entityType); /** * @param array $data * @param Reservation $reservation * @param bool $save * * @return CommandResult * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function processRequest($data, $reservation, $save); /** * @param CommandResult $result * * @return void * @throws ContainerException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws NotFoundException */ public function runPostBookingActions($result); /** * @param array $appointmentData * @param Reservation $reservation * @param bool $save * * @return void * * @throws BookingUnavailableException * @throws BookingsLimitReachedException * @throws CustomerBookedException * @throws PackageBookingUnavailableException * @throws EventBookingUnavailableException * @throws CouponExpiredException * @throws CouponInvalidException * @throws CouponUnknownException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception * @throws ContainerException */ public function book($appointmentData, $reservation, $save); /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param CommandResult $result * @param array $appointmentData * @param Reservation $reservation * @param bool $save * * @return void * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception * @throws ContainerException */ public function processBooking($result, $appointmentData, $reservation, $save); /** * @param CommandResult $result * @param Reservation $reservation * @param BookingType $bookingType * * @throws ContainerException */ public function finalize($result, $reservation, $bookingType); /** * @param CustomerBooking $booking * @param AbstractBookable $bookable * * @return float * * @throws InvalidArgumentException */ public function getPaymentAmount($booking, $bookable); /** * @param Appointment|Event $reservation * @param CustomerBooking $booking * @param AbstractBookable $bookable * * @return array */ public function getBookingPeriods($reservation, $booking, $bookable); /** * @return string */ public function getType(); /** * @param array $data * * @return AbstractBookable * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException */ public function getBookableEntity($data); /** * @param Service|Event $bookable * * @return boolean */ public function isAggregatedPrice($bookable); /** * @param BooleanValueObject $bookableAggregatedPrice * @param BooleanValueObject $extraAggregatedPrice * * @return boolean */ public function isExtraAggregatedPrice($extraAggregatedPrice, $bookableAggregatedPrice); /** * @param Reservation $reservation * @param string $paymentGateway * @param array $requestData * * @return array * * @throws InvalidArgumentException */ public function getWooCommerceData($reservation, $paymentGateway, $requestData); /** * @param array $reservation * * @return array * * @throws InvalidArgumentException */ public function getWooCommerceDataFromArray($reservation, $index); /** * @param int $id * * @return Appointment|Event * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws InvalidArgumentException */ public function getReservationByBookingId($id); /** * @param int $bookingId * * @return CommandResult * @throws InvalidArgumentException * @throws Exception */ public function getBookingResultByBookingId($bookingId); /** * @param DateTime $bookingStart * @param int $minimumCancelTime * * @return boolean * * @throws ContainerValueNotFoundException * @throws ContainerException * @throws BookingCancellationException */ public function inspectMinimumCancellationTime($bookingStart, $minimumCancelTime); /** * @param Reservation $reservation * @param BookingType $bookingType * * @return array */ public function getResultData($reservation, $bookingType); /** * @param bool $couponValidation * @param bool $customFieldsValidation * @param bool $availabilityValidation * * @return Reservation */ public function getNew($couponValidation, $customFieldsValidation, $availabilityValidation); /** * @param Payment $payment * @param boolean $fromLink * * @return CommandResult * @throws InvalidArgumentException * @throws Exception * @throws ContainerException */ public function getReservationByPayment($payment, $fromLink = false); /** * @param string $type * @param string $orderStatus * @param string $statusTarget * @param bool $isUpdate * * @return string|null */ public function getWcStatus($type, $orderStatus, $statusTarget, $isUpdate); } User/ProviderService.php 0000666 00000057670 15165343622 0011340 0 ustar 00 <?php namespace AmeliaBooking\Domain\Services\User; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\Entity\Schedule\DayOff; use AmeliaBooking\Domain\Entity\Schedule\Period; use AmeliaBooking\Domain\Entity\Schedule\PeriodLocation; use AmeliaBooking\Domain\Entity\Schedule\SpecialDay; use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriod; use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriodLocation; use AmeliaBooking\Domain\Entity\Schedule\WeekDay; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Bookable\Service\ServiceFactory; use AmeliaBooking\Domain\Factory\Booking\Appointment\AppointmentFactory; use AmeliaBooking\Domain\Factory\Schedule\PeriodFactory; use AmeliaBooking\Domain\Factory\Schedule\WeekDayFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Interval\IntervalService; use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue; use AmeliaBooking\Domain\ValueObjects\Duration; use AmeliaBooking\Domain\ValueObjects\String\Status; use DateTime; use DateTimeZone; use Exception; use Slim\Exception\ContainerValueNotFoundException; /** * Class ProviderService * * @package AmeliaBooking\Domain\Services\User */ class ProviderService { /** @var IntervalService */ private $intervalService; /** * ProviderService constructor. * * @param IntervalService $intervalService */ public function __construct( $intervalService ) { $this->intervalService = $intervalService; } /** * @param WeekDay|SpecialDay $day * * @return void * @throws InvalidArgumentException */ private function makePeriodsAvailable($day) { $periodsInSeconds = []; /** @var Period $period */ foreach ($day->getPeriodList()->getItems() as $key => $period) { if ($period->getLocationId()) { $startInSeconds = $this->intervalService->getSeconds( $period->getStartTime()->getValue()->format('H:i:s') ); $periodsInSeconds[$startInSeconds] = $this->intervalService->getSeconds( $period->getEndTime()->getValue()->format('H:i:s') ); } } if (!$periodsInSeconds) { $day->getPeriodList()->addItem( PeriodFactory::create( [ 'startTime' => '00:00:00', 'endTime' => '24:00:00', 'periodServiceList' => [], 'periodLocationList' => [], ] ) ); return; } $periodsStartTimes = array_keys($periodsInSeconds); sort($periodsStartTimes); $sortedPeriodsInSeconds = []; foreach ($periodsStartTimes as $seconds) { $sortedPeriodsInSeconds[$seconds] = $periodsInSeconds[$seconds]; } $periodsInSeconds = $sortedPeriodsInSeconds; $extraPeriods = []; $i = 0; $periodsCount = sizeof($periodsInSeconds); $periodsStarts = array_keys($periodsInSeconds); foreach ($periodsInSeconds as $secondsStart => $secondsEnd) { if ($i === 0) { if ($secondsStart !== 0) { $extraPeriods[0] = $secondsStart; } if (!empty($periodsStarts[$i + 1]) && $periodsStarts[$i + 1] !== $secondsEnd) { $extraPeriods[$secondsEnd] = $periodsStarts[$i + 1]; } if ($periodsCount === 1 && $secondsEnd !== 86400) { $extraPeriods[$secondsEnd] = 86400; } } elseif ($i === $periodsCount - 1) { if ($secondsEnd !== 86400) { $extraPeriods[$secondsEnd] = 86400; } } else { if ($periodsStarts[$i + 1] !== $secondsEnd) { $extraPeriods[$secondsEnd] = $periodsStarts[$i + 1]; } } $i++; } foreach ($extraPeriods as $extraPeriodStart => $extraPeriodEnd) { $day->getPeriodList()->addItem( PeriodFactory::create( [ 'startTime' => sprintf('%02d', floor($extraPeriodStart / 3600)) . ':' . sprintf('%02d', floor(($extraPeriodStart / 60) % 60)) . ':00', 'endTime' => sprintf('%02d', floor($extraPeriodEnd / 3600)) . ':' . sprintf('%02d', floor(($extraPeriodEnd / 60) % 60)) . ':00', 'periodServiceList' => [], 'periodLocationList' => [], ] ) ); } /** @var Collection $sortedPeriods */ $sortedPeriods = new Collection(); $allPeriodsInSeconds = []; /** @var Period $period */ foreach ($day->getPeriodList()->getItems() as $key => $period) { $startInSeconds = $this->intervalService->getSeconds( $period->getStartTime()->getValue()->format('H:i:s') ); $allPeriodsInSeconds[$startInSeconds] = $key; } $allPeriodsInSecondsKeys = array_keys($allPeriodsInSeconds); sort($allPeriodsInSecondsKeys); foreach ($allPeriodsInSecondsKeys as $periodStart) { $sortedPeriods->addItem($day->getPeriodList()->getItem($allPeriodsInSeconds[$periodStart])); } $day->setPeriodList($sortedPeriods); } /** * @param Collection $providers * * @return void * @throws InvalidArgumentException */ public function setProvidersAlwaysAvailable($providers) { /** @var Provider $provider */ foreach ($providers->getItems() as $k => $provider) { $providerWeekDayIndexes = []; /** @var WeekDay $weekDay */ foreach ($provider->getWeekDayList()->getItems() as $weekDay) { $providerWeekDayIndexes[] = $weekDay->getDayIndex()->getValue(); } for ($i = 1; $i <= 7; $i++) { if (!in_array($i, $providerWeekDayIndexes)) { $provider->getWeekDayList()->addItem( WeekDayFactory::create( [ 'dayIndex' => $i, 'startTime' => '00:00:00', 'endTime' => '00:00:00', 'timeOutList' => new Collection(), 'periodList' => new Collection( [ 'startTime' => '00:00:00', 'endTime' => '24:00:00', 'periodServiceList' => [], ] ) ] ) ); } } /** @var WeekDay $weekDay */ foreach ($provider->getWeekDayList()->getItems() as $index => $weekDay) { $this->makePeriodsAvailable($weekDay); } /** @var SpecialDay $specialDay */ foreach ($provider->getSpecialDayList()->getItems() as $specialDay) { $this->makePeriodsAvailable($specialDay); } $provider->setDayOffList(new Collection()); /** @var Collection $sortedPeriods */ $sortedWeekDays = new Collection(); $allWeekDaysIndexes = []; /** @var WeekDay $weekDay */ foreach ($provider->getWeekDayList()->getItems() as $key => $weekDay) { $allWeekDaysIndexes[$weekDay->getDayIndex()->getValue()] = $key; } $allWeekDaysKeysKeys = array_keys($allWeekDaysIndexes); sort($allWeekDaysKeysKeys); foreach ($allWeekDaysKeysKeys as $weekDayIndex) { $sortedWeekDays->addItem($provider->getWeekDayList()->getItem($allWeekDaysIndexes[$weekDayIndex])); } $provider->setWeekDayList($sortedWeekDays); } } /** * * @param Period|SpecialDayPeriod $period * @param Location $providerLocation * @param Collection $locations * @param bool $hasVisibleLocations * * @return Collection * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException */ public function getProviderPeriodLocations($period, $providerLocation, $locations, $hasVisibleLocations) { /** @var Collection $availablePeriodLocations */ $availablePeriodLocations = new Collection(); if ($period->getPeriodLocationList()->length()) { /** @var PeriodLocation|SpecialDayPeriodLocation $periodLocation */ foreach ($period->getPeriodLocationList()->getItems() as $periodLocation) { if ($providerLocation && $periodLocation->getLocationId()->getValue() === $providerLocation->getId()->getValue() && ($hasVisibleLocations ? $providerLocation->getStatus()->getValue() === Status::VISIBLE : true) ) { $availablePeriodLocations->addItem($providerLocation, $providerLocation->getId()->getValue()); } } /** @var PeriodLocation|SpecialDayPeriodLocation $periodLocation */ foreach ($period->getPeriodLocationList()->getItems() as $periodLocation) { /** @var Location $availableLocation */ $availableLocation = $locations->keyExists($periodLocation->getLocationId()->getValue()) ? $locations->getItem($periodLocation->getLocationId()->getValue()) : null; if ($availableLocation && ( $providerLocation ? $periodLocation->getLocationId()->getValue() !== $providerLocation->getId()->getValue() : true ) && ($hasVisibleLocations ? $availableLocation->getStatus()->getValue() === Status::VISIBLE : true) ) { $availablePeriodLocations->addItem($availableLocation, $availableLocation->getId()->getValue()); } } } elseif ($period->getLocationId() && $period->getLocationId()->getValue()) { /** @var Location $availableLocation */ $availableLocation = $locations->keyExists($period->getLocationId()->getValue()) ? $locations->getItem($period->getLocationId()->getValue()) : null; if ($availableLocation && ($hasVisibleLocations ? $availableLocation->getStatus()->getValue() === Status::VISIBLE : true) ) { $availablePeriodLocations->addItem($availableLocation, $availableLocation->getId()->getValue()); } } elseif ($providerLocation && ($hasVisibleLocations ? $providerLocation->getStatus()->getValue() === Status::VISIBLE : true) ) { $availablePeriodLocations->addItem($providerLocation, $providerLocation->getId()->getValue()); } return $availablePeriodLocations; } /** * @param Provider $provider * @param Collection $services * @param bool $allowHiddenServices * * @return void * @throws InvalidArgumentException * @throws Exception */ public function setProviderServices($provider, $services, $allowHiddenServices) { /** @var Collection $providerServiceList */ $providerServiceList = new Collection(); /** @var Service $providerService */ foreach ($provider->getServiceList()->getItems() as $providerService) { if ($services->keyExists($providerService->getId()->getValue())) { /** @var Service $service */ $service = $services->getItem($providerService->getId()->getValue()); if ($allowHiddenServices ? true : $service->getStatus()->getValue() === Status::VISIBLE) { $providerServiceList->addItem( ServiceFactory::create( array_merge( $service->toArray(), [ 'price' => $providerService->getPrice()->getValue(), 'minCapacity' => $providerService->getMinCapacity()->getValue(), 'maxCapacity' => $providerService->getMaxCapacity()->getValue(), 'customPricing' => $providerService->getCustomPricing() ? $providerService->getCustomPricing()->getValue() : null, ] ) ), $service->getId()->getValue() ); } } } $provider->setServiceList($providerServiceList); } /** * Add appointments to provider's appointments list * * @param Collection $providers * @param Collection $appointments * @param bool $isGloballyBusySlot * * @throws InvalidArgumentException */ public function addAppointmentsToAppointmentList($providers, $appointments, $isGloballyBusySlot) { $appointmentsDateData = []; $appointmentsIdOrder = []; /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointmentId => $appointment) { $providerId = $appointment->getProviderId()->getValue(); $appointmentStart = $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s'); $appointmentEnd = $appointment->getBookingEnd()->getValue()->format('Y-m-d H:i:s'); if (!array_key_exists($providerId, $appointmentsDateData)) { $appointmentsDateData[$providerId] = [ ]; } $appointmentsIdOrder[] = $appointmentId; $lastIndex = sizeof($appointmentsIdOrder) - 1; if (!array_key_exists($appointmentStart, $appointmentsDateData[$providerId])) { $appointmentsDateData[$providerId][$appointmentStart] = [ 'id' => $appointmentId, 'end' => $appointmentEnd, 'index' => $lastIndex ]; } else if ($appointmentsDateData[$providerId][$appointmentStart]['end'] !== $appointmentEnd && DateTimeService::getCustomDateTimeObject($appointmentEnd) > DateTimeService::getCustomDateTimeObject($appointmentsDateData[$providerId][$appointmentStart]['end']) ) { $appointmentsIdOrder[$appointmentsDateData[$providerId][$appointmentStart]['index']] = $appointmentId; $appointmentsIdOrder[$lastIndex] = $appointmentsDateData[$providerId][$appointmentStart]['id']; } } $providerStarts = []; foreach ($appointmentsIdOrder as $index) { /** @var Appointment $appointment */ $appointment = $appointments->getItem($index); /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { if (!array_key_exists($provider->getId()->getValue(), $providerStarts)) { $providerStarts[$provider->getId()->getValue()] = []; } $appointmentStartString = $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s'); if ($appointment->getProviderId()->getValue() === $provider->getId()->getValue() && array_key_exists($appointmentStartString, $providerStarts[$provider->getId()->getValue()]) ) { /** @var Appointment $duplicatedAppointment */ foreach ($provider->getAppointmentList()->getItems() as $duplicatedAppointment) { if ($duplicatedAppointment->getId() && in_array( $duplicatedAppointment->getId()->getValue(), $providerStarts[$provider->getId()->getValue()][$appointmentStartString] ) ) { /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { $duplicatedAppointment->getBookings()->addItem($booking, $booking->getId()->getValue()); } } } continue; } if ($appointment->getProviderId()->getValue() === $provider->getId()->getValue()) { $providerStarts[$provider->getId()->getValue()][$appointmentStartString][] = $appointment->getId()->getValue(); $provider->getAppointmentList()->addItem($appointment); if (!$isGloballyBusySlot) { break; } } else if ($isGloballyBusySlot) { $providerStarts[$provider->getId()->getValue()][$appointmentStartString][] = $appointment->getId()->getValue(); /** @var Appointment $fakeAppointment */ $fakeAppointment = AppointmentFactory::create( array_merge( $appointment->toArray(), ['providerId' => $provider->getId()->getValue()] ) ); if (!$fakeAppointment->getService()->getTimeBefore()) { $fakeAppointment->getService()->setTimeBefore(new Duration(0)); } if (!$fakeAppointment->getService()->getTimeAfter()) { $fakeAppointment->getService()->setTimeAfter(new Duration(0)); } $provider->getAppointmentList()->addItem($fakeAppointment); } } } } /** * @param Provider $provider * @param array $globalDaysOff * @param DateTime $startDateTime * @param DateTime $endDateTime * * @return void * @throws InvalidArgumentException */ public function modifyProviderTimeZone($provider, $globalDaysOff, $startDateTime, $endDateTime) { /** @var Appointment $appointment */ foreach ($provider->getAppointmentList()->getItems() as $appointment) { $appointment->getBookingStart()->getValue()->setTimezone( new DateTimeZone($provider->getTimeZone()->getValue()) ); $appointment->getBookingEnd()->getValue()->setTimezone( new DateTimeZone($provider->getTimeZone()->getValue()) ); } /** @var SpecialDay $specialDay */ foreach ($provider->getSpecialDayList()->getItems() as $specialDay) { $specialDay->setStartDate( new DateTimeValue( DateTimeService::getDateTimeObjectInTimeZone( $specialDay->getStartDate()->getValue()->format('Y-m-d') . ' 00:00:00', $provider->getTimeZone()->getValue() ) ) ); $specialDay->setEndDate( new DateTimeValue( DateTimeService::getDateTimeObjectInTimeZone( $specialDay->getEndDate()->getValue()->format('Y-m-d') . ' 00:00:00', $provider->getTimeZone()->getValue() ) ) ); } /** @var DayOff $dayOff */ foreach ($provider->getDayOffList()->getItems() as $dayOff) { $dayOff->setStartDate( new DateTimeValue( DateTimeService::getDateTimeObjectInTimeZone( $dayOff->getStartDate()->getValue()->format('Y-m-d') . ' 00:00:00', $provider->getTimeZone()->getValue() ) ) ); $dayOff->setEndDate( new DateTimeValue( DateTimeService::getDateTimeObjectInTimeZone( $dayOff->getEndDate()->getValue()->format('Y-m-d') . ' 00:00:00', $provider->getTimeZone()->getValue() ) ) ); } $yearsDiff = $startDateTime->diff($endDateTime)->format('%y'); $startYear = $startDateTime->format('Y'); /** @var Collection $fakeAppointments */ $fakeAppointments = new Collection(); foreach ($globalDaysOff as $globalDayOff) { $dayOffParts = explode('-', $globalDayOff); if (sizeof($dayOffParts) === 2) { for ($i = 0; $i <= $yearsDiff; $i++) { $dateOffStart = DateTimeService::getCustomDateTimeObject( $startYear . '-' . $globalDayOff . ' 00:00' )->modify("+$i years"); $dateOffEnd = DateTimeService::getCustomDateTimeObject( $startYear . '-' . $globalDayOff . ' 00:00' )->modify("+$i years")->modify('+1 days'); /** @var Appointment $fakeAppointment */ $fakeAppointment = AppointmentFactory::create( [ 'bookingStart' => $dateOffStart->format('Y-m-d H:i'), 'bookingEnd' => $dateOffEnd->format('Y-m-d H:i'), 'notifyParticipants' => false, 'serviceId' => 0, 'providerId' => $provider->getId()->getValue(), ] ); $fakeAppointment->getBookingStart()->getValue()->setTimezone( new DateTimeZone($provider->getTimeZone()->getValue()) ); $fakeAppointment->getBookingEnd()->getValue()->setTimezone( new DateTimeZone($provider->getTimeZone()->getValue()) ); $fakeAppointments->addItem($fakeAppointment); } } elseif (sizeof($dayOffParts) === 3) { /** @var Appointment $fakeAppointment */ $fakeAppointment = AppointmentFactory::create( [ 'bookingStart' => $globalDayOff . ' 00:00', 'bookingEnd' => DateTimeService::getCustomDateTimeObject( $globalDayOff . ' 00:00' )->modify('+1 days')->format('Y-m-d H:i'), 'notifyParticipants' => false, 'serviceId' => 0, 'providerId' => $provider->getId()->getValue(), ] ); $fakeAppointment->getBookingStart()->getValue()->setTimezone( new DateTimeZone($provider->getTimeZone()->getValue()) ); $fakeAppointment->getBookingEnd()->getValue()->setTimezone( new DateTimeZone($provider->getTimeZone()->getValue()) ); $fakeAppointments->addItem($fakeAppointment); } } /** @var Appointment $fakeAppointment */ foreach ($fakeAppointments->getItems() as $fakeAppointment) { $provider->getAppointmentList()->addItem($fakeAppointment); } } }
| ver. 1.4 |
Github
|
.
| PHP 5.4.45 | Generation time: 0 |
proxy
|
phpinfo
|
Settings