Skip to content
Snippets Groups Projects
Commit f9ab0960 authored by Alan Sherry's avatar Alan Sherry
Browse files

Issue #3407114: Http data issues and changes

parent e0243511
No related branches found
No related tags found
1 merge request!8Removes deprecated model naming scheme and moves client object naming over to...
<?php
namespace Drupal\apitools;
use Drupal\Component\Utility\NestedArray;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\ResponseInterface;
use Traversable;
/**
* A hybrid class to allow array iterating and ResponseInterface functionality.
*/
class IterableResponse extends Response implements \IteratorAggregate, \Countable, \ArrayAccess
{
protected $responseData;
protected $iterableData;
public function getIterator(): Traversable
{
return new \ArrayIterator($this->iterableData);
}
public function count(): int
{
return count($this->iterableData);
}
public function offsetExists(mixed $offset): bool
{
return isset($this->iterableData[$offset]);
}
public function offsetGet(mixed $offset): mixed
{
return $this->offsetExists($offset) ? $this->iterableData[$offset] : NULL;
}
public function offsetSet(mixed $offset, mixed $value): void
{
$this->iterableData[$offset] = $value;
}
public function offsetUnset(mixed $offset): void
{
unset($this->iterableData[$offset]);
}
public function __construct(array $parents, $data, $status = 200, array $headers = [], $body = null, $version = '1.1', $reason = null)
{
parent::__construct($status, $headers, $body, $version, $reason);
$this->responseData = $data;
$this->iterableData = &NestedArray::getValue($data, $parents);
}
public static function create(array $parents, array $data, ResponseInterface $response)
{
return new static(
$parents,
$data,
$response->getStatusCode(),
$response->getHeaders(),
$response->getBody(),
$response->getProtocolVersion(),
$response->getReasonPhrase()
);
}
public function getData()
{
return $this->responseData;
}
}
\ No newline at end of file
......@@ -2,15 +2,17 @@
namespace Drupal\apitools\Plugin\migrate_plus\data_fetcher;
use Drupal\apitools\Api\Client\ClientInterface;
use Drupal\apitools\ClientManagerInterface;
use Drupal\apitools\IterableResponse;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\migrate\MigrateException;
use Drupal\migrate\Plugin\migrate\source\SourcePluginBase;
use Drupal\migrate_plus\Plugin\migrate_plus\data_fetcher\Http as HttpBase;
use GuzzleHttp\Exception\RequestException;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Serializer\Serializer;
/**
* Retrieve data over an HTTP connection for migration.
......@@ -35,6 +37,8 @@ class Http extends HttpBase {
*/
protected $apitoolsClient;
protected $serializer;
/**
* {@inheritdoc}
*/
......@@ -44,14 +48,15 @@ class Http extends HttpBase {
$configuration,
$plugin_id,
$plugin_definition,
$container->get('plugin.manager.apitools_client')
$container->get('plugin.manager.apitools_client'),
$container->get('serializer')
);
}
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, ClientManagerInterface $client_manager) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, ClientManagerInterface $client_manager, Serializer $serializer) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
if (empty($configuration['client_plugin_id'])) {
throw new InvalidPluginDefinitionException('apitools_http', 'Missing value for "client_plugin_id" in migration definition');
......@@ -62,6 +67,7 @@ class Http extends HttpBase {
catch (PluginNotFoundException $e) {
throw new InvalidPluginDefinitionException('apitools_http', 'Invalid ID for "client_plugin_id" in migration definition');
}
$this->serializer = $serializer;
}
private function doGetResponse($url, $options) {
......@@ -73,8 +79,8 @@ class Http extends HttpBase {
}, $this->apitoolsClient);
if ($executable && $method) {
if (is_array($this->configuration['client_arguments'])) {
$options = array_merge($this->configuration['client_arguments'], [$options]);
if ($client_arguments = $this->getClientArguments()) {
$options = array_merge($client_arguments, [$options]);
return $executable->{$method}(...$options);
}
return $executable->{$method}($options);
......@@ -83,6 +89,16 @@ class Http extends HttpBase {
return $this->apitoolsClient->get($url, $options);
}
private function getClientArguments() {
if (!isset($this->configuration['client_arguments'])) {
return FALSE;
}
if (!is_array($this->configuration['client_arguments'])) {
return FALSE;
}
return $this->configuration['client_arguments'];
}
/**
* {@inheritdoc}
*/
......@@ -98,14 +114,18 @@ class Http extends HttpBase {
}
$options['count'] = $is_count;
$response = $this->doGetResponse($url, $options);
if (empty($response)) {
if ($response === NULL) {
throw new MigrateException('No response at ' . $url . '.');
}
}
catch (RequestException $e) {
throw new MigrateException('Error message: ' . $e->getMessage() . ' at ' . $url . '.');
}
return $response;
if (!is_array($response) && !is_a($response, ResponseInterface::class)) {
throw new MigrateException("Invalid response from controller $url. Required array or instance of ResponseInterface");
}
// Ensure apitools can return arrays and convert to follow return type declaration.
return is_array($response) ? new IterableResponse([], $response) : $response;
}
private function isCount() {
......@@ -114,7 +134,7 @@ class Http extends HttpBase {
if ($carry) {
return $carry;
}
$is_source_class = $item['class'] == SourcePluginBase::class;
$is_source_class = isset($item['class']) && $item['class'] == SourcePluginBase::class;
$is_count = $item['function'] == 'count';
if ($is_source_class && $is_count) {
$carry = TRUE;
......@@ -130,8 +150,15 @@ class Http extends HttpBase {
{
$is_count = $this->isCount();
$data = $this->getResponse($url, $is_count);
//$events = $data['events'];
//$events = array_map(function($value) { return $value['event']; }, $events);
return \Drupal::service('serializer')->encode($data, 'json');
if (is_a($data, IterableResponse::class)) {
$data = $data->getData();
}
// Convert back to expected response body with format matching parser.
$parser_plugin = $this->configuration['data_parser_plugin'];
if ($this->serializer->supportsEncoding($parser_plugin)) {
$encoded = $this->serializer->encode($data, $parser_plugin);
return $encoded;
}
return $data->getBody();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment