Skip to content

Commit

Permalink
Support for more value types in the v1 REST API
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom Walder committed Sep 3, 2016
1 parent d6fe8a2 commit ab58d31
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 45 deletions.
39 changes: 24 additions & 15 deletions src/GDS/Gateway/RESTv1.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?php namespace GDS\Gateway;

use GDS\Mapper;

use GDS\Entity;
use Google\Auth\ApplicationDefaultCredentials;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
Expand Down Expand Up @@ -56,17 +55,6 @@ public function __construct($str_project_id, $str_namespace = null)

}

/**
* Configure a Value parameter, based on the supplied object-type value
*
* @param object $obj_val
* @param object $mix_value
*/
protected function configureObjectValueParamForQuery($obj_val, $mix_value)
{
// TODO: Implement configureObjectValueParamForQuery() method.
}

/**
* Put an array of Entities into the Datastore. Return any that need AutoIDs
*
Expand Down Expand Up @@ -279,6 +267,7 @@ private function applyPartition(\stdClass $obj_request) {
if(null !== $this->str_namespace) {
$obj_request->partitionId->namespaceId = $this->str_namespace;
}
return $obj_request;
}

/**
Expand All @@ -297,6 +286,7 @@ private function applyTransaction(\stdClass $obj_request) {
];
$this->str_next_transaction = null;
}
return $obj_request;
}

/**
Expand All @@ -312,6 +302,7 @@ private function addParamsToQuery(\stdClass $obj_query, array $arr_params)
if(count($arr_params) > 0) {
$obj_bindings = new \stdClass();
foreach ($arr_params as $str_name => $mix_value) {
// @todo special case for endCursor?
$obj_bindings->{$str_name} = (object)['value' => $this->buildQueryParamValue($mix_value)];
}
$obj_query->namedBindings = $obj_bindings;
Expand All @@ -321,8 +312,6 @@ private function addParamsToQuery(\stdClass $obj_query, array $arr_params)
/**
* Build a JSON representation of a value
*
* @todo Handle arrays, objects (like Datetime)
*
* @param $mix_value
* @return \stdClass
*/
Expand Down Expand Up @@ -366,6 +355,26 @@ private function buildQueryParamValue($mix_value)
return $obj_val;
}

/**
* Configure a Value parameter, based on the supplied object-type value
*
* @param object $obj_val
* @param object $mix_value
*/
protected function configureObjectValueParamForQuery($obj_val, $mix_value)
{
if($mix_value instanceof Entity) {
/** @var Entity $mix_value */
$obj_val->keyValue = $this->applyPartition((object)['path' => $this->createMapper()->buildKeyPath($mix_value)]);
} elseif ($mix_value instanceof \DateTime) {
$obj_val->timestampValue = $mix_value->format(\GDS\Mapper\RESTv1::DATETIME_FORMAT);
} elseif (method_exists($mix_value, '__toString')) {
$obj_val->stringValue = $mix_value->__toString();
} else {
throw new \InvalidArgumentException('Unexpected, non-string-able object parameter: ' . get_class($mix_value));
}
}

/**
* Get the end cursor from the last response
*
Expand Down
77 changes: 47 additions & 30 deletions src/GDS/Mapper/RESTv1.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
*/
class RESTv1 extends \GDS\Mapper
{

/**
* This is the DateTime::format string required to support Datastore timestamps
*
* A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z".
*/
const DATETIME_FORMAT = 'Y-m-d\TH:i:s.u\Z';

/**
* Auto detect & extract a value
*
Expand Down Expand Up @@ -63,8 +71,6 @@ protected function extractAutoDetectValue($obj_property)
/**
* Extract a datetime value
*
* A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z".
*
* We will lose accuracy past microseconds (down from nanoseconds) when extracting
*
* @param $obj_property
Expand Down Expand Up @@ -335,9 +341,7 @@ protected function createKeyPathElement(array $arr_kpe)
/**
* Create a property object
*
* @todo Support other value types: date, Geo, Array/list
*
* @todo Compare with paraemter value from REST Gateway
* @todo Compare with parameter value method from REST Gateway
*
* @param array $arr_field_def
* @param $mix_value
Expand All @@ -363,15 +367,16 @@ protected function createPropertyValue(array $arr_field_def, $mix_value)
$obj_property_value->integerValue = $mix_value;
break;

// case Schema::PROPERTY_DATETIME:
// if($mix_value instanceof \DateTime) {
// $obj_dtm = $mix_value;
// } else {
// $obj_dtm = new \DateTime($mix_value);
// }
// $obj_property_value->setDateTimeValue($obj_dtm->format(\DateTime::ATOM));
// break;
//
case Schema::PROPERTY_DATETIME:
if($mix_value instanceof \DateTime) {
$obj_dtm = $mix_value;
} else {
$obj_dtm = new \DateTime($mix_value);
}
// A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z".
$obj_property_value->timestampValue = $obj_dtm->format(self::DATETIME_FORMAT);
break;

case Schema::PROPERTY_DOUBLE:
case Schema::PROPERTY_FLOAT:
$obj_property_value->doubleValue = floatval($mix_value);
Expand All @@ -380,22 +385,34 @@ protected function createPropertyValue(array $arr_field_def, $mix_value)
case Schema::PROPERTY_BOOLEAN:
$obj_property_value->booleanValue = (bool)$mix_value;
break;
//
// case Schema::PROPERTY_GEOPOINT:
// throw new \RuntimeException('Geopoint properties not supported over JSON API');
// break;
//
// case Schema::PROPERTY_STRING_LIST:
// $obj_property_value->setIndexed(null); // Ensure we only index the values, not the list
// $arr_values = [];
// foreach ((array)$mix_value as $str) {
// $obj_value = new \Google_Service_Datastore_Value();
// $obj_value->setStringValue($str);
// $obj_value->setIndexed($bol_index);
// $arr_values[] = $obj_value;
// }
// $obj_property_value->setListValue($arr_values);
// break;

case Schema::PROPERTY_GEOPOINT:
if($mix_value instanceof Geopoint) {
/** @var Geopoint $mix_value */
$obj_property_value->geoPointValue = (object)[
"latitude" => $mix_value->getLatitude(),
"longitude" => $mix_value->getLongitude()
];
} elseif (is_array($mix_value)) {
$obj_property_value->geoPointValue = (object)[
"latitude" => $mix_value[0],
"longitude" => $mix_value[1]
];
} else {
throw new \RuntimeException('Geopoint property data not supported: ' . gettype($mix_value));
}
break;

case Schema::PROPERTY_STRING_LIST:
// @todo Determine if we need to set excludeFromIndexes on the property
$arr_values = [];
foreach ((array)$mix_value as $str) {
$obj_value = (object)['stringValue' => $str];
$obj_value->excludeFromIndexes = !$bol_index;
$arr_values[] = $obj_value;
}
$obj_property_value->arrayValue = (object)['values' => $arr_values];
break;

default:
throw new \RuntimeException('Unable to process field type: ' . $arr_field_def['type']);
Expand Down

0 comments on commit ab58d31

Please sign in to comment.