Services_GeoNames
[ class tree: Services_GeoNames ] [ index: Services_GeoNames ] [ all elements ]

Source for file GeoNames.php

Documentation is available at GeoNames.php

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  4.  
  5. /**
  6.  * This file is part of the PEAR Services_GeoNames package.
  7.  *
  8.  * PHP version 5
  9.  *
  10.  * LICENSE: This source file is subject to the MIT license that is available
  11.  * through the world-wide-web at the following URI:
  12.  * http://opensource.org/licenses/mit-license.php
  13.  *
  14.  * @category  Services
  15.  * @package   Services_GeoNames
  16.  * @author    David JEAN LOUIS <izimobil@gmail.com>
  17.  * @copyright 2008 David JEAN LOUIS
  18.  * @license   http://opensource.org/licenses/mit-license.php MIT License
  19.  * @version   SVN: $Id: GeoNames.php,v 1.1 2008/12/19 13:44:49 izi Exp $
  20.  * @link      http://pear.php.net/package/Services_GeoNames
  21.  * @link      http://www.geonames.org/export/web-services.html
  22.  * @since     File available since release 0.1.0
  23.  * @filesource
  24.  */
  25.  
  26. /**
  27.  * Dependencies.
  28.  */
  29. require_once 'Services/GeoNames/Exception.php';
  30. require_once 'HTTP/Request2.php';
  31.  
  32. /**
  33.  * Main interface to the GeoNames API:
  34.  * {@link http://www.geonames.org/export/web-services.html}
  35.  *
  36.  * @category  Services
  37.  * @package   Services_GeoNames
  38.  * @author    David JEAN LOUIS <izimobil@gmail.com>
  39.  * @copyright 2008 David JEAN LOUIS
  40.  * @license   http://opensource.org/licenses/mit-license.php MIT License
  41.  * @version   Release: 0.2.2
  42.  * @link      http://pear.php.net/package/Services_GeoNames
  43.  * @link      http://www.geonames.org/export/web-services.html
  44.  * @link      http://www.geonames.org/export/ws-overview.html
  45.  * @since     Class available since release 0.1.0
  46.  *
  47.  * @method array    children()                children(array $params)
  48.  * @method array    cities()                  cities(array $params)
  49.  * @method stdclass countryCode()             countryCode(array $params)
  50.  * @method array    countryInfo()             countryInfo(array $params)
  51.  * @method stdclass countrySubdivision()      countrySubdivision(array $params)
  52.  * @method array    earthquakes()             earthquakes(array $params)
  53.  * @method array    findNearby()              findNearby(array $params)
  54.  * @method array    findNearbyPlaceName()     findNearbyPlaceName(array $params)
  55.  * @method array    findNearbyPostalCodes()   findNearbyPostalCodes(array $params)
  56.  * @method array    findNearbyStreets()       findNearbyStreets(array $params)
  57.  * @method stdclass findNearByWeather()       findNearByWeather(array $params)
  58.  * @method array    findNearbyWikipedia()     findNearbyWikipedia(array $params)
  59.  * @method stdclass findNearestAddress()      findNearestAddress(array $params)
  60.  * @method stdclass findNearestIntersection() findNearestIntersection(array $params)
  61.  * @method stdclass get()                     get(array $params)
  62.  * @method stdclass gtopo30()                 gtopo30(array $params)
  63.  * @method array    hierarchy()               hierarchy(array $params)
  64.  * @method stdclass neighbourhood()           neighbourhood(array $params)
  65.  * @method array    neighbours()              neighbours(array $params)
  66.  * @method array    postalCodeCountryInfo()   postalCodeCountryInfo(array $params)
  67.  * @method array    postalCodeLookup()        postalCodeLookup(array $params)
  68.  * @method array    postalCodeSearch()        postalCodeSearch(array $params)
  69.  * @method array    search()                  search(array $params)
  70.  * @method array    siblings()                siblings(array $params)
  71.  * @method array    weather()                 weather(array $params)
  72.  * @method stdclass weatherIcao()             weatherIcao(array $params)
  73.  * @method stdclass srtm3()                   srtm3(array $params)
  74.  * @method stdclass timezone()                timezone(array $params)
  75.  * @method array    wikipediaBoundingBox()    wikipediaBoundingBox(array $params)
  76.  * @method array    wikipediaSearch()         wikipediaSearch(array $params)
  77.  */
  78. {
  79.     // constants {{{
  80.  
  81.     /**
  82.      * Exception code constant defined by this package.
  83.      */
  84.     const UNSUPPORTED_ENDPOINT = 1;
  85.      
  86.     /**#@+
  87.      * Exception codes constants from:
  88.      * {@link http://www.geonames.org/export/webservice-exception.html}
  89.      */
  90.     const AUTHORIZATION_EXCEPTION          = 10;
  91.     const RECORD_DOES_NOT_EXIST            = 11;
  92.     const OTHER_ERROR                      = 12;
  93.     const DATABASE_TIMEOUT                 = 13;
  94.     const INVALID_PARAMETER                = 14;
  95.     const NO_RESULT_FOUND                  = 15;
  96.     const DUPLICATE_EXCEPTION              = 16;
  97.     const POSTAL_CODE_NOT_FOUND            = 17;
  98.     const DAILY_LIMIT_OF_CREDITS_EXCEEDED  = 18;
  99.     const HOURLY_LIMIT_OF_CREDITS_EXCEEDED = 19;
  100.     const WEEKLY_LIMIT_OF_CREDITS_EXCEEDED = 20;
  101.     /**#@-*/
  102.     
  103.     // }}}
  104.     // properties {{{
  105.  
  106.     /**
  107.      * Url of the GeoNames web service.
  108.      * This should not change but anyway we make it public.
  109.      *
  110.      * @var string $url 
  111.      */
  112.     public static $url 'http://ws.geonames.org';
  113.  
  114.     /**
  115.      * The HTTP_Request2 instance, you can customize the request if you want to
  116.      * (proxy, auth etc...) with the get/setRequest() methods.
  117.      *
  118.      * @var HTTP_Request2 $request 
  119.      */
  120.     protected $request;
  121.  
  122.     /**
  123.      * Auth username, for commercial webservices only.
  124.      *
  125.      * @var string $username 
  126.      */
  127.     protected $username;
  128.  
  129.     /**
  130.      * Auth token, for commercial webservices only.
  131.      *
  132.      * @var string $token 
  133.      */
  134.     protected $token;
  135.  
  136.     /**
  137.      * Array of supported endpoints (listed alphabetically) and their
  138.      * corresponding root property (if any).
  139.      * 
  140.      * Note that we only support json endpoints, so the following endpoints are
  141.      * not supported:
  142.      * - extendedFindNearby (JSON not available for now)
  143.      * - rssToGeo (RSS/KML only)
  144.      *
  145.      * For a full documentation of the available endpoints services, please
  146.      * see: {@link http://www.geonames.org/export/ws-overview.html}.
  147.      *
  148.      * @var array $endpoints 
  149.      */
  150.     protected $endpoints = array(
  151.         'children'                => 'geonames',
  152.         'cities'                  => 'geonames',
  153.         'countryCode'             => false,
  154.         'countryInfo'             => 'geonames',
  155.         'countrySubdivision'      => false,
  156.         'earthquakes'             => 'earthquakes',
  157.         'findNearby'              => 'geonames',
  158.         'findNearbyPlaceName'     => 'geonames',
  159.         'findNearbyPostalCodes'   => 'postalCodes',
  160.         'findNearbyStreets'       => 'streetSegment',
  161.         'findNearByWeather'       => 'weatherObservation',
  162.         'findNearbyWikipedia'     => 'geonames',
  163.         'findNearestAddress'      => 'address',
  164.         'findNearestIntersection' => 'intersection',
  165.         'get'                     => false,
  166.         'gtopo30'                 => false,
  167.         'hierarchy'               => 'geonames',
  168.         'neighbourhood'           => 'neighbourhood',
  169.         'neighbours'              => 'geonames',
  170.         'postalCodeCountryInfo'   => 'geonames',
  171.         'postalCodeLookup'        => 'postalcodes'// not a typo
  172.         'postalCodeSearch'        => 'postalCodes',
  173.         'search'                  => 'geonames',
  174.         'siblings'                => 'geonames',
  175.         'weather'                 => 'weatherObservations',
  176.         'weatherIcao'             => 'weatherObservation',
  177.         'srtm3'                   => false,
  178.         'timezone'                => false,
  179.         'wikipediaBoundingBox'    => 'geonames',
  180.         'wikipediaSearch'         => 'geonames',
  181.     );
  182.  
  183.     // }}}
  184.     // __construct() {{{
  185.     
  186.     /**
  187.      * Constructor, if you're using a commercial account (optional), you must
  188.      * pass your "username" and "token".
  189.      * 
  190.      * @param string $username Username for commercial webservice (optional)
  191.      * @param string $token    Token for commercial webservice (optional)
  192.      * 
  193.      * @return void 
  194.      * @access public
  195.      */
  196.     public function __construct($username = null$token = null)
  197.     {
  198.         if ($username !== null{
  199.             $this->username = $username;
  200.         }
  201.         if ($token !== null{
  202.             $this->token = $token;
  203.         }
  204.     }
  205.     
  206.     // }}}
  207.     // __call() {{{
  208.     
  209.     /**
  210.      * Method interceptor that retrieves the corresponding endpoint and return
  211.      * a json decoded object or throw a Services_GeoNames_Exception.
  212.      * 
  213.      * @param string $endpoint The endpoint to call
  214.      * @param array  $params   Array of parameters to pass to the endpoint
  215.      * 
  216.      * @return mixed stdclass|array The JSON decoded response or an array
  217.      * @throws Services_GeoNames_Exception When an invalid method is called or
  218.      *                                      when the websercices returns an error
  219.      */
  220.     public function __call($endpoint$params = array())
  221.     {
  222.         // check that endpoint is supported
  223.         if (!in_array($endpointarray_keys($this->endpoints))) {
  224.             throw new Services_GeoNames_Exception(
  225.                 'Unknown service endpoint "' $endpoint '"',
  226.                 self::UNSUPPORTED_ENDPOINT
  227.             );
  228.         }
  229.  
  230.         // handle params
  231.         if (isset($params[0])) {
  232.             $params is_array($params[0]
  233.                 ? $params[0
  234.                 : array('geonameId' => $params[0]);
  235.         else {
  236.             $params = array();
  237.         }
  238.         if (isset($params['type'])) {
  239.             // we only do json
  240.             unset($params['type']);
  241.         }
  242.         if ($this->username !== null{
  243.             $params['username'$this->username;
  244.         }
  245.         if ($this->token !== null{
  246.             $params['token'$this->token;
  247.         }
  248.  
  249.         // build the url and retrieve the result
  250.         $qString $this->formatQueryString($params);
  251.         $url     = self::$url '/' $endpoint 'JSON?' $qString;
  252.         $ret     = json_decode($this->sendRequest($url));
  253.  
  254.         // check if we have a error response
  255.         if (isset($ret->status->message&& isset($ret->status->value)) {
  256.             throw new Services_GeoNames_Exception(
  257.                 $ret->status->message,
  258.                 (int)$ret->status->value
  259.             );
  260.         }
  261.         
  262.         // remove useless root property, to make the result more user friendly
  263.         if ($this->endpoints[$endpoint!== false{
  264.             $prop $this->endpoints[$endpoint];
  265.             $ret  $ret->$prop;
  266.         }
  267.         return $ret;
  268.     }
  269.     
  270.     // }}}
  271.     // sendRequest() {{{
  272.     
  273.     /**
  274.      * Sends the request to the server using HTTP_Request2.
  275.      * 
  276.      * @param string $url The full service url (url + endpoint + query string)
  277.      * 
  278.      * @return string The response body
  279.      * @throws HTTP_Request2_Exception
  280.      * @throws Services_GeoNames_HTTPException When something goes wrong when
  281.      *                                          building the request or
  282.      *                                          requesting the server.
  283.      */
  284.     protected function sendRequest($url)
  285.     {
  286.         try {
  287.             $request $this->getRequest();
  288.             $request->setUrl($url);
  289.             $response $request->send();
  290.         catch (HTTP_Request2_Exception $exc{
  291.             throw new Services_GeoNames_HTTPException(
  292.                 $exc->getMessage(),
  293.                 $exc // the original exception cause
  294.             );
  295.         }
  296.         if ($response->getStatus(!= 200{
  297.             throw new Services_GeoNames_HTTPException(
  298.                 $response->getReasonPhrase(),
  299.                 $response->getStatus(),
  300.                 $response
  301.             );
  302.         }
  303.         return $response->getBody();
  304.     }
  305.     
  306.     // }}}
  307.     // formatQueryString() {{{
  308.     
  309.     /**
  310.      * Builds a valid query string (url and utf8 encoded) to pass to the
  311.      * endpoint and returns it.
  312.      * 
  313.      * @param array $params Array of arguments
  314.      * 
  315.      * @return string The formatted query string
  316.      */
  317.     protected function formatQueryString($params = array())
  318.     {
  319.         $qString = array();
  320.         foreach ($params as $name => $value{
  321.             if (is_array($value)) {
  322.                 foreach ($value as $val{
  323.                     $qString[$name '=' urlencode(utf8_encode($val));
  324.                 }
  325.             else {
  326.                 $qString[$name '=' urlencode(utf8_encode($value));
  327.             }
  328.         }
  329.         return implode('&'$qString);
  330.     }
  331.     
  332.     // }}}
  333.     // getRequest() {{{
  334.     
  335.     /**
  336.      * Returns the HTTP_Request2 instance.
  337.      * 
  338.      * @return HTTP_Request2 The request
  339.      */
  340.     public function getRequest()
  341.     {
  342.         if (!$this->request instanceof HTTP_Request2{
  343.             $this->request = new HTTP_Request2();
  344.         }
  345.         return $this->request;
  346.     }
  347.     
  348.     // }}}
  349.     // setRequest() {{{
  350.     
  351.     /**
  352.      * Sets the HTTP_Request2 instance.
  353.      * 
  354.      * @param HTTP_Request2 $request The request to set
  355.      *
  356.      * @return void 
  357.      */
  358.     public function setRequest(HTTP_Request2 $request)
  359.     {
  360.         $this->request = $request;
  361.     }
  362.     
  363.     // }}}
  364.     // getSupportedEndpoints() {{{
  365.     
  366.     /**
  367.      * Returns an array of supported services endpoints.
  368.      * 
  369.      * @return array The endpoints array
  370.      */
  371.     public function getSupportedEndpoints()
  372.     {
  373.         return array_keys($this->endpoints);
  374.     }
  375.     
  376.     // }}}
  377. }

Documentation generated on Mon, 11 Mar 2019 15:27:58 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.