EGCal - A Google Calendar Extension for Yii
EGCal is available on Github for Download:
Extensions, updates, and other news can be found on my blog
EGCal is a simple extension that enables Yii Applications to communicate with Google Calendar.
EGCal works by making a autorization request to Google Calendar via ClientLogin. All subsequent requests are then made through a single connection.
One of the projects I was working on required me to retrieve events from Google Calendar. I didn't see any good classes that were simple or intuitive to use, so I decided to build my own. The purpose of this class is to provide a simple interface between the programmer and Google Calendar. Once I have completed this class in it's entirety I may consider building an OAuth version of the class to use with Google Calendar API 3.0.
PHP 5.3+
Yii Framework 1.1.x
php-curl installed
Usage
Yii::import('application.extensions.EGCal.EGCal');
You have a couple of options here. All you need to do to get it working is to call:
$cal = new EGCal('username@gmail.com', 'gmail-password');
If you would like EGCal to provide debugging text:
$cal = new EGCal('username@gmail.com', 'gmail-password', TRUE);
By default, EGCal uses your application name (Yii::app()->name) for the source request identifier. This can be easily altered by calling (with debugging disable)
$cal = new EGCal('username@gmail.com', 'gmail-password', FALSE, 'companyName-applicationName-versionID');
Calendars (calendar id's) must be either own be owned by the user or granted read/write access to the calendar. Timezones should also be appropriatly set within Google Calendar.
Retrieving events can be done by calling find() as such:
$response = $cal->find( array( 'min'=>date('c', strtotime("8 am")), 'max'=>date('c', strtotime("5 pm")), 'limit'=>50, 'order'=>'a', 'calendar_id'=>'#stardate@group.v.calendar.google.com' ) );
The fields min, max, and calendar_id are required. The fields limit and order are option, and default to 50, and ascending respectivly.
The min and max times should be in ISO 8601 date format [ date('c') ], and may require a timezone offset.
Sometimes events may appear to be several hours off. This is due to the timezone of your Google Calendar differing from that of your PHP System Time. This can be easily corrected by modifying the calendar settings, and/or offseting the min and max request times by a timezone offset.
Responses will take the form of a php array, containing the total number of events , and an array of events. Each event will contain the calendar ID, the start and end times, and the title of the event.
For example:
Array ( [totalResults] => z [events] => Array ( [0] => Array ( [id] => n9af6k7fpbh4p90snih1vfe1bc [start] => 2011-12-19T08:20:00.000-06:00 [end] => 2011-12-19T08:40:00.000-06:00 [title] => Meeting with Josh ) [1] => Array ( [id] => ux5ohbtgbr0u2tk6cyivsi8tj9 [start] => 2011-12-19T15:30:00.000-06:00 [end] => 2011-12-19T17:00:00.000-06:00 [title] => Meeting with Jane ) [...] ) )
Single events can be created with the following format
$response = $cal->create( array( 'start'=>date('c', strtotime("4 pm")), 'end'=>date('c', strtotime("5 pm")), 'title'=>'Appointment with Jane', 'details'=>'Talk about business proposal', 'location'=>'My Office', 'calendar_id'=>'#stardate@group.v.calendar.google.com' ) );
As with retrieving events, you may have to offset your start and end times depending on your timezone.
An unsuccessful response will return an empty array
A successful response will look as follows:
Array ( [id] => GoogleCalendarID [title] => Appointment with Jane [details] => Talk about business proposal [location] => My Office [start] => 2011-12-19T16:00:00.000-06:00 [end] => 2011-12-19T17:00:00.000-06:00 )
Updating events is very simmilar to creating them, with the sole exception that with the request, you also pass the event_id you wish to update. Such a request may look as follows
$response = $cal->update( array( 'id'=>'calendar_id', 'start'=>date('c', strtotime("4 pm")), 'end'=>date('c', strtotime("5 pm")), 'title'=>'Appointment with Jane', 'details'=>'Talk about business proposal', 'location'=>'My Office', 'calendar_id'=>'#stardate@group.v.calendar.google.com' ) );
A successful response will look as follows:
Array ( [id] => GoogleCalendarID [title] => Appointment with Jane [details] => Talk about business proposal [location] => My Office [start] => 2011-12-19T16:00:00.000-06:00 [end] => 2011-12-19T17:00:00.000-06:00 )
Single events can be deleted by calling the delete method. Deleting an event requires both the specific event_id you with to delete, and the calendar_id that event belongs to.
For example:
$response = $cal->delete( array( 'id'=>'9u5fj46m0fcd8scb3dohds2kso', 'calendar_id'=>'#stardate@group.v.calendar.google.com' ) );
The delete method will return true if the event was deleted, and false if the event could not be deleted. If logging is enabled, the response code and message from Google will be provided.
Total 13 comments
The method itself re-wraps everything in the date('c'... call simply so it can handle other issues that may come up. The date function shouldn't have a problem handling something already date-ified. Additionally, the front end is setup to make it easier on the programmer. What is actually passed to Google Calendar is not the same data set that is passed to the method itself.
If you're unable to get the issue resolved, I recommend checking out Google's official Calendar API (v3), as this one will reach EOL (v2 will be deprecated by Google) within the next year or so.
@Charles,
I think there's something unclear in the docs.
Creating an Event states to use
date('c', ...Whereas in EGCal.php/create,
date('c', ...is also used?Perhaps you can also add this in function
createwhen addintstart/endto$data: (see https://developers.google.com/google-apps/calendar/v3/reference/events/insert)@jwerner,
Google Calendar is very picky about the way timestamps should be sent/received to it. If the timestamp is an invalid variable it will most likely default to 1970. (It's been a while since I've last looked a the API Documentation.)
Make sure your date('c', time()) call is generating the right timestamp. The date you're generating might not be resolving to the date you intended.
date('c', strtotime("5 pm"))If that doesn't work I recommend you looking at the cURL requests directly and looking at what responses you are sending/receiving.
Hi again,
I noticed that on updating an existing calendar event, the start date gets set to 1970-01-01 ?!
Regards,
Joachim
Hello,
thanks for this nice extension.
I stumbled upon being behind a company proxy, so I added functionality to pass options to the curl instance.
Usage:
This is the patch:
Save the patch into the file
extensions/egcal.patch.Apply the patch:
Regards,
Joachim
@Strangler's pull request has been merged. (Better late than never right? Been really busy the past few months).
@Strangler
I encourage your to make a GitHub pull request if that truly solves the issue. When I get a chance I'll try to merge it in if everything tests out. My concern with that approach is that it does not take into consideration the following:
During my initial tests I never once generated a request that didn't receive that redirect and assumed that it was the default behavior. If it is behaving differently then I believe another approach would be better suited for handling if a 302/301 redirects occurs with the gSessionId.
Submit a pull request to Github and I'll look at merging that updated code in with a gSessionId check in it.
Thanks,
@charlesportwoodii
I've got the same issue as warden, the entry gets doubled. I've even used the latest version from Github.
I've made a modification in EGCal.php:
This:
becomes this:
I've commented out the first request, then proceed to the second request, and everything works fine.
@warden
I haven't run the code, but just from looking I don't see anything that jumps out. If you run just
Does it do a double creation? The only thing I can think of that is causing that is a double POST/Form submission from your view or AJAX request.
Thanks for a quick fix! Indeed, it resolved the problem of time for created issues. And indeed, I was looking at APIv3, that's why I couldn't fix it myself :)
As for the double creation, it still happens, and I have no idea why, the code is nothing special, but any ideas welcome.. It happens for me in two different environments (mac and linux).
@warden
I'm not experiencing the double creation issue, but I did fix the "create on this day only" issue and have updated the github repository with the modified code. Can you post your code for the first problem? It sounds like the code is running twice.
Make sure the start and end times look like:
Just make sure strtotime can handle it.
Also, this code uses Calendar API2, not API3 (which is the latest version). The API reference is located here
Thank you for a great extension. I have a problem though, it seems that creating new events is not working properly. First problem: The events are created twice (so a double event is created with the same data) Second problem: no matter what date/time I specify and in what format, the event is always created for the current day and time.
Any ideas? can you test if it is working for you fine currently? I went briefly through GApi docs and it seems that there are differences in the data you are sending and the things that google is expecting ?
thanks
Hi, I have problems using this, I have cURL installed and Curl.php in the EGCal folder.
curl = curl_init($url); } /** * Allows for custom headers to be sent before the request is made * * @param array $headers * Headers to be sent with the request * * @param string $url * Modified URL if it needs to be changed from the original request * * @param bool $post * Whether we are performing a GET or POST requst, defaults to GET * * @param bool $follow * Whether we are to follow redirects * * @param int $redirects * Number of redirects to follow before stopping * **/ public function setHeader($headers=array(), $url=NULL, $post=NULL, $follow = TRUE, $redirects = 30) { curl_setopt($this->curl, CURLOPT_URL, $url == NULL ? $this->url : $url); curl_setopt($this->curl, CURLOPT_HTTPHEADER, $headers); if ($post != NULL) { curl_setopt($this->curl, CURLOPT_POST, $post); } curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, $follow); // follow redirects curl_setopt($this->curl, CURLOPT_MAXREDIRS, $redirects); // maximum number of redirects } public function run($method, $content = NULL) { if ($method != 'POST' && $method != 'GET') { curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method); } else { curl_setopt($this->curl, CURLOPT_POST, ($method == 'POST') ? true : false); } if ($content != NULL) { curl_setopt($this->curl, CURLOPT_POSTFIELDS, $content); } curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, 1); $response = curl_exec($this->curl); $this->error_code = curl_errno($this->curl); $this->status = curl_getinfo($this->curl, CURLINFO_HTTP_CODE); $this->error_string = curl_error($this->curl); $this->last_url = curl_getinfo($this->curl, CURLINFO_EFFECTIVE_URL); curl_close($this->curl); return $response; } /** * Retrieves the CURL error code retrieved from the last request * @return int $this->error_code **/ public function getErrorCode() { return $this->error_code; } /** * Retrieves the HTTP status code from the last request * @return int $this->status **/ public function getStatus() { return $this->status; } /** * Retrieves the error string from the last request * @return int $this->error_string **/ public function getErrorString() { return $this->error_string; } /** * Retrieves the last URL CURL processed * @return int $this->last_url **/ public function getLastURL() { return $this->last_url; } } ?> Fatal error: Class 'Curl' not found in D:\AppServ\www\icc\public\app\protected\extensions\EGCal\EGCal.php on line 103UPDATE: problem solved, my PHP does not support files that start with <?, I've changed it the Curl.php file to start with <?php and now it works...
Leave a comment
Please login to leave your comment.