芝麻web文件管理V1.00
编辑当前文件:/home/strato/chroot/opt/RZphp74/includes/Services/GeoNames.php
* @copyright 2008-2009 David Jean Louis * @license http://opensource.org/licenses/mit-license.php MIT License * @version CVS: $Id: GeoNames.php 303916 2010-10-01 10:54:24Z izi $ * @link http://pear.php.net/package/Services_GeoNames * @link http://www.geonames.org/export/web-services.html * @since File available since release 0.1.0 * @filesource */ /** * Dependencies. */ require_once 'Services/GeoNames/Exception.php'; require_once 'HTTP/Request2.php'; /** * Main interface to the GeoNames API: * {@link http://www.geonames.org/export/web-services.html} * * @category Services * @package Services_GeoNames * @author David Jean Louis
* @copyright 2008-2009 David Jean Louis * @license http://opensource.org/licenses/mit-license.php MIT License * @version Release: 1.0.1 * @link http://pear.php.net/package/Services_GeoNames * @link http://www.geonames.org/export/web-services.html * @link http://www.geonames.org/export/ws-overview.html * @since Class available since release 0.1.0 * * @method array children() children(array $params) * @method array cities() cities(array $params) * @method stdclass countryCode() countryCode(array $params) * @method array countryInfo() countryInfo(array $params) * @method stdclass countrySubdivision() countrySubdivision(array $params) * @method array earthquakes() earthquakes(array $params) * @method array findNearby() findNearby(array $params) * @method array findNearbyPlaceName() findNearbyPlaceName(array $params) * @method array findNearbyPostalCodes() findNearbyPostalCodes(array $params) * @method array findNearbyStreets() findNearbyStreets(array $params) * @method stdclass findNearByWeather() findNearByWeather(array $params) * @method array findNearbyWikipedia() findNearbyWikipedia(array $params) * @method stdclass findNearestAddress() findNearestAddress(array $params) * @method stdclass findNearestIntersection() findNearestIntersection(array $params) * @method stdclass get() get(array $params) * @method stdclass gtopo30() gtopo30(array $params) * @method array hierarchy() hierarchy(array $params) * @method stdclass neighbourhood() neighbourhood(array $params) * @method array neighbours() neighbours(array $params) * @method array postalCodeCountryInfo() postalCodeCountryInfo(array $params) * @method array postalCodeLookup() postalCodeLookup(array $params) * @method array postalCodeSearch() postalCodeSearch(array $params) * @method array search() search(array $params) * @method array siblings() siblings(array $params) * @method array weather() weather(array $params) * @method stdclass weatherIcao() weatherIcao(array $params) * @method stdclass srtm3() srtm3(array $params) * @method stdclass timezone() timezone(array $params) * @method array wikipediaBoundingBox() wikipediaBoundingBox(array $params) * @method array wikipediaSearch() wikipediaSearch(array $params) */ class Services_GeoNames { // constants {{{ /** * Exception code constant defined by this package. */ const UNSUPPORTED_ENDPOINT = 1; /**#@+ * Exception codes constants from: * {@link http://www.geonames.org/export/webservice-exception.html} */ const AUTHORIZATION_EXCEPTION = 10; const RECORD_DOES_NOT_EXIST = 11; const OTHER_ERROR = 12; const DATABASE_TIMEOUT = 13; const INVALID_PARAMETER = 14; const NO_RESULT_FOUND = 15; const DUPLICATE_EXCEPTION = 16; const POSTAL_CODE_NOT_FOUND = 17; const DAILY_LIMIT_OF_CREDITS_EXCEEDED = 18; const HOURLY_LIMIT_OF_CREDITS_EXCEEDED = 19; const WEEKLY_LIMIT_OF_CREDITS_EXCEEDED = 20; /**#@-*/ // }}} // properties {{{ /** * Url of the GeoNames web service. * * @var string $url */ public $url = 'http://ws.geonames.org'; /** * Array of failover servers. * * @var array $failoverServers * @see Services_GeoNames::sendRequest() */ public $failoverServers = array(); /** * The HTTP_Request2 instance, you can customize the request if you want to * (proxy, auth etc...) with the get/setRequest() methods. * * @var HTTP_Request2 $request * @see Services_GeoNames::getRequest() * @see Services_GeoNames::setRequest() */ protected $request; /** * Auth username, only relevant for the geonames commercial web services: * {@link http://www.geonames.org/commercial-webservices.html} * * @var string $username * @see Services_GeoNames::__construct() */ protected $username; /** * Auth token, only relevant for the geonames commercial web services: * {@link http://www.geonames.org/commercial-webservices.html} * * @var string $token * @see Services_GeoNames::__construct() */ protected $token; /** * Array of supported endpoints (listed alphabetically) and their * corresponding root property (if any). You can retrieve the list of * endpoints (only the keys of this array) with the * Services_GeoNames::getSupportedEndpoints() method. * * Note that we only support json endpoints, so the following endpoints are * not supported: * - extendedFindNearby (JSON not available for now) * - rssToGeo (RSS/KML only) * * For a full documentation of the available endpoints services, please * see: {@link http://www.geonames.org/export/ws-overview.html}. * * @var array $endpoints * @see Services_GeoNames::getSupportedEndpoints() */ protected $endpoints = array( 'children' => 'geonames', 'cities' => 'geonames', 'countryCode' => false, 'countryInfo' => 'geonames', 'countrySubdivision' => false, 'earthquakes' => 'earthquakes', 'findNearby' => 'geonames', 'findNearbyPlaceName' => 'geonames', 'findNearbyPostalCodes' => 'postalCodes', 'findNearbyStreets' => 'streetSegment', 'findNearByWeather' => 'weatherObservation', 'findNearbyWikipedia' => 'geonames', 'findNearestAddress' => 'address', 'findNearestIntersection' => 'intersection', 'get' => false, 'gtopo30' => false, 'hierarchy' => 'geonames', 'neighbourhood' => 'neighbourhood', 'neighbours' => 'geonames', 'postalCodeCountryInfo' => 'geonames', 'postalCodeLookup' => 'postalcodes', // not a typo 'postalCodeSearch' => 'postalCodes', 'search' => 'geonames', 'siblings' => 'geonames', 'weather' => 'weatherObservations', 'weatherIcao' => 'weatherObservation', 'srtm3' => false, 'timezone' => false, 'wikipediaBoundingBox' => 'geonames', 'wikipediaSearch' => 'geonames', ); // }}} // __construct() {{{ /** * Constructor, if you're using a commercial account (optional), you must * pass your "username" and "token". * * @param string $username Username for commercial webservice (optional) * @param string $token Token for commercial webservice (optional) * * @return void * @access public */ public function __construct($username = null, $token = null) { if ($username !== null) { $this->username = $username; } if ($token !== null) { $this->token = $token; } } // }}} // __call() {{{ /** * Method interceptor that retrieves the corresponding endpoint and return * a json decoded object or throw a Services_GeoNames_Exception. * * @param string $endpoint The endpoint to call * @param array $params Array of parameters to pass to the endpoint * * @return mixed stdclass|array The JSON decoded response or an array * @throws Services_GeoNames_Exception When an invalid method is called or * when the websercices returns an error */ public function __call($endpoint, $params = array()) { // check that endpoint is supported if (!in_array($endpoint, $this->getSupportedEndpoints())) { throw new Services_GeoNames_Exception( 'Unknown service endpoint "' . $endpoint . '"', self::UNSUPPORTED_ENDPOINT ); } // handle params if (isset($params[0])) { $params = is_array($params[0]) ? $params[0] : array('geonameId' => $params[0]); } else { $params = array(); } if (isset($params['type'])) { // we only do json unset($params['type']); } // manage authentication to commercial webservice if ($this->username !== null) { $params['username'] = $this->username; } if ($this->token !== null) { $params['token'] = $this->token; } // build the url and retrieve the result $qString = $this->formatQueryString($params); $urlPath = '/' . $endpoint . 'JSON?' . $qString; $ret = json_decode($this->sendRequest($urlPath)); // check if we have a error response if (isset($ret->status->message) && isset($ret->status->value)) { throw new Services_GeoNames_Exception( $ret->status->message, (int)$ret->status->value ); } // remove useless root property, to make the result more user friendly if ($this->endpoints[$endpoint] !== false && $ret instanceof stdclass) { $prop = $this->endpoints[$endpoint]; $ret = $ret->$prop; } return $ret; } // }}} // sendRequest() {{{ /** * Sends the request to the server using HTTP_Request2. * * @param string $urlPath The url path *without* the scheme://host * * @return string The response body * @throws HTTP_Request2_Exception * @throws Services_GeoNames_HTTPException When something goes wrong when * building the request or * requesting the server. */ protected function sendRequest($urlPath) { $exceptionStack = array(); $response = null; array_unshift($this->failoverServers, $this->url); foreach ($this->failoverServers as $server) { try { $request = clone $this->getRequest(); $request->setUrl(rtrim($server, '/') . $urlPath); $response = $request->send(); } catch (Exception $exc) { $exceptionStack[] = new Services_GeoNames_HTTPException( $exc->getMessage(), $exc ); continue; } if ($response->getStatus() != 200) { $exceptionStack[] = new Services_GeoNames_HTTPException( $response->getReasonPhrase(), $response->getStatus(), $response ); // reset the response variable since it's not a valid one $response = null; } else { break; } } if ($response == null && !empty($exceptionStack)) { $lastException = $exceptionStack[count($exceptionStack)-1]; if (count($exceptionStack) == 1) { throw $lastException; } else { throw new Services_GeoNames_HTTPException( $lastException->getMessage(), $exceptionStack ); } } return $response->getBody(); } // }}} // formatQueryString() {{{ /** * Builds a valid query string (url and utf8 encoded) to pass to the * endpoint and returns it. * * @param array $params Associative array of query parameters (name=>val) * * @return string The formatted query string */ protected function formatQueryString($params = array()) { $qString = array(); foreach ($params as $name => $value) { if (is_array($value)) { foreach ($value as $val) { $val = $this->isUtf8($val) ? $val : utf8_encode($val); $qString[] = $name . '=' . urlencode($val); } } else { $value = $this->isUtf8($value) ? $value : utf8_encode($value); $qString[] = $name . '=' . urlencode($value); } } return implode('&', $qString); } // }}} // getRequest() {{{ /** * Returns the HTTP_Request2 instance, if it's not yet set it is * instanciated on the fly. * * @return HTTP_Request2 The request * @see Services_GeoNames::$request */ public function getRequest() { if (!$this->request instanceof HTTP_Request2) { $this->request = new HTTP_Request2(); } return $this->request; } // }}} // setRequest() {{{ /** * Sets the HTTP_Request2 instance. * * @param HTTP_Request2 $request The request to set * * @return void * @see Services_GeoNames::$request */ public function setRequest(HTTP_Request2 $request) { $this->request = $request; } // }}} // getSupportedEndpoints() {{{ /** * Returns an array of supported services endpoints. * * @return array The endpoints array * @see Services_GeoNames::$endpoints */ public function getSupportedEndpoints() { return array_keys($this->endpoints); } // }}} // isUtf8() {{{ /** * Check if the given string is a UTF-8 string or an iso-8859-1 one. * * @param string $str The string to check * * @return boolean Wether the string is unicode or not */ protected function isUtf8($str) { return (bool)preg_match( '%^(?: [\x09\x0A\x0D\x20-\x7E] # ASCII | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 )*$%xs', $str ); } // }}} }