Вход Регистрация
Файл: library/Zend/Service/Amazon/SimpleDb.php
Строк: 656
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Service_Amazon
 * @subpackage SimpleDb
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */

/**
 * @see Zend_Service_Amazon_Abstract
 */
require_once 'Zend/Service/Amazon/Abstract.php';

/**
 * @see Zend_Service_Amazon_SimpleDb_Response
 */
require_once 'Zend/Service/Amazon/SimpleDb/Response.php';

/**
 * @see Zend_Service_Amazon_SimpleDb_Page
 */
require_once 'Zend/Service/Amazon/SimpleDb/Page.php';

/**
 * @see Zend_Service_Amazon_SimpleDb_Attribute
 */
require_once 'Zend/Service/Amazon/SimpleDb/Attribute.php';

/**
 * @see Zend_Service_Amazon_SimpleDb_Exception
 */
require_once 'Zend/Service/Amazon/SimpleDb/Exception.php';

/**
 * @see Zend_Crypt_Hmac
 */
require_once 'Zend/Crypt/Hmac.php';

/**
 * @category   Zend
 * @package    Zend_Service_Amazon
 * @subpackage SimpleDb
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Service_Amazon_SimpleDb extends Zend_Service_Amazon_Abstract
{
    
/* Notes */
    // TODO SSL is required

    /**
     * The HTTP query server
     */
    
protected $_sdbEndpoint 'sdb.amazonaws.com/';

    
/**
     * Period after which HTTP request will timeout in seconds
     */
    
protected $_httpTimeout 10;

    
/**
     * The API version to use
     */
    
protected $_sdbApiVersion '2009-04-15';

    
/**
     * Signature Version
     */
    
protected $_signatureVersion '2';

    
/**
     * Signature Encoding Method
     */
    
protected $_signatureMethod 'HmacSHA256';

    
/**
     * Create Amazon SimpleDB client.
     *
     * @param  string $access_key       Override the default Access Key
     * @param  string $secret_key       Override the default Secret Key
     * @param  string $region           Sets the AWS Region
     * @return void
     */
    
public function __construct($accessKey$secretKey)
    {
        
parent::__construct($accessKey$secretKey);
        
$this->setEndpoint("https://" $this->_sdbEndpoint);
    }

    
/**
     * Set SimpleDB endpoint to use
     *
     * @param string|Zend_Uri_Http $endpoint
     * @return Zend_Service_Amazon_SimpleDb
     */
    
public function setEndpoint($endpoint)
    {
        if(!(
$endpoint instanceof Zend_Uri_Http)) {
            
$endpoint Zend_Uri::factory($endpoint);
        }
        if(!
$endpoint->valid()) {
            require_once 
'Zend/Service/Amazon/SimpleDb/Exception.php';
            throw new 
Zend_Service_Amazon_SimpleDb_Exception("Invalid endpoint supplied");
        }
        
$this->_endpoint $endpoint;
        return 
$this;
    }

    
/**
     * Get SimpleDB endpoint
     *
     * @return Zend_Uri_Http
     */
    
public function getEndpoint() 
    {
        return 
$this->_endpoint;
    }

    
/**
     * Get attributes API method
     *
     * @param string $domainName Domain name within database
     * @param string 
     */
    
public function getAttributes(
        
$domainName$itemName$attributeName null
    
) {
        
$params               = array();
        
$params['Action']     = 'GetAttributes';
        
$params['DomainName'] = $domainName;
        
$params['ItemName']   = $itemName;

        if (isset(
$attributeName)) {
            
$params['AttributeName'] = $attributeName;
        }

        
$response $this->_sendRequest($params);
        
$document $response->getSimpleXMLDocument();

        
$attributeNodes $document->GetAttributesResult->Attribute;

        
// Return an array of arrays
        
$attributes = array();
        foreach(
$attributeNodes as $attributeNode) {
            
$name       = (string)$attributeNode->Name;
            
$valueNodes $attributeNode->Value;
            
$data       null;
            if (
is_array($valueNodes) && !empty($valueNodes)) {
                
$data = array();
                foreach(
$valueNodes as $valueNode) {
                    
$data[] = (string)$valueNode;
                }
            } elseif (isset(
$valueNodes)) {
                
$data = (string)$valueNodes;
            }
            if (isset(
$attributes[$name])) {
                
$attributes[$name]->addValue($data);    
            } else {
                
$attributes[$name] = new Zend_Service_Amazon_SimpleDb_Attribute($itemName$name$data);
            }
        }
        return 
$attributes;
    }

    
