/**
  * If the event times have changed, it checks to make sure that the resources
  * are still available. If not, it throws a validation exception.
  *
  * @throws ValiationException
  */
 public function onBeforeWrite()
 {
     $changed = $this->owner->getChangedFields();
     $check = array('StartDate', 'StartTime', 'EndDate', 'EndTime', 'is_all_day');
     if (!array_intersect_key(array_flip($check), $changed)) {
         return;
     }
     foreach ($this->owner->Resources() as $resource) {
         if ($resource->Type == 'Unlimited') {
             continue;
         }
         // If this is a recurring event, then check all other non-recurring
         // bookings for this resource to see if any conflict.
         if ($this->owner->Event()->Recursion) {
             $bookings = $resource->Events(sprintf('"CalendarEvent"."Recursion" = 0 AND "CalendarDateTime"."ID" <> %d', $this->owner->ID), null, 'INNER JOIN "CalendarEvent" ON "CalendarEvent"."ID" = "CalendarDateTime"."EventID"');
             foreach ($bookings as $booking) {
                 $counter = $booking->getStartTimestamp();
                 $end = $booking->getEndTimestamp();
                 // Loop through each day the other booking falls on, to see
                 // if it could cause a conflict.
                 while ($counter < $end) {
                     if ($this->owner->Event()->recursionHappensOn($counter)) {
                         $this->checkResourceAvailability($resource, $counter);
                     }
                     $counter = sfTime::add($counter, 1, sfTime::DAY);
                 }
             }
         } else {
             $this->checkResourceAvailability($resource);
         }
     }
 }
    public function bookings($request)
    {
        $start = (int) $request->getVar('start');
        $end = (int) $request->getVar('end');
        $result = array();
        // First load standard non-recurring events that fall between the start
        // and end date.
        $events = $this->parent->Events(sprintf('"CalendarEvent"."Recursion" = 0 AND (
					"StartDate" BETWEEN \'%1$s\' AND \'%2$s\'
					OR "EndDate" BETWEEN \'%1$s\' AND \'%2$s\'
					OR ("StartDate" < \'%1$s\' AND "EndDate" > \'%2$s\')
				)', date('Y-m-d', $start), date('Y-m-d', $end)), null, 'INNER JOIN "CalendarEvent" ON "CalendarEvent"."ID" = "CalendarDateTime"."EventID"');
        // Then load every recurring event and see if they fall between the start
        // and end.
        $recurring = $this->parent->Events(sprintf('"CalendarEvent"."Recursion" = 1
				AND ("EndDate" IS NULL OR "EndDate" > \'%s\')
				AND ("StartDate" IS NULL OR "StartDate" < \'%s\')', date('Y-m-d', $start), date('Y-m-d', $end)), null, 'INNER JOIN "CalendarEvent" ON "CalendarEvent"."ID" = "CalendarDateTime"."EventID"');
        // Now loop through each day in the specified date range, and check
        // each recurring date to see if it occurs on that day. Note that
        // recurring events always start and end on the same day.
        if ($recurring) {
            foreach ($recurring as $datetime) {
                $counter = $start;
                $days = 0;
                while ($counter <= $end) {
                    if ($counter > strtotime($datetime->EndDate)) {
                        break;
                    }
                    if ($datetime->Event()->recursionHappensOn($counter)) {
                        $_datetime = clone $datetime;
                        $_datetime->ID = -1;
                        $_datetime->StartDate = date('Y-m-d', $counter);
                        $_datetime->EndDate = date('Y-m-d', $counter);
                        $events->push($_datetime);
                    }
                    $counter = sfTime::add($counter, 1, sfTime::DAY);
                    $days++;
                }
            }
        }
        foreach ($events as $event) {
            $title = $event->EventTitle();
            if ($this->parent->Type != 'Single') {
                $title .= " ({$event->BookingQuantity} {$this->parent->Title})";
            }
            $result[] = array('id' => $event->ID, 'title' => $title, 'start' => $event->getStartTimestamp(), 'end' => $event->getEndTimestamp(), 'allDay' => (bool) $event->is_all_day, 'url' => Controller::join_links('admin/show', $event->EventID));
        }
        return Convert::array2json($result);
    }
Exemple #3
0
 /**
  * Adds the specified number of millenia to the timestamp.
  *
  * @param	timestamp
  * @param	int
  * @return	timestamp
  */
 public static function addMillenium($ts = null, $num = 1)
 {
     return sfTime::add($ts, $num, sfTime::MILLENIUM);
 }
    /**
     * Returns the number of this resource that are not booked during an event
     * time.
     *
     * @param  CalendarDateTime $time
     * @return bool|int
     */
    public function getAvailableForEvent($time)
    {
        if ($this->Type == 'Unlimited') {
            return true;
        }
        $start = $time->getStartTimestamp();
        $end = $time->getEndTimestamp();
        // First just get simple non-recurring bookings, often this will be
        // enough to check if a resource is available.
        $dateFilter = sprintf('"StartDate" BETWEEN \'%1$s\' AND \'%2$s\'
			OR "EndDate" BETWEEN \'%1$s\' AND \'%2$s\'
			OR ("StartDate" < \'%1$s\' AND "EndDate" > \'%2$s\')', date('Y-m-d', $start), date('Y-m-d', $end));
        $filter = "\"CalendarEvent\".\"Recursion\" = 0 AND \"CalendarDateTimeID\" <> {$time->ID} AND ({$dateFilter})";
        $bookings = $this->Events($filter, null, 'INNER JOIN "CalendarEvent" ON "CalendarEvent"."ID" = "CalendarDateTime"."EventID"');
        $bookings = $bookings->toArray('ID');
        // Since the event calendar doesn't use a proper date time storage, we
        // need to manually filter events again here.
        foreach ($bookings as $id => $booking) {
            if ($booking->getEndTimestamp() < $start || $booking->getStartTimestamp() > $end) {
                unset($bookings[$id]);
            }
        }
        if ($bookings && $this->Type == 'Single') {
            return false;
        }
        // Now also load all the recurring events, and check if they occur on
        // this day.
        $recurring = $this->Events(sprintf('"CalendarDateTimeID" <> %d
				AND "CalendarEvent"."Recursion" = 1
				AND ("EndDate" IS NULL OR "EndDate" > \'%s\')
				AND ("StartDate" IS NULL OR "StartDate" < \'%s\')', $time->ID, date('Y-m-d', $start), date('Y-m-d', $end)), null, 'INNER JOIN "CalendarEvent" ON "CalendarEvent"."ID" = "CalendarDateTime"."EventID"');
        // Now loop through each day this event runs on, and check if any of the
        // events fall on it. If they do just push them onto the bookings set.
        foreach ($recurring as $datetime) {
            $counter = $start;
            while ($counter <= $end) {
                if ($counter > strtotime($datetime->EndDate)) {
                    break;
                }
                if ($datetime->Event()->recursionHappensOn($counter)) {
                    $bookings[$datetime->ID] = $datetime;
                    break;
                }
                $counter = sfTime::add($counter, 1, sfTime::DAY);
            }
        }
        if ($bookings && $this->Type == 'Single') {
            return false;
        }
        if (!count($bookings)) {
            return $this->Type == 'Limited' ? (int) $this->Quantity : true;
        }
        $quantity = (int) $this->Quantity;
        foreach ($bookings as $booking) {
            $quantity -= $booking->BookingQuantity;
        }
        return $quantity > 0 ? $quantity : false;
    }