/** * @covers EventRegistrationPurgeTask::purgeUnconfirmedRegistrations */ public function testPurgeTaskCancelsUnconfirmedRegistrations() { $task = new EventRegistrationPurgeTask(); $unconfirmed1 = $this->objFromFixture('EventRegistration', 'unconfirmed_1'); $unconfirmed2 = $this->objFromFixture('EventRegistration', 'unconfirmed_2'); $canceled = 'SELECT COUNT(*) FROM "EventRegistration" WHERE "Status" = \'Canceled\''; $update = 'UPDATE "EventRegistration" SET "Created" = \'%s\' WHERE "ID" = %d'; ob_start(); $task->run(null); $this->assertEquals(0, DB::query($canceled)->value()); // Update the first task to be just shy of six hours less than the // created date. $created = strtotime($unconfirmed1->Created); $created = sfTime::subtract($created, 5, sfTime::HOUR); DB::query(sprintf($update, date('Y-m-d H:i:s', $created), $unconfirmed1->ID)); $task->run(null); $this->assertEquals(0, DB::query($canceled)->value()); // Now push it beyond six hours DB::query(sprintf($update, date('Y-m-d H:i:s', sfTime::subtract($created, 1, sfTime::HOUR)), $unconfirmed1->ID)); $task->run(null); $this->assertEquals(1, DB::query($canceled)->value()); // Now push the second one way back, and check it's also canceled $created = sfTime::subtract(time(), 1000, sfTime::DAY); DB::query(sprintf($update, date('Y-m-d H:i:s', $created), $unconfirmed2->ID)); $task->run(null); $this->assertEquals(2, DB::query($canceled)->value()); // Ensure the confirmed event is still there. $confirmed = DB::query('SELECT COUNT(*) FROM "EventRegistration" WHERE "Status" = \'Confirmed\''); $this->assertEquals(1, $confirmed->value()); ob_end_clean(); }
/** * 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); }
/** * If an email reminder is set, then this registers it in the queue. */ protected function onBeforeWrite() { parent::onBeforeWrite(); // If an email reminder has been set then register it with the queued // jobs module. if (class_exists('AbstractQueuedJob') && $this->EmailReminder) { $hasJob = $this->ReminderJobID; $changedStart = $this->isChanged('RemindDays'); if ($hasJob) { if (!$changedStart) { return; } else { $this->ReminderJob()->delete(); } } $start = $this->getStartDateTime()->getTimestamp(); $start = sfTime::subtract($start, $this->RemindDays, sfTime::DAY); $job = new EventReminderEmailJob($this); $srv = singleton('QueuedJobService'); $this->ReminderJobID = $srv->queueJob($job, date('Y-m-d H:i:s', $start)); } }
/** * Returns the timestamp for the most recent (previous) occurance of [month]. * * @param timestamp * @param int the month of year * @return timestamp */ public static function previousMonth($ts = null, $month = sfTime::JANUARY) { // default to now if ($ts === null) { $ts = sfDateTimeToolkit::now(); } // get offsets from january $offset1 = date('m', $ts); $offset2 = $month; // adjust if date wraps into last year $offset1 += $offset1 > $offset2 ? 0 : 12; return sfTime::subtractMonth($ts, $offset1 - $offset2); }
/** * Calculates the timestamp for when this ticket stops going on sale for an * event date time. * * @param RegistrableDateTime $datetime * @return int */ public function getSaleEndForDateTime(RegistrableDateTime $datetime) { if ($this->EndType == 'Date') { return strtotime($this->EndDate); } $time = $datetime->getStartDateTime()->getTimestamp(); $time = sfTime::subtract($time, $this->EndDays, sfTime::DAY); $time = sfTime::subtract($time, $this->EndHours, sfTime::HOUR); $time = sfTime::subtract($time, $this->EndMins, sfTime::MINUTE); return $time; }
/** * 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; }