Error->Code . ': ' . $errors->Error->Message; } } /** * This class is the abstraction layer to SimpleDb * * Takes ($key, $secret, $url) * - [str] $key: Your Amazon Web Services Access Key ID * - [str] $secret: Your Amazon Web Services Secret Access Key * - [str] $url: OPTIONAL (default: http://sdb.amazonaws.com/) * * Example Usage: * *
* $sd = new SimpleDb("AWS_KEY", "AWS_SECRET");
*
* $sd->listDomains();
* $sd->query("domain1");
*
* $sd->createDomain("domain1");
* $sd->putAttributes('item1', array('name', array('value1', 'value2'));
*
* $sd->getAttributes('item1');
*
* $sd->deleteAttributes('item1', array('name', 'name2'));
* $sd->deleteDomain('domain1');
*
*/
class SimpleDb {
/**#@+
* @ignore
*/
private $accessUrl;
private $accessKeyId;
private $accessSecret;
/**#@-*/
/**
* Constructor
*
* Takes ($key, $secret, $url)
*
* - [str] $key: Your Amazon Web Services "Access Key ID"
* - [str] $secret: Your Amazon Web Services "Secret Access Key"
* - [str] $url: OPTIONAL: defaults: http://sdb.amazonaws.com/
*
* @ignore
*/
public function __construct($key, $secret, $url = "https://sdb.amazonaws.com/")
{
$this->accessUrl = $url;
$this->accessKeyId = $key;
$this->accessSecret = $secret;
}
private static function implode_with_keys($array, $glue = '', $keyGlue = '')
{
$elements = array();
foreach ($array as $key => $value)
{
$elements[] = $key . $keyGlue . $value;
}
return implode($glue, $elements);
}
/**
* Convert a hex string to a base64 string
*
* @IGNORE
*/
private static function hex2b64($in_str)
{
$raw = '';
for ($i = 0; $i < strlen($in_str); $i += 2)
{
$raw .= chr(hexdec(substr($in_str, $i, 2)));
}
return base64_encode($raw);
}
/**
* Sign a string
*
* @ignore
*/
private static function sign($in_str, $in_key)
{
$hasher =& new Crypt_HMAC($in_key, "sha1");
$signature = self::hex2b64($hasher->hash($in_str));
return($signature);
}
/**
* Makes a request to the SimpleDb Service
*
* Takes ($params)
*
* - [arr] $params: custom query params to send to sdb
*/
private function request($action, $params)
{
$params['Action'] = $action;
$params['AWSAccessKeyId'] = $this->accessKeyId;
$params['SignatureVersion'] = 1;
$params['Timestamp'] = date('c', time());
$params['Version'] = '2007-11-07';
uksort($params, 'strnatcasecmp');
$params['Signature'] = self::sign(self::implode_with_keys($params), $this->accessSecret);
foreach ($params as &$param)
{
$param = rawurlencode($param);
}
$url = $this->accessUrl . '?' . self::implode_with_keys($params, '&', '=');
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$xml = simplexml_load_string(curl_exec($curl));
if ($xml->Errors) throw new SimpleDbException($xml->Errors);
return $xml;
}
/**
* Create a new domain
*
* [str] $name
*/
public function createDomain($in_name)
{
if (empty($in_name)) throw new Exception('invalid name for a domain');
return $this->request('CreateDomain', array('DomainName' => $in_name));
}
/**
* Create a new domain
*
* [str] $name
*/
public function deleteDomain($in_name)
{
if (empty($in_name)) throw new Exception('invalid name for a domain');
return $this->request('DeleteDomain', array('DomainName' => $in_name));
}
/**
* Get a list of domains
*
*/
public function listDomains($in_limit = 100, $in_token = NULL)
{
if ( !is_numeric($in_limit) or $in_limit > 100) throw new Exception('invalid limit');
return $this->request('ListDomains', array('MaxNumberOfDomains' => $in_limit));
}
/**
* Deletes data from an item
*
* [str] $in_domain - sdb domain item lives in
* [str] $in_item - name of item
*/
public function getAttributes($in_domain, $in_item)
{
if (empty($in_domain) or empty($in_item)) throw new Exception();
return $this->request('GetAttributes',array('DomainName' => $in_domain,'ItemName' => $in_item));
}
/**
* Deletes data from an item
*
* [str] $in_domain - sdb domain item lives in
* [str] $in_item - name of item
* [array] $in_data - name value pairs
*/
public function deleteAttributes($in_domain, $in_item, $in_data)
{
if (empty($in_domain) or empty($in_item)) throw new Exception();
$params = array('DomainName' => $in_domain, 'ItemName' => $in_item);
$i = 0;
foreach ($in_data as $name => $value)
{
$params['Attribute.' . $i . '.Name'] = $name;
$params['Attribute.' . $i . '.Value'] = $value;
$i++;
}
return $this->request('DeleteAttributes', $params);
}
/**
* Put data into an item in a domain
*
* [str] $in_domain - the domain to which the item belongs
* [str] $in_item - the unique id of the item
* [str] $in_name - an array of name value pairs to
*/
public function putAttributes($in_domain, $in_item, $in_data)
{
if (empty($in_domain) or empty($in_item) or !count($in_data)) throw new Exception();
$params = array('DomainName' => $in_domain, 'ItemName' => $in_item);
$i = 0;
foreach ($in_data as $name => $values)
{
foreach ($values as $value)
{
$params['Attribute.' . $i . '.Name'] = $name;
$params['Attribute.' . $i . '.Value'] = $value;
$params['Attribute.' . $i . '.Replace'] = 'true';
$i++;
}
}
if ($i > 100) throw new Exception();
return $this->request('PutAttributes', $params);
}
/**
* Query a domain to find item names
*
* [str] $in_domain - the domain to which the item belongs
* [str] $in_query - query expression
* [int] $in_limit - max number of items to get
* [str] $in_token - next list token
*/
public function query($in_domain, $in_query = '', $in_limit = 250, $in_token = NULL)
{
if (empty($in_domain) or !is_numeric($in_limit) or $in_limit > 250) throw new Exception();
$params = array('DomainName' => $in_domain, 'MaxNumberOfItems' => $in_limit);
if (!empty($in_query)) $params['QueryExpression'] = $in_query;
return $this->request('Query', $params);
}
}