// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // ============================================================================ $VIADEOAPI_VERSION = "0.2.2"; // == VIADEO API EXCEPTIONS =================================================== class ViadeoException extends Exception { } class ViadeoSDKException extends ViadeoException { } class ViadeoInvalidConfigurationException extends ViadeoException { } class ViadeoOAuth2Exception extends ViadeoException { } class ViadeoAuthenticationException extends ViadeoException { } class ViadeoAPIException extends ViadeoException { } class ViadeoConnectionException extends ViadeoException { } // == THE VIADEO API REQUEST CLASS ============================================ // // // After creating a ViadeoAPI instance, for instance using (w/ access token): // $VD = new ViadeoAPI('abcdef42ghijkl42mnopqr42stuvwxyz'); // // You can request for a ViadeoRequest instance using : // $req = $VD->id('abcdef42ghijkl'); // a graph object id // $req = $VD->get('/me'); // $req = $VD->post('/status'); // $req = $VD->put('/abcdef42ghijkl'); // $req = $VD->del('/abcdef42ghijkl'); // // Or directly using the constructor : // $req = new ViadeoRequest($VD, '/me'); // $req = new ViadeoRequest($VD, '/status', 'POST'); // // Once created a request can be manipulated : // // ** reset the request for a new usage (all is defaulted, ViadeoAPI is kept) // $req->reset(); // // ** set the request path : // $req->setPath('/me/contacts'); // // ** set a complete Viadeo API URL (limited on domain setting to Viadeo) : // $req->setURL('https://api.viadeo.com/me?user_detail=partial'); // // ** add a connection (mainly used when created the request with $VD->id()) // $req = $VD->id('abcdef42ghijkl')->connection('contacts') // print $req->getPath(); // >> "/abcdef42ghijkl/contacts" // // ** set the HTTP method // $req = $VD->id('abcdef42ghijkl'); // id of a removable item // $req.setMethod("DELETE"); // prepare for removal using // // the same request instance // // ** set parameters (every unknown method call is mapped to setParam()) // // Prepare a search request for users with name 'loic dias da sila' // $req = $VD->get('/search/users')->name('loic dias da silva'); // // Add another parameter, on a new line, setting search results limit // $req.limit('50') // // Another way to set parameter, through setParam() // $req.setParam('user_detail', 'partial') // // ** then execute the request : // $result = $req->execute(); // $result = $req->x(); // $result = $req(); // // ** you can retrieve informations about the request : // // $req-getPath(); // Get the path (aka: '/me', '/status', ...) // // Return null if setURL() was called before // $req->getFullPath(); // Compute the callable Viadeo API URI // $req->getMethod(); // The HTTP method (aka. 'GET', 'POST', ...) // $req->getParams(); // The url encoded parameters // // ============================================================================ class ViadeoRequest { private $api; // Used to store the ViadeoAPI linked instance private $path; // The API path ('/me', '/status', '//contacts', ) private $params; // The parameters of the request private $method; // The HTTP method to be used // -- Initialization ------------------------------------------------------ function __construct($api, $path, $method = "GET") { $this->reset(); $this->api = $api; $this->setPath($path); $this->method = $method; } public function reset() { $this->path = null; $this->params = array(); $this->method = "GET"; } // -- URI/Path management ------------------------------------------------- public function setPath($path) { if (substr($path, 0, 1) != '/') { $path = '/' . $path; } $this->path = $path; return $this; } public function setURL($url) { # FIXME: waiting for API correction on paging links #if (stripos($this->rawURL, ViadeoAPI::$api_base, 0) != 0) { # throw new ViadeoSDKException("You cannot override API base"); #} $obj_url = parse_url($url); $this->path = $obj_url['path']; parse_str($obj_url['query'], $queryArr); $this->params = array_merge($this->params, $queryArr); return $this; } public function connection($connection) { $connection = preg_replace('/^\/*(.*)\/*?$/', '$1', $connection); $this->path .= '/' . $connection; return $this; } public function getPath() { return ViadeoAPI::$api_base . $this->path; } public function getFullPath($extras = array()) { $path = $this->getPath(); if ((count($this->params) > 0) || (count($extras) > 0)) { $path .= "?" . $this->getParams($extras); } return $path; } public function getFullPathWithToken($extras = array()) { return $this->getFullPath(array('access_token' => $this->api->getAccessToken())); } // -- HTTP Method management ---------------------------------------------- public function setMethod($method) { $this->method = $method; return $this; } public function getMethod() { return $this->method; } // -- Parameters management ----------------------------------------------- public function getParams($extras = array(), $json = false) { $params = ""; if ((count($this->params) > 0) || (count($extras) > 0)) { if ( ! $json ) { $params = http_build_query(array_merge($this->params, $extras), null, '&'); } else { $params = json_encode(array_merge($this->params, $extras)); } } return $params; } public function setParam($name, $value) { $this->params[$name] = $value; return $this; } public function __call($name, $arguments) { $value = null; if (count($arguments) == 0) { $value = 'true'; } else if (count($arguments) > 1) { throw new ViadeoIllegalArgumentException(); } else { $value = $arguments[0]; if (is_bool($value)) { $value = $value ? 'true' : 'false'; } } $this->params[$name] = $value; return $this; } // -- Execute the query --------------------------------------------------- public function execute() { return $this->api->execute($this); } public function x() { return $this->execute(); } public function __invoke() { return $this->execute(); } } // == THE VIADEO GRAPH OBJECT CLASS =========================================== // // After executing a request : // // $me = $VD->get('/me').x(); // $contacts = $VD->id('me')->connection('contacts')->x(); // // You obtain a ViadeoGraphObject if the result contains the 'id' property. // // You can then use it to retrieve its properties : // // $name = $me->name; // // If the property is also an object, you get another ViadeoGraphObject instance : // // $firstcontact = $contacts->data[0]; // $name = $firstcontact->name; // // You can execute a new request using a ViadeoGraphObject instance : // // $req = $obj->connection($connection); // $req = $obj->get(); // $req = $obj->put(); // $req = $obj->del(); // // ex: // // // get my contacts // $contacts = $me->connection('contacts')->x(); // // // retrieve all my data // $fullme = $me->get()->user_detail('full')->x(); // // // update my interests // $me->put()->interests($me->interests . ", Coding")->x(); // // ============================================================================ class ViadeoGraphObject { private $api; private $data; // -- Initialization ------------------------------------------------------ function __construct($api, $data) { $this->api = $api; $this->data = $data; } private function req() { return $this->api->id($this->data->id); } // -- Request builders ---------------------------------------------------- public function connection($connection) { return $this->req()->connection($connection); } public function get() { return $this->req(); } public function del() { return $this->req()->setMethod('DELETE'); } public function put() { return $this->req()->setMethod('PUT'); } // -- Get object properties ----------------------------------------------- public function __get($name) { if (isset($this->data->$name)) { $data = $this->data->$name; if (isset($data->id)) { return new ViadeoGraphObject($this->api, $data); } if (is_array($data) && (count($data) > 0) && isset($data[0]->id)) { $newdata = array(); foreach ($data as $item) { $newdata[] = new ViadeoGraphObject($this->api, $item); } return $newdata; } return $data; } return null; } public function __isset($name) { return isset($this->data->$name); } } // == THE VIADEO API CLASS ==================================================== // // You can create an instance in two ways : // // // Empty instance, needs authentication // $VD = new ViadeoAPI(); // // or // // // With an access token, authentication is done // $AT = "abcdef42ghijkl42mnopqr42stuvwxyz"; // $VD = new ViadeoAPI($AT); // // You can also specify some options : // // $VD->init(array( // 'client_id' => 'CLIENTID', // 'client_secret' => 'CLIENTSECRE' // )); // // $VD->setOption('store', true); // // Available options are : // // - client_id (OAuth 2.0 - mandatory for authentication) // - client_secret (OAuth 2.0 - mandatory for authentication) // - access_token (other way to specify access_token) // - store (bool) (enable/disable access_token storing into cookie) // // You can also specify cURL options to be used during connections : // // $VD->setCurlOption(CURLOPT_TIMEOUT, 10); // // OAuth 2.0 Connection management : // // $VD->isAuthenticated(); // True if access_token is set // // $VD->disconnect(); // if access_token storage is activated // // delete the cookie // // $VD->(set/get)AccessToken($AT); // The Viadeo API Acccess Token // // $VD->(set/get)AuthorizationCode($AC); // The OAuth2.0 step 1 code) // // Try to get from $_REQUEST if not set // // $VD->(set/get)RedirectURI('http://...'); // Defaulted to current script URI // // OAuth 2.0 - step 1 : // // $VD->getAuthorizationURL(); // Return the URL for user redirection // $VD->getAuthorizationURLPopup(); // Same thing but with popup layout // $VD-authorize(); // Helper, redirects user to the getAuthorizationURL() // // Send header('Location') // // OAuth 2.0 - step 2 : // // $VD->setAccessTokenFromCode(); // Use the step 1 code (getAuthorizationCode()) // // in order to fill-in the access token from cURL // // OAuth helper : // // $VD->OAuth_auto(); // Automatically runs all the OAuth 2.0 workflow // // on main page // ex : // // // insert here $VD initialization, setting client_id and client_secret // try { $VD->OAuth_auto(); } catch (ViadeoException $e) { // echo "An error occurred during Viadeo API authentication: $e"; // } // // insert here API calls, ex: $me = $VD->get('me')->execute(); // // Execute a ViadeoRequest : // // $res = $VD->execute($req); // // ============================================================================ class ViadeoAPI { private $authorization_code; // OAuth 2.0 - The authorization code private $redirect_uri; // OAuth 2.0 - The redirection URI private $access_token; // OAuth 2.0 - The Access Token for API calls private $config; // The Viadeo API configuration // -- Static URIs --------------------------------------------------------- public static $api_base = "https://api.viadeo.com"; public static $authorize_url = "https://secure.viadeo.com/oauth-provider/authorize2"; public static $token_url = "https://secure.viadeo.com/oauth-provider/access_token2"; // -- Default CURL options ------------------------------------------------ private $curl_opts = array( CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_HEADER => TRUE, CURLOPT_TIMEOUT => 60, CURLOPT_USERAGENT => "viadeo-api-php-sdk-agent", // FIXME: add version CURLOPT_HTTPHEADER => array("Accept: application/json; charset=UTF-8") ); // == Initialization / Configuration ====================================== // ======================================================================== function __construct($access_token = null) { $this->setAccessToken($access_token); } public function init($config) { $this->config = $config; return $this; } public function setOption($name, $value) { $this->config[$name] = $value; } private function getConfigKey($key, $mandatory = false) { if (isset($this->config[$key])) { return $this->config[$key]; } else if ($mandatory) { throw new ViadeoInvalidConfigurationException( "Configuration key '".$key."' is missing"); } else { return null; } } private function getCookieName() { $suffix = $this->getConfigKey('client_id'); if ($suffix == null) { $suffix = "default"; } return "vds_" . $suffix; } public function setCurlOption($key, $value) { $this->curl_opts[$key] = $value; } // == OAuth2 Authentication layer ========================================= // ======================================================================== // -- Access Token mgt ---------------------------------------------------- public function isAuthenticated() { return ($this->getAccessToken() != null); } public function disconnect() { $this->access_token = null; if ($this->getConfigKey('store') === true) { setcookie($this->getCookieName(), "", time() - 3600); unset($_COOKIE[$this->getCookieName()]); } return $this; } public function setAccessToken($access_token) { $this->access_token = $access_token; if ($this->getConfigKey('store') === true) { setrawcookie($this->getCookieName(), '"access_token='.$access_token.'"', time() + 3600); } return $this; } public function getAccessToken() { $token = null; if (isset($this->access_token)) { $token = $this->access_token; } else if ($this->getConfigKey('access_token') != null) { $this->access_token = $this->getConfigKey('access_token'); $token = $this->access_token; } else if ($this->getConfigKey('store') === true) { if (isset($_COOKIE[$this->getCookieName()])) { $cookVal = $_COOKIE[$this->getCookieName()]; parse_str(str_replace('"', '', $cookVal), $cookArr); if (isset($cookArr['access_token'])) { $this->access_token = $cookArr['access_token']; $token = $this->access_token; } } } return $token; } // -- Authorization code -------------------------------------------------- public function setAuthorizationCode($authorization) { $this->authorization_code = $authorization_code; return $this; } public function getAuthorizationCode() { $code = null; if (isset($this->authorization_code)) { $code = $this->authorization_code; } else if (isset($_REQUEST["code"])) { $this->authorization_code = $_REQUEST["code"]; $code = $this->authorization_code; } else if (isset($_REQUEST["error"])) { throw new ViadeoOAuth2Exception($_REQUEST["error"]); } return $code; } // -- redirect uri -------------------------------------------------------- public function setRedirectURI($redirect_uri) { $this->redirect_uri = $redirect_uri; return $this; } public function getRedirectURI() { if (isset($this->redirect_uri)) { return $this->redirect_uri; } else { return ViadeoHelper::getCurrentURL(); } } // -- OAuth2.0 step 1 -- get authorization code --------------------------- public function getAuthorizationURL($extras = array()) { $params = array_merge(array( 'response_type' => 'code', 'client_id' => self::getConfigKey('client_id', true), 'redirect_uri' => self::getRedirectURI() ), $extras); $url = self::$authorize_url . "?" . http_build_query($params, null, '&'); return $url; } public function getAuthorizationURLPopup($extras = array()) { $extras['display'] = 'popup'; return $this->getAuthorizationURL($extras); } public function authorize($extras = array()) { header("Location: " . self::getAuthorizationURL($extras)); } // -- OAuth2.0 step 2 -- exchange code with access_token ------------------ public function setAccessTokenFromCode($extras = array()) { $curl_opts = $this->curl_opts; $params = array_merge(array( 'grant_type' => 'authorization_code', 'client_id' => $this->getConfigKey('client_id', true), 'client_secret' => $this->getConfigKey('client_secret', true), 'redirect_uri' => $this->getRedirectURI(), 'code' => $this->getAuthorizationCode()), $extras); $curl_opts[CURLOPT_URL] = self::$token_url; $curl_opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&'); $ch = curl_init(self::$token_url); curl_setopt_array($ch, $curl_opts); // mod:btw:dont yell at me curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $result = curl_exec($ch); if ($result === false) { throw new ViadeoConnectionException(curl_error($ch)); } list($headers, $body) = explode("\r\n\r\n", $result); $result = json_decode($body); $ex = null; try { if (isset($result->error)) { throw new ViadeoOAuth2Exception($result->error); } else if (isset($result->access_token)) { $this->setAccessToken($result->access_token); } else { throw new ViadeoOAuth2Exception("No token returned !"); } } catch (ViadeoException $e) { $ex = $e; } curl_close($ch); if ($ex) { throw $ex; } return $this; } // -- OAuth2.0 - Automation ----------------------------------------------- public function OAuth_auto() { if ($this->isAuthenticated()) { return; } else if ($this->getAuthorizationCode() != null) { $this->setAccessTokenFromCode(); } else { $this->authorize(); } } // == Request management ================================================== // ======================================================================== public function id($id) { $d = preg_replace('/^\/*(.*)\/*?$/', '$1', $id); return new ViadeoRequest($this, '/' . $id); } public function get($path) { return new ViadeoRequest($this, $path); } public function post($path) { return new ViadeoRequest($this, $path, "POST"); } public function put($path) { return new ViadeoRequest($this, $path, "PUT"); } public function del($path) { return new ViadeoRequest($this, $path, "DELETE"); } // ------------------------------------------------------------------------ public function execute(ViadeoRequest $request) { if (!$this->isAuthenticated()) { throw new ViadeoAuthenticationException("No access token is defined"); } $curl_opts = $this->curl_opts; $curl_opts[CURLOPT_HTTPHEADER] = array('Authorization: Bearer ' . $this->getAccessToken()); $headers = array('Authorization: Bearer ' . $this->getAccessToken()); if ($request->getMethod() != "GET") { # post method dynamically overriden by Tianji adaptation scripts $post_method = "application/x-www-form-urlencoded; charset=UTF-8"; $headers[] = 'Content-Type: '.$post_method; $json = (strpos($post_method, 'json') == FALSE) ? false : true; $curl_opts[CURLOPT_POSTFIELDS] = $request->getParams(array(), $json); $curl_opts[CURLOPT_CUSTOMREQUEST] = $request->getMethod(); $url = $request->getPath(); } else { $url = $request->getFullPath(); } $curl_opts[CURLOPT_HTTPHEADER] = $headers; $curl_opts[CURLOPT_URL] = $url; $ch = curl_init($url); curl_setopt_array($ch, $curl_opts); // mod:btw:dont yell at me curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $result = curl_exec($ch); if ($result === false) { throw new ViadeoConnectionException(curl_error($ch)); } list($headers, $body) = explode("\r\n\r\n", $result); $result = json_decode($body); $ex = null; if (isset($result->error)) { curl_close($ch); throw new ViadeoAPIException($result->error->type . " - " . $result->error->message[0]); } curl_close($ch); return isset($result->id) ? new ViadeoGraphObject($this, $result) : $result; } public function object($data) { return new ViadeoGraphObject($this, $data); } } class ViadeoHelper { // == Helper tools ======================================================== // ======================================================================== // Retrieve the current page URL ------------------------------------------ public static function getCurrentURL() { $pageURL = 'http'; if (isset($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] == "on")) {$pageURL .= "s";} $pageURL .= "://"; $pageURL .= $_SERVER["SERVER_NAME"]; if ($_SERVER["SERVER_PORT"] != "80") { $pageURL .= ":".$_SERVER["SERVER_PORT"]; } $pageURL .= $_SERVER["SCRIPT_NAME"]; return $pageURL; } }