/**
     * Push attributes
     *
     * @param  string $domainName
     * @param  string $itemName
     * @param  array|Traverable $attributes
     * @param  array $replace
     * @return void
     */
    
public function putAttributes(
        
$domainName$itemName$attributes$replace = array()
    ) {
        
$params               = array();
        
$params['Action']     = 'PutAttributes';
        
$params['DomainName'] = $domainName;
        
$params['ItemName']   = $itemName;

        
$index 0;
        foreach (
$attributes as $attribute) {
            
$attributeName $attribute->getName();
            foreach (
$attribute->getValues() as $value) {
                
$params['Attribute.' $index '.Name']  = $attributeName;
                
$params['Attribute.' $index '.Value'] = $value;

                
// Check if it should be replaced
                
if(array_key_exists($attributeName$replace) && $replace[$attributeName]) {
                    
$params['Attribute.' $index '.Replace'] = 'true';
                }
                
$index++;
            }
        }

        
// Exception should get thrown if there's an error
        
$response $this->_sendRequest($params);
    }

    
/**
     * Add many attributes at once
     * 
     * @param  array $items 
     * @param  string $domainName 
     * @param  array $replace 
     * @return void
     */
    
public function batchPutAttributes($items$domainName, array $replace = array()) 
    {

        
$params               = array();
        
$params['Action']     = 'BatchPutAttributes';
        
$params['DomainName'] = $domainName;

        
$itemIndex 0;
        foreach (
$items as $name => $attributes) {
            
$params['Item.' $itemIndex '.ItemName'] = $name;
            
$attributeIndex 0;
            foreach (
$attributes as $attribute) {
                
// attribute value cannot be array, so when several items are passed
                // they are treated as separate values with the same attribute name
                
foreach($attribute->getValues() as $value) {
                    
$params['Item.' $itemIndex '.Attribute.' $attributeIndex '.Name'] = $attribute->getName();
                    
$params['Item.' $itemIndex '.Attribute.' $attributeIndex '.Value'] = $value;
                    if (isset(
$replace[$name]) 
                        && isset(
$replace[$name][$attribute->getName()]) 
                        && 
$replace[$name][$attribute->getName()]
                    ) {
                        
$params['Item.' $itemIndex '.Attribute.' $attributeIndex '.Replace'] = 'true';
                    }
                    
$attributeIndex++;
                }
            }
            
$itemIndex++;
        }

        
$response $this->_sendRequest($params);
    }

    
/**
     * Delete attributes
     * 
     * @param  string $domainName 
     * @param  string $itemName 
     * @param  array $attributes 
     * @return void
     */
    
public function deleteAttributes($domainName$itemName, array $attributes = array()) 
    {
        
$params               = array();
        
$params['Action']     = 'DeleteAttributes';
        
$params['DomainName'] = $domainName;
        
$params['ItemName']   = $itemName;

        
$attributeIndex 0;
        foreach (
$attributes as $attribute) {
            foreach (
$attribute->getValues() as $value) {
                
$params['Attribute.' $attributeIndex '.Name'] = $attribute->getName();
                
$params['Attribute.' $attributeIndex '.Value'] = $value;
                
$attributeIndex++;
            }
        }

        
$response $this->_sendRequest($params);

        return 
true;
    }

    
/**
     * List domains
     *
     * @param $maxNumberOfDomains int
     * @param $nextToken          int
     * @return array              0 or more domain names
     */
    
