Unverified Commit a3ca88eb authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2882276 by benjifisher, estoyausente, nuez, kristiaanvandeneynde,...

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
parent b48ad909
Loading
Loading
Loading
Loading
+30 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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:
 *
@@ -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(
@@ -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);
  }

+54 −2
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

namespace Drupal\Tests\migrate\Unit\process;

use Drupal\migrate\MigrateException;
use Drupal\migrate\Plugin\migrate\process\Callback;

/**
@@ -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');
  }

  /**
@@ -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.',
      ],
    ];
  }