nach mehrere Gläsern Rotwein und ausgiebigem Googlen (welche Ironie…) ist es mir nun gelungen, die „neue“ Google Calendar API zum Laufen zu bringen.
Leider sind hier noch ein „paar" manuelle Schritte beim Konfigurieren notwendig, daher ist die Lösung m.E. noch nicht ganz rund.
Aber das ist zum Glück nur einmalig (!) erforderlich, dann nicht mehr.
Ich versuche hier mal den Weg aufzuschreiben, jede Vereinfachung ist willkommen…
Vorarbeiten bei Google:
- Anmelden bei der Google Developer console: https://console.developers.google.com
- erstellen eines „Projektes“ -> heisst bei mir einfach API Project, ist aber egal
- Dann links „APIs“ auswählen und die „Calendar API“ einschalten.
- Dann links „Zugangsdaten“ auswählen und „Neue CliendID erstellen"
- Wichtig: hier „Installierte Anwendung“ auswählen, NICHT Webanwendung (!) - sonst muss man jedesmal ein Popup bestätigen, was den WAF definitiv nach unten treibt…
- dann den „Zustimmungsbildschirm“ so konfigurieren, wie man es möchte - ist aber eigentlich egal, nur ein Projekt muß drinstehen.
- Dann wieder „Installierte Anwendung“ und bei Anwendungstyp „sonstige“ auswählen und endlich „Client ID erstellen“.
- Damit tauchen jetzt in der Dev.Console die „Client-ID“, „Clientschlüssel“ und „Weiterleitung-URI“ auf - die brauchen wir gleich.
Der Access an sich ist damit konfiguriert - der Trick ist nun, einen „Authorization Code“ und "RefreshToken“ zu erzeugen:
- Die Werte für „ClientID“ und „redirect-URI“ in das script „google_1.php“ eintragen und das script ausführen mit
Code:
php -q google_1.php
- Zurück kommt eine URL, diese im Browser aufrufen. Es erscheint die berühmte Bestätigungsseite, hier bestätigen und Voila, es erscheint der Auhorization Code.
- Den also nun merken und in das script google_2.php als „code“ eintragen (ebenso wie ClientID, ClientKey und redirect_URI)
- Das script ausführen mit
Code:
php -q google_2.php
Die ganze Übung oben muss man zum Glück nur einmal machen, mit dem Refresh Token kann man immer wieder einen AuthorizationToken erzeugen.
Die scripte also irgendwo hinlegen aber nicht vergessen…
(Herzlichen Dank auch an Google und diese tolle OAuth. /ironie off )
Wichtig also nun das googeV3.php, dieses in
Code:
/var/www/smartvisu/lib/calendar/service/googleV3.php
Dann in der Smartvisu-Config noch googleV3 statt google auswählen und freuen !
Zum Glück muss man die Konfig-Orgie oben nur einmal machen (außer man ändert den Authorization Code…), aber eigentlich könnte das auch automatisch gehen.
Meine Vorstellung wäre, die Werte für ClientID,ClientSecret und WeiterleitungsURI in der Smartvisu-Configseite einzugeben und die berechnung auf Knopfdruck zu machen. Den PopUp kann man dann ja bestätigen.
Die GUI mit den Feldern kriege ich noch hin, für den Rest fehlt mir aber schlicht und ergreifend das PHP-Knowhow bzw. der smartvisu-Kontext. (Bis vor zwei Tagen konnte ich PHP nichtmal fehlerfrei buchstabieren, geschweige denn verstehen…)
Noch ein anderer Punkt zum Optimieren und eigentlich wichtiger: Das AuthToken ist eigentlich 3600 sec. gültig - aktuell wird es aber jedes Mal neu angefragt. Das dauert unnötig lang, eigentlich sollte man das cachen und nur bei Bedarf neu anfragen. Auch hier - ich hab’ einfach keine Ahnung, wie das hier gehen könnte…
Schaut Euch das doch mal an und testet ausführlich - Bei mir funzt es bislang ohne Probleme !
Viele Grüße - Carsten
Was also jetzt geht (zumindest bei mir):
- normale Termine innerhalb eines Tages
- Ganztagestermine
- Multi-Day Termine
- Farbe wird vom Termin im google Calendar übernommen, sofern fort gesetzt. Ist aber in der Beschreibung des Termins @color enhalten, geht das vor.
- Ein Icon kann über eine Zeile in der Beschreibung gesetzt werden mit @icon
- Sommer/Winterzeit wird entsprechend berücksichtigt, sofern (WICHTIG!) die Zeitzone auf dem smartvisu stimmt.
- Der count kann im calenda-widget gesetzt werden und wird ausgewertet
- Der Kalendername (typischerweise "primary") wird auf der Config-seite der smartvisu gesetzt im Feld "URL"
- Wichtig dabei: hier wirklich NUR "primary" eintragen, nicht die ganze URL !!!
PS: Die Anhänge funktionieren irgendwie nicht, hier also der code...
google_1.php:
PHP-Code:
<?php
$scope = 'https://www.google.com/calendar/feeds/';
$client_id = ''; // insert your client ID from Google Developer console (web)
$redirect_uri = ''; // insert your redirect URI here (first line only)
$params = array(
'response_type' => 'code',
'client_id' => $client_id,
'redirect_uri' => $redirect_uri,
'scope' => $scope
);
$url = 'https://accounts.google.com/o/oauth2/auth?' . http_build_query($params);
echo $url."\n";
?>
google_2.php:
PHP-Code:
<?php
$url = 'https://accounts.google.com/o/oauth2/token';
$post_data = array(
'code' => '', // insert the code here that was shown after calling the URL from google_1.php
'client_id' => '', // insert your client ID here
'client_secret' => '', // insert your client secret here
'redirect_uri' => '', //insert your redirect URI here (first line only)
'grant_type' => 'authorization_code',
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$token = json_decode($result);
echo $token->refresh_token . "\n";
?>
und hier die googleV3.php:
PHP-Code:
<?php
/**
* -----------------------------------------------------------------------------
* @package smartVISU
* @author Martin Gleiß, updated by Carsten Gotschlich for google API V3
* @copyright 2012
* @license GPL [http://www.gnu.de]
* -----------------------------------------------------------------------------
*/
// Note: for debugging purposes you can execute this script from commandline with php -q <scriptname>
require_once '../../../lib/includes.php';
require_once const_path_system.'calendar/calendar.php';
/**
* This class reads a google calenda
*/
class calendar_google extends calendar
{
/**
* initialization of some parameters
*/
public function init($request)
{
parent::init($request);
if ($this->url == '')
$this->url = 'primary';
if ($this->count == 0)
$this->count = 10;
}
/**
* Check if the cache-file exists
*/
public function run()
{
//---------------------------------------------------------------------
// let's define some parameters - they need to be fetched manually
$client_id = ''; // put your clientID here - from Google website
$client_secret = ''; // put your client Secret here - from Google WebSitr
$redirect_uri = ''; // put your redirect URI here from Google Website - only first line !
$refresh_token = ''; // Put your google refresh token here - from other PHP script
$calendar_id = $this->calendar; // get it this way: http://googleappstroubleshootinghelp.blogspot.de/2012/09/how-to-find-calendar-id-of-google.html
//---------------------------------------------------------------------
// get access token first
$token_url = 'https://accounts.google.com/o/oauth2/token';
$post_data = array(
'client_secret' => $client_secret,
'grant_type' => 'refresh_token',
'refresh_token' => $refresh_token,
'client_id' => $client_id
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $token_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$token_object = json_decode($result);
$access_token = $token_object->access_token;
//---------------------------------------------------------------------
// so now we have an access-token, let's use it to access the calendar
$context = stream_context_create(array('http' => array('method' => "GET", 'header' => "Authorization: OAuth " . $access_token)));
// first let's retrieve the colors
$resturl = 'https://www.googleapis.com/calendar/v3/colors';
$content = @file_get_contents($resturl, false, $context);
$colors = array();
if ($content !== false)
{
$result = json_decode($content,true);
$colors = $result["event"];
// var_dump($colors);
}
// then retrieve the calendar entries
$resturl = 'https://www.googleapis.com/calendar/v3/calendars/'. $this->url . '/events?maxResults='. $this->count .'&singleEvents=true&orderBy=startTime&timeMin='.urlencode(date('c'));
$content = @file_get_contents($resturl, false, $context);
$this->debug($content);
// for debugging purposes only
// echo $content;
// echo "###########";
if ($content !== false)
{
$result = json_decode($content,true);
$i = 1;
foreach ($result["items"] as $entry)
{
$startstamp = (string)($entry["start"]["dateTime"]);
$endstamp = (string)($entry["end"]["dateTime"]);
if ($startstamp == '')
$startstamp = (string)($entry["start"]["date"]);
if ($endstamp == '')
$endstamp = (string)($entry["end"]["date"]);
$start = strtotime($startstamp);
$end = strtotime($endstamp);
$color = '';
if (((string)($entry["colorId"]))!='')
$color=$colors[(string)($entry["colorId"])]["background"];
$this->data[] = array('pos' => $i++,
'start' => date('y-m-d', $start).' '.date('H:i:s', $start),
'end' => date('y-m-d', $end).' '.date('H:i:s', $end),
'title' => (string)($entry["summary"]),
'content' => (string)($entry["description"]),
'where' => (string)($entry["location"]),
'color' => $color,
'link' => (string)($entry["htmlLink"])
);
}
}
else
$this->error('Calendar: Google', 'Calendar read request failed!');
}
}
// -----------------------------------------------------------------------------
// call the service
// ----------------------------------------------------------------------------
//
$service = new calendar_google(array_merge($_GET, $_POST));
echo $service->json();
?>
Kommentar