Last active
December 29, 2015 22:29
-
-
Save dmitriz/7736870 to your computer and use it in GitHub Desktop.
StackMob PHP Library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class StackmobStore implements OutStore { | |
// Create new hashes with preserved Ids | |
public function createManyWithId ($schema, array $array) { | |
$adjustedArray = $this->_adjustIdMany($schema, $array); | |
return $this->createMany($schema, $adjustedArray); | |
} | |
/** Creating new hashes on StackMob DB | |
* @param {string} $schema - StackMob schema | |
* @param {array} $array - Array of Hashes | |
* @return {array} $ids - StackMob IDs of entries created | |
*/ | |
public function createMany ($schema, array $bundle) { | |
// keys should not be called 'id' or else would be messed up by Stackmob | |
$this->_ensureNoId($bundle); | |
$response = $this->wrapped_request('POST', $schema, $bundle); | |
return $this->_getSucceeded($schema, $response); | |
} | |
// read one entry from $schema by $id | |
public function read ($schema, $id) { | |
return $this->wrapped_request('GET', $schema.'/'.$id); | |
} | |
// read all entries as array | |
public function readAll ($schema) { | |
return $this->wrapped_request('GET', $schema); | |
} | |
// update db entry with schema $schema and id $id from hash $body | |
public function updateManyWithId ($schema, array $bundle) { | |
foreach ($bundle as $hash) { | |
$id = $hash[ID_KEY]; | |
$hash = $this->_adjustId($schema, $hash); | |
try { | |
$this->update($schema, $id, $hash); | |
} catch (Exception $e) { | |
Utils::message("Cannot update hash: ", $hash, $e->message()); | |
} | |
} | |
} | |
// update db entry with schema $schema and id $id from hash $body | |
public function update ($schema, $id, array $body) { | |
return $this->wrapped_request('PUT', $schema.'/'.$id, $body); | |
} | |
public function deleteMany ($schema, array $ids) { | |
foreach($ids as $id) { | |
$this->delete('smtest', $id); | |
} | |
} | |
public function delete ($schema, $id) { | |
return $this->wrapped_request('DELETE', $schema.'/'.$id); | |
} | |
// Move Id keys to be Ids in database for all hashes from $array | |
// @param {array} $array - must be array of hashes | |
private function _adjustIdMany ($schema, array $array) { | |
$adjustedArray = array(); | |
foreach ($array as $hash) { | |
$hashAdjusted = $this->_adjustId($schema, $hash); | |
array_push($adjustedArray, $hashAdjusted); | |
} | |
return $adjustedArray; | |
} | |
// Move Id key so it becomes Id in the database | |
private function _adjustId ($schema, array $hash) { | |
$id = $hash[ID_KEY]; | |
$newId = $schema . '_id'; | |
unset($hash[ID_KEY]); | |
$hash[$newId] = $id; | |
return $hash; | |
} | |
private function _ensureNoId (array $bundle) { | |
foreach($bundle as $hash) { | |
if (isset($hash['id'])) throw new Exception("\nHash has key 'id' - to be messed up by Stackmob"); | |
} | |
} | |
private function _getIdKey ($schema) { | |
return $schema."_id"; | |
} | |
private function _getSucceeded ($schema, array $response) { | |
if ( isset($response['succeeded']) ) { | |
// more than 1 entry in $array | |
return $response['succeeded']; | |
} else { | |
// only 1 entry in $array | |
return array($response[$this->_getIdKey($schema)]); | |
} | |
} | |
// REST api request | |
function wrapped_request($http_method, $path, $body=null) { | |
$endpoint = STACKMOB_URL."/$path"; | |
// Setup OAuth request | |
$request = new Request($http_method, $endpoint); | |
// Sign the constructed OAuth request using HMAC-SHA1 | |
//$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $consumer); | |
$request->sign_request(); | |
// Extract OAuth header from OAuth request object and keep it handy in a variable | |
$oauth_header = $request->to_header(); | |
// MAKE API CALL TO STACKMOB | |
$response = $this->send_request($http_method, $endpoint, $oauth_header, $body); | |
return json_decode($response, true); | |
} | |
function send_request($http_method, $url, $auth_header=null, $postData=null) { | |
$curl = curl_init($url); | |
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($curl, CURLOPT_FAILONERROR, true); | |
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method); // maybe don't need for GET | |
if ($postData) curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($postData)); | |
$contentLength = $postData ? strlen(json_encode($postData)) : 0; | |
$headers = array("Accept: application/vnd.stackmob+json; version=0", | |
"Content-Type: application/json", | |
'Content-Length: ' . $contentLength, | |
$auth_header, | |
); | |
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); | |
if (PROXY) { | |
curl_setopt($curl, CURLOPT_PROXY, PROXY); | |
//curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyauth); | |
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); | |
} | |
$response = curl_exec($curl); | |
if (curl_error($curl)) { | |
throw new exception("Backend Connection Error: |".curl_error($curl)."|, Response: |$response|"); | |
} | |
curl_close($curl); | |
return $response; | |
} | |
} | |
class Request { | |
protected $parameters; | |
protected $http_method; | |
protected $http_url; | |
public static $version = '1.0'; | |
private static $signature_method = "HMAC-SHA1"; | |
function __construct($http_method, $http_url) { | |
$this->http_method = $http_method; | |
$this->http_url = $http_url; | |
$this->parameters = array("oauth_version" => self::$version, | |
"oauth_signature_method" => self::$signature_method, | |
"oauth_nonce" => self::generate_nonce(), | |
"oauth_timestamp" => self::generate_timestamp(), | |
"oauth_consumer_key" => STACKMOB_KEY, | |
// "oauth_signature" => $this->build_signature(), | |
); | |
} | |
private static function generate_timestamp() { | |
return time(); | |
} | |
private static function generate_nonce() { | |
$mt = microtime(); | |
$rand = mt_rand(); | |
return md5($mt . $rand); // md5s look nicer than numbers | |
} | |
public function sign_request() { | |
$this->set_parameter( "oauth_signature", $this->build_signature() ); | |
} | |
public function set_parameter($name, $value) { | |
$this->parameters[$name] = $value; | |
} | |
public function build_signature() { | |
$base_string = $this->get_signature_base_string(); | |
$key_parts = array(STACKMOB_SECRET, ""); | |
$key_parts = Util::urlencode_rfc3986($key_parts); | |
$key = implode('&', $key_parts); | |
return base64_encode(hash_hmac('sha1', $base_string, $key, true)); | |
} | |
/** | |
* Returns the base string of this request | |
* | |
* The base string defined as the method, the url | |
* and the parameters (normalized), each urlencoded | |
* and the concated with &. | |
*/ | |
public function get_signature_base_string() { | |
$parts = array( | |
$this->get_normalized_http_method(), | |
$this->get_normalized_http_url(), | |
$this->get_signable_parameters() | |
); | |
$parts = Util::urlencode_rfc3986($parts); | |
return implode('&', $parts); | |
} | |
/** | |
* just uppercases the http method | |
*/ | |
public function get_normalized_http_method() { | |
return strtoupper($this->http_method); | |
} | |
public function get_normalized_http_url() { | |
return $this->http_url; | |
} | |
/** | |
* The request parameters, sorted and concatenated into a normalized string. | |
* @return string | |
*/ | |
public function get_signable_parameters() { | |
// Grab all parameters | |
$params = $this->parameters; | |
// Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") | |
unset($params['oauth_signature']); | |
return Util::build_http_query($params); | |
} | |
/** | |
* builds the Authorization: header | |
*/ | |
public function to_header() { | |
$first = true; | |
$out = 'Authorization: OAuth'; | |
foreach ($this->parameters as $k => $v) { | |
if (is_array($v)) { | |
throw new Exception('Arrays not supported in headers'); | |
} | |
$out .= ($first) ? ' ' : ','; | |
$out .= $k . '="' . | |
Util::urlencode_rfc3986($v) . | |
'"'; | |
$first = false; | |
} | |
return $out; | |
} | |
} | |
class Util { | |
public static function urlencode_rfc3986($input) { | |
if (is_array($input)) { | |
return array_map(array('Util', 'urlencode_rfc3986'), $input); | |
} else if (is_scalar($input)) { | |
return str_replace( | |
'+', | |
' ', | |
str_replace('%7E', '~', rawurlencode($input)) | |
); | |
} else { | |
return ''; | |
} | |
} | |
public static function build_http_query($params) { | |
// Parameters are sorted by name, using lexicographical byte value ordering. | |
// Ref: Spec: 9.1.1 (1) | |
uksort($params, 'strcmp'); | |
$pairs = array(); | |
foreach ($params as $parameter => $value) { | |
$pairs[] = $parameter . '=' . $value; | |
} | |
return implode('&', $pairs); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment