Commit bd2227e4 authored by larowlan's avatar larowlan

Issue #2893061 by maxocub, Jo Fitzgerald, heddn, phenaproxima: Create a...

Issue #2893061 by maxocub, Jo Fitzgerald, heddn, phenaproxima: Create a ProcessField plugin to process the field types
parent cfbe5da7
......@@ -15,8 +15,9 @@ process:
langcode: 'constants/langcode'
field_name: field_name
type:
plugin: field_type
plugin: process_field
source: type
method: getFieldType
# Translatable is not migrated and the Drupal 8 default of true is used.
# If translatable is false in field storage then the field can not be
# set to translatable via the UI.
......
<?php
namespace Drupal\field\Plugin\migrate\process;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface;
use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Get the value from a method call on a field plugin instance.
*
* This process plugin will instantiate a field plugin based on the given
* field type and then call the given method on it for the return value.
*
* Available configuration keys:
* - source: The source field type to use to instantiate a field plugin.
* - method: The method to be called on the field plugin instance.
*
* If no field plugin for the given field type is found, NULL will be returned.
*
* Example:
*
* @code
* process:
* type:
* plugin: process_field
* source: type
* method: getFieldType
* @endcode
*
* @see \Drupal\migrate\Plugin\MigrateProcessInterface
* @see \Drupal\migrate_drupal\Plugin\MigrateFieldInterface;
*
* @MigrateProcessPlugin(
* id = "process_field"
* )
*/
class ProcessField extends ProcessPluginBase implements ContainerFactoryPluginInterface {
/**
* The cckfield plugin manager.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface
*/
protected $cckPluginManager;
/**
* The field plugin manager.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
*/
protected $fieldPluginManager;
/**
* The migration being run.
*
* @var \Drupal\migrate\Plugin\MigrationInterface
*/
protected $migration;
/**
* Constructs a ProcessField plugin.
*
* @param array $configuration
* The plugin configuration.
* @param string $plugin_id
* The plugin ID.
* @param mixed $plugin_definition
* The plugin definition.
* @param \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface $cck_plugin_manager
* The cckfield plugin manager.
* @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager
* The field plugin manager.
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
* The migration being run.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrateCckFieldPluginManagerInterface $cck_plugin_manager, MigrateFieldPluginManagerInterface $field_plugin_manager, MigrationInterface $migration = NULL) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->cckPluginManager = $cck_plugin_manager;
$this->fieldPluginManager = $field_plugin_manager;
$this->migration = $migration;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('plugin.manager.migrate.cckfield'),
$container->get('plugin.manager.migrate.field'),
$migration
);
}
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (!is_string($value)) {
throw new MigrateException('The input value must be a string.');
}
if (empty($this->configuration['method'])) {
throw new MigrateException('You need to specify the name of a method to be called on the Field plugin.');
}
$method = $this->configuration['method'];
try {
return $this->callMethodOnFieldPlugin($this->fieldPluginManager, $value, $method, $row);
}
catch (PluginNotFoundException $e) {
try {
return $this->callMethodOnFieldPlugin($this->cckPluginManager, $value, $method, $row);
}
catch (PluginNotFoundException $e) {
return NULL;
}
}
}
/**
* Instantiate a field plugin and call a method on it.
*
* @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager
* The field plugin manager.
* @param string $field_type
* The field type for which to get the field plugin.
* @param string $method
* The method to call on the field plugin.
* @param \Drupal\migrate\Row $row
* The row from the source to process.
*
* @return mixed
* The return value from the method called on the field plugin.
*/
protected function callMethodOnFieldPlugin(MigrateFieldPluginManagerInterface $field_plugin_manager, $field_type, $method, Row $row) {
$plugin_id = $field_plugin_manager->getPluginIdFromFieldType($field_type, [], $this->migration);
$plugin_instance = $field_plugin_manager->createInstance($plugin_id, [], $this->migration);
if (!is_callable([$plugin_instance, $method])) {
throw new MigrateException('The specified method does not exists or is not callable.');
}
return call_user_func_array([$plugin_instance, $method], [$row]);
}
}
<?php
namespace Drupal\Tests\field\Unit\Plugin\migrate\process;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\field\Plugin\migrate\process\ProcessField;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface;
use Drupal\migrate_drupal\Plugin\MigrateFieldInterface;
use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
use Drupal\Tests\migrate\Unit\MigrateTestCase;
/**
* Tests the ProcessField migrate process plugin.
*
* @coversDefaultClass \Drupal\field\Plugin\migrate\process\ProcessField
* @group field
* @group legacy
*/
class ProcessFieldTest extends MigrateTestCase {
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->cckFieldManager = $this->prophesize(MigrateCckFieldPluginManagerInterface::class);
$this->fieldManager = $this->prophesize(MigrateFieldPluginManagerInterface::class);
$this->fieldPlugin = $this->prophesize(MigrateFieldInterface::class);
$this->migrateExecutable = $this->prophesize(MigrateExecutable::class);
$this->migration = $this->prophesize(MigrationInterface::class);
$this->row = $this->prophesize(Row::class);
$this->fieldManager->getPluginIdFromFieldType('foo', [], $this->migration->reveal())->willReturn('foo');
$this->fieldManager->createInstance('foo', [], $this->migration->reveal())->willReturn($this->fieldPlugin);
parent::setUp();
}
/**
* Tests the transform method.
*
* @param string $method
* The method to call.
* @param string $value
* The value to process.
* @param mixed $expected_value
* The expected transformed value.
* @param string $migrate_exception
* The MigrateException message to expect.
* @param bool $plugin_not_found
* Whether the field plugin is not found.
*
* @covers ::transform
* @dataProvider providerTestTransform
*/
public function testTransform($method, $value, $expected_value, $migrate_exception = '', $plugin_not_found = FALSE) {
if ($method) {
$this->fieldPlugin->$method($this->row->reveal())->willReturn($expected_value);
}
$this->plugin = new ProcessField(['method' => $method], $value, [], $this->cckFieldManager->reveal(), $this->fieldManager->reveal(), $this->migration->reveal());
if ($migrate_exception) {
$this->setExpectedException(MigrateException::class, $migrate_exception);
}
if ($plugin_not_found) {
$exception = new PluginNotFoundException('foo');
$this->cckFieldManager->getPluginIdFromFieldType()->willThrow($exception);
$this->fieldManager->getPluginIdFromFieldType()->willThrow($exception);
}
$transformed_value = $this->plugin->transform($value, $this->migrateExecutable->reveal(), $this->row->reveal(), 'foo');
$this->assertSame($transformed_value, $expected_value);
}
/**
* Provides data for the transform method test.
*
* @return array
* - The method to call.
* - The value to process.
* - The expected transformed value.
* - The MigrateException message to expect.
* - Whether the field plugin is not found.
*/
public function providerTestTransform() {
return [
// Tests the getFieldType() method.
[
'method' => 'getFieldType',
'value' => 'foo',
'expected_value' => 'bar',
],
// Tests the getFieldFormatterMap() method.
[
'method' => 'getFieldFormatterMap',
'value' => 'foo',
'expected_value' => ['foo' => 'bar'],
],
// Tests the getFieldWidgetMap() method.
[
'method' => 'getFieldWidgetMap',
'value' => 'foo',
'expected_value' => ['foo' => 'bar'],
],
// Tests that an exception is thrown if the value is not a string.
[
'method' => 'getFieldType',
'value' => ['foo'],
'expected_value' => '',
'migrate_exception' => 'The input value must be a string.',
],
// Tests that an exception is thrown if no method name is provided.
[
'method' => '',
'value' => '',
'expected_value' => '',
'migrate_exception' => 'You need to specify the name of a method to be called on the Field plugin.',
],
// Tests that NULL is returned if no field plugin is found.
[
'method' => 'getFieldType',
'value' => 'foo',
'expected_value' => NULL,
'migrate_exception' => '',
'plugin_not_found' => TRUE,
],
];
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment