Serializer.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. namespace GuzzleHttp\Command\Guzzle;
  3. use GuzzleHttp\Command\CommandInterface;
  4. use GuzzleHttp\Command\Guzzle\RequestLocation\BodyLocation;
  5. use GuzzleHttp\Command\Guzzle\RequestLocation\FormParamLocation;
  6. use GuzzleHttp\Command\Guzzle\RequestLocation\HeaderLocation;
  7. use GuzzleHttp\Command\Guzzle\RequestLocation\JsonLocation;
  8. use GuzzleHttp\Command\Guzzle\RequestLocation\MultiPartLocation;
  9. use GuzzleHttp\Command\Guzzle\RequestLocation\QueryLocation;
  10. use GuzzleHttp\Command\Guzzle\RequestLocation\RequestLocationInterface;
  11. use GuzzleHttp\Command\Guzzle\RequestLocation\XmlLocation;
  12. use GuzzleHttp\Psr7\Request;
  13. use GuzzleHttp\Psr7\Uri;
  14. use Psr\Http\Message\RequestInterface;
  15. /**
  16. * Serializes requests for a given command.
  17. */
  18. class Serializer
  19. {
  20. /** @var RequestLocationInterface[] */
  21. private $locations;
  22. /** @var DescriptionInterface */
  23. private $description;
  24. /**
  25. * @param DescriptionInterface $description
  26. * @param RequestLocationInterface[] $requestLocations Extra request locations
  27. */
  28. public function __construct(
  29. DescriptionInterface $description,
  30. array $requestLocations = []
  31. ) {
  32. static $defaultRequestLocations;
  33. if (!$defaultRequestLocations) {
  34. $defaultRequestLocations = [
  35. 'body' => new BodyLocation(),
  36. 'query' => new QueryLocation(),
  37. 'header' => new HeaderLocation(),
  38. 'json' => new JsonLocation(),
  39. 'xml' => new XmlLocation(),
  40. 'formParam' => new FormParamLocation(),
  41. 'multipart' => new MultiPartLocation(),
  42. ];
  43. }
  44. $this->locations = $requestLocations + $defaultRequestLocations;
  45. $this->description = $description;
  46. }
  47. /**
  48. * @param CommandInterface $command
  49. * @return RequestInterface
  50. */
  51. public function __invoke(CommandInterface $command)
  52. {
  53. $request = $this->createRequest($command);
  54. return $this->prepareRequest($command, $request);
  55. }
  56. /**
  57. * Prepares a request for sending using location visitors
  58. *
  59. * @param CommandInterface $command
  60. * @param RequestInterface $request Request being created
  61. * @return RequestInterface
  62. * @throws \RuntimeException If a location cannot be handled
  63. */
  64. protected function prepareRequest(
  65. CommandInterface $command,
  66. RequestInterface $request
  67. ) {
  68. $visitedLocations = [];
  69. $operation = $this->description->getOperation($command->getName());
  70. // Visit each actual parameter
  71. foreach ($operation->getParams() as $name => $param) {
  72. /* @var Parameter $param */
  73. $location = $param->getLocation();
  74. // Skip parameters that have not been set or are URI location
  75. if ($location == 'uri' || !$command->hasParam($name)) {
  76. continue;
  77. }
  78. if (!isset($this->locations[$location])) {
  79. throw new \RuntimeException("No location registered for $name");
  80. }
  81. $visitedLocations[$location] = true;
  82. $request = $this->locations[$location]->visit($command, $request, $param);
  83. }
  84. // Ensure that the after() method is invoked for additionalParameters
  85. /** @var Parameter $additional */
  86. if ($additional = $operation->getAdditionalParameters()) {
  87. $visitedLocations[$additional->getLocation()] = true;
  88. }
  89. // Call the after() method for each visited location
  90. foreach (array_keys($visitedLocations) as $location) {
  91. $request = $this->locations[$location]->after($command, $request, $operation);
  92. }
  93. return $request;
  94. }
  95. /**
  96. * Create a request for the command and operation
  97. *
  98. * @param CommandInterface $command
  99. *
  100. * @return RequestInterface
  101. * @throws \RuntimeException
  102. */
  103. protected function createRequest(CommandInterface $command)
  104. {
  105. $operation = $this->description->getOperation($command->getName());
  106. // If command does not specify a template, assume the client's base URL.
  107. if (null === $operation->getUri()) {
  108. return new Request(
  109. $operation->getHttpMethod(),
  110. $this->description->getBaseUri()
  111. );
  112. }
  113. return $this->createCommandWithUri($operation, $command);
  114. }
  115. /**
  116. * Create a request for an operation with a uri merged onto a base URI
  117. *
  118. * @param \GuzzleHttp\Command\Guzzle\Operation $operation
  119. * @param \GuzzleHttp\Command\CommandInterface $command
  120. *
  121. * @return \GuzzleHttp\Psr7\Request
  122. */
  123. private function createCommandWithUri(
  124. Operation $operation,
  125. CommandInterface $command
  126. ) {
  127. // Get the path values and use the client config settings
  128. $variables = [];
  129. foreach ($operation->getParams() as $name => $arg) {
  130. /* @var Parameter $arg */
  131. if ($arg->getLocation() == 'uri') {
  132. if (isset($command[$name])) {
  133. $variables[$name] = $arg->filter($command[$name]);
  134. if (!is_array($variables[$name])) {
  135. $variables[$name] = (string) $variables[$name];
  136. }
  137. }
  138. }
  139. }
  140. // Expand the URI template.
  141. $uri = \GuzzleHttp\uri_template($operation->getUri(), $variables);
  142. return new Request(
  143. $operation->getHttpMethod(),
  144. Uri::resolve($this->description->getBaseUri(), $uri)
  145. );
  146. }
  147. }