/** * Custom handling for objects * * @param Parameter $param Parameter for the object * @param array $value Value that is set for this parameter * @param string $prefix Prefix for the resulting key * @param array $query Query string array passed by reference */ protected function resolveObject(Parameter $param, array $value, $prefix, array &$query) { // Maps are implemented using additional properties $hasAdditionalProperties = $param->getAdditionalProperties() instanceof Parameter; $additionalPropertyCount = 0; foreach ($value as $name => $v) { if ($subParam = $param->getProperty($name)) { // if the parameter was found by name as a regular property $key = $prefix . '.' . $subParam->getWireName(); $this->customResolver($v, $subParam, $query, $key); } elseif ($hasAdditionalProperties) { // Handle map cases like &Attribute.1.Name=<name>&Attribute.1.Value=<value> $additionalPropertyCount++; $data = $param->getData(); $keyName = isset($data['keyName']) ? $data['keyName'] : 'key'; $valueName = isset($data['valueName']) ? $data['valueName'] : 'value'; $query["{$prefix}.{$additionalPropertyCount}.{$keyName}"] = $name; $newPrefix = "{$prefix}.{$additionalPropertyCount}.{$valueName}"; if (is_array($v)) { $this->customResolver($v, $param->getAdditionalProperties(), $query, $newPrefix); } else { $query[$newPrefix] = $param->filter($v); } } } }
protected function resolveRecursively(array $value, Parameter $param) { foreach ($value as $name => &$v) { switch ($param->getType()) { case 'object': if ($subParam = $param->getProperty($name)) { $key = $subParam->getWireName(); $value[$key] = $this->prepareValue($v, $subParam); if ($name != $key) { unset($value[$name]); } } elseif ($param->getAdditionalProperties() instanceof Parameter) { $v = $this->prepareValue($v, $param->getAdditionalProperties()); } break; case 'array': if ($items = $param->getItems()) { $v = $this->prepareValue($v, $items); } break; } } return $param->filter($value); }
/** * Map nested parameters into the location_key based parameters * * @param array $value Value to map * @param Parameter $param Parameter that holds information about the current key * @param array $query Built up query string values * @param string $prefix String to prepend to sub query values */ protected function customResolver($value, Parameter $param, array &$query, $prefix = '') { if ($param->getType() == 'object') { foreach ($value as $name => $v) { if ($subParam = $param->getProperty($name)) { $key = $prefix . '.' . $subParam->getWireName(); if (is_array($v)) { $this->customResolver($v, $subParam, $query, $key); } else { $query[$key] = $v; } } } } elseif ($param->getType() == 'array') { $offset = $param->getData('offset') ?: 0; foreach ($value as $index => $v) { $index += $offset; if (is_array($v) && ($items = $param->getItems())) { $this->customResolver($v, $items, $query, $prefix . '.' . $index); } else { $query[$prefix . '.' . $index] = $v; } } } else { $query[$prefix] = $value; } }
/** * Map nested parameters into the location_key based parameters * * @param array $value Value to map * @param Parameter $param Parameter that holds information about the current key * * @return array Returns the mapped array */ protected function resolveRecursively(array $value, Parameter $param) { foreach ($value as $name => $v) { if ($subParam = $param->getProperty($name)) { $key = $subParam->getWireName(); if (is_array($v)) { $value[$key] = $this->resolveRecursively($v, $subParam); } elseif ($name != $key) { $value[$key] = $param->filter($v); unset($value[$name]); } } } return $value; }
/** * Add an object to the XML */ protected function addXmlObject(\XMLWriter $xmlWriter, Parameter $param, &$value) { $noAttributes = array(); // add values which have attributes foreach ($value as $name => $v) { if ($property = $param->getProperty($name)) { if ($property->getData('xmlAttribute')) { $this->addXml($xmlWriter, $property, $v); } else { $noAttributes[] = array('value' => $v, 'property' => $property); } } } // now add values with no attributes foreach ($noAttributes as $element) { $this->addXml($xmlWriter, $element['property'], $element['value']); } }
protected function visitAdditionalProperties(Parameter $model, CommandInterface $command, Response $response, Parameter $additional, &$result, array &$foundVisitors) { // Only visit when a location is specified if ($location = $additional->getLocation()) { if (!isset($foundVisitors[$location])) { $foundVisitors[$location] = $this->factory->getResponseVisitor($location); $foundVisitors[$location]->before($command, $result); } // Only traverse if an array was parsed from the before() visitors if (is_array($result)) { // Find each additional property foreach (array_keys($result) as $key) { // Check if the model actually knows this property. If so, then it is not additional if (!$model->getProperty($key)) { // Set the name to the key so that we can parse it with each visitor $additional->setName($key); $foundVisitors[$location]->visit($command, $response, $additional, $result); } } // Reset the additionalProperties name to null $additional->setName(null); } } }
/** * Processes model data according to a parameter schema * * @param Desk\Relationship\Resource\EmbeddedCommand $command * @param Guzzle\Service\Description\Parameter $schema * @param array $data * * @return array */ public function process(EmbeddedCommand $command, Parameter $schema, array $data) { $result = array(); $visitors = array(); $properties = $schema->getProperties(); foreach ($properties as $property) { $location = $property->getLocation(); if ($location && !isset($visitors[$location])) { // add visitor for this location and trigger before() $visitor = $this->visitors->getResponseVisitor($location); $visitor->before($command, $result); $visitors[$location] = $visitor; } } $response = $command->getResponse(); // Visit additional properties when it is an actual schema $additional = $schema->getAdditionalProperties(); if ($additional instanceof Parameter) { // Only visit when a location is specified $location = $additional->getLocation(); if ($location) { if (!isset($visitors[$location])) { $visitors[$location] = $this->visitors->getResponseVisitor($location); $visitors[$location]->before($command, $result); } // Only traverse if an array was parsed from the before() visitors if (is_array($result)) { // Find each additional property foreach (array_keys($result) as $key) { // Check if the model actually knows this property. If so, then it is not additional if (!$schema->getProperty($key)) { // Set the name to the key so that we can parse it with each visitor $additional->setName($key); $visitors[$location]->visit($command, $response, $additional, $result); } } // Reset the additionalProperties name to null $additional->setName(null); } } } // Apply the parameter value with the location visitor foreach ($properties as $property) { $location = $property->getLocation(); if ($location) { $visitors[$location]->visit($command, $response, $property, $result); } } // Call the after() method of each found visitor foreach ($visitors as $visitor) { $visitor->after($command); } return $result; }
public function testAllowsNestedShape() { $command = $this->getServiceBuilder()->get('mock')->getCommand('mock_command')->getOperation(); $param = new Parameter(array('parent' => $command, 'name' => 'foo', 'type' => 'object', 'location' => 'query', 'properties' => array('foo' => array('type' => 'object', 'required' => true, 'properties' => array('baz' => array('name' => 'baz', 'type' => 'bool'))), 'bar' => array('name' => 'bar', 'default' => '123')))); $this->assertSame($command, $param->getParent()); $this->assertNotEmpty($param->getProperties()); $this->assertInstanceOf('Guzzle\\Service\\Description\\Parameter', $param->getProperty('foo')); $this->assertSame($param, $param->getProperty('foo')->getParent()); $this->assertSame($param->getProperty('foo'), $param->getProperty('foo')->getProperty('baz')->getParent()); $this->assertInstanceOf('Guzzle\\Service\\Description\\Parameter', $param->getProperty('bar')); $this->assertSame($param, $param->getProperty('bar')->getParent()); $array = $param->toArray(); $this->assertInternalType('array', $array['properties']); $this->assertArrayHasKey('foo', $array['properties']); $this->assertArrayHasKey('bar', $array['properties']); }
protected function visitAdditionalProperties( Parameter $model, CommandInterface $command, Response $response, Parameter $additional, &$result, array &$foundVisitors ) { if ($location = $additional->getLocation()) { if (!isset($foundVisitors[$location])) { $foundVisitors[$location] = $this->factory->getResponseVisitor($location); $foundVisitors[$location]->before($command, $result); } if (is_array($result)) { foreach (array_keys($result) as $key) { if (!$model->getProperty($key)) { $additional->setName($key); $foundVisitors[$location]->visit($command, $response, $additional, $result); } } $additional->setName(null); } } }
/** * Perform transformations on the result array * * @param Parameter $model Model that defines the structure * @param CommandInterface $command Command that performed the operation * @param Response $response Response received * * @return array Returns the array of result data */ protected function visitResult(Parameter $model, CommandInterface $command, Response $response) { $foundVisitors = $result = array(); $props = $model->getProperties(); foreach ($props as $schema) { if ($location = $schema->getLocation()) { // Trigger the before method on the first found visitor of this type if (!isset($foundVisitors[$location])) { $foundVisitors[$location] = $this->factory->getResponseVisitor($location); $foundVisitors[$location]->before($command, $result); } } } // Visit additional properties when it is an actual schema if ($additional = $model->getAdditionalProperties()) { if ($additional instanceof Parameter) { // Only visit when a location is specified if ($location = $additional->getLocation()) { if (!isset($foundVisitors[$location])) { $foundVisitors[$location] = $this->factory->getResponseVisitor($location); $foundVisitors[$location]->before($command, $result); } // Only traverse if an array was parsed from the before() visitors if (is_array($result)) { // Find each additional property foreach (array_keys($result) as $key) { // Check if the model actually knows this property. If so, then it is not additional if (!$model->getProperty($key)) { // Set the name to the key so that we can parse it with each visitor $additional->setName($key); $foundVisitors[$location]->visit($command, $response, $additional, $result); } } // Reset the additionalProperties name to null $additional->setName(null); } } } } // Apply the parameter value with the location visitor foreach ($props as $schema) { if ($location = $schema->getLocation()) { $foundVisitors[$location]->visit($command, $response, $schema, $result); } } // Call the after() method of each found visitor foreach ($foundVisitors as $visitor) { $visitor->after($command); } return $result; }
/** * Add an object to the XML */ protected function addXmlObject(\SimpleXMLElement $xml, Parameter $param, &$value) { foreach ($value as $name => $v) { if ($property = $param->getProperty($name)) { $this->addXml($xml, $property, $v); } } }
/** * Add an object to the XML */ protected function addXmlObject(\XMLWriter $xmlWriter, Parameter $param, &$value) { foreach ($value as $name => $v) { if ($property = $param->getProperty($name)) { $this->addXml($xmlWriter, $property, $v); } } }
/** * Add an object to the XML * * @param \SimpleXMLElement $xml XML to modify * @param Parameter $param API Parameter * @param mixed $value Value to add */ protected function addXmlObject(\SimpleXMLElement $xml, Parameter $param, &$value) { foreach ($value as $name => $v) { // Don't add null values if ($v !== null) { // Continue recursing if a matching property is found if ($property = $param->getProperty($name)) { if ($property->getType() == 'object' || $property->getType() == 'array') { // Account for flat arrays, meaning the contents of the array are not wrapped in a container $child = $property->getData('xmlFlattened') ? $xml : $xml->addChild($property->getWireName()); $this->addXml($child, $property, $v); } else { if ($property->getData('xmlAttribute')) { $xml->addAttribute($property->getWireName(), $v, $property->getData('xmlNamespace')); } else { $xml->addChild($property->getWireName(), $v, $property->getData('xmlNamespace')); } } } } } }