Uname: Linux webm005.cluster107.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64
User: 6036 (villadal)
Group: 100 (users)
Disabled functions: NONE
Safe mode: On[ PHPinfo ]
//home/villadal/www///old/booked/Domain      ( Reset | Go to )
File Name: Quota.php
Edit
<?php
/**
Copyright 2011-2014 Nick Korbel

This file is part of Booked Scheduler.

Booked Scheduler is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Booked Scheduler is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Booked Scheduler.  If not, see <http://www.gnu.org/licenses/>.
 */

interface IQuota
{
    
/**
     * @param ReservationSeries $reservationSeries
     * @param User $user
     * @param Schedule $schedule
     * @param IReservationViewRepository $reservationViewRepository
     * @return bool
     */
    
public function ExceedsQuota($reservationSeries$user$scheduleIReservationViewRepository $reservationViewRepository);

    public function 
ToString();
}

class 
Quota implements IQuota
{
    
/**
     * @var int
     */
    
private $quotaId;

    
/**
     * @var \IQuotaDuration
     */
    
private $duration;

    
/**
     * @var \IQuotaLimit
     */
    
private $limit;

    
/**
     * @var int
     */
    
private $resourceId;

    
/**
     * @var int
     */
    
private $groupId;

    
/**
     * @var int
     */
    
private $scheduleId;

    
/**
     * @param int $quotaId
     * @param IQuotaDuration $duration
     * @param IQuotaLimit $limit
     * @param int $resourceId
     * @param int $groupId
     * @param int $scheduleId
     */
    
public function __construct($quotaId$duration$limit$resourceId null$groupId null$scheduleId null)
    {
        
$this->quotaId $quotaId;
        
$this->duration $duration;
        
$this->limit $limit;
        
$this->resourceId = empty($resourceId) ? null $resourceId;
        
$this->groupId = empty($groupId) ? null $groupId;
        
$this->scheduleId = empty($scheduleId) ? null $scheduleId;
    }

    
/**
     * @static
     * @param string $duration
     * @param decimal $limit
     * @param string $unit
     * @param int $resourceId
     * @param int $groupId
     * @param int $scheduleId
     * @return Quota
     */
    
public static function Create($duration$limit$unit$resourceId$groupId$scheduleId)
    {
        return new 
Quota(0self::CreateDuration($duration), self::CreateLimit($limit$unit), $resourceId$groupId$scheduleId);
    }

    
/**
     * @static
     * @param decimal $limit
     * @param string $unit QuotaUnit
     * @return IQuotaLimit
     */
    
public static function CreateLimit($limit$unit)
    {
        if (
$unit == QuotaUnit::Reservations)
        {
            return new 
QuotaLimitCount($limit);
        }

        return new 
QuotaLimitHours($limit);
    }

    
/**
     * @static
     * @param string $duration QuotaDuration
     * @return IQuotaDuration
     */
    
public static function CreateDuration($duration)
    {
        if (
$duration == QuotaDuration::Day)
        {
            return new 
QuotaDurationDay();
        }

        if (
$duration == QuotaDuration::Week)
        {
            return new 
QuotaDurationWeek();
        }

        return new 
QuotaDurationMonth();
    }

    
/**
     * @param ReservationSeries $reservationSeries
     * @param User $user
     * @param Schedule $schedule
     * @param IReservationViewRepository $reservationViewRepository
     * @return bool
     */
    
public function ExceedsQuota($reservationSeries$user$scheduleIReservationViewRepository $reservationViewRepository)
    {
        
$timezone $schedule->GetTimezone();

        if (!
is_null($this->resourceId))
        {
            
$appliesToResource false;

            foreach (
$reservationSeries->AllResourceIds() as $resourceId)
            {
                if (!
$appliesToResource && $this->AppliesToResource($resourceId))
                {
                    
$appliesToResource true;
                }
            }

            if (!
$appliesToResource)
            {
                return 
false;
            }
        }

        if (!
is_null($this->groupId))
        {
            
$appliesToGroup false;
            foreach (
$user->Groups() as $group)
            {
                if (!
$appliesToGroup && $this->AppliesToGroup($group->GroupId))
                {
                    
$appliesToGroup true;
                }
            }

            if (!
$appliesToGroup)
            {
                return 
false;
            }
        }

        if (!
$this->AppliesToSchedule($reservationSeries->ScheduleId()))
        {
            return 
false;
        }

        if (
count($reservationSeries->Instances()) == 0)
        {
            return 
false;
        }

        
$dates $this->duration->GetSearchDates($reservationSeries$timezone);
        
$reservationsWithinRange $reservationViewRepository->GetReservationList($dates->Start(), $dates->End(), $reservationSeries->UserId(), ReservationUserLevel::OWNER);

        try
        {
            
$this->CheckAll($reservationsWithinRange$reservationSeries$timezone);
        }
        catch (
QuotaExceededException $ex)
        {
            return 
true;
        }

        return 
false;
    }

    public function 
ToString()
    {
        return 
$this->__toString();
    }

    public function 
__toString()
    {
        return 
sprintf('Quota Id=%s, ResourceId=%s, ScheduleId=%s, GroupId=%s, Limit=%s, Duration=%s'$this->quotaId,
                       
$this->ResourceId(), $this->ScheduleId(), $this->GroupId(), $this->GetLimit(), $this->GetDuration());
    }

    
/**
     * @return IQuotaLimit
     */
    
public function GetLimit()
    {
        return 
$this->limit;
    }

    
/**
     * @return IQuotaDuration
     */
    
public function GetDuration()
    {
        return 
$this->duration;
    }

    
/**
     * @param int $resourceId
     * @return bool
     */
    
public function AppliesToResource($resourceId)
    {
        return 
is_null($this->resourceId) || $this->resourceId == $resourceId;
    }

    
/**
     * @param int $groupId
     * @return bool
     */
    
public function AppliesToGroup($groupId)
    {
        return 
is_null($this->groupId) || $this->groupId == $groupId;
    }

    
/**
     * @param int $scheduleId
     * @return bool
     */
    
public function AppliesToSchedule($scheduleId)
    {
        return 
is_null($this->scheduleId) || $this->scheduleId == $scheduleId;
    }

    
/**
     * @return int|null
     */
    
public function ResourceId()
    {
        return 
$this->resourceId;
    }

    
/**
     * @return int|null
     */
    
public function GroupId()
    {
        return 
$this->groupId;
    }

    
/**
     * @return int|null
     */
    
public function ScheduleId()
    {
        return 
$this->scheduleId;
    }

    private function 
AddExisting(ReservationItemView $reservation$timezone)
    {
        
$this->_breakAndAdd($reservation->StartDate$reservation->EndDate$timezone);
    }

    private function 
AddInstance(Reservation $reservation$timezone)
    {
        
$this->_breakAndAdd($reservation->StartDate(), $reservation->EndDate(), $timezone);
    }

    
/**
     * @param array|ReservationItemView[] $reservationsWithinRange
     * @param ReservationSeries $series
     * @param string $timezone
     * @throws QuotaExceededException
     */
    
private function CheckAll($reservationsWithinRange$series$timezone)
    {
        
$toBeSkipped = array();

        
/** @var $instance Reservation */
        
foreach ($series->Instances() as $instance)
        {
            
$toBeSkipped[$instance->ReferenceNumber()] = true;

            if (!
is_null($this->scheduleId))
            {
                foreach (
$series->AllResources() as $resource)
                {
                    
// add each resource instance
                    
if ($this->AppliesToResource($resource->GetResourceId()))
                    {
                        
$this->AddInstance($instance$timezone);
                    }
                }
            }
            else
            {
                
$this->AddInstance($instance$timezone);
            }
        }

        
/** @var $reservation ReservationItemView */
        
foreach ($reservationsWithinRange as $reservation)
        {
            if (!empty(
$this->resourceId))
            {
                
$applies = ($this->AppliesToResource($reservation->ResourceId) && $series->ContainsResource($reservation->ResourceId));
            }
            else
            {
                
$applies $series->ContainsResource($reservation->ResourceId) || ($series->ScheduleId() == $reservation->ScheduleId);
            }

            if ( 
$applies &&
                 !
array_key_exists($reservation->ReferenceNumber$toBeSkipped) &&
                 !
$this->willBeDeleted($series$reservation->ReservationId )
            )
            {
                
$this->AddExisting($reservation$timezone);
            }
        }
    }

    
/**
     * @param ExistingReservationSeries $series
     * @param int $reservationId
     * @return bool
     */
    
private function willBeDeleted($series$reservationId)
    {
        if (
method_exists($series'IsMarkedForDelete'))
        {
            return 
$series->IsMarkedForDelete($reservationId);
        }

        return 
false;
    }

    private function 
_breakAndAdd(Date $startDateDate $endDate$timezone)
    {
        
$start $startDate->ToTimezone($timezone);
        
$end $endDate->ToTimezone($timezone);

        
$range = new DateRange($start$end);

        
$ranges $this->duration->Split($range);

        foreach (
$ranges as $dr)
        {
            
$this->_add($dr);
        }
    }

    private function 
_add(DateRange $dateRange)
    {
        
$durationKey $this->duration->GetDurationKey($dateRange->GetBegin());

        
$this->limit->TryAdd($dateRange->GetBegin(), $dateRange->GetEnd(), $durationKey);
    }

}

class 
QuotaUnit
{
    const 
Hours 'hours';
    const 
Reservations 'reservations';
}


interface 
IQuotaDuration
{
    
/**
     * @abstract
     * @return string QuotaDuration
     */
    
public function Name();

    
/**
     * @param ReservationSeries $reservationSeries
     * @param string $timezone
     * @return QuotaSearchDates
     */
    
public function GetSearchDates(ReservationSeries $reservationSeries$timezone);

    
/**
     * @abstract
     * @param DateRange $dateRange
     * @return array|DateRange[]
     */
    
public function Split(DateRange $dateRange);

    
/**
     * @abstract
     * @param Date $date
     * @return string
     */
    
public function GetDurationKey(Date $date);
}

class 
QuotaSearchDates
{
    
/**
     * @var \Date
     */
    
private $start;

    
/**
     * @var \Date
     */
    
private $end;

    public function 
__construct(Date $startDate $end)
    {
        
$this->start $start;
        
$this->end $end;
    }

    
/**
     * @return Date
     */
    
public function Start()
    {
        return 
$this->start;
    }

    
/**
     * @return Date
     */
    
public function End()
    {
        return 
$this->end;
    }
}

abstract class 
QuotaDuration implements IQuotaDuration
{
    const 
Day 'day';
    const 
Week 'week';
    const 
Month 'month';

    
/**
     * @param ReservationSeries $reservationSeries
     * @return array|Date[]
     */
    
protected function GetFirstAndLastReservationDates(ReservationSeries $reservationSeries)
    {
        
/** @var $instances Reservation[] */
        
$instances $reservationSeries->Instances();
        
usort($instances, array('Reservation''Compare'));

        return array(
$instances[0]->StartDate(), $instances[count($instances) - 1]->EndDate());
    }

    public function 
__toString()
    {
        return 
sprintf('QuotaDuration Name=%s'$this->Name());
    }
}

class 
QuotaDurationDay extends QuotaDuration
{
    
/**
     * @param ReservationSeries $reservationSeries
     * @param string $timezone
     * @return QuotaSearchDates
     */
    
public function GetSearchDates(ReservationSeries $reservationSeries$timezone)
    {
        
$dates $this->GetFirstAndLastReservationDates($reservationSeries);

        
$startDate $dates[0]->ToTimezone($timezone)->GetDate();
        
$endDate $dates[1]->ToTimezone($timezone)->AddDays(1)->GetDate();

        return new 
QuotaSearchDates($startDate$endDate);
    }

    public function 
Split(DateRange $dateRange)
    {
        
$start $dateRange->GetBegin();
        
$end $dateRange->GetEnd();

        
$ranges = array();

        if (!
$start->DateEquals($end))
        {
            
$beginningOfNextDay $start->AddDays(1)->GetDate();
            
$ranges[] = new DateRange($start$beginningOfNextDay);

            
$currentDate $beginningOfNextDay;

            for (
$i 1$currentDate->LessThan($end) < 0$i++)
            {
                
$currentDate $start->AddDays($i);
                
$ranges[] = new DateRange($currentDate$currentDate->AddDays(1)->GetDate());
            }

            
$ranges[] = new DateRange($currentDate$end);
        }
        else
        {
            
$ranges[] = new DateRange($start$end);
        }

        return 
$ranges;
    }

    
/**
     * @param Date $date
     * @return string
     */
    
public function GetDurationKey(Date $date)
    {
        return 
sprintf("%s%s%s"$date->Year(), $date->Month(), $date->Day());
    }

    
/**
     * @return string QuotaDuration
     */
    
public function Name()
    {
        return 
QuotaDuration::Day;
    }
}

