From fc622f3d89cb99151a372cbf3068c2c2617cb75f Mon Sep 17 00:00:00 2001 From: mikeryan <mikeryan@4420.no-reply.drupal.org> Date: Mon, 11 Jul 2016 10:30:28 -0500 Subject: [PATCH] Issue #2726443 by mikeryan: SOAP Source plugin --- .../migrate_plus.migration.weather_soap.yml | 36 +++++ src/Plugin/migrate_plus/data_parser/Soap.php | 123 ++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100755 migrate_example_advanced/config/install/migrate_plus.migration.weather_soap.yml create mode 100755 src/Plugin/migrate_plus/data_parser/Soap.php diff --git a/migrate_example_advanced/config/install/migrate_plus.migration.weather_soap.yml b/migrate_example_advanced/config/install/migrate_plus.migration.weather_soap.yml new file mode 100755 index 00000000..da425215 --- /dev/null +++ b/migrate_example_advanced/config/install/migrate_plus.migration.weather_soap.yml @@ -0,0 +1,36 @@ +# This migration demonstrates importing from SOAP/WSDL. +id: weather_soap +label: SOAP service providing weather. +migration_group: wine +source: + # We use the SOAP parser source plugin. + plugin: url + data_fetcher_plugin: http # Ignored - SoapClient does the fetching. + data_parser_plugin: soap + # URL of a WSDL endpoint. + urls: http://www.webservicex.net/globalweather.asmx?WSDL + # The function to call on the service, and the parameters to pass. + function: GetCitiesByCountry + parameters: + CountryName: Spain + response_type: xml + item_selector: /NewDataSet/Table + fields: + - + name: Country + label: Country + selector: Country + - + name: City + label: City + selector: City + ids: + City: + type: string +process: + vid: + plugin: default_value + default_value: migrate_example_wine_varieties + name: City +destination: + plugin: entity:taxonomy_term diff --git a/src/Plugin/migrate_plus/data_parser/Soap.php b/src/Plugin/migrate_plus/data_parser/Soap.php new file mode 100755 index 00000000..60db9020 --- /dev/null +++ b/src/Plugin/migrate_plus/data_parser/Soap.php @@ -0,0 +1,123 @@ +<?php + +namespace Drupal\migrate_plus\Plugin\migrate_plus\data_parser; + +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\migrate\MigrateException; +use Drupal\migrate_plus\DataParserPluginBase; + +/** + * Obtain SOAP data for migration. + * + * @DataParser( + * id = "soap", + * title = @Translation("SOAP") + * ) + */ +class Soap extends DataParserPluginBase implements ContainerFactoryPluginInterface { + + /** + * Iterator over the SOAP data. + * + * @var \Iterator + */ + protected $iterator; + + /** + * Method to call on the SOAP service. + * + * @var string + */ + protected $function; + + /** + * Parameters to pass to the SOAP service function. + * + * @var array + */ + protected $parameters; + + /** + * Form of the function response - 'xml', 'object', or 'array'. + * + * @var string + */ + protected $responseType; + + /** + * {@inheritdoc} + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->function = $configuration['function']; + $this->parameters = $configuration['parameters']; + $this->responseType = $configuration['response_type']; + } + + /** + * {@inheritdoc} + * + * @throws \SoapFault + * If there's an error in a SOAP call. + * @throws \Drupal\migrate\MigrateException + * If we can't resolve the SOAP function or its response property. + */ + protected function openSourceUrl($url) { + // Will throw SoapFault if there's + $client = new \SoapClient($url); + // Determine the response property name. + $function_found = FALSE; + foreach ($client->__getFunctions() as $function_signature) { + // E.g., "GetWeatherResponse GetWeather(GetWeather $parameters)". + $response_type = strtok($function_signature, ' '); + $function_name = strtok('('); + if (strcasecmp($function_name, $this->function) === 0) { + $function_found = TRUE; + foreach ($client->__getTypes() as $type_info) { + // E.g., "struct GetWeatherResponse {\n string GetWeatherResult;\n}". + if (preg_match('|struct (.*?) {\s*[a-z]+ (.*?);|is', $type_info, $matches)) { + if ($matches[1] == $response_type) { + $response_property = $matches[2]; + } + } + } + break; + } + } + if (!$function_found) { + throw new MigrateException("SOAP function {$this->function} not found."); + } + elseif (!isset($response_property)) { + throw new MigrateException("Response property not found for SOAP function {$this->function}."); + } + $response = $client->{$this->function}($this->parameters); + $response_value = $response->$response_property; + switch ($this->responseType) { + case 'xml': + $xml = simplexml_load_string($response_value); + $this->iterator = new \ArrayIterator($xml->xpath($this->itemSelector)); + break; + case 'object': + $this->iterator = new \ArrayIterator($response_value->{$this->itemSelector}); + break; + case 'array': + $this->iterator = new \ArrayIterator($response_value[$this->itemSelector]); + break; + } + return TRUE; + } + + /** + * {@inheritdoc} + */ + protected function fetchNextRow() { + $current = $this->iterator->current(); + if ($current) { + foreach ($this->fieldSelectors() as $field_name => $selector) { + $this->currentItem[$field_name] = $current->$selector; + } + $this->iterator->next(); + } + } + +} -- GitLab