PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/api/vendor/guzzle/guzzle/src/Guzzle/Service/Command/OperationResponseParser.php

https://gitlab.com/x33n/respond
PHP | 195 lines | 117 code | 24 blank | 54 comment | 18 complexity | bbeeaf651605a494a97315e221f5eb1a MD5 | raw file
  1. <?php
  2. namespace Guzzle\Service\Command;
  3. use Guzzle\Http\Message\Response;
  4. use Guzzle\Service\Command\LocationVisitor\VisitorFlyweight;
  5. use Guzzle\Service\Command\LocationVisitor\Response\ResponseVisitorInterface;
  6. use Guzzle\Service\Description\Parameter;
  7. use Guzzle\Service\Description\OperationInterface;
  8. use Guzzle\Service\Description\Operation;
  9. use Guzzle\Service\Exception\ResponseClassException;
  10. use Guzzle\Service\Resource\Model;
  11. /**
  12. * Response parser that attempts to marshal responses into an associative array based on models in a service description
  13. */
  14. class OperationResponseParser extends DefaultResponseParser
  15. {
  16. /** @var VisitorFlyweight $factory Visitor factory */
  17. protected $factory;
  18. /** @var self */
  19. protected static $instance;
  20. /** @var bool */
  21. private $schemaInModels;
  22. /**
  23. * @return self
  24. * @codeCoverageIgnore
  25. */
  26. public static function getInstance()
  27. {
  28. if (!static::$instance) {
  29. static::$instance = new static(VisitorFlyweight::getInstance());
  30. }
  31. return static::$instance;
  32. }
  33. /**
  34. * @param VisitorFlyweight $factory Factory to use when creating visitors
  35. * @param bool $schemaInModels Set to true to inject schemas into models
  36. */
  37. public function __construct(VisitorFlyweight $factory, $schemaInModels = false)
  38. {
  39. $this->factory = $factory;
  40. $this->schemaInModels = $schemaInModels;
  41. }
  42. /**
  43. * Add a location visitor to the command
  44. *
  45. * @param string $location Location to associate with the visitor
  46. * @param ResponseVisitorInterface $visitor Visitor to attach
  47. *
  48. * @return self
  49. */
  50. public function addVisitor($location, ResponseVisitorInterface $visitor)
  51. {
  52. $this->factory->addResponseVisitor($location, $visitor);
  53. return $this;
  54. }
  55. protected function handleParsing(CommandInterface $command, Response $response, $contentType)
  56. {
  57. $operation = $command->getOperation();
  58. $type = $operation->getResponseType();
  59. $model = null;
  60. if ($type == OperationInterface::TYPE_MODEL) {
  61. $model = $operation->getServiceDescription()->getModel($operation->getResponseClass());
  62. } elseif ($type == OperationInterface::TYPE_CLASS) {
  63. return $this->parseClass($command);
  64. }
  65. if (!$model) {
  66. // Return basic processing if the responseType is not model or the model cannot be found
  67. return parent::handleParsing($command, $response, $contentType);
  68. } elseif ($command[AbstractCommand::RESPONSE_PROCESSING] != AbstractCommand::TYPE_MODEL) {
  69. // Returns a model with no visiting if the command response processing is not model
  70. return new Model(parent::handleParsing($command, $response, $contentType));
  71. } else {
  72. // Only inject the schema into the model if "schemaInModel" is true
  73. return new Model($this->visitResult($model, $command, $response), $this->schemaInModels ? $model : null);
  74. }
  75. }
  76. /**
  77. * Parse a class object
  78. *
  79. * @param CommandInterface $command Command to parse into an object
  80. *
  81. * @return mixed
  82. * @throws ResponseClassException
  83. */
  84. protected function parseClass(CommandInterface $command)
  85. {
  86. // Emit the operation.parse_class event. If a listener injects a 'result' property, then that will be the result
  87. $event = new CreateResponseClassEvent(array('command' => $command));
  88. $command->getClient()->getEventDispatcher()->dispatch('command.parse_response', $event);
  89. if ($result = $event->getResult()) {
  90. return $result;
  91. }
  92. $className = $command->getOperation()->getResponseClass();
  93. if (!method_exists($className, 'fromCommand')) {
  94. throw new ResponseClassException("{$className} must exist and implement a static fromCommand() method");
  95. }
  96. return $className::fromCommand($command);
  97. }
  98. /**
  99. * Perform transformations on the result array
  100. *
  101. * @param Parameter $model Model that defines the structure
  102. * @param CommandInterface $command Command that performed the operation
  103. * @param Response $response Response received
  104. *
  105. * @return array Returns the array of result data
  106. */
  107. protected function visitResult(Parameter $model, CommandInterface $command, Response $response)
  108. {
  109. $foundVisitors = $result = $knownProps = array();
  110. $props = $model->getProperties();
  111. foreach ($props as $schema) {
  112. if ($location = $schema->getLocation()) {
  113. // Trigger the before method on the first found visitor of this type
  114. if (!isset($foundVisitors[$location])) {
  115. $foundVisitors[$location] = $this->factory->getResponseVisitor($location);
  116. $foundVisitors[$location]->before($command, $result);
  117. }
  118. }
  119. }
  120. // Visit additional properties when it is an actual schema
  121. if (($additional = $model->getAdditionalProperties()) instanceof Parameter) {
  122. $this->visitAdditionalProperties($model, $command, $response, $additional, $result, $foundVisitors);
  123. }
  124. // Apply the parameter value with the location visitor
  125. foreach ($props as $schema) {
  126. $knownProps[$schema->getName()] = 1;
  127. if ($location = $schema->getLocation()) {
  128. $foundVisitors[$location]->visit($command, $response, $schema, $result);
  129. }
  130. }
  131. // Remove any unknown and potentially unsafe top-level properties
  132. if ($additional === false) {
  133. $result = array_intersect_key($result, $knownProps);
  134. }
  135. // Call the after() method of each found visitor
  136. foreach ($foundVisitors as $visitor) {
  137. $visitor->after($command);
  138. }
  139. return $result;
  140. }
  141. protected function visitAdditionalProperties(
  142. Parameter $model,
  143. CommandInterface $command,
  144. Response $response,
  145. Parameter $additional,
  146. &$result,
  147. array &$foundVisitors
  148. ) {
  149. // Only visit when a location is specified
  150. if ($location = $additional->getLocation()) {
  151. if (!isset($foundVisitors[$location])) {
  152. $foundVisitors[$location] = $this->factory->getResponseVisitor($location);
  153. $foundVisitors[$location]->before($command, $result);
  154. }
  155. // Only traverse if an array was parsed from the before() visitors
  156. if (is_array($result)) {
  157. // Find each additional property
  158. foreach (array_keys($result) as $key) {
  159. // Check if the model actually knows this property. If so, then it is not additional
  160. if (!$model->getProperty($key)) {
  161. // Set the name to the key so that we can parse it with each visitor
  162. $additional->setName($key);
  163. $foundVisitors[$location]->visit($command, $response, $additional, $result);
  164. }
  165. }
  166. // Reset the additionalProperties name to null
  167. $additional->setName(null);
  168. }
  169. }
  170. }
  171. }