class 
QuotaDurationWeek extends QuotaDuration
{
    
/**
     * @param ReservationSeries $reservationSeries
     * @param string $timezone
     * @return QuotaSearchDates
     */
    
public function GetSearchDates(ReservationSeries $reservationSeries$timezone)
    {
        
$dates $this->GetFirstAndLastReservationDates($reservationSeries);

        
$startDate $dates[0]->ToTimezone($timezone);
        
$daysFromWeekStart $startDate->Weekday();
        
$startDate $startDate->AddDays(-$daysFromWeekStart)->GetDate();

        
$endDate $dates[1]->ToTimezone($timezone);
        
$daysFromWeekEnd $endDate->Weekday();
        
$endDate $endDate->AddDays($daysFromWeekEnd)->GetDate();

        return new 
QuotaSearchDates($startDate$endDate);
    }

    
/**
     * @param Date $date
     * @return string
     */
    
public function GetDurationKey(Date $date)
    {
        
$daysFromWeekStart $date->Weekday();
        
$firstDayOfWeek $date->AddDays(-$daysFromWeekStart)->GetDate();
        return 
sprintf("%s%s%s"$firstDayOfWeek->Year(), $firstDayOfWeek->Month(), $firstDayOfWeek->Day());
    }

    
/**
     * @param DateRange $dateRange
     * @return array|DateRange[]
     */
    
public function Split(DateRange $dateRange)
    {
        
$start $dateRange->GetBegin();
        
$end $dateRange->GetEnd();

        
$ranges = array();

        if (!
$start->DateEquals($end))
        {
            
$nextWeek $this->GetStartOfNextWeek($start);

            if (
$nextWeek->LessThan($end))
            {
                
$ranges[] = new DateRange($start$nextWeek);
                while (
$nextWeek->LessThan($end))
                {
                    
$thisEnd $this->GetStartOfNextWeek($nextWeek);

                    if (
$thisEnd->LessThan($end))
                    {
                        
$ranges[] = new DateRange($nextWeek$thisEnd);
                    }
                    else
                    {
                        
$ranges[] = new DateRange($nextWeek$end);
                    }

                    
$nextWeek $thisEnd;
                }
            }
            else
            {
                
$ranges[] = new DateRange($start$end);
            }
        }
        else
        {
            
$ranges[] = new DateRange($start$end);
        }


        return 
$ranges;
    }

    
/**
     * @param Date $date
     * @return Date
     */
    
private function GetStartOfNextWeek(Date $date)
    {
        
$daysFromWeekEnd $date->Weekday();
        return 
$date->AddDays($daysFromWeekEnd)->GetDate();
    }

    
/**
     * @return string QuotaDuration
     */
    
public function Name()
    {
        return 
QuotaDuration::Week;
    }
}

class 
QuotaDurationMonth extends QuotaDuration
{
    
/**
     * @param ReservationSeries $reservationSeries
     * @param string $timezone
     * @return QuotaSearchDates
     */
    
public function GetSearchDates(ReservationSeries $reservationSeries$timezone)
    {
        
$minMax $this->GetFirstAndLastReservationDates($reservationSeries);

        
/** @var $start Date */
        
$start $minMax[0]->ToTimezone($timezone);
        
/** @var $end Date */
        
$end $minMax[1]->ToTimezone($timezone);

        
$searchStart Date::Create($start->Year(), $start->Month(), 1000$timezone);
        
$searchEnd Date::Create($end->Year(), $end->Month() + 11000$timezone);

        return new 
QuotaSearchDates($searchStart$searchEnd);
    }

    
/**
     * @param DateRange $dateRange
     * @return array|DateRange[]
     */
    
public function Split(DateRange $dateRange)
    {
        
$ranges = array();

        
$start $dateRange->GetBegin();
        
$end $dateRange->GetEnd();

        if (!
$this->SameMonth($start$end))
        {
            
$current $start;

            while (!
$this->SameMonth($current$end))
            {
                
$next $this->GetFirstOfMonth($current1);

                
$ranges[] = new DateRange($current$next);

                
$current $next;

                if (
$this->SameMonth($current$end))
                {
                    
$ranges[] = new DateRange($current$end);
                }
            }
        }
        else
        {
            
$ranges[] = $dateRange;
        }

        return 
$ranges;
    }

    
/**
     * @param Date $date
     * @param int $monthOffset
     * @return Date
     */
    
private function GetFirstOfMonth(Date $date$monthOffset 0)
    {
        return 
Date::Create($date->Year(), $date->Month() + $monthOffset1000$date->Timezone());
    }

    
/**
     * @param Date $d1
     * @param Date $d2
     * @return bool
     */
    
private function SameMonth(Date $d1Date $d2)
    {
        return (
$d1->Month() == $d2->Month()) && ($d1->Year() == $d2->Year());
    }

    
/**
     * @param Date $date
     * @return string
     */
    
public function GetDurationKey(Date $date)
    {
        return 
sprintf("%s%s"$date->Year(), $date->Month());
    }

    
/**
     * @return string QuotaDuration
     */
    
public function Name()
    {
        return 
QuotaDuration::Month;
    }
}

