htools-8.x-1.x-dev/modules/htools_migrate/src/Plugin/migrate/process/ConditionalProcess.php
modules/htools_migrate/src/Plugin/migrate/process/ConditionalProcess.php
<?php
namespace Drupal\htools_migrate\Plugin\migrate\process;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\MigrateSkipProcessException;
use Drupal\migrate\Plugin\MigratePluginManagerInterface;
use Drupal\migrate\Plugin\MigrateProcessInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
use function call_user_func;
use function is_array;
use function is_callable;
use function is_string;
/**
* Executes a plugin if the provided condition is TRUE.
*
* The conditional_process plugin applies a configured callback over the source
* field value. If the callback returns TRUE the configured process plugin is
* invoked to process the value, otherwise the value is returned as-is.
*
* Available configuration keys:
* - callback: A callable to which pass the source field value and must return
* a boolean.
* - pass: The process plugin to apply over the value if the callback returns
* TRUE.
* - fail: The process plugin to apply over the value if the callback returns
* false. Leave it blank to return the value as-is.
* - multiple: If the transformed value needs multiple handling.
*
* Examples:
*
* @code
* process:
* destination_field:
* plugin: conditional_process
* callback: is_array
* source: field
* pass:
* plugin: pass_plugin
* source: bar
* fail:
* plugin: fail_plugin
* source: bar
* @endcode
*
* If 'parent' is empty, any further processing of the property is skipped and
* the next process plugin (migration_lookup) will not be run. Combining
* skip_on_empty and migration_lookup is a typical process pipeline combination
* for hierarchical entities where the root entity does not have a parent.
*
* @see \Drupal\migrate\Plugin\MigrateProcessInterface
*
* @MigrateProcessPlugin(
* id = "conditional_process",
* handle_multiples = "true"
* )
*/
class ConditionalProcess extends ProcessPluginBase implements ContainerFactoryPluginInterface {
/**
* The migration.
*
* @var \Drupal\migrate\Plugin\MigrationInterface
*/
protected $migration;
/**
* The migrate plugin manager.
*
* @var \Drupal\migrate\Plugin\MigratePluginManagerInterface
*/
protected $pluginManager;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, MigratePluginManagerInterface $pluginManager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->migration = $migration;
$this->pluginManager = $pluginManager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$migration,
$container->get('plugin.manager.migrate.process')
);
}
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (empty($this->configuration['callback'])) {
throw new MigrateSkipProcessException('The callback key is empty.');
}
if (!is_callable($this->configuration['callback'])) {
throw new MigrateSkipProcessException('The provided callback is not callable.');
}
if (empty($this->configuration['pass'])) {
//throw new MigrateSkipProcessException('The pass plugin is empty.');
}
if (empty($value) && !empty($this->configuration['not_null'])) {
return $value;
}
$assert = call_user_func($this->configuration['callback'], $value);
if ((bool) $assert === TRUE && !empty($this->configuration['pass'])) {
$value = $this->pass($value, $migrate_executable, $row, $destination_property);
}
elseif (!empty($this->configuration['fail'])) {
$value = $this->fail($value, $migrate_executable, $row, $destination_property);
}
return $value;
}
/**
* {@inheritdoc}
*/
public function multiple() {
return $this->configuration['multiple'] ?? FALSE;
}
/**
* {@inheritdoc}
*/
private function pass($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
$plugin = $this->getPluginInstance($this->configuration['pass']);
return $plugin->transform($value, $migrate_executable, $row, $destination_property);
}
/**
* {@inheritdoc}
*/
private function fail($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (empty($this->configuration['fail'])) {
return $value;
}
$plugin = $this->getPluginInstance($this->configuration['fail']);
return $plugin->transform($value, $migrate_executable, $row, $destination_property);
}
/**
* The getPluginInstance implementation.
*
* @param array|string $definition
* Plugin id or plugin definition.
*
* @return \Drupal\migrate\Plugin\MigrateProcessInterface
* The plugin instance.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* @throws \Drupal\migrate\MigrateSkipProcessException
*/
private function getPluginInstance($definition): MigrateProcessInterface {
if (is_string($definition)) {
return $this->pluginManager->createInstance($definition, [], $this->migration);
}
if (!is_array($definition) || empty($definition['plugin'])) {
throw new MigrateSkipProcessException('Invalid plugin definition in conditional_process plugin configuration.');
}
$plugin_id = $definition['plugin'];
unset($definition['plugin']);
return $this->pluginManager->createInstance($plugin_id, $definition, $this->migration);
}
}
