summaryrefslogtreecommitdiff
path: root/server/vendor/php-opencloud/common/src/Common/Api/Parameter.php
diff options
context:
space:
mode:
authorroot <root@kabir-PC>2016-03-23 11:31:51 +0100
committerroot <root@kabir-PC>2016-03-23 11:31:51 +0100
commita26989103d70fb0dd3ff6834de107cae246778c3 (patch)
tree0f243c83b790ffb57f19261fc2a509131f6776ce /server/vendor/php-opencloud/common/src/Common/Api/Parameter.php
parent1342db60283cb61a1c3810993575d35b9fb33ac0 (diff)
parent6e78d76f887d1149ea85bfb06db7ee7ad7435f5a (diff)
Merge branch 'develop' of https://github.com/manzerbredes/istic-openstack into develop
Diffstat (limited to 'server/vendor/php-opencloud/common/src/Common/Api/Parameter.php')
-rw-r--r--server/vendor/php-opencloud/common/src/Common/Api/Parameter.php389
1 files changed, 389 insertions, 0 deletions
diff --git a/server/vendor/php-opencloud/common/src/Common/Api/Parameter.php b/server/vendor/php-opencloud/common/src/Common/Api/Parameter.php
new file mode 100644
index 0000000..97330a4
--- /dev/null
+++ b/server/vendor/php-opencloud/common/src/Common/Api/Parameter.php
@@ -0,0 +1,389 @@
+<?php
+
+namespace OpenCloud\Common\Api;
+
+use OpenCloud\Common\HydratorStrategyTrait;
+
+/**
+ * Represents an individual request parameter in a RESTful operation. A parameter can take on many forms:
+ * in a URL path, in a URL query, in a JSON body, and in a HTTP header. It is worth documenting brifly each
+ * variety of parameter:
+ *
+ * * Header parameters are those which populate a HTTP header in a request. Header parameters can have
+ * aliases; for example, a user-facing name of "Foo" can be sent over the wire as "X-Foo_Bar", as defined
+ * by ``sentAs``. Prefixes can also be used.
+ *
+ * * Query parameters are those which populate a URL query parameter. The value is therefore usually
+ * confined to a string.
+ *
+ * * JSON parameters are those which populate a JSON request body. These are the most complex variety
+ * of Parameter, since there are so many different ways a JSON document can be constructed. The SDK
+ * supports deep-nesting according to a XPath syntax; for more information, see {@see \OpenCloud\Common\JsonPath}.
+ * Nested object and array properties are also supported since JSON is a recursive data type. What
+ * this means is that a Parameter can have an assortment of child Parameters, one for each object
+ * property or array element.
+ *
+ * * Raw parameters are those which populate a non-JSON request body. This is typically used for
+ * uploading payloads (such as Swift object data) to a remote API.
+ *
+ * * Path parameters are those which populate a URL path. They are serialized according to URL
+ * placeholders.
+ *
+ * @package OpenCloud\Common\Api
+ */
+class Parameter
+{
+ use HydratorStrategyTrait;
+
+ const DEFAULT_LOCATION = 'json';
+
+ /**
+ * The human-friendly name of the parameter. This is what the user will input.
+ *
+ * @var string
+ */
+ private $name;
+
+ /**
+ * The alias for this parameter. Although the user will always interact with the human-friendly $name property,
+ * the $sentAs is what's used over the wire.
+ *
+ * @var string
+ */
+ private $sentAs;
+
+ /**
+ * For array parameters (for example, an array of security group names when creating a server), each array element
+ * will need to adhere to a common schema. For the aforementioned example, each element will need to be a string.
+ * For more complicated parameters, you might be validated an array of complicated objects.
+ *
+ * @var Parameter
+ */
+ private $itemSchema;
+
+ /**
+ * For object parameters, each property will need to adhere to a specific schema. For every property in the
+ * object, it has its own schema - meaning that this property is a hash of name/schema pairs.
+ *
+ * The *only* exception to this rule is for metadata parameters, which are arbitrary key/value pairs. Since it does
+ * not make sense to have a schema for each metadata key, a common schema is use for every one. So instead of this
+ * property being a hash of schemas, it is a single Parameter object instead. This single Parameter schema will
+ * then be applied to each metadata key provided.
+ *
+ * @var []Parameter|Parameter
+ */
+ private $properties;
+
+ /**
+ * The value's PHP type which this parameter represents; either "string", "bool", "object", "array", "NULL".
+ *
+ * @var string
+ */
+ private $type;
+
+ /**
+ * Indicates whether this parameter requires a value from the user.
+ *
+ * @var bool
+ */
+ private $required;
+
+ /**
+ * The location in the HTTP request where this parameter will populate; either "header", "url", "query", "raw" or
+ * "json".
+ *
+ * @var string
+ */
+ private $location;
+
+ /**
+ * Relevant to "json" location parameters only. This property allows for deep nesting through the use of
+ * {@see OpenCloud\Common\JsonPath}.
+ *
+ * @var string
+ */
+ private $path;
+
+ /**
+ * Allows for the prefixing of parameter names.
+ *
+ * @var string
+ */
+ private $prefix;
+
+ /**
+ * The enum values for which this param is restricted.
+ *
+ * @var array
+ */
+ private $enum;
+
+ /**
+ * @param array $data
+ */
+ public function __construct(array $data)
+ {
+ $this->hydrate($data);
+
+ $this->required = (bool)$this->required;
+
+ $this->stockLocation($data);
+ $this->stockItemSchema($data);
+ $this->stockProperties($data);
+ }
+
+ private function stockLocation(array $data)
+ {
+ $this->location = isset($data['location']) ? $data['location'] : self::DEFAULT_LOCATION;
+
+ if (!AbstractParams::isSupportedLocation($this->location)) {
+ throw new \RuntimeException(sprintf("%s is not a permitted location", $this->location));
+ }
+ }
+
+ private function stockItemSchema(array $data)
+ {
+ if (isset($data['items'])) {
+ $this->itemSchema = new Parameter($data['items']);
+ }
+ }
+
+ private function stockProperties(array $data)
+ {
+ if (isset($data['properties'])) {
+ if (stripos($this->name, 'metadata') !== false) {
+ $this->properties = new Parameter($data['properties']);
+ } else {
+ foreach ($data['properties'] as $name => $property) {
+ $this->properties[$name] = new Parameter($property + ['name' => $name]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Retrieve the name that will be used over the wire.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->sentAs ?: $this->name;
+ }
+
+ /**
+ * Indicates whether the user must provide a value for this parameter.
+ *
+ * @return bool
+ */
+ public function isRequired()
+ {
+ return $this->required === true;
+ }
+
+ /**
+ * Validates a given user value and checks whether it passes basic sanity checking, such as types.
+ *
+ * @param $userValues The value provided by the user
+ *
+ * @return bool TRUE if the validation passes
+ * @throws \Exception If validation fails
+ */
+ public function validate($userValues)
+ {
+ $this->validateEnums($userValues);
+ $this->validateType($userValues);
+
+ if ($this->isArray()) {
+ $this->validateArray($userValues);
+ } elseif ($this->isObject()) {
+ $this->validateObject($userValues);
+ }
+
+ return true;
+ }
+
+ private function validateEnums($userValues)
+ {
+ if (!empty($this->enum) && $this->type == 'string' && !in_array($userValues, $this->enum)) {
+ throw new \Exception(sprintf(
+ 'The only permitted values are %s. You provided %s', implode(', ', $this->enum), print_r($userValues, true)
+ ));
+ }
+ }
+
+ private function validateType($userValues)
+ {
+ if (!$this->hasCorrectType($userValues)) {
+ throw new \Exception(sprintf(
+ 'The key provided "%s" has the wrong value type. You provided %s (%s) but was expecting %s',
+ $this->name, print_r($userValues, true), gettype($userValues), $this->type
+ ));
+ }
+ }
+
+ private function validateArray($userValues)
+ {
+ foreach ($userValues as $userValue) {
+ $this->itemSchema->validate($userValue);
+ }
+ }
+
+ private function validateObject($userValues)
+ {
+ foreach ($userValues as $key => $userValue) {
+ $property = $this->getNestedProperty($key);
+ $property->validate($userValue);
+ }
+ }
+
+ /**
+ * Internal method which retrieves a nested property for object parameters.
+ *
+ * @param $key The name of the child parameter
+ *
+ * @returns Parameter
+ * @throws \Exception
+ */
+ private function getNestedProperty($key)
+ {
+ if (stripos($this->name, 'metadata') !== false && $this->properties instanceof Parameter) {
+ return $this->properties;
+ } elseif (isset($this->properties[$key])) {
+ return $this->properties[$key];
+ } else {
+ throw new \Exception(sprintf('The key provided "%s" is not defined', $key));
+ }
+ }
+
+ /**
+ * Internal method which indicates whether the user value is of the same type as the one expected
+ * by this parameter.
+ *
+ * @param $userValue The value being checked
+ *
+ * @return bool
+ */
+ private function hasCorrectType($userValue)
+ {
+ // Helper fn to see whether an array is associative (i.e. a JSON object)
+ $isAssociative = function ($value) {
+ return is_array($value) && array_keys($value) !== range(0, count($value) - 1);
+ };
+
+ // For params defined as objects, we'll let the user get away with
+ // passing in an associative array - since it's effectively a hash
+ if ($this->type == 'object' && $isAssociative($userValue)) {
+ return true;
+ }
+
+ if (class_exists($this->type) || interface_exists($this->type)) {
+ return is_a($userValue, $this->type);
+ }
+
+ if (!$this->type) {
+ return true;
+ }
+
+ return gettype($userValue) == $this->type;
+ }
+
+ /**
+ * Indicates whether this parameter represents an array type
+ *
+ * @return bool
+ */
+ public function isArray()
+ {
+ return $this->type == 'array' && $this->itemSchema instanceof Parameter;
+ }
+
+ /**
+ * Indicates whether this parameter represents an object type
+ *
+ * @return bool
+ */
+ public function isObject()
+ {
+ return $this->type == 'object' && !empty($this->properties);
+ }
+
+ public function getLocation()
+ {
+ return $this->location;
+ }
+
+ /**
+ * Verifies whether the given location matches the parameter's location.
+ *
+ * @param $value
+ *
+ * @return bool
+ */
+ public function hasLocation($value)
+ {
+ return $this->location == $value;
+ }
+
+ /**
+ * Retrieves the parameter's path.
+ *
+ * @return string|null
+ */
+ public function getPath()
+ {
+ return $this->path;
+ }
+
+ /**
+ * Retrieves the common schema that an array parameter applies to all its child elements.
+ *
+ * @return Parameter
+ */
+ public function getItemSchema()
+ {
+ return $this->itemSchema;
+ }
+
+ /**
+ * Sets the name of the parameter to a new value
+ *
+ * @param string $name
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * Retrieves the child parameter for an object parameter.
+ *
+ * @param string $name The name of the child property
+ *
+ * @return null|Parameter
+ */
+ public function getProperty($name)
+ {
+ if ($this->properties instanceof Parameter) {
+ $this->properties->setName($name);
+ return $this->properties;
+ }
+
+ return isset($this->properties[$name]) ? $this->properties[$name] : null;
+ }
+
+ /**
+ * Retrieves the prefix for a parameter, if any.
+ *
+ * @return string|null
+ */
+ public function getPrefix()
+ {
+ return $this->prefix;
+ }
+
+ public function getPrefixedName()
+ {
+ return $this->prefix . $this->getName();
+ }
+}