Location: PHPKode > scripts > Best Buy Service Remix > bestbuy-service-remix/lib/BestBuy/Service/Remix.php
<?php

/**
 * LICENSE
 *
 * This source file is subject to the BSD license bundled with this package.
 *
 * Available online: {@link http://www.opensource.org/licenses/bsd-license.php}
 *
 * If you did not receive a copy of the license, and are unable to obtain it,
 * email {@link mailto:hide@address.com hide@address.com},
 * and I will send you a copy.
 *
 * {@link http://mattwilliamsnyc.com Matt Williams}, the author,
 * is neither affiliated with, nor endorsed by,
 * {@link http://www.bestbuy.com/ Best Buy}.
 *
 * @category   BestBuy
 * @package    BestBuy_Service_Remix
 * @author     Matt Williams <hide@address.com>
 * @copyright  Copyright (c) 2008 {@link http://mattwilliamsnyc.com Matt Williams}
 * @license    http://www.opensource.org/licenses/bsd-license.php
 * @version    $Id: Remix.php 23 2010-01-14 15:27:13Z mattwilliamsnyc $
 */

/**
 * @see BestBuy_Service_Remix_Response
 */
require_once 'BestBuy/Service/Remix/Response.php';

/**
 * @see BestBuy_Service_Remix_Type
 */
require_once 'BestBuy/Service/Remix/Type.php';

/**
 * {@link BestBuy_Service_Remix} provides methods for interacting with (version 1 of)
 * {@link http://www.bestbuy.com Best Buy}'s {@link http://remix.bestbuy.com Remix} API
 * and is based on the publicly available {@link http://remix.bestbuy.com/docs API documentation}.
 *
 * @category   BestBuy
 * @package    BestBuy_Service_Remix
 * @author     Matt Williams <hide@address.com>
 * @copyright  Copyright (c) 2008 {@link http://mattwilliamsnyc.com Matt Williams}
 */
class BestBuy_Service_Remix
{
    /**
     * Entry point for all API requests
     */
    const API_BASE = 'http://api.remix.bestbuy.com/v1';

    /**
     * Key used to identify a client application to the API service
     */
    protected $_apiKey;

    /**
     * Length of time (in seconds) to wait for a response to an API call
     */
    protected $_timeout = 10;

    /**
     * Query parameters to be appended to an API request URI
     */
    protected $_params = array();

    /**
     * Resource types (e.g. stores, products) to be targeted by an API call
     */
    protected $_types = array();

    /**
     * Constructor.
     *
     * Instantiates a new Remix API client with an API Key identifier
     *
     * @param string $apiKey Key used to identify a client application to the API service
     */
    public function __construct($apiKey)
    {
        $this->_apiKey = $apiKey;
    }

    /**
     * Allows query parameters to be assigned using a convenient key($value) syntax (e.g. format('json')).
     *
     * This is an alternative to setting all parameters simultaneously via the {@link params()} method.
     *
     * @param string $method Name of the query parameter to which a value will be assigned
     * @param array  $args   List of arguments; the first value is assigned to the targeted query parameter
     *
     * @return BestBuy_Service_Remix
     */
    public function __call($method, $args)
    {
        if(count($args))
        {
            if(is_array($args[0]))
            {
                $args[0] = join(',', $args[0]);
            }

            $this->_params[$method] = $args[0];

            return $this;
        }
    }

    /**
     * Targets the (optionally filtered) {@link http://remix.bestbuy.com/docs/Types/Products products}
     * resource for an API call.
     *
     * May be used in combination with {@link stores()} to check for
     * {@link http://remix.bestbuy.com/docs/Types/Store_Availability store availability}.
     *
     * @param array $filters One or more criteria used to filter results
     *
     * @return BestBuy_Service_Remix
     * @throws BestBuy_Service_Remix_Exception
     */
    public function products(array $filters =array())
    {
        $this->_types['products'] = self::_buildType('products', $filters);

        return $this;
    }

    /**
     * Targets a specific {@link http://remix.bestbuy.com/docs/Types/Products product}
     * resource (by SKU #) for an API call.
     *
     * @param string $sku    Identifier (SKU #) of the product to be targeted
     * @param string $format Desired response format ('xml' or 'json')
     *
     * @return BestBuy_Service_Remix
     * @throws BestBuy_Service_Remix_Exception
     */
    public function product($sku, $format ='xml')
    {
        $this->_types['products'] = self::_buildType('products', $sku, $format);

        return $this;
    }

