data_pipelines-1.x-dev/src/DatasetPipelineBase.php
src/DatasetPipelineBase.php
<?php
declare(strict_types=1);
namespace Drupal\data_pipelines;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\MapDataDefinition;
use Drupal\Core\TypedData\TypedDataManagerInterface;
use Drupal\data_pipelines\Transform\DatasetTransformPluginManager;
use Drupal\data_pipelines\Transform\TransformInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ConstraintViolationListInterface;
/**
* Defines a generic class for a dataset pipeline.
*/
class DatasetPipelineBase extends PluginBase implements DatasetPipelineInterface, ContainerFactoryPluginInterface {
/**
* The logger.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected $loggerChannel;
/**
* Transform plugin manager.
*
* @var \Drupal\data_pipelines\Transform\DatasetTransformPluginManager
*/
protected $transformPluginManager;
/**
* Typed data manager.
*
* @var \Drupal\Core\TypedData\TypedDataManagerInterface
*/
protected $typedDataManager;
/**
* Data definition.
*
* @var \Drupal\Core\TypedData\MapDataDefinition
*/
protected $dataDefinition;
/**
* Constructs a new DatasetPipelineBase.
*
* @param array $configuration
* Configuration.
* @param string $plugin_id
* Plugin ID.
* @param array $plugin_definition
* Plugin definition.
* @param \Drupal\Core\Logger\LoggerChannelInterface $logger_channel
* Logger.
* @param \Drupal\data_pipelines\Transform\DatasetTransformPluginManager $transformPluginManager
* Transform plugin manager.
* @param \Drupal\Core\TypedData\TypedDataManagerInterface $typedDataManager
* Typed data manager.
*/
public function __construct(array $configuration, string $plugin_id, array $plugin_definition, LoggerChannelInterface $logger_channel, DatasetTransformPluginManager $transformPluginManager, TypedDataManagerInterface $typedDataManager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->loggerChannel = $logger_channel;
$this->transformPluginManager = $transformPluginManager;
$this->typedDataManager = $typedDataManager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('logger.channel.data_pipelines'),
$container->get('plugin.manager.data_pipelines_transform'),
$container->get('typed_data_manager')
);
}
/**
* {@inheritdoc}
*/
public function validate(DatasetData $data): ConstraintViolationListInterface {
if (!$this->hasValidation()) {
return new ConstraintViolationList();
}
if (!isset($this->dataDefinition)) {
$this->dataDefinition = MapDataDefinition::create('data_pipelines_data');
foreach ($this->pluginDefinition['validations']['field'] as $field_name => $definitions) {
// @todo do we want to support other than string data-types?
$this->dataDefinition->setPropertyDefinition($field_name, DataDefinition::create('string')->setConstraints($definitions));
}
$this->dataDefinition->setConstraints($this->pluginDefinition['validations']['record']);
}
$typed_data = $this->typedDataManager->create($this->dataDefinition, $data, $this->getPluginId());
$violations = $typed_data->validate();
return $violations;
}
/**
* {@inheritdoc}
*/
public function transform(DatasetData $data): DatasetData {
foreach ($this->pluginDefinition['transforms']['record'] as $transform) {
if ($instance = $this->getTransformPluginInstance($transform)) {
$data = $instance->transformRecord($data);
}
}
foreach ($this->pluginDefinition['transforms']['field'] as $field_name => $transforms) {
foreach ($transforms as $transform) {
if ($instance = $this->getTransformPluginInstance($transform)) {
$data = $instance->transformField($field_name, $data);
}
}
}
return $data;
}
/**
* Gets a transform plugin instance.
*
* @param array $definition
* Plugin instance definition. Expects a key of 'plugin' for the plugin ID.
* All other keys are interpreted as plugin configuration.
*
* @return \Drupal\data_pipelines\Transform\TransformInterface|null
* Transform plugin instance if it exists.
*/
protected function getTransformPluginInstance(array $definition): ?TransformInterface {
if (!array_key_exists('plugin', $definition)) {
$this->loggerChannel->warning('Missing plugin ID for transform.');
return NULL;
}
$plugin_id = $definition['plugin'];
if (!$this->transformPluginManager->hasDefinition($plugin_id)) {
$this->loggerChannel->error(sprintf('Invalid plugin ID %s for transform.', $plugin_id));
return NULL;
}
$instance = $this->transformPluginManager->createInstance($plugin_id, array_diff_key($definition, array_flip(['plugin'])));
assert($instance instanceof TransformInterface);
return $instance;
}
/**
* {@inheritdoc}
*/
public function hasValidation(): bool {
return !empty($this->pluginDefinition['validations']['field']) || !empty($this->pluginDefinition['validations']['record']);
}
/**
* {@inheritdoc}
*/
public function getDestinationSettings(string $destination_id): array {
return $this->pluginDefinition['destinationSettings'][$destination_id] ?? [];
}
}