interface 
IQuotaLimit
{
    
/**
     * @abstract
     * @param Date $start
     * @param Date $end
     * @param string $key
     * @return void
     * @throws QuotaExceededException
     */
    
public function TryAdd($start$end$key);

    
/**
     * @abstract
     * @return decimal
     */
    
public function Amount();

    
/**
     * @abstract
     * @return string|QuotaUnit
     */
    
public function Name();
}

class 
QuotaLimitCount implements IQuotaLimit
{
    
/**
     * @var array|int[]
     */
    
private $aggregateCounts = array();

    
/**
     * @var int
     */
    
private $totalAllowed;

    
/**
     * @param int $totalAllowed
     */
    
public function __construct($totalAllowed)
    {
        
$this->totalAllowed $totalAllowed;
    }

    public function 
TryAdd($start$end$key)
    {
        if (
array_key_exists($key$this->aggregateCounts))
        {
            
$this->aggregateCounts[$key] = $this->aggregateCounts[$key] + 1;
        }
        else
        {
            
$this->aggregateCounts[$key] = 1;
        }

        if (
$this->aggregateCounts[$key] > $this->totalAllowed)
        {
            throw new 
QuotaExceededException("Only {$this->totalAllowed} reservations are allowed for this duration");
        }
    }

    
/**
     * @return decimal
     */
    
public function Amount()
    {
        return 
$this->totalAllowed;
    }

    
/**
     * @return string|QuotaUnit
     */
    
public function Name()
    {
        return 
QuotaUnit::Reservations;
    }

    public function 
__toString()
    {
        return 
sprintf('QuotaLimitCount Name=%s, Amount=%s'$this->Name(), $this->Amount());
    }
}

class 
QuotaLimitHours implements IQuotaLimit
{
    
/**
     * @var array|DateDiff[]
     */
    
private $aggregateCounts = array();

    
/**
     * @var \DateDiff
     */
    
private $allowedDuration;

    
/**
     * @var decimal
     */
    
private $allowedHours;

    
/**
     * @param decimal $allowedHours
     */
    
public function __construct($allowedHours)
    {
        
$this->allowedHours $allowedHours;
        
$this->allowedDuration = new DateDiff($allowedHours 3600);
    }

    
/**
     * @param Date $start
     * @param Date $end
     * @param string $key
     * @return void
     * @throws QuotaExceededException
     */
    
public function TryAdd($start$end$key)
    {
        
$diff $start->GetDifference($end);

        if (
array_key_exists($key$this->aggregateCounts))
        {
            
$this->aggregateCounts[$key] = $this->aggregateCounts[$key]->Add($diff);
        }
        else
        {
            
$this->aggregateCounts[$key] = $diff;
        }

        if (
$this->aggregateCounts[$key]->GreaterThan($this->allowedDuration))
        {
            throw new 
QuotaExceededException("Cumulative reservation length cannot exceed {$this->allowedHours} hours for this duration");
        }
    }

    
/**
     * @return decimal
     */
    
public function Amount()
    {
        return 
$this->allowedHours;
    }

    
/**
     * @return string|QuotaUnit
     */
    
public function Name()
    {
        return 
QuotaUnit::Hours;
    }

    public function 
__toString()
    {
        return 
sprintf('QuotaLimitHours Name=%s Amount=%s'$this->Name(), $this->Amount());
    }
}

class 
QuotaExceededException extends Exception
{
    
/**
     * @param string $message
     */
    
public function __construct($message)
    {
        
parent::__construct($message);
    }
}

?>

All system for education purposes only. For more tools: Telegram @jackleet

Mr.X Private Shell

Logo
-
New File | New Folder
Command
SQL