    /**
     * Targets the (optionally filtered) {@link http://remix.bestbuy.com/docs/Types/Stores stores}
     * resource for an API call.
     *
     * May be used in combination with {@link products()} to check for
     * {@link http://remix.bestbuy.com/docs/Types/Store_Availability store availability}.
     *
     * @param array $filters One or more criteria used to filter results
     *
     * @return BestBuy_Service_Remix
     * @throws BestBuy_Service_Remix_Exception
     */
    public function stores(array $filters =array())
    {
        $this->_types['stores'] = self::_buildType('stores', $filters);

        return $this;
    }

    /**
     * Targets a specific {@link http://remix.bestbuy.com/docs/Types/Stores store}
     * resource (by Store ID) for an API call.
     *
     * @param string $storeId Identifier (Store ID) of the store to be targeted
     * @param string $format  Desired response format ('xml' or 'json')
     *
     * @return BestBuy_Service_Remix
     * @throws BestBuy_Service_Remix_Exception
     */
    public function store($identifier, $format ='xml')
    {
        $this->_types['stores'] = new BestBuy_Service_Remix_Type('stores', $identifier, $format);

        return $this;
    }

    /**
     * Assigns one or more query parameters (as name/value pairs) to be included with an API call.
     *
     * @param array $params Name/value pairs to be assigned as query parameters
     *
     * @return BestBuy_Service_Remix
     */
    public function params(array $params)
    {
        foreach($params as $key => $value)
        {
            if(is_array($value))
            {
                $params[$key] = join(',', $value);
            }
        }

        $this->_params = $params;

        return $this;
    }

    /**
     * Clears all targeted resource types and query parameters; called after every {@link query()}.
     *
     * @return BestBuy_Service_Remix
     */
    public function clear()
    {
        $this->_types  = array();
        $this->_params = array();

        return $this;
    }

    /**
     * Returns the current target URI including any assigned query parameters.
     *
     * IMPORTANT: Target URIs include the API key assigned to this client; protect this data appropriately.
     *
     * @return string
     */
    public function getTargetUri()
    {
        $types = array();

        foreach($this->_types as $type)
        {
            $types[] = (string) $type;
        }

        $params = array_merge($this->_params, array('apiKey' => $this->_apiKey));
        $uri    = sprintf('/%s?%s', join('+', $types), urldecode(http_build_query($params, '', '&')));

        return self::API_BASE . $uri;
    }

    /**
     * Sets the amount of time (in seconds) to wait for a response to an API call.
     *
     * @param integer $timeout Length of time (in seconds) to wait before timing out
     *
     * @return BestBuy_Service_Remix
     * @throws BestBuy_Service_Remix_Exception
     */
    public function setTimeout($timeout)
    {
        if(0 >= $timeout || !(is_numeric($timeout) && ($f = floatval($timeout)) == intval($f)))
        {
            self::_throwException("Timeout ({$timeout}) must be a positive integer");
        }

        $this->_timeout = $timeout;

        return $this;
    }

    /**
     * Submits a query to the Remix API and returns the {@link BestBuy_Service_Remix_Response response}.
     *
     * @return BestBuy_Service_Remix_Response
     * @throws BestBuy_Service_Remix_Exception
     */
    public function query()
    {
        if(!count($this->_types))
        {
            self::_throwException(
                'At least one resource (e.g. products, stores) must be targeted in order to perform an API query'
            );
        }

        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $this->getTargetUri());
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, TRUE);
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout);

        $data = curl_exec($ch);
        $meta = curl_getinfo($ch);

        curl_close($ch);

        $this->clear();

        return new BestBuy_Service_Remix_Response($data, $meta);
    }

    /**
     * Builds a resource {@link BestBuy_Service_Remix_Type type} to be targeted for an API call.
     *
     * @param string       $type   Desired resource type ('stores' or 'products')
     * @param string|array $filter Identifier or filter array used to target this type resource
     * @param string       $format Desired response format ('json' or 'xml')
     *
     * @return BestBuy_Service_Remix_Type
     */
    protected static function _buildType($type, $filter, $format ='xml')
    {
        try
        {
            $type = new BestBuy_Service_Remix_Type($type, $filter, $format);
        }
        catch(BestBuy_Service_Remix_Type_Exception $e)
        {
            self::_throwException(sprintf("Invalid '%s' target:\n%s", $type, $e->getMessage()));
        }

        return $type;
    }

    /**
     * Throws an exception with a user-supplied message.
     *
     * @param string $message Message to be provided with the exception being raised
     *
     * @throws BestBuy_Service_Remix_Exception
     */
    protected static function _throwException($message)
    {
        /** @see BestBuy_Service_Remix_Exception */
        require_once 'BestBuy/Service/Remix/Exception.php';

        throw new BestBuy_Service_Remix_Exception($message);
    }
}
Return current item: Best Buy Service Remix