value = self::VEVENT; break;
case 'VTODO': $this->value = self::VTODO; break;
case 'VJOURNAL': $this->value = self::VJOURNAL; break;
case 'VFREEBUSY': $this->value = self::VFREEBUSY; break;
case 'VTIMEZONE': $this->value = self::VTIMEZONE; break;
case 'VALARM': $this->value = self::VALARM; break;
case self::VEVENT:
case self::VTODO:
case self::VJOURNAL:
case self::VFREEBUSY:
case self::VTIMEZONE:
case self::VALARM: $this->value = $value; break;
default: throw new Exception ("$value: Invalid VTYPE");
}
}
private function __clone() {}
public function ordinal() {
return $this->value;
}
public function __toString() {
switch ($this->value) {
case self::VEVENT: return 'VEVENT'; break;
case self::VTODO: return 'VTODO'; break;
case self::VJOURNAL: return 'VJOURNAL'; break;
case self::VFREEBUSY: return 'VFREEBUSY'; break;
case self::VTIMEZONE: return 'VTIMEZONE'; break;
case self::VALARM: return 'VALARM'; break;
}
}
}
abstract class CaldavRessource
implements ArrayAccess, IteratorAggregate {
private $client;
function __construct($url, $uid = '', $pwd = '', $cal = '') {
if (empty($url))
throw new Exception("Missing URL");
$this->client = new CalDAVClient($url, $uid, $pwd, $cal);
}
/**
* abstract functions to be implemented by sub classes
*/
abstract function update($url, $etag = NULL);
abstract function newComponent($c_type);
abstract function getComponents($start, $end);
abstract function delete($url, $etag = NULL);
protected function callServer($method, $param = array()) {
$error = TRUE;
$msg = "Unknown error";
if (! is_array($param))
throw new Exception("Parameters must be inclosed in an array");
switch (strtolower($method)) {
case 'getevents':
if (count($param) != 2) {
$error = TRUE;
$msg = "Expected 2 parameters";
break;
}
if ($this->isDateTime($param[0]) &&
$this->isDateTime($param[1])) {
$res = $this->client->GetEvents($param[0], $param[1]);
$error = FALSE;
}
else {
$msg = "[${param[0]},${param[1]}]: Invalid DateTime";
$error = TRUE;
}
break;
case 'getbyuid':
if (count($param) != 1) {
$error = TRUE;
$msg = "Expected 1 parameter";
break;
}
$res = $this->client->GetEntryByUid($param[0]);
$error = FALSE;
break;
case 'put':
if (count($param) < 2 || count($param) > 3) {
$error = TRUE;
$msg = "Syntax: URL, CalDAV_resource[, ETag]";
break;
}
if (count($param) == 2)
$res = $this->client->DoPUTRequest($param[0], $param[1]);
else
$res = $this->client->DoPUTRequest($param[0], $param[1], $param[2]);
$error = FALSE;
break;
case 'delete':
if (count($param) < 1 || count($param) > 2) {
$error = TRUE;
$msg = "Syntax: URL[, ETag]";
break;
}
if (count($param) == 1)
$res = $this->client->DoDELETERequest($param[0]);
else
$res = $this->client->DoDELETERequest($param[0], $param[1]);
$error = FALSE;
break;
default:
throw new Exception("$method: Unknown method");
}
if ($error)
throw new Exception($msg);
else
return $res;
}
static function isDateTime($var) {
return (preg_match("/^([0-9]{8})T([0-9]{6})Z?$/", $var) > 0);
}
/**
* Returned date-time will always be in UTC
*/
static function timestamp2ICal($ts, $localtime = TRUE) {
$ts = (int) $ts;
if ($ts < 0)
throw new Exception("$ts: invalid timestamp");
if ($localtime) {
$date = date('Ymd', $ts);
$time = date('His', $ts);
$res = sprintf("%sT%s", $date, $time);
}
else {
$date = gmdate('Ymd', $ts);
$time = gmdate('His', $ts);
$res = sprintf("%sT%sZ", $date, $time);
}
return $res;
}
static function iCal2Timestamp($ical) {
if (! self::isDateTime($ical)) {
// test for badly formed all-day event
//print "$ical";
$res = preg_match("/^([0-9]{4})([0-9]{2})([0-9]{2})$/",
$ical, $parts);
if ($res == 0)
throw new Exception("$ical: invalid CalDAV Date-Time");
else {
$timepart = array('00', '00', '00');
$parts = array_merge($parts, $timepart);
}
}
else {
$date = "([0-9]{4})([0-9]{2})([0-9]{2})";
$time = "([0-9]{2})([0-9]{2})([0-9]{2})";
preg_match("/^${date}T${time}(Z?)$/", $ical, $parts);
}
if (count($parts) == 8 && ! empty($parts[7]))
return gmmktime($parts[4], $parts[5], $parts[6],
$parts[2], $parts[3], $parts[1]);
else
return mktime($parts[4], $parts[5], $parts[6],
$parts[2], $parts[3], $parts[1]);
}
private static function down_hour($date) {
//print "$date
";
if (! self::isDateTime($date)) {
// test for badly formed all-day event
$res = preg_match("/^([0-9]{4})([0-9]{2})([0-9]{2})$/",
$date, $parts);
if ($res == 0)
throw new Exception("$date: invalid CalDAV Date-Time");
else {
array_shift($parts);
$timepart = array('T', '00', '00', '00');
$parts = array_merge($parts, $timepart);
return implode('', $parts);
}
}
else {
$a = explode('T', $date);
$a[1] = substr_replace($a[1], '0000', 2);
return $a[0].'T'.$a[1];
}
}
static function fix_allday_event(&$date_a, &$date_b) {
//print "$date_a : $date_b
";
if ($date_a == $date_b) {
if (! self::isDateTime($date_a) && ! self::isDateTime($date_b)) {
$res1 = preg_match("/^([0-9]{4})([0-9]{2})([0-9]{2})$/",
$date_a);
$res2 = preg_match("/^([0-9]{4})([0-9]{2})([0-9]{2})$/",
$date_b);
if ($res1 == 0 || $res2 == 0)
throw new Exception("$date_a, $date_b: invalid CalDAV Date-Time");
else {
$date_a .= "T000000";
$date_b .= "T235959";
}
}
else {
preg_match("/^([0-9]{4}[0-9]{2}[0-9]{2})T([0-9]{6})$/",
$date_a, $part_a);
preg_match("/^([0-9]{4}[0-9]{2}[0-9]{2})T([0-9]{6})$/",
$date_b, $part_b);
$date_a = $part_a[1]."T000000";
$date_b = $part_b[1]."T235959";
//print "$date_a : $date_b
";
}
//print "$date_a : $date_b
";
}
}
static function datecmp($date_a, $date_b) {
$date_a = self::iCal2Timestamp($date_a);
$date_b = self::iCal2Timestamp(self::down_hour($date_b));
if ($date_a < $date_b)
$res = -1;
else if ($date_a > $date_b)
$res = 1;
else
$res = 0;
return $res;
}
private static function intcmpstr($a_str, $b_str) {
$a = (int) $a_str;
$b = (int) $b_str;
//print "$a:$b
";
if ($a > $b)
return 1;
else if ($a < $b)
return -1;
else
return 0;
}
static function cmpdate($date_a, $date_b) {
$datepart = explode('T', $date_a);
$d_a = $datepart[0];
$datepart = explode('T', $date_b);
$d_b = $datepart[0];
$y_cmp = self::intcmpstr(substr($d_a, 0, 4), substr($d_b, 0, 4));
if ($y_cmp == 0) {
$m_cmp = self::intcmpstr(substr($d_a, 4, 2), substr($d_b, 4, 2));
if ($m_cmp == 0) {
return self::intcmpstr(substr($d_a, 6, 2), substr($d_b, 6, 2));
}
return $m_cmp;
}
return $y_cmp;
}
static function cmptime($time_a, $time_b) {
$timepart = explode('T', $time_a);
$t_a = $timepart[1];
$timepart = explode('T', $time_b);
$t_b = $timepart[1];
//print "$t_a:$t_b
";
$h_cmp = self::intcmpstr(substr($t_a, 0, 2), substr($t_b, 0, 2));
if ($h_cmp == 0) {
$m_cmp = self::intcmpstr(substr($t_a, 2, 2), substr($t_b, 2, 2));
if ($m_cmp == 0) {
return self::intcmpstr(substr($t_a, 4, 2), substr($t_b, 4, 2));
}
return $m_cmp;
}
return $h_cmp;
}
static function allDayEvent($time_a, $time_b) {
//echo $time_a.':'.$time_b.'
';
$a = explode('T', $time_a);
if (count($a) < 2)
array_push($a, '0000');
$b = explode('T', $time_b);
if (count($b) < 2)
array_push($b, '0000');
$t = strtotime($time_b) - 3600;
$t = date("Ymd\THm", $t);
return (self::cmpdate($time_a, $t) == 0 &&
$a[1] == '0000' && $b[1] == '0000');
}
}