Loading core/modules/migrate/src/Plugin/migrate/process/Callback.php +30 −2 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ namespace Drupal\migrate\Plugin\migrate\process; use Drupal\migrate\MigrateException; use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\ProcessPluginBase; use Drupal\migrate\Row; Loading @@ -10,11 +11,13 @@ * Passes the source value to a callback. * * The callback process plugin allows simple processing of the value, such as * strtolower(). The callable takes the source value as the single mandatory * argument. No additional arguments can be passed to the callback. * strtolower(). To pass more than one argument, pass an array as the source * and set the unpack_source option. * * Available configuration keys: * - callable: The name of the callable method. * - unpack_source: (optional) Whether to interpret the source as an array of * arguments. * * Examples: * Loading @@ -38,6 +41,25 @@ * source: source_field * @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 * * @MigrateProcessPlugin( Loading @@ -63,6 +85,12 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition * {@inheritdoc} */ 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); } Loading core/modules/migrate/tests/src/Unit/process/CallbackTest.php +54 −2 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ namespace Drupal\Tests\migrate\Unit\process; use Drupal\migrate\MigrateException; use Drupal\migrate\Plugin\migrate\process\Callback; /** Loading Loading @@ -33,15 +34,60 @@ public function providerCallback() { ]; } /** * 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. * * @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 */ public function testCallbackExceptions($message, $configuration) { $this->expectException(\InvalidArgumentException::class); public function testCallbackExceptions($message, array $configuration, $class = 'InvalidArgumentException', $args = NULL) { $this->expectException($class); $this->expectExceptionMessage($message); $this->plugin = new Callback($configuration, 'map', []); $this->plugin->transform($args, $this->migrateExecutable, $this->row, 'destination_property'); } /** Loading @@ -57,6 +103,12 @@ public function providerCallbackExceptions() { 'message' => 'The "callable" must be a valid function or method.', '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.', ], ]; } Loading Loading
core/modules/migrate/src/Plugin/migrate/process/Callback.php +30 −2 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ namespace Drupal\migrate\Plugin\migrate\process; use Drupal\migrate\MigrateException; use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\ProcessPluginBase; use Drupal\migrate\Row; Loading @@ -10,11 +11,13 @@ * Passes the source value to a callback. * * The callback process plugin allows simple processing of the value, such as * strtolower(). The callable takes the source value as the single mandatory * argument. No additional arguments can be passed to the callback. * strtolower(). To pass more than one argument, pass an array as the source * and set the unpack_source option. * * Available configuration keys: * - callable: The name of the callable method. * - unpack_source: (optional) Whether to interpret the source as an array of * arguments. * * Examples: * Loading @@ -38,6 +41,25 @@ * source: source_field * @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 * * @MigrateProcessPlugin( Loading @@ -63,6 +85,12 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition * {@inheritdoc} */ 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); } Loading
core/modules/migrate/tests/src/Unit/process/CallbackTest.php +54 −2 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ namespace Drupal\Tests\migrate\Unit\process; use Drupal\migrate\MigrateException; use Drupal\migrate\Plugin\migrate\process\Callback; /** Loading Loading @@ -33,15 +34,60 @@ public function providerCallback() { ]; } /** * 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. * * @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 */ public function testCallbackExceptions($message, $configuration) { $this->expectException(\InvalidArgumentException::class); public function testCallbackExceptions($message, array $configuration, $class = 'InvalidArgumentException', $args = NULL) { $this->expectException($class); $this->expectExceptionMessage($message); $this->plugin = new Callback($configuration, 'map', []); $this->plugin->transform($args, $this->migrateExecutable, $this->row, 'destination_property'); } /** Loading @@ -57,6 +103,12 @@ public function providerCallbackExceptions() { 'message' => 'The "callable" must be a valid function or method.', '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.', ], ]; } Loading