summaryrefslogtreecommitdiff
path: root/vendor/guzzle/guzzle/src/Guzzle/Service/Command/OperationResponseParser.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/guzzle/guzzle/src/Guzzle/Service/Command/OperationResponseParser.php')
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Service/Command/OperationResponseParser.php195
1 files changed, 195 insertions, 0 deletions
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Service/Command/OperationResponseParser.php b/vendor/guzzle/guzzle/src/Guzzle/Service/Command/OperationResponseParser.php
new file mode 100644
index 0000000..ca00bc0
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Service/Command/OperationResponseParser.php
@@ -0,0 +1,195 @@
+<?php
+
+namespace Guzzle\Service\Command;
+
+use Guzzle\Http\Message\Response;
+use Guzzle\Service\Command\LocationVisitor\VisitorFlyweight;
+use Guzzle\Service\Command\LocationVisitor\Response\ResponseVisitorInterface;
+use Guzzle\Service\Description\Parameter;
+use Guzzle\Service\Description\OperationInterface;
+use Guzzle\Service\Description\Operation;
+use Guzzle\Service\Exception\ResponseClassException;
+use Guzzle\Service\Resource\Model;
+
+/**
+ * Response parser that attempts to marshal responses into an associative array based on models in a service description
+ */
+class OperationResponseParser extends DefaultResponseParser
+{
+ /** @var VisitorFlyweight $factory Visitor factory */
+ protected $factory;
+
+ /** @var self */
+ protected static $instance;
+
+ /** @var bool */
+ private $schemaInModels;
+
+ /**
+ * @return self
+ * @codeCoverageIgnore
+ */
+ public static function getInstance()
+ {
+ if (!static::$instance) {
+ static::$instance = new static(VisitorFlyweight::getInstance());
+ }
+
+ return static::$instance;
+ }
+
+ /**
+ * @param VisitorFlyweight $factory Factory to use when creating visitors
+ * @param bool $schemaInModels Set to true to inject schemas into models
+ */
+ public function __construct(VisitorFlyweight $factory, $schemaInModels = false)
+ {
+ $this->factory = $factory;
+ $this->schemaInModels = $schemaInModels;
+ }
+
+ /**
+ * Add a location visitor to the command
+ *
+ * @param string $location Location to associate with the visitor
+ * @param ResponseVisitorInterface $visitor Visitor to attach
+ *
+ * @return self
+ */
+ public function addVisitor($location, ResponseVisitorInterface $visitor)
+ {
+ $this->factory->addResponseVisitor($location, $visitor);
+
+ return $this;
+ }
+
+ protected function handleParsing(CommandInterface $command, Response $response, $contentType)
+ {
+ $operation = $command->getOperation();
+ $type = $operation->getResponseType();
+ $model = null;
+
+ if ($type == OperationInterface::TYPE_MODEL) {
+ $model = $operation->getServiceDescription()->getModel($operation->getResponseClass());
+ } elseif ($type == OperationInterface::TYPE_CLASS) {
+ return $this->parseClass($command);
+ }
+
+ if (!$model) {
+ // Return basic processing if the responseType is not model or the model cannot be found
+ return parent::handleParsing($command, $response, $contentType);
+ } elseif ($command[AbstractCommand::RESPONSE_PROCESSING] != AbstractCommand::TYPE_MODEL) {
+ // Returns a model with no visiting if the command response processing is not model
+ return new Model(parent::handleParsing($command, $response, $contentType));
+ } else {
+ // Only inject the schema into the model if "schemaInModel" is true
+ return new Model($this->visitResult($model, $command, $response), $this->schemaInModels ? $model : null);
+ }
+ }
+
+ /**
+ * Parse a class object
+ *
+ * @param CommandInterface $command Command to parse into an object
+ *
+ * @return mixed
+ * @throws ResponseClassException
+ */
+ protected function parseClass(CommandInterface $command)
+ {
+ // Emit the operation.parse_class event. If a listener injects a 'result' property, then that will be the result
+ $event = new CreateResponseClassEvent(array('command' => $command));
+ $command->getClient()->getEventDispatcher()->dispatch('command.parse_response', $event);
+ if ($result = $event->getResult()) {
+ return $result;
+ }
+
+ $className = $command->getOperation()->getResponseClass();
+ if (!method_exists($className, 'fromCommand')) {
+ throw new ResponseClassException("{$className} must exist and implement a static fromCommand() method");
+ }
+
+ return $className::fromCommand($command);
+ }
+
+ /**
+ * 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 = $knownProps = 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()) instanceof Parameter) {
+ $this->visitAdditionalProperties($model, $command, $response, $additional, $result, $foundVisitors);
+ }
+
+ // Apply the parameter value with the location visitor
+ foreach ($props as $schema) {
+ $knownProps[$schema->getName()] = 1;
+ if ($location = $schema->getLocation()) {
+ $foundVisitors[$location]->visit($command, $response, $schema, $result);
+ }
+ }
+
+ // Remove any unknown and potentially unsafe top-level properties
+ if ($additional === false) {
+ $result = array_intersect_key($result, $knownProps);
+ }
+
+ // Call the after() method of each found visitor
+ foreach ($foundVisitors as $visitor) {
+ $visitor->after($command);
+ }
+
+ return $result;
+ }
+
+ 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);
+ }
+ }
+ }
+}