<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
/**
* PHP versions 4 and 5
*
* LICENSE: Copyright 2007 Shinichi Hisamatsu. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this
*   list of conditions and the following disclaimer.
* o Redistributions in binary form must reproduce the above copyright notice,
*   this list of conditions and the following disclaimer in the documentation
*   and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of The PEAR Group.
*
* @category  Web Services
* @package   Services_Gnavi
* @author    Shinichi Hisamatsu <hisamatsu@gmail.com>
* @copyright 2007 Shinichi Hisamatsu
* @license   http://www.freebsd.org/copyright/freebsd-license.html 2 Clause BSD License
* @see       http://api.gnavi.co.jp/api/manual.htm
* @filesource
*/
 
require_once LIB_DIR.'PEAR/PEAR.php';
require_once LIB_DIR.'PEAR/HTTP/Request.php';
require_once LIB_DIR.'PEAR/XML/Unserializer.php';

/**
 * Class for accessing and retrieving information from Gnavi's Web service.
 *
 * @package Services_Gnavi
 * @author  Shinichi Hisamatsu <hisamatsu@gmail.com>
 * @access  public
 * @version Release: 0.1.0
 * @uses    PEAR
 * @uses    HTTP_Request
 * @uses    XML_Unserializer
 */
class Services_Gnavi
{

    /**
    * @access private
    * @static string $api_version
    */
    static $api_version = '0.1.0';

    /**
    * @access private
    * @var string $access_key
    */
    var $access_key = null;

    /**
    * @access private
    * @static array $base_urls
    */
    static $base_urls = array(
        'restaurant_search' => 'http://api.gnavi.co.jp/ver1/RestSearchAPI/',
        'area_search' => 'http://api.gnavi.co.jp/ver1/AreaSearchAPI/',
        'pref_search' => 'http://api.gnavi.co.jp/ver1/PrefSearchAPI/',
        'category_search' => 'http://api.gnavi.co.jp/ver1/CategoryLargeSearchAPI/',
        'subcategory_search' => 'http://api.gnavi.co.jp/ver1/CategorySmallSearchAPI/'
    );


    /**
    * @access private
    * @static array $error_codes
    */
    static $error_codes = array(
        '600' => array( 'message' => 'NoShop',
                        'text' => '指定された店舗の情報が存在しない。'),
        '601' => array( 'message' => 'Invalid Access',
                        'text' => '不正なアクセス（認証エラー）。'),
        '602' => array( 'message' => 'Invalid Shop Number',
                        'text' => '不正なぐるなび店舗IDパラメータが指定された。'),
        '603' => array( 'message' => 'InvalidType',
                        'text' => '不正な取得種別が指定された。'),
        '604' => array( 'message' => 'Internal Server Error',
                        'text' => '処理中にエラーが発生した。')
        );

    /**
     * Constructor
     *
     * @access public
     * @param  string $access_key
     */
    function Services_Gnavi($access_key = null) {

        if (!is_null($access_key)) {
            $this->access_key = $access_key;
        }
    }

    /**
     * Send Restaurant search requset
     *
     * @param  array   $options
     * @see http://api.gnavi.co.jp/api/manual.htm
     */
    function searchRestaurant($options = array()) {
        $this->sendRequest('restaurant_search', $options);
    }

    /**
     * Send Restaurant search requset
     *
     * @param  array   $options
     * @see http://api.gnavi.co.jp/api/manual.htm
     */
    function searchArea() {
        $this->sendRequest('area_search');
    }

    /**
     * Send Restaurant search requset
     *
     * @param  array   $options
     * @see http://api.gnavi.co.jp/api/manual.htm
     */
    function searchPref() {
        $this->sendRequest('pref_search');
    }

    /**
     * Send Restaurant search requset
     *
     * @param  array   $options
     * @see http://api.gnavi.co.jp/api/manual.htm
     */
    function searchCategory() {
        $this->sendRequest('category_search');
    }

    /**
     * Send Restaurant search requset
     *
     * @param  array   $options
     * @see http://api.gnavi.co.jp/api/manual.htm
     */
    function searchSubcategory() {
        $this->sendRequest('subcategory_search');
    }

    /**
     * Send Request
     *
     * @param  string  $operation
     * @param  array   $options
     */
    function sendRequest($operation, $options = array()) {
        if (empty($this->access_key)) return PEAR::raiseError('Access Key is required.');
        $url = self::$base_urls[$operation];
        $params = $options;
        $params['keyid'] = $this->access_key;
        
        $query = "";
        foreach ($params as $key => $value) {
          if (!empty($query)) {
            $query .= "&";
          }
          $query .= sprintf("%s=%s", $key, urlencode($value));
        }

        $url .= '?' . $query;

        $http =& new HTTP_Request($url);
        $http->addHeader('User-Agent', 'Services_Gnavi');
        $http->sendRequest();

        if ($http->getResponseCode() != 200) return PEAR::raiseError('HTTP Request Error' . $http->getResponseCode());

        $result = $http->getResponseBody();

        $xml =& new XML_Unserializer();
        $xml->unserialize($result);
        $data = $xml->getUnserializedData();
        if(!empty($data['error'])){
            $error = self::$error_codes[ $data['error']['code'] ];
            $error_message = $data['error']['code'].':'.$error['message'].' '.$error['text'];
            return PEAR::raiseError('Gurunavi API Error' . $error_message);
        }else{
            $this->data = $data;
        }
    }
    
    /**
     * set Access key
     *
     * @return void
     */
    function setAccessKey($access_key){
        $this->access_key = $access_key;
    }
    
    /**
     * get Access key
     *
     * @return array
     */
    function getAccessKey(){
        return $this->access_key;
    }
    
    /**
     * get search result
     *
     * @return array
     */
    function &getResult() {
        return $this->data;
    }

    /**
     * get Rakuten API version
     *
     * @param  stinrg $operation
     * @return string
     */
    function getApiVersion() {
        return $this->api_version;
    }
}
?>
