diff --git a/src/DependencyInjection/CsaGuzzleExtension.php b/src/DependencyInjection/CsaGuzzleExtension.php
index f44e19cf..adfb643b 100644
--- a/src/DependencyInjection/CsaGuzzleExtension.php
+++ b/src/DependencyInjection/CsaGuzzleExtension.php
@@ -115,7 +115,19 @@ private function processClientsConfiguration(array $config, ContainerBuilder $co
'service("csa_guzzle.description_factory").getDescription("%s")',
$name
)));
+ $serviceDefinition->addArgument(['process' => false]);
+ $serviceDefinition->addMethodCall('setSerializer', [new Reference('serializer')]);
+ $serviceDefinition->addMethodCall('addProcess');
+
$container->setDefinition(sprintf('csa_guzzle.service.%s', $name), $serviceDefinition);
+ $container->getDefinition('csa_guzzle.paramconverter.guzzle')->addMethodCall(
+ 'addService',
+ [
+ sprintf('csa_guzzle.service.%s', $name),
+ new Reference(sprintf('csa_guzzle.service.%s', $name))
+ ]
+ );
+
}
}
}
diff --git a/src/GuzzleHttp/Command/Guzzle/GuzzleClient.php b/src/GuzzleHttp/Command/Guzzle/GuzzleClient.php
new file mode 100644
index 00000000..c55d9658
--- /dev/null
+++ b/src/GuzzleHttp/Command/Guzzle/GuzzleClient.php
@@ -0,0 +1,45 @@
+serializer = $serializer;
+ }
+
+
+ public function addProcess()
+ {
+ $this->getEmitter()->attach(
+ new ProcessResponse(
+ $this->getDescription(),
+ $this->serializer,
+ isset($config['response_locations'])
+ ? $config['response_locations']
+ : []
+ )
+ );
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/GuzzleHttp/Command/Guzzle/Subscriber/ProcessResponse.php b/src/GuzzleHttp/Command/Guzzle/Subscriber/ProcessResponse.php
new file mode 100644
index 00000000..c6f178a1
--- /dev/null
+++ b/src/GuzzleHttp/Command/Guzzle/Subscriber/ProcessResponse.php
@@ -0,0 +1,229 @@
+ new BodyLocation('body'),
+ 'header' => new HeaderLocation('header'),
+ 'reasonPhrase' => new ReasonPhraseLocation('reasonPhrase'),
+ 'statusCode' => new StatusCodeLocation('statusCode'),
+ 'xml' => new XmlLocation('xml'),
+ 'json' => new JsonLocation('json')
+ ];
+ }
+
+ $this->responseLocations = $responseLocations + $defaultResponseLocations;
+ $this->description = $description;
+ $this->serializer = $serializer;
+ }
+
+ public function getEvents()
+ {
+ return ['process' => ['onProcess']];
+ }
+
+ public function onProcess(ProcessEvent $event)
+ {
+ // Only add a result object if no exception was encountered.
+ if ($event->getException()) {
+ return;
+ }
+
+ $command = $event->getCommand();
+
+ // Do not overwrite a previous result
+ if ($event->getResult()) {
+ return;
+ }
+
+ $operation = $this->description->getOperation($command->getName());
+
+ // Add a default Model as the result if no matching schema was found.
+ if (!($modelName = $operation->getResponseModel())) {
+ $event->setResult([]);
+ return;
+ }
+
+ $model = $operation->getServiceDescription()->getModel($modelName);
+ if (!$model) {
+ throw new \RuntimeException("Unknown model: {$modelName}");
+ }
+
+ $event->setResult($this->visit($model, $event));
+ }
+
+ protected function visit(Parameter $model, ProcessEvent $event)
+ {
+ $result = [];
+ $context = ['client' => $event->getClient(), 'visitors' => []];
+ $command = $event->getCommand();
+ $response = $event->getResponse();
+
+ if ($model->getType() == 'object') {
+ $this->visitOuterObject($model, $result, $command, $response, $context);
+ } elseif ($model->getType() == 'array') {
+ $this->visitOuterArray($model, $result, $command, $response, $context);
+ } elseif ($model->getType() == 'serializer') {
+ $this->visitOuterSerializer($model, $result, $command, $response, $context);
+ } else {
+ throw new \InvalidArgumentException('Invalid response model: ' . $model->getType());
+ }
+
+ // Call the after() method of each found visitor
+ foreach ($context['visitors'] as $visitor) {
+ $visitor->after($command, $response, $model, $result, $context);
+ }
+
+ return $result;
+ }
+
+ private function triggerBeforeVisitor(
+ $location,
+ Parameter $model,
+ array &$result,
+ CommandInterface $command,
+ ResponseInterface $response,
+ array &$context
+ ) {
+ if (!isset($this->responseLocations[$location])) {
+ throw new \RuntimeException("Unknown location: $location");
+ }
+
+ $context['visitors'][$location] = $this->responseLocations[$location];
+
+ $this->responseLocations[$location]->before(
+ $command,
+ $response,
+ $model,
+ $result,
+ $context
+ );
+ }
+
+ private function visitOuterObject(
+ Parameter $model,
+ array &$result,
+ CommandInterface $command,
+ ResponseInterface $response,
+ array &$context
+ ) {
+ $parentLocation = $model->getLocation();
+
+ // If top-level additionalProperties is a schema, then visit it
+ $additional = $model->getAdditionalProperties();
+ if ($additional instanceof Parameter) {
+ // Use the model location if none set on additionalProperties.
+ $location = $additional->getLocation() ?: $parentLocation;
+ $this->triggerBeforeVisitor(
+ $location, $model, $result, $command, $response, $context
+ );
+ }
+
+ // Use 'location' from all individual defined properties, but fall back
+ // to the model location if no per-property location is set. Collect
+ // the properties that need to be visited into an array.
+ $visitProperties = [];
+ foreach ($model->getProperties() as $schema) {
+ $location = $schema->getLocation() ?: $parentLocation;
+ if ($location) {
+ $visitProperties[] = [$location, $schema];
+ // Trigger the before method on each unique visitor location
+ if (!isset($context['visitors'][$location])) {
+ $this->triggerBeforeVisitor(
+ $location, $model, $result, $command, $response, $context
+ );
+ }
+ }
+ }
+
+ // Actually visit each response element
+ foreach ($visitProperties as $prop) {
+ $this->responseLocations[$prop[0]]->visit(
+ $command, $response, $prop[1], $result, $context
+ );
+ }
+ }
+
+ private function visitOuterArray(
+ Parameter $model,
+ array &$result,
+ CommandInterface $command,
+ ResponseInterface $response,
+ array &$context
+ ) {
+ // Use 'location' defined on the top of the model
+ if (!($location = $model->getLocation())) {
+ return;
+ }
+
+ if (!isset($foundVisitors[$location])) {
+ $this->triggerBeforeVisitor(
+ $location, $model, $result, $command, $response, $context
+ );
+ }
+
+ // Visit each item in the response
+ $this->responseLocations[$location]->visit(
+ $command, $response, $model, $result, $context
+ );
+ }
+
+ private function visitOuterSerializer(
+ Parameter $model,
+ array &$result,
+ CommandInterface $command,
+ ResponseInterface $response,
+ array &$context
+ ) {
+ $result = $this->serializer->deserialize($response->getBody(), $model->class, 'json');
+ }
+}
\ No newline at end of file
diff --git a/src/Request/ParamConverter/GuzzleConverter.php b/src/Request/ParamConverter/GuzzleConverter.php
new file mode 100644
index 00000000..bc392467
--- /dev/null
+++ b/src/Request/ParamConverter/GuzzleConverter.php
@@ -0,0 +1,111 @@
+services;
+ }
+
+ /**
+ * @param array $services
+ */
+ public function setServices($services)
+ {
+ $this->services = $services;
+ }
+
+ public function addService($name, $service)
+ {
+ $this->services[$name] = $service;
+ }
+
+ /**
+ * Stores the object in the request.
+ *
+ * @param Request $request The request
+ * @param ParamConverter $configuration Contains the name, class and options of the object
+ *
+ * @return bool True if the object has been successfully set, else false
+ */
+ public function apply(Request $request, ParamConverter $configuration)
+ {
+ $client = $this->findService($configuration);
+ $description = $client->getDescription();
+ /** @var Description $description */
+ if (isset($configuration->getOptions()['operation'])) {
+ $function = $configuration->getOptions()['operation'];
+ } else {
+ foreach ($description->getOperations() as $name => $searchOperation) {
+ if (isset($searchOperation['responseModel']) && $searchOperation['responseModel'] == $configuration->getClass()) {
+ $function = $name;
+ break;
+ }
+ }
+ }
+
+ $operation = $description->getOperation($function);
+ if (isset($operation)) {
+ $parameters = [];
+ foreach ($operation->getParams() as $param) {
+ $parameters[$param->getName()] = $request->get($param->getName());
+ }
+ try {
+ $request->attributes->set($configuration->getName(), $client->$function($parameters));
+ } catch (\Exception $e) {
+ }
+ }
+
+ }
+
+ /**
+ * Checks if the object is supported.
+ *
+ * @param ParamConverter $configuration Should be an instance of ParamConverter
+ *
+ * @return bool True if the object is supported, else false
+ */
+ public function supports(ParamConverter $configuration)
+ {
+ return ($this->findService($configuration) !== null);
+ }
+
+ public function findService($configuration)
+ {
+
+ foreach ($this->services as $service) {
+ $description = $service->getDescription();
+ /** @var Description $description */
+
+ foreach ($description->getModels() as $model) {
+ if ($configuration->getClass() == $model->class) {
+ return $service;
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml
index fd728f5f..ef4f77c9 100644
--- a/src/Resources/config/services.xml
+++ b/src/Resources/config/services.xml
@@ -27,7 +27,12 @@
-
+
+
+
+
+
+