diff --git a/CalDAVClient.php b/CalDAVClient.php index 10a2eb6..89f0a16 100644 --- a/CalDAVClient.php +++ b/CalDAVClient.php @@ -1065,7 +1065,7 @@ function GetEntryByUid( $uid, $relative_url = null ) { * * @param string $href The href from a call to GetEvents or GetTodos etc. * - * @return string The iCalendar of the calendar entry + * @return array The iCalendar of the calendar entry */ function GetEntryByHref( $href ) { //$href = str_replace( rawurlencode('/'),'/',rawurlencode($href)); diff --git a/CalDAVObject.php b/CalDAVObject.php index 6cf94c4..df5324a 100644 --- a/CalDAVObject.php +++ b/CalDAVObject.php @@ -16,6 +16,7 @@ * The assignment of an entity tag ensures, that you know what you are changing/deleting. It ensures, that no one * changed the resource between your viewing of the resource and your change/delete-request. Assigning an entity tag * provides you of accidently destroying the work of others. + * cal: The {@link CalDAVCalendar} this object belongs to. * * @package simpleCalDAV * @@ -26,26 +27,49 @@ class CalDAVObject { private $data; private $etag; - public function __construct ($href, $data, $etag) { + /** + * @param string $href + * @param string $data + * @param string $etag + * @param CalDAVCalendar|null $cal + */ + public function __construct ($href, $data, $etag, $cal = null) { $this->href = $href; $this->data = $data; $this->etag = $etag; + $this->cal = $cal; } // Getter - + /** + * @return string + */ public function getHref () { return $this->href; } + /** + * @return string + */ public function getData () { return $this->data; } + /** + * @return string + */ public function getEtag () { return $this->etag; } + + /** + * Returns the {@link CalDAVCalendar} this object belongs to. + * @return CalDAVCalendar|null + */ + public function getCalendar() { + return $this->cal; + } } ?> \ No newline at end of file diff --git a/README b/README deleted file mode 100644 index cd39f07..0000000 --- a/README +++ /dev/null @@ -1,59 +0,0 @@ -simpleCalDAV - -Copyright 2014 Michael Palm - -Table of content -1. About -2. Requirements -3. Installation -4. How to get started -5. Example Code - ------------------------- - -1. About - -simpleCalDAV is a php library that allows you to connect to a calDAV-server to get event-, todo- and free/busy-calendar resources from the server, to change them, to delete them, to create new ones, etc. -simpleCalDAV was made and tested for connections to the CalDAV-server Baikal 0.2.7. But it should work with any other CalDAV-server too. - -It contains the following functions: - - connect() - - findCalendars() - - setCalendar() - - create() - - change() - - delete() - - getEvents() - - getTODOs() - - getCustomReport() - -All of those functions are really easy to use, self-explanatory and are deliverd with a big innitial comment, which explains all needed arguments and the return values. - -This library is heavily based on AgenDAV caldav-client-v2.php by Jorge López Pérez which again is heavily based on DAViCal caldav-client-v2.php by Andrew McMillan . -Actually, I hardly added any features. The main point of my work is to make everything straight forward and easy to use. You can use simpleCalDAV whithout a deeper understanding of the calDAV-protocol. - - -2. Requirements - -Requirements of this library are - - The php extension cURL ( http://www.php.net/manual/en/book.curl.php ) - - -3. Installation - -Just navigate into a directory on your server and execute -git clone https://github.com/wvrzel/simpleCalDAV.git - -Assure yourself that cURL is installed. - -Import SimpleCalDAVClient.php in your code and you are ready to go ;-) - - -4. How to get started - -Read the comments in SimpleCalDAVClient.php and the example code. - - -5. Example Code - -Example code is provided under "/example code/". diff --git a/README.md b/README.md new file mode 100644 index 0000000..6af1a71 --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +simpleCalDAV +============ + +Copyright 2014 Michael Palm + +Table of contents +----------------- + +1. [About](#1-about) +2. [Requirements](#2-requirements) +3. [Installation](#3-installation) +4. [How to get started](#4-how-to-get-started) +5. [Example Code](#5-example-code) + +------------------------ + +## 1. About + +simpleCalDAV is a php library that allows you to connect to a calDAV-server to get event-, todo- +and free/busy-calendar resources from the server, to change them, to delete them, to create new +ones, etc. +simpleCalDAV was made and tested for connections to the CalDAV-server Baikal 0.2.7. But it should +work with any other CalDAV-server too. + +It contains the following functions: + - connect() + - findCalendars() + - setCalendar() + - getCalendar() + - create() + - change() + - delete() + - getEvents() + - getAllEvents() + - getTODOs() + - getAllTODOs() + - getCustomReport() + +All of those functions are really easy to use, self-explanatory and are delivered with a big initial +comment, which explains all needed arguments and the return values. + +This library is heavily based on AgenDAV caldav-client-v2.php by Jorge López Pérez +which again is heavily based on DAViCal caldav-client-v2.php by Andrew McMillan +. +Actually, I hardly added any features. The main point of my work is to make everything straight +forward and easy to use. You can use simpleCalDAV without a deeper understanding of the +calDAV-protocol. + + +## 2. Requirements + +Requirements of this library are + - The php extension cURL ( http://www.php.net/manual/en/book.curl.php ) + + +## 3. Installation + +Just navigate into a directory on your server and execute + + git clone https://github.com/wvrzel/simpleCalDAV.git + +Assure yourself that cURL is installed. + +Import `SimpleCalDAVClient.php` in your code and you are ready to go ;-) + + +## 4. How to get started + +Read the comments in `SimpleCalDAVClient.php` and the example code. + + +## 5. Example Code + +Example code is provided under "/example code/". diff --git a/SimpleCalDAVClient.php b/SimpleCalDAVClient.php index 2cebbea..10832d4 100644 --- a/SimpleCalDAVClient.php +++ b/SimpleCalDAVClient.php @@ -14,11 +14,14 @@ * - connect() * - findCalendars() * - setCalendar() + * - getCalendar() * - create() * - change() * - delete() * - getEvents() + * - getAllEvents() * - getTODOs() + * - getAllTODOs() * - getCustomReport() * * All of those functions - except the last one - are realy easy to use, self-explanatory and are @@ -48,6 +51,10 @@ require_once('CalDAVObject.php'); class SimpleCalDAVClient { + + /** @var CalDAVCalendar|null $calendar The currently set calendar. */ + private $calendar; + /** @var CalDAVClient $client */ private $client; private $url; @@ -56,15 +63,15 @@ class SimpleCalDAVClient { * Connects to a CalDAV-Server. * * Arguments: - * @param $url URL to the CalDAV-server. E.g. http://exam.pl/baikal/cal.php/username/calendername/ - * @param $user Username to login with - * @param $pass Password to login with + * @param string $url URL to the CalDAV-server. E.g. http://exam.pl/baikal/cal.php/username/calendername/ + * @param string $user Username to login with + * @param string $pass Password to login with * * Debugging: * @throws CalDAVException - * For debugging purposes, just sorround everything with try { ... } catch (Exception $e) { echo $e->__toString(); } + * For debugging purposes, just surround everything with try { ... } catch (Exception $e) { echo $e->__toString(); } */ - function connect ( $url, $user, $pass ) + public function connect ( $url, $user, $pass ) { // Connect to CalDAV-Server and log in @@ -74,7 +81,7 @@ function connect ( $url, $user, $pass ) if( ! $client->isValidCalDAVServer() ) { - if( $client->GetHttpResultCode() == '401' ) // unauthorisized + if( $client->GetHttpResultCode() == '401' ) // unauthorized { throw new CalDAVException('Login failed', $client); } @@ -89,7 +96,7 @@ function connect ( $url, $user, $pass ) // Check for errors if( $client->GetHttpResultCode() != '200' ) { - if( $client->GetHttpResultCode() == '401' ) // unauthorisized + if( $client->GetHttpResultCode() == '401' ) // unauthorized { throw new CalDAVException('Login failed', $client); } @@ -101,7 +108,7 @@ function connect ( $url, $user, $pass ) else // Unknown status { - throw new CalDAVException('Recieved unknown HTTP status while checking the connection after establishing it', $client); + throw new CalDAVException('Received unknown HTTP status while checking the connection after establishing it', $client); } } @@ -114,15 +121,15 @@ function connect ( $url, $user, $pass ) * Requests a list of all accessible calendars on the server * * Return value: - * @return an array of CalDAVCalendar-Objects (see CalDAVCalendar.php), representing all calendars accessible by the current principal (user). + * @return CalDAVCalendar[] an array of CalDAVCalendar-Objects (see CalDAVCalendar.php), representing all calendars accessible by the current principal (user). * * Debugging: - * @throws CalDAVException - * For debugging purposes, just sorround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } + * @throws Exception + * For debugging purposes, just surround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } */ - function findCalendars() + public function findCalendars() { - if(!isset($this->client)) throw new Exception('No connection. Try connect().'); + $this->checkClient(); return $this->client->FindCalendars(true); } @@ -130,21 +137,26 @@ function findCalendars() /** * function setCalendar() * - * Sets the actual calendar to work with + * Sets the current calendar to work with + * + * Arguments: + * @param CalDAVCalendar $calendar Calendar to be set as current calendar. * * Debugging: - * @throws CalDAVException - * For debugging purposes, just sorround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } + * @throws Exception + * For debugging purposes, just surround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } */ - function setCalendar ( CalDAVCalendar $calendar ) + public function setCalendar ( CalDAVCalendar $calendar ) { - if(!isset($this->client)) throw new Exception('No connection. Try connect().'); + if (!isset($calendar)) return; + + $this->checkClient(); + $this->calendar = $calendar; $this->client->SetCalendar($this->client->first_url_part.$calendar->getURL()); - // Is there a '/' at the end of the calendar_url? - if ( ! preg_match( '#^.*?/$#', $this->client->calendar_url, $matches ) ) { $this->url = $this->client->calendar_url.'/'; } - else { $this->url = $this->client->calendar_url; } + // Add trailing slash to url if not already existing. + $this->url = preg_replace('#(?client->calendar_url); } /** @@ -152,21 +164,21 @@ function setCalendar ( CalDAVCalendar $calendar ) * Creates a new calendar resource on the CalDAV-Server (event, todo, etc.). * * Arguments: - * @param $cal iCalendar-data of the resource you want to create. - * Notice: The iCalendar-data contains the unique ID which specifies where the event is being saved. + * @param string $cal iCalendar-data of the resource you want to create. + * Notice: The iCalendar-data contains the unique ID which specifies where the event is being saved. * * Return value: - * @return An CalDAVObject-representation (see CalDAVObject.php) of your created resource + * @return CalDAVObject An CalDAVObject-representation (see CalDAVObject.php) of your created resource * * Debugging: + * @throws Exception * @throws CalDAVException - * For debugging purposes, just sorround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } + * For debugging purposes, just surround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } */ - function create ( $cal ) + public function create ( $cal ) { // Connection and calendar set? - if(!isset($this->client)) throw new Exception('No connection. Try connect().'); - if(!isset($this->client->calendar_url)) throw new Exception('No calendar selected. Try findCalendars() and setCalendar().'); + $this->checkCalendar(); // Parse $cal for UID if (! preg_match( '#^UID:(.*?)\r?\n?$#m', $cal, $matches ) ) { throw new Exception('Can\'t find UID in $cal'); } @@ -176,12 +188,12 @@ function create ( $cal ) $result = $this->client->GetEntryByHref( $this->url.$uid.'.ics' ); if ( $this->client->GetHttpResultCode() == '200' ) { throw new CalDAVException($this->url.$uid.'.ics already exists. UID not unique?', $this->client); } else if ( $this->client->GetHttpResultCode() == '404' ); - else throw new CalDAVException('Recieved unknown HTTP status', $this->client); + else throw new CalDAVException('Received unknown HTTP status', $this->client); // Put it! $newEtag = $this->client->DoPUTRequest( $this->url.$uid.'.ics', $cal ); - - // PUT-request successfull? + + // PUT-request successful? if ( $this->client->GetHttpResultCode() != '201' ) { if ( $this->client->GetHttpResultCode() == '204' ) // $url.$uid.'.ics' already existed on server @@ -191,11 +203,11 @@ function create ( $cal ) else // Unknown status { - throw new CalDAVException('Recieved unknown HTTP status', $this->client); + throw new CalDAVException('Received unknown HTTP status', $this->client); } } - return new CalDAVObject($this->url.$uid.'.ics', $cal, $newEtag); + return new CalDAVObject($this->url.$uid.'.ics', $cal, $newEtag, $this->calendar); } /** @@ -203,28 +215,28 @@ function create ( $cal ) * Changes a calendar resource (event, todo, etc.) on the CalDAV-Server. * * Arguments: - * @param $href See CalDAVObject.php - * @param $cal The new iCalendar-data that should be used to overwrite the old one. - * @param $etag See CalDAVObject.php + * @param string $href See CalDAVObject.php + * @param string $new_data The new iCalendar-data that should be used to overwrite the old one. + * @param string $etag See CalDAVObject.php * * Return value: - * @return An CalDAVObject-representation (see CalDAVObject.php) of your changed resource + * @return CalDAVObject An CalDAVObject-representation (see CalDAVObject.php) of your changed resource * * Debugging: + * @throws Exception * @throws CalDAVException - * For debugging purposes, just sorround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } + * For debugging purposes, just surround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } */ - function change ( $href, $new_data, $etag ) + public function change ( $href, $new_data, $etag ) { // Connection and calendar set? - if(!isset($this->client)) throw new Exception('No connection. Try connect().'); - if(!isset($this->client->calendar_url)) throw new Exception('No calendar selected. Try findCalendars() and setCalendar().'); + $this->checkCalendar(); // Does $href exist? $result = $this->client->GetEntryByHref($href); - if ( $this->client->GetHttpResultCode() == '200' ); + if ( $this->client->GetHttpResultCode() == '200' ); else if ( $this->client->GetHttpResultCode() == '404' ) throw new CalDAVException('Can\'t find '.$href.' on the server', $this->client); - else throw new CalDAVException('Recieved unknown HTTP status', $this->client); + else throw new CalDAVException('Received unknown HTTP status', $this->client); // $etag correct? if($result[0]['etag'] != $etag) { throw new CalDAVException('Wrong entity tag. The entity seems to have changed.', $this->client); } @@ -232,32 +244,32 @@ function change ( $href, $new_data, $etag ) // Put it! $newEtag = $this->client->DoPUTRequest( $href, $new_data, $etag ); - // PUT-request successfull? + // PUT-request successful? if ( $this->client->GetHttpResultCode() != '204' && $this->client->GetHttpResultCode() != '200' ) { - throw new CalDAVException('Recieved unknown HTTP status', $this->client); + throw new CalDAVException('Received unknown HTTP status', $this->client); } - return new CalDAVObject($href, $new_data, $newEtag); + return new CalDAVObject($href, $new_data, $newEtag, $this->calendar); } /** * function delete() - * Delets an event or a TODO from the CalDAV-Server. + * Deletes an event or a TODO from the CalDAV-Server. * * Arguments: - * @param $href See CalDAVObject.php - * @param $etag See CalDAVObject.php + * @param string $href See CalDAVObject.php + * @param string $etag See CalDAVObject.php * * Debugging: + * @throws Exception * @throws CalDAVException - * For debugging purposes, just sorround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } + * For debugging purposes, just surround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } */ - function delete ( $href, $etag ) + public function delete ( $href, $etag ) { // Connection and calendar set? - if(!isset($this->client)) throw new Exception('No connection. Try connect().'); - if(!isset($this->client->calendar_url)) throw new Exception('No calendar selected. Try findCalendars() and setCalendar().'); + $this->checkCalendar(); // Does $href exist? $result = $this->client->GetEntryByHref($href); @@ -269,104 +281,184 @@ function delete ( $href, $etag ) // Do the deletion $this->client->DoDELETERequest($href, $etag); - // Deletion successfull? + // Deletion successful? if ( $this->client->GetHttpResultCode() != '200' and $this->client->GetHttpResultCode() != '204' ) { - throw new CalDAVException('Recieved unknown HTTP status', $this->client); + throw new CalDAVException('Received unknown HTTP status', $this->client); } } /** * function getEvents() - * Gets a all events from the CalDAV-Server which lie in a defined time interval. + * Gets all events from the current calendar on the CalDAV-Server which lie in a defined time + * interval. * * Arguments: - * @param $start The starting point of the time interval. Must be in the format yyyymmddThhmmssZ and should be in - * GMT. If omitted the value is set to -infinity. - * @param $end The end point of the time interval. Must be in the format yyyymmddThhmmssZ and should be in - * GMT. If omitted the value is set to +infinity. + * @param DateTime|string|null $start The starting point of the time interval. Must be in the format yyyymmddThhmmssZ and should be in + * GMT. If omitted the value is set to -infinity. + * @param DateTime|string|null $end The end point of the time interval. Must be in the format yyyymmddThhmmssZ and should be in + * GMT. If omitted the value is set to +infinity. * * Return value: - * @return an array of CalDAVObjects (See CalDAVObject.php), representing the found events. + * @return \CalDAVObject[] an array of CalDAVObjects (See CalDAVObject.php), representing the found events. * * Debugging: + * @throws Exception * @throws CalDAVException - * For debugging purposes, just sorround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } + * For debugging purposes, just surround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } */ - function getEvents ( $start = null, $end = null ) + public function getEvents ( $start = null, $end = null ) { // Connection and calendar set? - if(!isset($this->client)) throw new Exception('No connection. Try connect().'); - if(!isset($this->client->calendar_url)) throw new Exception('No calendar selected. Try findCalendars() and setCalendar().'); + $this->checkCalendar(); // Are $start and $end in the correct format? - if ( ( isset($start) and ! preg_match( '#^\d\d\d\d\d\d\d\dT\d\d\d\d\d\dZ$#', $start, $matches ) ) - or ( isset($end) and ! preg_match( '#^\d\d\d\d\d\d\d\dT\d\d\d\d\d\dZ$#', $end, $matches ) ) ) - { trigger_error('$start or $end are in the wrong format. They must have the format yyyymmddThhmmssZ and should be in GMT', E_USER_ERROR); } - + $start = $this->convertToGmtString($start); + $end = $this->convertToGmtString($end); + // Get it! $results = $this->client->GetEvents( $start, $end ); - // GET-request successfull? + // GET-request successful? if ( $this->client->GetHttpResultCode() != '207' ) { - throw new CalDAVException('Recieved unknown HTTP status', $this->client); + throw new CalDAVException('Received unknown HTTP status', $this->client); } // Reformat $report = array(); - foreach($results as $event) $report[] = new CalDAVObject($this->url.$event['href'], $event['data'], $event['etag']); + foreach($results as $event) $report[] = new CalDAVObject($this->url.$event['href'], $event['data'], $event['etag'], $this->calendar); return $report; } + + /** + * Returns all the events from all available calendars passing its parameters directly to + * {@link getEvents}. + * + * @param DateTime|string|null $start Interval start as either DateTime object or GMT string (yyyymmddThhmmssZ). + * @param DateTime|string|null $end Interval end as either DateTime object or GMT string (yyyymmddThhmmssZ). + * + * @return CalDAVObject[] + * + * @throws Exception + * @throws CalDAVException + */ + public function getAllEvents($start = null, $end = null) + { + // remember the current calendar + $current_calendar = $this->getCalendar(); + + // fetch all events + $events = array(); + foreach ($this->findCalendars() as $calendar) { + $this->setCalendar($calendar); + $events[] = $this->getEvents($start, $end); + } + + // flatten two dimensional array + if (!empty($events)) + $events = call_user_func_array('array_merge', $events); + + // restore previously set calendar + if (isset($current_calendar)) + $this->setCalendar($current_calendar); + + return $events; + } /** * function getTODOs() - * Gets a all TODOs from the CalDAV-Server which lie in a defined time interval and match the - * given criteria. + * Gets all TODOs from the current calendar on the CalDAV-Server which lie in a defined time + * interval and match the given criteria. * * Arguments: - * @param $start The starting point of the time interval. Must be in the format yyyymmddThhmmssZ and should be in - * GMT. If omitted the value is set to -infinity. - * @param $end The end point of the time interval. Must be in the format yyyymmddThhmmssZ and should be in - * GMT. If omitted the value is set to +infinity. - * @param $complete Filter for completed tasks (true) or for uncompleted tasks (false). If omitted, the function will return both. - * @param $cancelled Filter for cancelled tasks (true) or for uncancelled tasks (false). If omitted, the function will return both. + * @param DateTime|string|null $start The starting point of the time interval. Must be in the format yyyymmddThhmmssZ and should be in + * GMT. If omitted the value is set to -infinity. + * @param DateTime|string|null $end The end point of the time interval. Must be in the format yyyymmddThhmmssZ and should be in + * GMT. If omitted the value is set to +infinity. + * @param bool|null $completed Filter for completed tasks (true) or for uncompleted tasks (false). If omitted, the function will return both. + * @param bool|null $cancelled Filter for cancelled tasks (true) or for uncancelled tasks (false). If omitted, the function will return both. * * Return value: - * @return an array of CalDAVObjects (See CalDAVObject.php), representing the found TODOs. + * @return CalDAVObject[] an array of CalDAVObjects (See CalDAVObject.php), representing the found TODOs. * * Debugging: + * @throws Exception * @throws CalDAVException - * For debugging purposes, just sorround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } + * For debugging purposes, just surround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } */ - function getTODOs ( $start = null, $end = null, $completed = null, $cancelled = null ) + public function getTODOs ( $start = null, $end = null, $completed = null, $cancelled = null ) { // Connection and calendar set? - if(!isset($this->client)) throw new Exception('No connection. Try connect().'); - if(!isset($this->client->calendar_url)) throw new Exception('No calendar selected. Try findCalendars() and setCalendar().'); + $this->checkCalendar(); // Are $start and $end in the correct format? - if ( ( isset($start) and ! preg_match( '#^\d\d\d\d\d\d\d\dT\d\d\d\d\d\dZ$#', $start, $matches ) ) - or ( isset($end) and ! preg_match( '#^\d\d\d\d\d\d\d\dT\d\d\d\d\d\dZ$#', $end, $matches ) ) ) - { trigger_error('$start or $end are in the wrong format. They must have the format yyyymmddThhmmssZ and should be in GMT', E_USER_ERROR); } - + $start = $this->convertToGmtString($start); + $end = $this->convertToGmtString($end); + // Get it! $results = $this->client->GetTodos( $start, $end, $completed, $cancelled ); - // GET-request successfull? + // GET-request successful? if ( $this->client->GetHttpResultCode() != '207' ) { - throw new CalDAVException('Recieved unknown HTTP status', $this->client); + throw new CalDAVException('Received unknown HTTP status', $this->client); } // Reformat $report = array(); - foreach($results as $event) $report[] = new CalDAVObject($this->url.$event['href'], $event['data'], $event['etag']); + foreach($results as $event) $report[] = new CalDAVObject($this->url.$event['href'], $event['data'], $event['etag'], $this->calendar); return $report; } - + + /** + * Returns all the TODOs from all available calendars passing its parameters directly to + * {@link getTodos}. + * + * @param DateTime|string|null $start Interval start as either DateTime object or GMT string (yyyymmddThhmmssZ). + * @param DateTime|string|null $end Interval end as either DateTime object or GMT string (yyyymmddThhmmssZ). + * @param bool|null $completed Returns completed (true), uncompleted (false) or both (null). + * @param bool|null $cancelled Returns cancelled (true), uncancelled (false) or both (null). + * + * @return CalDAVObject[] + * + * @throws Exception + * @throws CalDAVException + */ + public function getAllTODOs($start = null, $end = null, $completed = null, $cancelled = null) + { + // remember the current calendar + $current_calendar = $this->getCalendar(); + + // fetch all TODOs + $todos = array(); + foreach ($this->findCalendars() as $calendar) { + $this->setCalendar($calendar); + $todos[] = $this->getTODOs($start, $end, $completed, $cancelled); + } + + // flatten two dimensional array + if (!empty($todos)) + $todos = call_user_func_array('array_merge', $todos); + + // restore previously set calendar + if (isset($current_calendar)) + $this->setCalendar($current_calendar); + + return $todos; + } + + /** + * Returns the currently selected {@link CalDAVCalendar calendar} or null if none is selected. + * @return CalDAVCalendar|null + */ + public function getCalendar() + { + return $this->calendar; + } + /** * function getCustomReport() * Sends a custom request to the server @@ -377,20 +469,20 @@ function getTODOs ( $start = null, $end = null, $completed = null, $cancelled = * See http://www.rfcreader.com/#rfc4791_line1524 for more information about how to write filters on your own. * * Arguments: - * @param $filterXML The stuff, you want to send encapsulated in the -tag. + * @param string $filterXML The stuff, you want to send encapsulated in the -tag. * * Return value: - * @return an array of CalDAVObjects (See CalDAVObject.php), representing the found calendar resources. + * @return CalDAVObject[] an array of CalDAVObjects (See CalDAVObject.php), representing the found calendar resources. * * Debugging: + * @throws Exception * @throws CalDAVException - * For debugging purposes, just sorround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } + * For debugging purposes, just surround everything with try { ... } catch (Exception $e) { echo $e->__toString(); exit(-1); } */ - function getCustomReport ( $filterXML ) + public function getCustomReport ( $filterXML ) { // Connection and calendar set? - if(!isset($this->client)) throw new Exception('No connection. Try connect().'); - if(!isset($this->client->calendar_url)) throw new Exception('No calendar selected. Try findCalendars() and setCalendar().'); + $this->checkCalendar(); // Get report! $this->client->SetDepth('1'); @@ -398,18 +490,70 @@ function getCustomReport ( $filterXML ) // Get it! $results = $this->client->DoCalendarQuery(''.$filterXML.''); - // GET-request successfull? + // GET-request successful? if ( $this->client->GetHttpResultCode() != '207' ) { - throw new CalDAVException('Recieved unknown HTTP status', $this->client); + throw new CalDAVException('Received unknown HTTP status', $this->client); } // Reformat $report = array(); - foreach($results as $event) $report[] = new CalDAVObject($this->url.$event['href'], $event['data'], $event['etag']); + foreach($results as $event) $report[] = new CalDAVObject($this->url.$event['href'], $event['data'], $event['etag'], $this->calendar); return $report; } + + /** + * Checks whether a calendar is selected and throws an exception if not. Also calls {@link checkClient} before. + * @throws Exception + * @return bool + */ + protected function checkCalendar() + { + $this->checkClient(); + if (!isset($this->client->calendar_url)) + throw new Exception('No calendar selected. Try findCalendars() and setCalendar().'); + + return true; + } + + /** + * Checks whether the client is set properly and throws an exception if not. + * @throws Exception + * @return bool + */ + protected function checkClient() + { + if (!isset($this->client)) + throw new Exception('No connection. Try connect().'); + + return true; + } + + /** + * Converts the given time to a string in the following format: yyyymmddThhmmssZ where T and Z + * are the letters themselves. + * @param DateTime|string|null $time Time to be converted. When given as null it will be + * directly returned as null. When given as string in a wrong format an error will get + * triggered. + * @return null|string + */ + protected function convertToGmtString($time) + { + if (!isset($time)) return null; + + // Convert $time from DateTime object to string in GMT/UTC time. + if ($time instanceof DateTime) + { + $time->setTimezone(new DateTimeZone('GMT')); + $time = $time->format('Ymd\THis\Z'); + } + // Check format + elseif ( ! preg_match( '/^\d{8}T\d{6}Z$/', $time ) ) + trigger_error('$start or $end are in the wrong format. They must have the format yyyymmddThhmmssZ and should be in GMT', E_USER_ERROR); + + return $time; + } } ?>