Add ical Library
This commit is contained in:
		
							
								
								
									
										684
									
								
								ical_library.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										684
									
								
								ical_library.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,684 @@
 | 
				
			|||||||
 | 
					<?php if(!defined('APP_ROOT')) exit('No direct script access allowed');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					date_default_timezone_set('America/Chicago');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Anvil_iCal {
 | 
				
			||||||
 | 
					  var $calURL = '';
 | 
				
			||||||
 | 
					  var $rawCalendar = '';
 | 
				
			||||||
 | 
					  var $iCal;
 | 
				
			||||||
 | 
					  var $dev_mode = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function __construct($calURL=false) { 
 | 
				
			||||||
 | 
					    if($calURL) {
 | 
				
			||||||
 | 
					      $this->calURL = $calURL;
 | 
				
			||||||
 | 
					      $this->fetchCalendar();
 | 
				
			||||||
 | 
					      $this->createCalendarFromRaw();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function fetchCalendar() {
 | 
				
			||||||
 | 
					    $ch = curl_init($this->calURL);
 | 
				
			||||||
 | 
					    curl_setopt($ch, CURLOPT_HEADER, 0);
 | 
				
			||||||
 | 
					    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 | 
				
			||||||
 | 
					    $this->rawCalendar = curl_exec($ch);
 | 
				
			||||||
 | 
					    curl_close($ch);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function createCalendarFromRaw() {
 | 
				
			||||||
 | 
					    $this->iCal = new ICal($this->rawCalendar);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function getCalendar() {
 | 
				
			||||||
 | 
					    return $this->iCal;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function getTimezone() {
 | 
				
			||||||
 | 
					    return new DateTimeZone($this->iCal->cal['VCALENDAR']['X-WR-TIMEZONE']);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function getEvents() {
 | 
				
			||||||
 | 
					    if(isset($this->iCal->cal['VEVENT'])) {
 | 
				
			||||||
 | 
					      return $this->iCal->cal['VEVENT'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return [];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function getUpcomingEvents() {
 | 
				
			||||||
 | 
					    $ret = [];
 | 
				
			||||||
 | 
					    $earliest = new DateTime(date('Y-m-d H:i:s', strtotime('now')));
 | 
				
			||||||
 | 
					    $allEvents = $this->iCal->cal['VEVENT'];
 | 
				
			||||||
 | 
					    foreach($allEvents as $anEvent) {
 | 
				
			||||||
 | 
					      $tstDt = new DateTime(date('Y-m-d H:i:s', strtotime($anEvent['DTSTART'])));
 | 
				
			||||||
 | 
					      if($tstDt <= $earliest) { continue; }
 | 
				
			||||||
 | 
					      $ret[] = $anEvent;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return $ret;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function getNextEvent() {
 | 
				
			||||||
 | 
					    $earliest = new DateTime(date('Y-m-d H:i:s', strtotime('2016-04-21 17:00:00')));
 | 
				
			||||||
 | 
					    $dt = new DateTime();
 | 
				
			||||||
 | 
					    foreach($this->getEvents() as $anEv) {
 | 
				
			||||||
 | 
					      $tstDt = new DateTime(date('Y-m-d H:i:s', strtotime($anEv['DTSTART'])));
 | 
				
			||||||
 | 
					      // $tstDt is the _STARTING_ date of the event
 | 
				
			||||||
 | 
					      if($tstDt <= $earliest) { continue; }
 | 
				
			||||||
 | 
					      $diff = $dt->diff($tstDt);
 | 
				
			||||||
 | 
					      if(!isset($nextDt)) {
 | 
				
			||||||
 | 
					        $nextDt = $tstDt;
 | 
				
			||||||
 | 
					        $ret = $anEv;
 | 
				
			||||||
 | 
					      } else if($dt < $tstDt && $tstDt < $nextDt) {
 | 
				
			||||||
 | 
					        $nextDt = $tstDt;
 | 
				
			||||||
 | 
					        $ret = $anEv;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(isset($ret)) {
 | 
				
			||||||
 | 
					      return $ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // getNextEventWithCurrent will get the next event, including ones that
 | 
				
			||||||
 | 
					  // are occurring right now, but haven't ended yet.
 | 
				
			||||||
 | 
					  function getNextEventWithCurrent() {
 | 
				
			||||||
 | 
					    $dt = new DateTime();
 | 
				
			||||||
 | 
					    foreach($this->getEvents() as $anEv) {
 | 
				
			||||||
 | 
					      $tstDt = new DateTime(date('Y-m-d H:i:s', strtotime($anEv['DTSTART'])));
 | 
				
			||||||
 | 
					      // $tstDt is the _STARTING_ date of the event
 | 
				
			||||||
 | 
					      $diff = $dt->diff($tstDt);
 | 
				
			||||||
 | 
					      if(!isset($nextDt)) {
 | 
				
			||||||
 | 
					        $nextDt = $tstDt;
 | 
				
			||||||
 | 
					      } else if($dt < $tstDt && $tstDt < $nextDt) {
 | 
				
			||||||
 | 
					        $nextDt = $tstDt;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ICal {
 | 
				
			||||||
 | 
					  private $timezone = 'UTC';
 | 
				
			||||||
 | 
					  private $events = [];
 | 
				
			||||||
 | 
					  private $recEvents = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function __construct($ICalString) {
 | 
				
			||||||
 | 
					    if(!$ICalString) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $lines = explode("\r\n", $ICalString);
 | 
				
			||||||
 | 
					    if(stristr($lines[0], 'BEGIN:VCALENDAR') === false) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // First, fix all multiline values
 | 
				
			||||||
 | 
					    $badIdx = [];
 | 
				
			||||||
 | 
					    foreach($lines as $idx => &$line) {
 | 
				
			||||||
 | 
					      $line = ltrim(str_replace('\,',',',$line));
 | 
				
			||||||
 | 
					      //$line = ltrim(str_replace('','<br/>',$line));
 | 
				
			||||||
 | 
					      $add  = $this->keyValueFromString($line);
 | 
				
			||||||
 | 
					      if ($add === false) {
 | 
				
			||||||
 | 
					        $badIdx[] = $idx;
 | 
				
			||||||
 | 
					      } 
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $newLines = [];
 | 
				
			||||||
 | 
					    $lastGood = '';
 | 
				
			||||||
 | 
					    foreach($lines as $idx => $aLine) {
 | 
				
			||||||
 | 
					      if(in_array($idx, $badIdx)) {
 | 
				
			||||||
 | 
					        $lastGood .= $aLine;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        if(!empty($lastGood)) {
 | 
				
			||||||
 | 
					          $newLines[] = $lastGood;
 | 
				
			||||||
 | 
					          $lastGood = '';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $lastGood = $aLine;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $newLines[] = $lastGood;
 | 
				
			||||||
 | 
					    $lines = $newLines;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for($idx = 0; $idx < count($lines); $idx++) {
 | 
				
			||||||
 | 
					      $line = $lines[$idx];
 | 
				
			||||||
 | 
					      if($line == 'BEGIN:VTIMEZONE') {
 | 
				
			||||||
 | 
					        $i = $this->_parseFindNext('END:VTIMEZONE', $lines, $idx);
 | 
				
			||||||
 | 
					        $this->timezone = $this->parseTimezone($i);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if($line == 'BEGIN:VEVENT') {
 | 
				
			||||||
 | 
					        $i = $this->_parseFindNext('END:VEVENT', $lines, $idx);
 | 
				
			||||||
 | 
					        if($i !== false) {
 | 
				
			||||||
 | 
					          $newEvent = $this->parseEvent($i);
 | 
				
			||||||
 | 
					          if($newEvent->isValid()) {
 | 
				
			||||||
 | 
					            $this->events[] = $newEvent;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getEvents() {
 | 
				
			||||||
 | 
					    return $this->events;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getEventsInRange($stDtTm, $endDtTm) {
 | 
				
			||||||
 | 
					    $ret = [];
 | 
				
			||||||
 | 
					    foreach($this->events as $anEv) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $evStTm = $anEv->getStartDttm();
 | 
				
			||||||
 | 
					      $evEndTm = $anEv->getEndDttm();
 | 
				
			||||||
 | 
					      if($anEv->getRecurFlag() && $evStTm < $endDtTm) {
 | 
				
			||||||
 | 
					        $evLength = $evStTm->diff($evEndTm);
 | 
				
			||||||
 | 
					        // Recurrences are defined by the original startDttm
 | 
				
			||||||
 | 
					        $recurUntil = $anEv->getRecurUntil();
 | 
				
			||||||
 | 
					        if(!empty($recurUntil)) {
 | 
				
			||||||
 | 
					          // So there is an end date
 | 
				
			||||||
 | 
					          if($recurUntil < $stDtTm) {
 | 
				
			||||||
 | 
					            // Past the recur until
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $recurFreq = $anEv->getRecurFrequency();
 | 
				
			||||||
 | 
					        if(!empty($recurFreq)) {
 | 
				
			||||||
 | 
					          switch($recurFreq) {
 | 
				
			||||||
 | 
					          case 'WEEKLY':
 | 
				
			||||||
 | 
					            $dow = $anEv->getRecurByDay();
 | 
				
			||||||
 | 
					            $newArr = [];
 | 
				
			||||||
 | 
					            if(empty($dow)) {
 | 
				
			||||||
 | 
					              // If 'recurByDay' is blank, just recur on the event start date
 | 
				
			||||||
 | 
					              array_push($newArr, $evStTm->format('w'));
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              if(is_array($dow)) {
 | 
				
			||||||
 | 
					                foreach($dow as &$ad) {
 | 
				
			||||||
 | 
					                  $ad = $this->shortDayToDOWNum($ad);
 | 
				
			||||||
 | 
					                  array_push($newArr, $ad);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                $ad = $this->shortDayToDOWNum($dow);
 | 
				
			||||||
 | 
					                array_push($newArr, $ad);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $dow = $newArr;
 | 
				
			||||||
 | 
					            $evStDay = new DateTime($evStTm->format('Y-m-d'));
 | 
				
			||||||
 | 
					            for($tstDt = new DateTime($stDtTm->format(DATE_RFC3339)); 
 | 
				
			||||||
 | 
					                $tstDt <= $endDtTm; 
 | 
				
			||||||
 | 
					                $tstDt->add(new DateInterval('P1D'))) {
 | 
				
			||||||
 | 
					              if(!in_array($tstDt->format('w'), $dow)) { continue; } // Same day of week
 | 
				
			||||||
 | 
					              if($tstDt < $evStDay) { continue; }            // After the recurrence started
 | 
				
			||||||
 | 
					              if(!empty($recurUntil) && $tstDt > $recurUntil) { continue; } // Before it ended
 | 
				
			||||||
 | 
												$recurInt = $anEv->getRecurInterval();
 | 
				
			||||||
 | 
												if($recurInt != 0) {
 | 
				
			||||||
 | 
													// Figure out how many 'FREQ's have passed (weeks in this case)
 | 
				
			||||||
 | 
													// 7 Days in a Week, recurring every $recurInt weeks
 | 
				
			||||||
 | 
													$recurInt *= 7;
 | 
				
			||||||
 | 
													$daysSince = $tstDt->diff($evStTm)->days;
 | 
				
			||||||
 | 
													if($daysSince%$recurInt != 0) {
 | 
				
			||||||
 | 
														continue;
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
												$recurCnt = $anEv->getRecurCount();
 | 
				
			||||||
 | 
												if($recurCnt != 0) {
 | 
				
			||||||
 | 
													// Recurring weekly
 | 
				
			||||||
 | 
													$recurInt = 7;
 | 
				
			||||||
 | 
													$daysSince = $tstDt->diff($evStDay)->days + 1;
 | 
				
			||||||
 | 
													if($daysSince/$recurInt > $recurCnt) {
 | 
				
			||||||
 | 
														// Too many occurrences already
 | 
				
			||||||
 | 
														continue;
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
					              $tstDt->setTime($evStTm->format('H'), $evStTm->format('i'), $evStTm->format('s'));
 | 
				
			||||||
 | 
					              // The recurrence appears to be valid, check the exception dates
 | 
				
			||||||
 | 
					              if($anEv->isExceptionDate($tstDt)) {
 | 
				
			||||||
 | 
					                // An exception for this date
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              $rEv = new ICalEvent();
 | 
				
			||||||
 | 
					              $rEv->setStartDttm(new DateTime($tstDt->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setEndDttm(new DateTime($tstDt->add($evLength)->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setDescription($anEv->getDescription());
 | 
				
			||||||
 | 
					              $rEv->setSummary($anEv->getSummary());
 | 
				
			||||||
 | 
					              $rEv->setLocation($anEv->getLocation());
 | 
				
			||||||
 | 
					              $rEv->setICalTag("RecurringCopy", "true");
 | 
				
			||||||
 | 
					              $ret[] = $rEv;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'MONTHLY':
 | 
				
			||||||
 | 
					            // TODO: TEST
 | 
				
			||||||
 | 
					            $dom = $evStTm->format('d');
 | 
				
			||||||
 | 
					            for($tstDt = new DateTime($stDtTm->format(DATE_RFC3339)); 
 | 
				
			||||||
 | 
					                $tstDt <= $endDtTm; 
 | 
				
			||||||
 | 
					                $tstDt->add(new DateInterval('P1M'))) {
 | 
				
			||||||
 | 
					              if($tstDt->format('d') != $dom) { continue; } // Same day of month
 | 
				
			||||||
 | 
					              if($tstDt < $evStTm) { continue; }            // After the recurrence started
 | 
				
			||||||
 | 
					              if(!empty($recurUntil) && $tstDt > $recurUntil) { continue; } // Before it ended
 | 
				
			||||||
 | 
												// TODO: Check Recurrence Interval
 | 
				
			||||||
 | 
					              $tstDt->setTime($evStTm->format('H'), $evStTm->format('i'), $evStTm->format('s'));
 | 
				
			||||||
 | 
					              $evLength = $evStTm->diff($evEndTm);
 | 
				
			||||||
 | 
					              $rEv = new ICalEvent();
 | 
				
			||||||
 | 
					              $rEv->setStartDttm(new DateTime($tstDt->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setEndDttm(new DateTime($tstDt->add($evLength)->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setDescription($anEv->getDescription());
 | 
				
			||||||
 | 
					              $rEv->setSummary($anEv->getSummary());
 | 
				
			||||||
 | 
					              $rEv->setLocation($anEv->getLocation());
 | 
				
			||||||
 | 
					              $rEv->setICalTag("RecurringCopy", "true");
 | 
				
			||||||
 | 
					              $ret[] = $rEv;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'YEARLY':
 | 
				
			||||||
 | 
					            // TODO: TEST
 | 
				
			||||||
 | 
					            $doy = $evStTm->format('z');
 | 
				
			||||||
 | 
					            for($tstDt = new DateTime($stDtTm->format(DATE_RFC3339)); 
 | 
				
			||||||
 | 
					                $tstDt <= $endDtTm; 
 | 
				
			||||||
 | 
					                $tstDt->add(new DateInterval('P1Y'))) {
 | 
				
			||||||
 | 
					              if($tstDt->format('z') != $doy) { continue; } // Same day of year
 | 
				
			||||||
 | 
					              if($tstDt < $evStTm) { continue; }            // After the recurrence started
 | 
				
			||||||
 | 
					              if(!empty($recurUntil) && $tstDt > $recurUntil) { continue; } // Before it ended
 | 
				
			||||||
 | 
												// TODO: Check Recurrence Interval
 | 
				
			||||||
 | 
					              $tstDt->setTime($evStTm->format('H'), $evStTm->format('i'), $evStTm->format('s'));
 | 
				
			||||||
 | 
					              $evLength = $evStTm->diff($evEndTm);
 | 
				
			||||||
 | 
					              $rEv = new ICalEvent();
 | 
				
			||||||
 | 
					              $rEv->setStartDttm(new DateTime($tstDt->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setEndDttm(new DateTime($tstDt->add($evLength)->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setDescription($anEv->getDescription());
 | 
				
			||||||
 | 
					              $rEv->setSummary($anEv->getSummary());
 | 
				
			||||||
 | 
					              $rEv->setLocation($anEv->getLocation());
 | 
				
			||||||
 | 
					              $rEv->setICalTag("RecurringCopy", "true");
 | 
				
			||||||
 | 
					              $ret[] = $rEv;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'DAILY':
 | 
				
			||||||
 | 
					            // TODO: TEST
 | 
				
			||||||
 | 
					            for($tstDt = new DateTime($stDtTm->format(DATE_RFC3339)); 
 | 
				
			||||||
 | 
					                $tstDt <= $endDtTm; 
 | 
				
			||||||
 | 
					                $tstDt->add(new DateInterval('P1D'))) {
 | 
				
			||||||
 | 
					              if($tstDt < $evStTm) { continue; }            // After the recurrence started
 | 
				
			||||||
 | 
					              if(!empty($recurUntil) && $tstDt > $recurUntil) { continue; } // Before it ended
 | 
				
			||||||
 | 
												// TODO: Check Recurrence Interval
 | 
				
			||||||
 | 
					              $tstDt->setTime($evStTm->format('H'), $evStTm->format('i'), $evStTm->format('s'));
 | 
				
			||||||
 | 
					              $evLength = $evStTm->diff($evEndTm);
 | 
				
			||||||
 | 
					              $rEv = new ICalEvent();
 | 
				
			||||||
 | 
					              $rEv->setStartDttm(new DateTime($tstDt->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setEndDttm(new DateTime($tstDt->add($evLength)->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setDescription($anEv->getDescription());
 | 
				
			||||||
 | 
					              $rEv->setSummary($anEv->getSummary());
 | 
				
			||||||
 | 
					              $rEv->setLocation($anEv->getLocation());
 | 
				
			||||||
 | 
					              $rEv->setICalTag("RecurringCopy", "true");
 | 
				
			||||||
 | 
					              $ret[] = $rEv;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'HOURLY':
 | 
				
			||||||
 | 
					            // TODO: TEST
 | 
				
			||||||
 | 
					            for($tstDt = new DateTime($stDtTm->format(DATE_RFC3339)); 
 | 
				
			||||||
 | 
					                $tstDt <= $endDtTm; 
 | 
				
			||||||
 | 
					                $tstDt->add(new DateInterval('PT1H'))) {
 | 
				
			||||||
 | 
					              if($tstDt < $evStTm) { continue; }            // After the recurrence started
 | 
				
			||||||
 | 
					              if(!empty($recurUntil) && $tstDt > $recurUntil) { continue; } // Before it ended
 | 
				
			||||||
 | 
												// TODO: Check Recurrence Interval
 | 
				
			||||||
 | 
					              $evLength = $evStTm->diff($evEndTm);
 | 
				
			||||||
 | 
					              $rEv = new ICalEvent();
 | 
				
			||||||
 | 
					              $rEv->setStartDttm(new DateTime($tstDt->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setEndDttm(new DateTime($tstDt->add($evLength)->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setDescription($anEv->getDescription());
 | 
				
			||||||
 | 
					              $rEv->setSummary($anEv->getSummary());
 | 
				
			||||||
 | 
					              $rEv->setLocation($anEv->getLocation());
 | 
				
			||||||
 | 
					              $rEv->setICalTag("RecurringCopy", "true");
 | 
				
			||||||
 | 
					              $ret[] = $rEv;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'MINUTELY':
 | 
				
			||||||
 | 
					            // TODO: TEST
 | 
				
			||||||
 | 
					            for($tstDt = new DateTime($stDtTm->format(DATE_RFC3339)); 
 | 
				
			||||||
 | 
					                $tstDt <= $endDtTm; 
 | 
				
			||||||
 | 
					                $tstDt->add(new DateInterval('PT1M'))) {
 | 
				
			||||||
 | 
					              if($tstDt < $evStTm) { continue; }            // After the recurrence started
 | 
				
			||||||
 | 
					              if(!empty($recurUntil) && $tstDt > $recurUntil) { continue; } // Before it ended
 | 
				
			||||||
 | 
												// TODO: Check Recurrence Interval
 | 
				
			||||||
 | 
					              $evLength = $evStTm->diff($evEndTm);
 | 
				
			||||||
 | 
					              $rEv = new ICalEvent();
 | 
				
			||||||
 | 
					              $rEv->setStartDttm(new DateTime($tstDt->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setEndDttm(new DateTime($tstDt->add($evLength)->format(DATE_RFC3339)));
 | 
				
			||||||
 | 
					              $rEv->setDescription($anEv->getDescription());
 | 
				
			||||||
 | 
					              $rEv->setSummary($anEv->getSummary());
 | 
				
			||||||
 | 
					              $rEv->setLocation($anEv->getLocation());
 | 
				
			||||||
 | 
					              $rEv->setICalTag("RecurringCopy", "true");
 | 
				
			||||||
 | 
					              $ret[] = $rEv;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        // Normal Event, just check the dates
 | 
				
			||||||
 | 
					        // If any part of the event takes place in the range, append it
 | 
				
			||||||
 | 
					        if(($evStTm >= $stDtTm && $evStTm < $endDtTm) 
 | 
				
			||||||
 | 
					            || ($evEndTm > $stDtTm && $evEndTm <= $endDtTm)) {
 | 
				
			||||||
 | 
					          $ret[] = $anEv;  
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    usort($ret, "_eventSortHelper");
 | 
				
			||||||
 | 
					    return $ret;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function parseTimezone($lines) {
 | 
				
			||||||
 | 
					    $defaultTZ = 'UTC';
 | 
				
			||||||
 | 
					    foreach($lines as $line) {
 | 
				
			||||||
 | 
					      $line = trim($line);
 | 
				
			||||||
 | 
					      if($line == "END:VTIMEZONE") {
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      $add  = $this->keyValueFromString($line);
 | 
				
			||||||
 | 
					      if ($add === false) {
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      } 
 | 
				
			||||||
 | 
					      list($keyword, $value) = $add;
 | 
				
			||||||
 | 
					      if($keyword == 'TZID') {
 | 
				
			||||||
 | 
					        return $value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return $defaultTZ;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Parses and returns the first event out of $lines
 | 
				
			||||||
 | 
					  public function parseEvent($lines) {
 | 
				
			||||||
 | 
					    $newEvent = new ICalEvent();
 | 
				
			||||||
 | 
					    foreach($lines as $line) {
 | 
				
			||||||
 | 
					      $line = trim($line);
 | 
				
			||||||
 | 
					      if($line == 'END:VEVENT') {
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      $add = $this->keyValueFromString($line);
 | 
				
			||||||
 | 
					      if($add === FALSE) {
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      list($keyword, $value) = $add;
 | 
				
			||||||
 | 
					      $newEvent->setICalTag($keyword, $value);
 | 
				
			||||||
 | 
					      if(stristr($keyword, "DTSTART") 
 | 
				
			||||||
 | 
					            || stristr($keyword, "DTEND")
 | 
				
			||||||
 | 
					            || stristr($keyword, "EXDATE")) {
 | 
				
			||||||
 | 
					        $tz = 'UTC';
 | 
				
			||||||
 | 
					        if(stristr($keyword, ';')) {
 | 
				
			||||||
 | 
					          $keywordPts = explode(';', $keyword);
 | 
				
			||||||
 | 
					          $keyword = $keywordPts[0];
 | 
				
			||||||
 | 
					          $tzPts = $keywordPts[1];
 | 
				
			||||||
 | 
					          $tzPts = explode('=', $tzPts);
 | 
				
			||||||
 | 
					          if($tzPts[0] == 'TZID') {
 | 
				
			||||||
 | 
					            $tz = $tzPts[1];
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if($keyword == 'EXDATE') {
 | 
				
			||||||
 | 
					          // Exception Dates (could be an array)
 | 
				
			||||||
 | 
					          if(stristr($value, ',')) {
 | 
				
			||||||
 | 
					            $exDates = explode(',', $value);
 | 
				
			||||||
 | 
					            foreach($exDates as $exDt) {
 | 
				
			||||||
 | 
					              $date = new DateTime($exDt, new DateTimeZone($tz));
 | 
				
			||||||
 | 
					              $date->setTimezone(new DateTimeZone($this->timezone));
 | 
				
			||||||
 | 
					              $newEvent->addExceptionDate($date);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            $date = new DateTime($value, new DateTimeZone($tz));
 | 
				
			||||||
 | 
					            $date->setTimezone(new DateTimeZone($this->timezone));
 | 
				
			||||||
 | 
					            $newEvent->addExceptionDate($date);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          $date = new DateTime($value, new DateTimeZone($tz));
 | 
				
			||||||
 | 
					          $date->setTimezone(new DateTimeZone($this->timezone));
 | 
				
			||||||
 | 
					          if($keyword == 'DTSTART') {
 | 
				
			||||||
 | 
					            $newEvent->setStartDttm($date);
 | 
				
			||||||
 | 
					          } else if($keyword == 'DTEND') {
 | 
				
			||||||
 | 
					            $newEvent->setEndDttm($date);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      switch($keyword) {
 | 
				
			||||||
 | 
					      case 'RRULE': // Recurrence Rule
 | 
				
			||||||
 | 
					        // http://www.kanzaki.com/docs/ical/rrule.html
 | 
				
			||||||
 | 
					        $pts = explode(';', $value);
 | 
				
			||||||
 | 
					        foreach($pts as $recRules) {
 | 
				
			||||||
 | 
					          $recRulePts = explode('=', $recRules);
 | 
				
			||||||
 | 
					          switch($recRulePts[0]) {
 | 
				
			||||||
 | 
					          case 'FREQ': // (MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY)
 | 
				
			||||||
 | 
					            $newEvent->setRecurFrequency($recRulePts[1]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'INTERVAL': // 1 out of every x of FREQ that it recurs
 | 
				
			||||||
 | 
					            $newEvent->setRecurInterval($recRulePts[1]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'COUNT': // Number of times it recurs
 | 
				
			||||||
 | 
					            $newEvent->setRecurCount($recRulePts[1]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'UNTIL': // Recur until this date
 | 
				
			||||||
 | 
					            // TODO: Create a DateTime
 | 
				
			||||||
 | 
					            $date = new DateTime($recRulePts[1], new DateTimeZone('UTC'));
 | 
				
			||||||
 | 
					            $date->setTimezone(new DateTimeZone($this->timezone));
 | 
				
			||||||
 | 
					            $newEvent->setRecurUntil($date);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'BYMONTH': // idx of months that it recurs (1 indexed)
 | 
				
			||||||
 | 
					            $newEvent->setRecurByMonth($recRulePts[1]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'BYDAY': // (SU,MO,TU,WE,TH,FR,SA)
 | 
				
			||||||
 | 
					            $newEvent->setRecurByDay($recRulePts[1]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'BYMONTHDAY': // idx of day of month, 1 indexed, <0 is from end
 | 
				
			||||||
 | 
					            $newEvent->setRecurByMonthDay($recRulePts[1]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'BYYEARDAY': // idx of day of year
 | 
				
			||||||
 | 
					            $newEvent->setRecurByYearDay($recRulePts[1]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'WKST': // Week Start?
 | 
				
			||||||
 | 
					            $newEvent->setRecurWkSt($recRulePts[1]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case 'DESCRIPTION': // Event Description
 | 
				
			||||||
 | 
					        $newEvent->setDescription($value);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case 'LOCATION': // Event Location
 | 
				
			||||||
 | 
					        $newEvent->setLocation($value);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case 'SUMMARY': // Event Summary
 | 
				
			||||||
 | 
					        $newEvent->setSummary($value);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return $newEvent;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function _parseFindNext($needle, $haystack, $start=0) {
 | 
				
			||||||
 | 
					    $ret = [];
 | 
				
			||||||
 | 
					    for($i = $start; $i < count($haystack); $i++) {
 | 
				
			||||||
 | 
					      if(!empty(trim($haystack[$i]))) {
 | 
				
			||||||
 | 
					        $ret[] = $haystack[$i];
 | 
				
			||||||
 | 
					        if($haystack[$i] == $needle) {
 | 
				
			||||||
 | 
					          return $ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // Didn't find it.
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function keyValueFromString($text) {
 | 
				
			||||||
 | 
					    preg_match("/([^:]+)[:]([\w\W]*)/", $text, $matches);
 | 
				
			||||||
 | 
					    if (count($matches) == 0) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $matches = array_splice($matches, 1, 2);
 | 
				
			||||||
 | 
					    return $matches;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // shortDayToDOWNum takes a 'Recur By Day' value (SU,MO,TU,WE,TH,FR,SA)
 | 
				
			||||||
 | 
					  public function shortDayToDOWNum($shortDay) {
 | 
				
			||||||
 | 
					    switch($shortDay) {
 | 
				
			||||||
 | 
					    case 'SU': return 0;
 | 
				
			||||||
 | 
					    case 'MO': return 1;
 | 
				
			||||||
 | 
					    case 'TU': return 2;
 | 
				
			||||||
 | 
					    case 'WE': return 3;
 | 
				
			||||||
 | 
					    case 'TH': return 4;
 | 
				
			||||||
 | 
					    case 'FR': return 5;
 | 
				
			||||||
 | 
					    case 'SA': return 6;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ICalEvent {
 | 
				
			||||||
 | 
					  private $summary = '';
 | 
				
			||||||
 | 
					  private $description = '';
 | 
				
			||||||
 | 
					  private $location = '';
 | 
				
			||||||
 | 
					  private $isRecurring = false;
 | 
				
			||||||
 | 
					  private $_recurRules = [];
 | 
				
			||||||
 | 
					  private $exceptionDates = [];
 | 
				
			||||||
 | 
					  private $stDtTm;
 | 
				
			||||||
 | 
					  private $endDtTm;
 | 
				
			||||||
 | 
					  private $valid = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private $ICalTags = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function __construct() { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function setSummary($s) { $this->summary = $s; }
 | 
				
			||||||
 | 
					  public function getSummary() { return $this->summary; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function setDescription($s) { $this->description = $s; }
 | 
				
			||||||
 | 
					  public function getDescription() { return $this->description; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function setStartDttm($dttm) { $this->stDtTm = $dttm; }
 | 
				
			||||||
 | 
					  public function getStartDttm() { return $this->stDtTm; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function setEndDttm($dttm) { $this->endDtTm = $dttm; }
 | 
				
			||||||
 | 
					  public function getEndDttm() { return $this->endDtTm; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function setLocation($loc) { $this->location = $loc; }
 | 
				
			||||||
 | 
					  public function getLocation() { return $this->location; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // getDuration returns a DateInterval for how long this event lasts
 | 
				
			||||||
 | 
					  public function getDuration() {
 | 
				
			||||||
 | 
					    return $this->stDtTm->diff($this->endDtTm);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function isValid() {
 | 
				
			||||||
 | 
					    return ($this->stDtTm < $this->endDtTm);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getRecurFlag() {
 | 
				
			||||||
 | 
					    return $this->isRecurring;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getRecurRules() {
 | 
				
			||||||
 | 
					    return $this->_recurRules;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getRecurRule($rule) {
 | 
				
			||||||
 | 
					    if(isset($this->_recurRules[$rule])) {
 | 
				
			||||||
 | 
					      return $this->_recurRules[$rule];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return '';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Frequency to recur
 | 
				
			||||||
 | 
					  public function setRecurFrequency($fr) {
 | 
				
			||||||
 | 
					    if($fr == 'MINUTELY' || $fr == 'HOURLY' || $fr == 'DAILY' 
 | 
				
			||||||
 | 
					          || $fr == 'WEEKLY' || $fr == 'MONTHLY' || $fr == 'YEARLY') {
 | 
				
			||||||
 | 
					      $this->_recurRules['frequency'] = $fr;
 | 
				
			||||||
 | 
					      $this->isRecurring = true;
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  public function getRecurFrequency() {
 | 
				
			||||||
 | 
					    return $this->getRecurRule('frequency');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // One out of every $i of Frequency to occur
 | 
				
			||||||
 | 
					  public function setRecurInterval($i) {
 | 
				
			||||||
 | 
					    $this->_recurRules['interval'] = $i;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  public function getRecurInterval() {
 | 
				
			||||||
 | 
					    return $this->getRecurRule('interval');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // How many times it should recur
 | 
				
			||||||
 | 
					  public function setRecurCount($i) {
 | 
				
			||||||
 | 
					    $this->_recurRules['count'] = $i;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  public function getRecurCount() {
 | 
				
			||||||
 | 
					    return $this->getRecurRule('count');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Date to stop recurring
 | 
				
			||||||
 | 
					  public function setRecurUntil($dt) {
 | 
				
			||||||
 | 
					    $this->_recurRules['until'] = $dt;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  public function getRecurUntil() {
 | 
				
			||||||
 | 
					    return $this->getRecurRule('until');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // array of 1-indexed months to recur on
 | 
				
			||||||
 | 
					  public function setRecurByMonth($mos) {
 | 
				
			||||||
 | 
					    $mos = is_array($mos)?$mos:[$mos];
 | 
				
			||||||
 | 
					    $this->_recurRules['byMonth'] = $mos;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  public function getRecurByMonth() {
 | 
				
			||||||
 | 
					    return $this->getRecurRule('byMonth');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // array of abbreviated days to recur on (SU,MO,TU,WE,TH,FR,SA)
 | 
				
			||||||
 | 
					  public function setRecurByDay($dys) {
 | 
				
			||||||
 | 
					    $dys = is_array($dys)?$dys:[$dys];
 | 
				
			||||||
 | 
					    $this->_recurRules['byDay'] = explode(',',$dys[0]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  public function getRecurByDay() {
 | 
				
			||||||
 | 
					    return $this->getRecurRule('byDay');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // arary of 1-indexed day-of-months to recur on
 | 
				
			||||||
 | 
					  public function setRecurByMonthDay($doms) {
 | 
				
			||||||
 | 
					    $doms = is_array($doms)?$doms:[$doms];
 | 
				
			||||||
 | 
					    $this->_recurRules['byMonthDay'] = $doms;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  public function getRecurByMonthDay() {
 | 
				
			||||||
 | 
					    return $this->getRecurRule('byMonthDay');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // array of 1-indexed day-of-years to recur on
 | 
				
			||||||
 | 
					  public function setRecurByYearDay($doys) {
 | 
				
			||||||
 | 
					    $doys = is_array($doys)?$doys:[$doys];
 | 
				
			||||||
 | 
					    $this->_recurRules['byYearDay'] = $doys;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  public function getRecurByYearDay() {
 | 
				
			||||||
 | 
					    return $this->getRecurRule('byYearDay');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Set the week start day for the recurrence
 | 
				
			||||||
 | 
					  public function setRecurWkSt($wkst) {
 | 
				
			||||||
 | 
					    $this->_recurRules['wkSt'] = $wkst;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  public function getRecurWkSt() {
 | 
				
			||||||
 | 
					    return $this->getRecurRule('wkSt');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function setICalTag($key, $val) {
 | 
				
			||||||
 | 
					    $this->ICalTags[$key] = $val;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function addExceptionDate($dy) {
 | 
				
			||||||
 | 
					    array_push($this->exceptionDates, $dy);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function isExceptionDate($dy) {
 | 
				
			||||||
 | 
					    foreach($this->exceptionDates as $exDt) {
 | 
				
			||||||
 | 
					      if($dy == $exDt) {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function _eventSortHelper($a, $b) {
 | 
				
			||||||
 | 
					  if($a->getStartDttm() == $b->getStartDttm()) {
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return ($a->getStartDttm() > $b->getStartDttm())?1:-1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reference in New Issue
	
	Block a user