Issue #2882276 by benjifisher, estoyausente, nuez, kristiaanvandeneynde, alexpott, ravi.shankar, osopolar, marvil07, danflanagan8, heddn, quietone, Matroskeen, hudri, joshi.rohit100: Extended callback process plugin to call functions with multiple parameters

merge-requests/634/head
Alex Pott 2021-05-06 01:16:13 +01:00
parent b48ad9091d
commit a3ca88ebbf
No known key found for this signature in database
GPG Key ID: 31905460D4A69276
2 changed files with 84 additions and 4 deletions

View File

@ -2,6 +2,7 @@
namespace Drupal\migrate\Plugin\migrate\process; namespace Drupal\migrate\Plugin\migrate\process;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase; use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row; use Drupal\migrate\Row;
@ -10,11 +11,13 @@ use Drupal\migrate\Row;
* Passes the source value to a callback. * Passes the source value to a callback.
* *
* The callback process plugin allows simple processing of the value, such as * The callback process plugin allows simple processing of the value, such as
* strtolower(). The callable takes the source value as the single mandatory * strtolower(). To pass more than one argument, pass an array as the source
* argument. No additional arguments can be passed to the callback. * and set the unpack_source option.
* *
* Available configuration keys: * Available configuration keys:
* - callable: The name of the callable method. * - callable: The name of the callable method.
* - unpack_source: (optional) Whether to interpret the source as an array of
* arguments.
* *
* Examples: * Examples:
* *
@ -38,6 +41,25 @@ use Drupal\migrate\Row;
* source: source_field * source: source_field
* @endcode * @endcode
* *
* An example where the callback accepts more than one argument:
*
* @code
* source:
* plugin: source_plugin_goes_here
* constants:
* slash: /
* process:
* field_link_url:
* plugin: callback
* callable: rtrim
* unpack_source: true
* source:
* - url
* - constants/slash
* @endcode
*
* This will remove the trailing '/', if any, from a URL.
*
* @see \Drupal\migrate\Plugin\MigrateProcessInterface * @see \Drupal\migrate\Plugin\MigrateProcessInterface
* *
* @MigrateProcessPlugin( * @MigrateProcessPlugin(
@ -63,6 +85,12 @@ class Callback extends ProcessPluginBase {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (!empty($this->configuration['unpack_source'])) {
if (!is_array($value)) {
throw new MigrateException(sprintf("When 'unpack_source' is set, the source must be an array. Instead it was of type '%s'", gettype($value)));
}
return call_user_func($this->configuration['callable'], ...$value);
}
return call_user_func($this->configuration['callable'], $value); return call_user_func($this->configuration['callable'], $value);
} }

View File

@ -2,6 +2,7 @@
namespace Drupal\Tests\migrate\Unit\process; namespace Drupal\Tests\migrate\Unit\process;
use Drupal\migrate\MigrateException;
use Drupal\migrate\Plugin\migrate\process\Callback; use Drupal\migrate\Plugin\migrate\process\Callback;
/** /**
@ -33,15 +34,60 @@ class CallbackTest extends MigrateProcessTestCase {
]; ];
} }
/**
* Test callback with valid "callable" and multiple arguments.
*
* @dataProvider providerCallbackArray
*/
public function testCallbackArray($callable, $args, $result) {
$configuration = ['callable' => $callable, 'unpack_source' => TRUE];
$this->plugin = new Callback($configuration, 'map', []);
$value = $this->plugin->transform($args, $this->migrateExecutable, $this->row, 'destination_property');
$this->assertSame($result, $value);
}
/**
* Data provider for ::testCallbackArray().
*/
public function providerCallbackArray() {
return [
'date format' => [
'date',
['Y-m-d', 995328000],
'2001-07-17',
],
'rtrim' => [
'rtrim',
['https://www.example.com/', '/'],
'https://www.example.com',
],
'str_replace' => [
'str_replace',
[['One', 'two'], ['1', '2'], 'One, two, three!'],
'1, 2, three!',
],
];
}
/** /**
* Test callback exceptions. * Test callback exceptions.
* *
* @param string $message
* The expected exception message.
* @param array $configuration
* The plugin configuration being tested.
* @param string $class
* (optional) The expected exception class.
* @param mixed $args
* (optional) Arguments to pass to the transform() method.
*
* @dataProvider providerCallbackExceptions * @dataProvider providerCallbackExceptions
*/ */
public function testCallbackExceptions($message, $configuration) { public function testCallbackExceptions($message, array $configuration, $class = 'InvalidArgumentException', $args = NULL) {
$this->expectException(\InvalidArgumentException::class); $this->expectException($class);
$this->expectExceptionMessage($message); $this->expectExceptionMessage($message);
$this->plugin = new Callback($configuration, 'map', []); $this->plugin = new Callback($configuration, 'map', []);
$this->plugin->transform($args, $this->migrateExecutable, $this->row, 'destination_property');
} }
/** /**
@ -57,6 +103,12 @@ class CallbackTest extends MigrateProcessTestCase {
'message' => 'The "callable" must be a valid function or method.', 'message' => 'The "callable" must be a valid function or method.',
'configuration' => ['callable' => 'nonexistent_callable'], 'configuration' => ['callable' => 'nonexistent_callable'],
], ],
'array required' => [
'message' => "When 'unpack_source' is set, the source must be an array. Instead it was of type 'string'",
'configuration' => ['callable' => 'count', 'unpack_source' => TRUE],
'class' => MigrateException::class,
'args' => 'This string is not an array.',
],
]; ];
} }