View source
<?php
namespace Drupal\feeds\Feeds\Target;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\TypedData\DataDefinitionInterface;
use Drupal\feeds\EntityFinderInterface;
use Drupal\feeds\Exception\EmptyFeedException;
use Drupal\feeds\Exception\ReferenceNotFoundException;
use Drupal\feeds\Exception\TargetValidationException;
use Drupal\feeds\FeedInterface;
use Drupal\feeds\FieldTargetDefinition;
use Drupal\feeds\Plugin\Type\Target\ConfigurableTargetInterface;
use Drupal\feeds\Plugin\Type\Target\FieldTargetBase;
use Drupal\feeds\StateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class EntityReference extends FieldTargetBase implements ConfigurableTargetInterface, ContainerFactoryPluginInterface {
protected $entityTypeManager;
protected $entityFieldManager;
protected $entityFinder;
public function __construct(array $configuration, $plugin_id, array $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, EntityFinderInterface $entity_finder) {
$this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager;
$this->entityFinder = $entity_finder;
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('entity_type.manager'), $container
->get('entity_field.manager'), $container
->get('feeds.entity_finder'));
}
protected static function prepareTarget(FieldDefinitionInterface $field_definition) {
$type = $field_definition
->getSetting('target_type');
if (!\Drupal::entityTypeManager()
->getDefinition($type)
->entityClassImplements(ContentEntityInterface::class)) {
return;
}
return FieldTargetDefinition::createFromFieldDefinition($field_definition)
->addProperty('target_id');
}
public function setTarget(FeedInterface $feed, EntityInterface $entity, $field_name, array $raw_values) {
$values = [];
foreach ($raw_values as $delta => $columns) {
try {
$this
->prepareValue($delta, $columns);
$values[] = $columns;
} catch (ReferenceNotFoundException $e) {
$entity
->get('feeds_item')->hash = NULL;
$feed
->getState(StateInterface::PROCESS)
->setMessage($e
->getFormattedMessage(), 'warning', TRUE);
} catch (EmptyFeedException $e) {
} catch (TargetValidationException $e) {
$this
->addMessage($e
->getFormattedMessage(), 'error');
}
}
if (!empty($values)) {
$entity_target = $this
->getEntityTarget($feed, $entity);
if ($entity_target) {
$item_list = $entity_target
->get($field_name);
$values = array_merge($item_list
->getValue(), $values);
$item_list
->setValue($values);
}
}
}
protected function getPotentialFields() {
$field_definitions = $this->entityFieldManager
->getFieldStorageDefinitions($this
->getEntityType());
$field_definitions = array_filter($field_definitions, [
$this,
'filterFieldTypes',
]);
$options = [];
foreach ($field_definitions as $id => $definition) {
$options[$id] = Html::escape($definition
->getLabel());
}
return $options;
}
protected function filterFieldTypes(FieldStorageDefinitionInterface $field) {
if ($field instanceof DataDefinitionInterface && $field
->isComputed()) {
return FALSE;
}
switch ($field
->getType()) {
case 'integer':
case 'string':
case 'text_long':
case 'path':
case 'uuid':
case 'feeds_item':
return TRUE;
default:
return FALSE;
}
}
protected function getEntityType() {
return $this->settings['target_type'];
}
protected function getBundles() {
if (!empty($this->settings['handler_settings']['target_bundles'])) {
return $this->settings['handler_settings']['target_bundles'];
}
return [];
}
protected function getBundleKey() {
return $this->entityTypeManager
->getDefinition($this
->getEntityType())
->getKey('bundle');
}
protected function getLabelKey() {
return $this->entityTypeManager
->getDefinition($this
->getEntityType())
->getKey('label');
}
protected function getLangcodeKey() {
$entity_type = $this->entityTypeManager
->getDefinition($this
->getEntityType());
if ($entity_type
->hasKey('langcode')) {
return $entity_type
->getKey('langcode');
}
}
protected function prepareValue($delta, array &$values) {
if (!isset($values['target_id']) || strlen(trim($values['target_id'])) === 0) {
throw new EmptyFeedException();
}
$target_ids = $this
->findEntities($this->configuration['reference_by'], $values['target_id']);
if (empty($target_ids)) {
throw new ReferenceNotFoundException($this
->t('Referenced entity not found for field %field with value %target_id.', [
'%target_id' => $values['target_id'],
'%field' => $this->configuration['reference_by'],
]));
}
$values['target_id'] = reset($target_ids);
}
protected function findEntity(string $field, $search) {
$entities = $this
->findEntities($field, $search);
if (!empty($entities)) {
return reset($entities);
}
return FALSE;
}
protected function findEntities(string $field, $search) {
if ($field == 'feeds_item') {
$field = 'feeds_item.' . $this->configuration['feeds_item'];
}
$target_ids = $this->entityFinder
->findEntities($this
->getEntityType(), $field, $search, $this
->getBundles());
if (!empty($target_ids)) {
return $target_ids;
}
if ($this->configuration['autocreate'] && $field === $this
->getLabelKey()) {
return [
$this
->createEntity($search),
];
}
return [];
}
protected function createEntity($label) {
if (!strlen(trim($label))) {
return FALSE;
}
$bundles = $this
->getBundles();
$values = [
$this
->getLabelKey() => $label,
$this
->getBundleKey() => reset($bundles),
];
if ($langcode = $this
->getLangcodeKey()) {
$values[$langcode] = $this
->getLangcode();
}
$entity = $this->entityTypeManager
->getStorage($this
->getEntityType())
->create($values);
$entity
->save();
return $entity
->id();
}
public function defaultConfiguration() {
$config = parent::defaultConfiguration() + [
'reference_by' => $this
->getLabelKey(),
'autocreate' => FALSE,
];
if (array_key_exists('feeds_item', $this
->getPotentialFields())) {
$config['feeds_item'] = FALSE;
}
return $config;
}
public function getFeedsItemOptions() {
return [
'guid' => $this
->t('Item GUID'),
];
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$options = $this
->getPotentialFields();
$delta = 0;
foreach ($form_state
->getValues() as $key => $value) {
if (strpos($key, 'target-settings-') === 0) {
list(, , $delta) = explode('-', $key);
break;
}
}
$form['reference_by'] = [
'#type' => 'select',
'#title' => $this
->t('Reference by'),
'#options' => $options,
'#default_value' => $this->configuration['reference_by'],
];
$feed_item_options = $this
->getFeedsItemOptions();
$form['feeds_item'] = [
'#type' => 'select',
'#title' => $this
->t('Feed item'),
'#options' => $feed_item_options,
'#default_value' => $this
->getConfiguration('feeds_item'),
'#states' => [
'visible' => [
':input[name="mappings[' . $delta . '][settings][reference_by]"]' => [
'value' => 'feeds_item',
],
],
],
];
$form['autocreate'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Autocreate entity'),
'#default_value' => $this->configuration['autocreate'],
'#states' => [
'visible' => [
':input[name="mappings[' . $delta . '][settings][reference_by]"]' => [
'value' => $this
->getLabelKey(),
],
],
],
];
return $form;
}
public function getSummary() {
$options = $this
->getPotentialFields();
$summary = parent::getSummary();
if ($this->configuration['reference_by'] && isset($options[$this->configuration['reference_by']])) {
$summary[] = $this
->t('Reference by: %message', [
'%message' => $options[$this->configuration['reference_by']],
]);
if ($this->configuration['reference_by'] == 'feeds_item') {
$feed_item_options = $this
->getFeedsItemOptions();
$summary[] = $this
->t('Feed item: %feed_item', [
'%feed_item' => $feed_item_options[$this->configuration['feeds_item']],
]);
}
}
else {
$summary[] = [
'#prefix' => '<div class="messages messages--warning">',
'#markup' => $this
->t('Please select a field to reference by.'),
'#suffix' => '</div>',
];
}
if ($this->configuration['reference_by'] === $this
->getLabelKey()) {
$create = $this->configuration['autocreate'] ? $this
->t('Yes') : $this
->t('No');
$summary[] = $this
->t('Autocreate terms: %create', [
'%create' => $create,
]);
}
return $summary;
}
}