Server IP : 184.154.167.98 / Your IP : 3.142.195.182 Web Server : Apache System : Linux pink.dnsnetservice.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 User : puertode ( 1767) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /home/puertode/public_html/nextcloud/3rdparty/php-opencloud/openstack/src/Common/Api/ |
Upload File : |
<?php declare(strict_types=1); namespace OpenStack\Common\Api; use OpenStack\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 \OpenStack\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. */ 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 OpenStack\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 ($this->name && false !== stripos($this->name, 'metadata')) { $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(): string { return $this->sentAs ?: $this->name; } /** * Indicates whether the user must provide a value for this parameter. * * @return bool */ public function isRequired(): bool { return true === $this->required; } /** * 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): bool { $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) && 'string' == $this->type && !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 string $key The name of the child parameter * * @returns Parameter * * @throws \Exception */ private function getNestedProperty($key): Parameter { if ($this->name && false !== stripos($this->name, 'metadata') && $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): bool { // 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 ('object' == $this->type && $isAssociative($userValue)) { return true; } if (class_exists($this->type) || interface_exists($this->type)) { return is_a($userValue, $this->type); } if (!$this->type) { return true; } // allow string nulls if ('string' == $this->type && null === $userValue) { return true; } return gettype($userValue) == $this->type; } /** * Indicates whether this parameter represents an array type. * * @return bool */ public function isArray(): bool { return 'array' == $this->type && $this->itemSchema instanceof Parameter; } /** * Indicates whether this parameter represents an object type. * * @return bool */ public function isObject(): bool { return 'object' == $this->type && !empty($this->properties); } public function getLocation(): string { return $this->location; } /** * Verifies whether the given location matches the parameter's location. * * @param $value * * @return bool */ public function hasLocation($value): bool { return $this->location == $value; } /** * Retrieves the parameter's path. * * @return string|null */ public function getPath(): string { return $this->path; } /** * Retrieves the common schema that an array parameter applies to all its child elements. * * @return Parameter|null */ public function getItemSchema() { return $this->itemSchema; } /** * Sets the name of the parameter to a new value. * * @param string $name */ public function setName(string $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(string $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(): string { return $this->prefix; } public function getPrefixedName(): string { return $this->prefix.$this->getName(); } }