public function listDomains($maxNumberOfDomains 100$nextToken null
    {
        
$params                       = array();
        
$params['Action']             = 'ListDomains';
        
$params['MaxNumberOfDomains'] = $maxNumberOfDomains;

        if (
null !== $nextToken) {
            
$params['NextToken'] = $nextToken;
        }
        
$response $this->_sendRequest($params);

        
$domainNodes $response->getSimpleXMLDocument()->ListDomainsResult->DomainName;

        
$data = array();
        foreach (
$domainNodes as $domain) {
            
$data[] = (string)$domain;
        }

        
$nextTokenNode $response->getSimpleXMLDocument()->ListDomainsResult->NextToken;
        
$nextToken     = (string)$nextTokenNode;
        
$nextToken     = (trim($nextToken) === '') ? null $nextToken;

        return new 
Zend_Service_Amazon_SimpleDb_Page($data$nextToken);
    }

    
/**
     * Retrieve domain metadata
     *
     * @param $domainName string Name of the domain for which metadata will be requested
     * @return array Key/value array of metadatum names and values.
     */
    
public function domainMetadata($domainName
    {
        
$params               = array();
        
$params['Action']     = 'DomainMetadata';
        
$params['DomainName'] = $domainName;
        
$response             $this->_sendRequest($params);

        
$document $response->getSimpleXMLDocument();

        
$metadataNodes $document->DomainMetadataResult->children();
        
$metadata      = array();
        foreach (
$metadataNodes as $metadataNode) {
            
$name            $metadataNode->getName();
            
$metadata[$name] = (string)$metadataNode;
        }

        return 
$metadata;
    }

    
/**
     * Create a new domain
     *
     * @param $domainName    string    Valid domain name of the domain to create
     * @return                 boolean True if successful, false if not
     */
    
public function createDomain($domainName
    {
        
$params               = array();
        
$params['Action']     = 'CreateDomain';
        
$params['DomainName'] = $domainName;
        
$response             $this->_sendRequest($params);
        return 
$response->getHttpResponse()->isSuccessful();
    }

    
/**
     * Delete a domain
     *
     * @param     $domainName string  Valid domain name of the domain to delete
     * @return                 boolean True if successful, false if not
     */
    
public function deleteDomain($domainName
    {
        
$params               = array();
        
$params['Action']     = 'DeleteDomain';
        
$params['DomainName'] = $domainName;
        
$response             $this->_sendRequest($params);
        return 
$response->getHttpResponse()->isSuccessful();
    }

    
/**
     * Select items from the database
     *
     * @param  string $selectExpression
     * @param  null|string $nextToken
     * @return Zend_Service_Amazon_SimpleDb_Page
     */
    
public function select($selectExpression$nextToken null
    {
        
$params                     = array();
        
$params['Action']           = 'Select';
        
$params['SelectExpression'] = $selectExpression;

        if (
null !== $nextToken) {
            
$params['NextToken'] = $nextToken;
        }

        
$response $this->_sendRequest($params);
        
$xml      $response->getSimpleXMLDocument();

        
$attributes = array();
        foreach (
$xml->SelectResult->Item as $item) {
            
$itemName = (string)$item->Name;

            foreach (
$item->Attribute as $attribute) {
                
$attributeName = (string)$attribute->Name;

                
$values = array();
                foreach (
$attribute->Value as $value) {
                    
$values[] = (string)$value;
                }
                
$attributes[$itemName][$attributeName] = new Zend_Service_Amazon_SimpleDb_Attribute($itemName$attributeName$values);
            }
        }

        
$nextToken = (string)$xml->NextToken;

        return new 
Zend_Service_Amazon_SimpleDb_Page($attributes$nextToken);
    }
    
    
/**
     * Quote SDB value
     * 
     * Wraps it in ''
     * 
     * @param string $value
     * @return string
     */
    
public function quote($value)
    {
        
// wrap in single quotes and convert each ' inside to ''
        
return "'" str_replace("'""''"$value) . "'";
    }
    
    
/**
     * Quote SDB column or table name
     * 
     * Wraps it in ``
     * @param string $name
     * @return string
     */
    
public function quoteName($name)
    {
        if (
preg_match('/^[a-z_$][a-z0-9_$-]*$/i'$name) == false) {
            throw new 
Zend_Service_Amazon_SimpleDb_Exception("Invalid name: can contain only alphanumeric characters, $ and _");
        }
        return 
"`$name`";
    }
    
   
/**
     * Sends a HTTP request to the SimpleDB service using Zend_Http_Client
     *
     * @param array $params         List of parameters to send with the request
     * @return Zend_Service_Amazon_SimpleDb_Response
     * @throws Zend_Service_Amazon_SimpleDb_Exception
     */
    
protected function _sendRequest(array $params = array())
    {
        
// UTF-8 encode all parameters and replace '+' characters
        
foreach ($params as $name => $value) {
            unset(
$params[$name]);
            
$params[utf8_encode($name)] = $value;
        }

        
$params $this->_addRequiredParameters($params);

        try {
            
/* @var $request Zend_Http_Client */
            
$request self::getHttpClient();
            
$request->resetParameters();

            
$request->setConfig(array(
                
'timeout' => $this->_httpTimeout
            
));


            
$request->setUri($this->getEndpoint());
            
$request->setMethod(Zend_Http_Client::POST);
            foreach (
$params as $key => $value) {
                
$params_out[] = rawurlencode($key)."=".rawurlencode($value);
            }
            
$request->setRawData(join('&'$params_out), Zend_Http_Client::ENC_URLENCODED);
            
$httpResponse $request->request();
        } catch (
Zend_Http_Client_Exception $zhce) {
            
$message 'Error in request to AWS service: ' $zhce->getMessage();
            throw new 
Zend_Service_Amazon_SimpleDb_Exception($message$zhce->getCode());
        }
        
$response = new Zend_Service_Amazon_SimpleDb_Response($httpResponse);
        
$this->_checkForErrors($response);
        return 
$response;
    }

    
/**
     * Adds required authentication and version parameters to an array of
     * parameters
     *
     * The required parameters are:
     * - AWSAccessKey
     * - SignatureVersion
     * - Timestamp
     * - Version and
     * - Signature
     *
     * If a required parameter is already set in the <tt>$parameters</tt> array,
     * it is overwritten.
     *
     * @param array $parameters the array to which to add the required
     *                          parameters.
     *
     * @return array
     */
    
protected function _addRequiredParameters(array $parameters)
    {
        
$parameters['AWSAccessKeyId']   = $this->_getAccessKey();
        
$parameters['SignatureVersion'] = $this->_signatureVersion;
        
$parameters['Timestamp']        = gmdate('c');
        
$parameters['Version']          = $this->_sdbApiVersion;
        
$parameters['SignatureMethod']  = $this->_signatureMethod;
        
$parameters['Signature']        = $this->_signParameters($parameters);

        return 
$parameters;
    }

    
/**
     * Computes the RFC 2104-compliant HMAC signature for request parameters
     *
     * This implements the Amazon Web Services signature, as per the following
     * specification:
     *
     * 1. Sort all request parameters (including <tt>SignatureVersion</tt> and
     *    excluding <tt>Signature</tt>, the value of which is being created),
     *    ignoring case.
     *
     * 2. Iterate over the sorted list and append the parameter name (in its
     *    original case) and then its value. Do not URL-encode the parameter
     *    values before constructing this string. Do not use any separator
     *    characters when appending strings.
     *
     * @param array  $parameters the parameters for which to get the signature.
     * @param string $secretKey  the secret key to use to sign the parameters.
     *
     * @return string the signed data.
     */
    
protected function _signParameters(array $paramaters)
    {
        
$data  "POSTn";
        
$data .= $this->getEndpoint()->getHost() . "n";
        
$data .= "/n";

        
uksort($paramaters'strcmp');
        unset(
$paramaters['Signature']);

        
$arrData = array();
        foreach (
$paramaters as $key => $value) {
            
$value urlencode($value);
            
$value str_replace("%7E""~"$value);
            
$value str_replace("+""%20"$value);
            
$arrData[] = urlencode($key) . '=' $value;
        }

        
$data .= implode('&'$arrData);

        require_once 
'Zend/Crypt/Hmac.php';
        
$hmac Zend_Crypt_Hmac::compute($this->_getSecretKey(), 'SHA256'$dataZend_Crypt_Hmac::BINARY);

        return 
base64_encode($hmac);
    }

    
/**
     * Checks for errors responses from Amazon
     *
     * @param Zend_Service_Amazon_SimpleDb_Response $response the response object to
     *                                                   check.
     *
     * @return void
     *
     * @throws Zend_Service_Amazon_SimpleDb_Exception if one or more errors are
     *         returned from Amazon.
     */
    
private function _checkForErrors(Zend_Service_Amazon_SimpleDb_Response $response)
    {
        
$xpath = new DOMXPath($response->getDocument());
        
$list  $xpath->query('//Error');
        if (
$list->length 0) {
            
$node    $list->item(0);
            
$code    $xpath->evaluate('string(Code/text())'$node);
            
$message $xpath->evaluate('string(Message/text())'$node);
            throw new 
Zend_Service_Amazon_SimpleDb_Exception($message0$code);
        }
    }
}
Онлайн: 3
Реклама