From 7202cd445b1c4f2338fd394161812292204ea7e0 Mon Sep 17 00:00:00 2001 From: Ken Guest Date: Sun, 1 Apr 2012 15:18:36 +0100 Subject: [PATCH] even more merges from CloCkWeRX's clone - new cache transport type --- Services/OpenStreetMap.php | 2 +- Services/OpenStreetMap/Transport.php | 340 ++-------------- Services/OpenStreetMap/Transport/HTTP.php | 367 ++++++++++++++++++ .../OpenStreetMap/Transport/HTTPCached.php | 119 ++++++ 4 files changed, 511 insertions(+), 317 deletions(-) create mode 100644 Services/OpenStreetMap/Transport/HTTP.php create mode 100644 Services/OpenStreetMap/Transport/HTTPCached.php diff --git a/Services/OpenStreetMap.php b/Services/OpenStreetMap.php index 8b8d087..982131d 100644 --- a/Services/OpenStreetMap.php +++ b/Services/OpenStreetMap.php @@ -76,7 +76,7 @@ public function __construct($configuration = array()) $config = new Services_OpenStreetMap_Config(); $this->setConfig($config); - $transport = new Services_OpenStreetMap_Transport(); + $transport = new Services_OpenStreetMap_Transport_HTTP(); $transport->setConfig($config); $this->setTransport($transport); diff --git a/Services/OpenStreetMap/Transport.php b/Services/OpenStreetMap/Transport.php index f0b307a..d616303 100644 --- a/Services/OpenStreetMap/Transport.php +++ b/Services/OpenStreetMap/Transport.php @@ -13,10 +13,6 @@ * @link http://pear.php.net/package/Services_OpenStreetMap */ - -require_once 'Log.php'; -require_once 'Log/null.php'; - /** * Services_OpenStreetMap_Transport * @@ -26,10 +22,12 @@ * @license BSD http://www.opensource.org/licenses/bsd-license.php * @link Transport.php */ -class Services_OpenStreetMap_Transport +interface Services_OpenStreetMap_Transport { + /**#@+ * @link http://tools.ietf.org/html/rfc2616 + * @access public */ /** * Ok @@ -43,71 +41,36 @@ class Services_OpenStreetMap_Transport * Resource not found. */ const NOT_FOUND = 404; - /** - * Method not allowed. - */ - const METHOD_NOT_ALLOWED = 405; - /** - * Conflict. - */ - const CONFLICT = 409; /** * Resource no longer available. */ const GONE = 410; - /** - * Precondition failed. - */ - const PRECONDITION_FAILED = 412; - /** - * Internal server error. - */ - const INTERNAL_SERVER_ERROR = 500; - /** - * Service unavailable. - */ - const SERVICE_UNAVAILABLE = 503; - /** - * Bandwidth limited exceeded. - * @link http://wiki.openstreetmap.org/wiki/API_v0.6 - */ - const BANDWIDTH_LIMIT_EXCEEDED = 509; /**#@-*/ + /** - * The HTTP_Request2 instance. + * getObject * - * Customise this for proxy settings etc with the getRequest/setRequest - * methods if necessary. + * Returns false if the object is not found * - * @var HTTP_Request2 $request - * @internal - * @see Services_OpenStreetMap::getRequest - * @see Services_OpenStreetMap::setRequest - */ - protected $request = null; - - /** - * @var Services_OpenStreetMap_Config $config - */ - protected $config = null; - - /** - * @var log $log + * @param string $type object type + * @param mixed $id id of object to retrieve + * @param mixed $version version of object + * + * @return object + * @throws Services_OpenStreetMap_Exception */ - protected $log = null; + public function getObject($type, $id, $version = null); /** - * __construct + * getObjects + * + * @param string $type object type + * @param array $ids ids of objects to retrieve * - * @return Services_OpenStreetMap_Transport + * @return void */ - public function __construct() - { - $this->setConfig(new Services_OpenStreetMap_Config()); - $this->setRequest(new HTTP_Request2()); - $this->setLog(new Log_null(null)); - } + public function getObjects($type, array $ids); /** * Send request to OSM server and return the response. @@ -120,7 +83,9 @@ public function __construct() * @param array $post_data (optional) * @param array $headers (optional) * + * @access public * @return HTTP_Request2_Response + * @todo Consider just returning the content? * @throws Services_OpenStreetMap_Exception If something unexpected has * happened while conversing with * the server. @@ -133,218 +98,7 @@ public function getResponse( $body = null, array $post_data = null, array $headers = null - ) { - $response = null; - $eMsg = null; - - if ($this->getConfig()->getValue('verbose')) { - $this->log->debug($url); - } - $request = $this->getRequest(); - $request->setUrl($url); - $request->setMethod($method); - $request->setAdapter($this->getConfig()->getValue('adapter')); - - - $request->setHeader( - 'User-Agent', - $this->getConfig()->getValue('User-Agent') - ); - if (!is_null($user) && !is_null($password)) { - $request->setAuth($user, $password); - } - if ($post_data != array()) { - $request->setMethod(HTTP_Request2::METHOD_POST); - foreach ($post_data as $key => $value) { - $request->addPostParameter($key, $value); - } - } - if ($headers != array()) { - foreach ($headers as $header) { - $request->setHeader($header[0], $header[1], $header[2]); - } - } - if (!is_null($body)) { - $request->setBody($body); - } - $code = 0; - try { - $response = $request->send(); - $code = $response->getStatus(); - - if ($this->getConfig()->getValue('verbose')) { - $this->log->debug($response->getHeader()); - $this->log->debug($response->getBody()); - } - - if (Services_OpenStreetMap_Transport::OK == $code) { - return $response; - } else { - $eMsg = 'Unexpected HTTP status: ' - . $code . ' ' - . $response->getReasonPhrase(); - $error = $response->getHeader('error'); - if (!is_null($error)) { - $eMsg .= " ($error)"; - } - - } - } catch (HTTP_Request2_Exception $e) { - $this->log->warning($response->getHeader()); - throw new Services_OpenStreetMap_Exception( - $e->getMessage(), - $code, - $e - ); - } - if ($eMsg != null) { - throw new Services_OpenStreetMap_Exception($eMsg, $code); - } - } - - /** - * Get HTTP_Request2 instance. - * - * @return HTTP_Request2 - */ - public function getRequest() - { - return $this->request; - } - - /** - * Set the HTTP_Request2 instance and return the Services_OpenStreetMap - * instance. - * - * Use this to inject a specific HTTP_Request2 instance. - * - * @param HTTP_Request2 $request The HTTP_Request2 instance to set. - * - * @return Services_OpenStreetMap - */ - public function setRequest(HTTP_Request2 $request) - { - $this->request = $request; - return $this; - } - - /** - * getObject - * - * Returns false if the object is not found - * - * @param string $type object type - * @param mixed $id id of object to retrieve - * @param mixed $version version of object - * - * @return object - * @throws Services_OpenStreetMap_Exception - */ - public function getObject($type, $id, $version = null) - { - /* - if (!in_array($type, $this->elements)) { - throw new Services_OpenStreetMap_Exception( - sprintf("Invalid Element Type '%s'", $type) - ); - }*/ - - $config = $this->getConfig()->asArray(); - $url = $config['server'] - . 'api/' - . $config['api_version'] - . '/' . $type . '/' - . $id; - if (!is_null($version)) { - $url .= "/$version"; - } - try { - $response = $this->getResponse($url); - } catch (Services_OpenStreetMap_Exception $ex) { - $code = $ex->getCode(); - if (Services_OpenStreetMap_Transport::NOT_FOUND == $code) { - return false; - } elseif (Services_OpenStreetMap_Transport::GONE == $code) { - return false; - } else { - throw $ex; - } - } - $class = 'Services_OpenStreetMap_' . ucfirst(strtolower($type)); - $obj = new $class(); - $obj->setXml(simplexml_load_string($response->getBody())); - return $obj; - } - - /** - * getObjects - * - * @param string $type object type - * @param array $ids ids of objects to retrieve - * - * @return void - * - */ - public function getObjects($type, array $ids) - { - $config = $this->getConfig(); - $url = $config->getValue('server') - . 'api/' - . $config->getValue('api_version') - . '/' . $type . 's?' . $type . 's=' - . implode(',', $ids); - try { - $response = $this->getResponse($url); - } catch (Services_OpenStreetMap_Exception $ex) { - if (isset($response)) { - $this->log->warning($response->getHeader()); - } - switch ($ex->getCode()) { - case Services_OpenStreetMap_Transport::NOT_FOUND: - case Services_OpenStreetMap_Transport::UNAUTHORISED: - case Services_OpenStreetMap_Transport::GONE: - return false; - default: - throw $ex; - } - } - - $class = 'Services_OpenStreetMap_' . ucfirst(strtolower($type)) . 's'; - $obj = new $class(); - if (!is_null($config)) { - $obj->setConfig($config); - } - $obj->setTransport($this); - $sxe = @simplexml_load_string($response->getBody()); - if ($sxe === false) { - $obj->setVal(trim($response->getBody())); - } else { - $obj->setXml($sxe); - } - return $obj; - } - - /** - * Set Config object - * - * @param Services_OpenStreetMap_Config $config Config settings. - * - * @return Services_OpenStreetMap_API_V06 - */ - public function setConfig(Services_OpenStreetMap_Config $config) - { - $this->config = $config; - } - - /** - * Get current Config object - * - * @return Services_OpenStreetMap_Config - */ - public function getConfig() - { - return $this->config; - } + ); /** * searchObjects @@ -354,53 +108,7 @@ public function getConfig() * * @return Services_OpenStreetMap_Objects */ - public function searchObjects($type, array $criteria) - { - $query = array(); - foreach ($criteria as $criterion) { - $query[] = $criterion->query(); - } - $config = $this->getConfig(); - $url = $config->getValue('server') - . 'api/' - . $config->getValue('api_version') - . '/' . $type . 's?' . implode('&', $query); - try { - $response = $this->getResponse($url); - } catch (Services_OpenStreetMap_Exception $ex) { - $this->log->warning($response->getHeader()); - switch ($ex->getCode()) { - case Services_OpenStreetMap_Transport::NOT_FOUND: - case Services_OpenStreetMap_Transport::UNAUTHORISED: - case Services_OpenStreetMap_Transport::GONE: - return false; - default: - throw $ex; - } - } - $class = 'Services_OpenStreetMap_' . ucfirst(strtolower($type)) . 's'; - $obj = new $class(); - $sxe = @simplexml_load_string($response->getBody()); - if ($sxe === false) { - $obj->setVal(trim($response->getBody())); - } else { - $obj->setXml($sxe); - } - return $obj; - } + public function searchObjects($type, array $criteria); + - /** - * set Log object - * - * @param Log $log Log object - * - * @return Services_OpenStreetMap_Transport - */ - public function setLog($log) - { - $this->log = $log; - return $this; - } } -// vim:set et ts=4 sw=4: -?> diff --git a/Services/OpenStreetMap/Transport/HTTP.php b/Services/OpenStreetMap/Transport/HTTP.php new file mode 100644 index 0000000..ff9eb69 --- /dev/null +++ b/Services/OpenStreetMap/Transport/HTTP.php @@ -0,0 +1,367 @@ + + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version Release: @package_version@ + * @link http://pear.php.net/package/Services_OpenStreetMap + */ +require_once 'Services/OpenStreetMap/Transport.php'; + +require_once 'Log.php'; +require_once 'Log/null.php'; +require_once 'HTTP/Request2.php'; + +/** + * Services_OpenStreetMap_Transport + * + * @category Services + * @package Services_OpenStreetMap + * @author Ken Guest + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link Transport.php + */ +class Services_OpenStreetMap_Transport_HTTP + implements Services_OpenStreetMap_Transport +{ + /** + * __construct + * + * @return Services_OpenStreetMap_Transport_HTTP + */ + public function __construct() + { + $this->setConfig(new Services_OpenStreetMap_Config()); + $this->setRequest(new HTTP_Request2()); + $this->setLog(new Log_null(null, null)); + } + + /** + * The HTTP_Request2 instance. + * + * Customise this for proxy settings etc with the getRequest/setRequest + * methods if necessary. + * + * @var HTTP_Request2 $request + * @internal + * @see Services_OpenStreetMap::getRequest + * @see Services_OpenStreetMap::setRequest + */ + protected $request = null; + + /** + * @var Services_OpenStreetMap_Config $config + */ + protected $config = null; + + /** + * @var Log $log + */ + protected $log = null; + + + + /** + * Send request to OSM server and return the response. + * + * @param string $url URL + * @param string $method GET (default)/POST/PUT + * @param string $user user (optional for read-only actions) + * @param string $password password (optional for read-only actions) + * @param string $body body (optional) + * @param array $post_data (optional) + * @param array $headers (optional) + * + * @return HTTP_Request2_Response + * @throws Services_OpenStreetMap_Exception If something unexpected has + * happened while conversing with + * the server. + */ + public function getResponse( + $url, + $method = HTTP_Request2::METHOD_GET, + $user = null, + $password = null, + $body = null, + array $post_data = null, + array $headers = null + ) { + $response = null; + $eMsg = null; + + if ($this->getConfig()->getValue('verbose')) { + $this->log->debug($url); + } + + $request = $this->getRequest(); + $request->setUrl($url); + $request->setMethod($method); + $request->setAdapter($this->getConfig()->getValue('adapter')); + + + $request->setHeader( + 'User-Agent', + $this->getConfig()->getValue('User-Agent') + ); + + if ($user !== null && $password !== null) { + $request->setAuth($user, $password); + } + if ($post_data != array()) { + $request->setMethod(HTTP_Request2::METHOD_POST); + foreach ($post_data as $key => $value) { + $request->addPostParameter($key, $value); + } + } + if ($headers != array()) { + foreach ($headers as $header) { + $request->setHeader($header[0], $header[1], $header[2]); + } + } + if ($body !== null) { + $request->setBody($body); + } + $code = 0; + try { + $response = $request->send(); + $code = $response->getStatus(); + + $this->log->debug($response->getHeader()); + $this->log->debug($response->getBody()); + + if (self::OK == $code) { + return $response; + } else { + $eMsg = 'Unexpected HTTP status: ' + . $code . ' ' + . $response->getReasonPhrase(); + $error = $response->getHeader('error'); + if (!is_null($error)) { + $eMsg .= " ($error)"; + } + + } + } catch (HTTP_Request2_Exception $e) { + $this->log->warning((string)$e); + throw new Services_OpenStreetMap_Exception( + $e->getMessage(), + $code, + $e + ); + } + if ($eMsg != null) { + throw new Services_OpenStreetMap_Exception($eMsg, $code); + } + } + + /** + * Get HTTP_Request2 instance. + * + * @access public + * @return HTTP_Request2 + */ + public function getRequest() + { + return $this->request; + } + + /** + * Set the HTTP_Request2 instance and return the Services_OpenStreetMap + * instance. + * + * Use this to inject a specific HTTP_Request2 instance. + * + * @param HTTP_Request2 $request The HTTP_Request2 instance to set. + * + * @return Services_OpenStreetMap + */ + public function setRequest(HTTP_Request2 $request) + { + $this->request = $request; + return $this; + } + + /** + * set Log object + * + * @param Log $log Log object + * + * @return Services_OpenStreetMap_Transport_HTTP + */ + public function setLog(Log $log) + { + $this->log = $log; + } + + /** + * getObject + * + * Returns false if the object is not found + * + * @param string $type object type + * @param mixed $id id of object to retrieve + * @param mixed $version version of object + * + * @return object + * @throws Services_OpenStreetMap_Exception + */ + public function getObject($type, $id, $version = null) + { + /* + if (!in_array($type, $this->elements)) { + throw new Services_OpenStreetMap_Exception( + sprintf("Invalid Element Type '%s'", $type) + ); + }*/ + + $config = $this->getConfig()->asArray(); + $url = $config['server'] + . 'api/' + . $config['api_version'] + . '/' . $type . '/' + . $id; + if ($version !== null) { + $url .= "/$version"; + } + try { + $response = $this->getResponse($url); + } catch (Services_OpenStreetMap_Exception $ex) { + $this->log->warning((string)$ex); + + $code = $ex->getCode(); + if (self::NOT_FOUND == $code) { + return false; + } elseif (self::GONE == $code) { + return false; + } else { + throw $ex; + } + } + $class = 'Services_OpenStreetMap_' . ucfirst(strtolower($type)); + $obj = new $class(); + $obj->setXml(simplexml_load_string($response->getBody())); + return $obj; + } + + /** + * getObjects + * + * @param string $type object type + * @param array $ids ids of objects to retrieve + * + * @return void + * + */ + public function getObjects($type, array $ids) + { + /* + if (!in_array($type, $this->elements)) { + throw new Services_OpenStreetMap_Exception('Invalid Element Type'); + } + */ + $config = $this->getConfig(); + $url = $config->getValue('server') + . 'api/' + . $config->getValue('api_version') + . '/' . $type . 's?' . $type . 's=' + . implode(',', $ids); + try { + $response = $this->getResponse($url); + } catch (Services_OpenStreetMap_Exception $ex) { + $this->log->warning((string)$ex); + switch ($ex->getCode()) { + case self::NOT_FOUND: + case self::UNAUTHORISED: + case self::GONE: + return false; + default: + throw $ex; + } + } + + $class = 'Services_OpenStreetMap_' . ucfirst(strtolower($type)) . 's'; + $obj = new $class(); + if (!is_null($config)) { + $obj->setConfig($config); + } + $obj->setTransport($this); + $sxe = @simplexml_load_string($response->getBody()); + if ($sxe === false) { + $obj->setVal(trim($response->getBody())); + } else { + $obj->setXml($sxe); + } + return $obj; + } + + /** + * Set Config object + * + * @param Services_OpenStreetMap_Config $config Config settings. + * + * @return Services_OpenStreetMap_API_V06 + */ + public function setConfig(Services_OpenStreetMap_Config $config) + { + $this->config = $config; + } + + /** + * Get current Config object + * + * @return Services_OpenStreetMap_Config + */ + public function getConfig() + { + return $this->config; + } + + /** + * searchObjects + * + * @param string $type object type (e.g. changeset) + * @param array $criteria array of criterion objects. + * + * @return Services_OpenStreetMap_Objects + */ + public function searchObjects($type, array $criteria) + { + $query = array(); + foreach ($criteria as $criterion) { + $query[] = $criterion->query(); + } + $config = $this->getConfig(); + $url = $config->getValue('server') + . 'api/' + . $config->getValue('api_version') + . '/' . $type . 's?' . implode('&', $query); + try { + $response = $this->getResponse($url); + } catch (Services_OpenStreetMap_Exception $ex) { + $this->log->warning((string)$ex); + switch ($ex->getCode()) { + case self::NOT_FOUND: + case self::UNAUTHORISED: + case self::GONE: + return false; + default: + throw $ex; + } + } + $class = 'Services_OpenStreetMap_' . ucfirst(strtolower($type)) . 's'; + $obj = new $class(); + $sxe = @simplexml_load_string($response->getBody()); + if ($sxe === false) { + $obj->setVal(trim($response->getBody())); + } else { + $obj->setXml($sxe); + } + return $obj; + } +} diff --git a/Services/OpenStreetMap/Transport/HTTPCached.php b/Services/OpenStreetMap/Transport/HTTPCached.php new file mode 100644 index 0000000..85dfdc8 --- /dev/null +++ b/Services/OpenStreetMap/Transport/HTTPCached.php @@ -0,0 +1,119 @@ + + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version Release: @package_version@ + * @link http://pear.php.net/package/Services_OpenStreetMap + */ +require_once 'Cache.php'; +require_once 'Services/OpenStreetMap/Transport/HTTP.php'; + +/** + * Services_OpenStreetMap_Transport_HTTPCached + * + * @category Services + * @package Services_OpenStreetMap + * @author Ken Guest + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link HTTPCached.php + */ +class Services_OpenStreetMap_Transport_HTTPCached + extends Services_OpenStreetMap_Transport_HTTP +{ + + protected $cache; + + /** + * __construct + * + * @return Services_OpenStreetMap_Transport_HTTPCached + */ + public function __construct() + { + parent::__construct(); + + $this->setCache(new Cache('file')); + } + + /** + * setCache + * + * @param Cache $cache Cache object + * + * @return Services_OpenStreetMap_Transport_HTTPCached + */ + public function setCache($cache) + { + $this->cache = $cache; + return $this; + } + + /** + * Send request to OSM server and return the response. + * + * @param string $url URL + * @param string $method GET (default)/POST/PUT + * @param string $user user (optional for read-only actions) + * @param string $password password (optional for read-only actions) + * @param string $body body (optional) + * @param array $post_data (optional) + * @param array $headers (optional) + * + * @access public + * @return HTTP_Request2_Response + * @todo Consider just returning the content? + * @throws Services_OpenStreetMap_Exception If something unexpected has + * happened while conversing with + * the server. + */ + public function getResponse( + $url, + $method = HTTP_Request2::METHOD_GET, + $user = null, + $password = null, + $body = null, + array $post_data = null, + array $headers = null + ) { + $arguments = array( + $url, + $method, + $user, + $password, + $body, + implode(":", (array) $post_data), + implode(":", (array) $headers) + ); + $id = md5(implode(":", $arguments)); + + $data = $this->cache->get($id); + if ($data) { + $response = new HTTP_Request2_Response(); + $response->setStatus(200); + $response->setBody($data); + + return $response; + } + + $response = parent::getResponse( + $url, + $method, + $user, + $password, + $body, + $post_data, + $headers + ); + + $this->cache->save($id, $response->getBody()); + + return $response; + } +}