View source
<?php
namespace Drupal\feeds_para_mapper;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\feeds\Plugin\Type\FeedsPluginManager;
use Drupal\feeds_para_mapper\Utility\TargetInfo;
use Drupal\field\FieldConfigInterface;
class Mapper {
protected $targetsManager;
protected $entityFieldManager;
protected $bundleInfo;
public function __construct(FeedsPluginManager $targetsManager, EntityFieldManagerInterface $entityFieldManager, EntityTypeBundleInfoInterface $bundleInfo) {
$this->targetsManager = $targetsManager;
$this->entityFieldManager = $entityFieldManager;
$this->bundleInfo = $bundleInfo;
}
public function getTargets($entityType, $bundle) {
$paragraphs_fields = $this
->findParagraphsFields($entityType, $bundle);
$fields = array();
foreach ($paragraphs_fields as $paragraphs_field) {
$subFields = $this
->getSubFields($paragraphs_field);
$fields = array_merge($fields, $subFields);
}
$definitions = $this->targetsManager
->getDefinitions();
$supported = array();
foreach ($fields as $field) {
foreach ($definitions as $name => $plugin) {
if (in_array($field
->getType(), $plugin['field_types'])) {
$this
->updateInfo($field, "plugin", $plugin);
$this
->updateInfo($field, "type", $field
->getType());
$supported[] = $field;
break;
}
}
}
return $supported;
}
public function findParagraphsFields($entity_type, $bundle) {
$fields = array();
$entityFields = $this->entityFieldManager
->getFieldDefinitions($entity_type, $bundle);
if (!isset($entityFields)) {
return $fields;
}
$entityFields = array_filter($entityFields, function ($item) {
return $item instanceof FieldConfigInterface;
});
foreach ($entityFields as $field) {
if ($field
->getType() === 'entity_reference_revisions') {
$fields[] = $field;
}
}
return $fields;
}
public function getSubFields($target, array $result = array(), array $first_host = array()) {
$target_bundles = $this
->getEnabledBundles($target);
foreach ($target_bundles as $target_bundle) {
$sub_fields = $this->entityFieldManager
->getFieldDefinitions('paragraph', $target_bundle);
$sub_fields = array_filter($sub_fields, function ($item) {
return $item instanceof FieldConfigInterface;
});
foreach ($sub_fields as $machine_name => $sub_field) {
if ($target
->getTargetEntityTypeId() !== 'paragraph') {
$first_host = array(
'bundle' => $target_bundle,
'host_field' => $target
->getName(),
'host_entity' => $target
->getTargetEntityTypeId(),
'host_field_bundle' => $target
->get('bundle'),
);
}
$wrapped = $this
->isWrapped($sub_field, $first_host);
if ($sub_field
->getType() === 'entity_reference_revisions' && !$wrapped) {
$result = $this
->getSubFields($sub_field, $result, $first_host);
}
else {
if ($sub_field
->getType() !== "feeds_item" && !$wrapped) {
$sub_field = clone $sub_field;
$host_allowed = $target
->getFieldStorageDefinition()
->getCardinality();
$fieldAllowed = $sub_field
->getFieldStorageDefinition()
->getCardinality();
$unlimited = FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED;
$has_settings = FALSE;
if ($host_allowed === $unlimited || $host_allowed > 1) {
if ($fieldAllowed === $unlimited || $fieldAllowed > 1) {
$has_settings = TRUE;
}
}
$this
->updateInfo($sub_field, "has_settings", $has_settings);
$path = $this
->buildPath($sub_field, $first_host);
$this
->updateInfo($sub_field, "path", $path);
$this
->setFieldsInCommon($sub_field, $result);
$result[] = $sub_field;
}
else {
if ($wrapped) {
$type = $sub_field->target_info->type;
$sub_field
->set('field_type', $type);
$result[] = $sub_field;
}
}
}
}
}
return $result;
}
protected function isWrapped(&$sub_field, $first_host) {
$wrapped = isset($sub_field->target_info);
if (!$wrapped) {
return false;
}
$path = $this
->buildPath($sub_field, $first_host);
$duplicates = 0;
foreach ($path as $i => $new_path) {
if (isset($sub_field->target_info->path[$i]) && $sub_field->target_info->path[$i]['bundle'] === $new_path['bundle']) {
$duplicates++;
}
}
$wrapped = $duplicates == count($sub_field->target_info->path);
if (!$wrapped) {
unset($sub_field->target_info);
}
return $wrapped;
}
private function getEnabledBundles($target) {
$settings = $target
->getSettings();
$target_bundles = array();
if (isset($settings['handler_settings']['target_bundles'])) {
$target_bundles = $settings['handler_settings']['target_bundles'];
$target_bundles = array_values($target_bundles);
}
else {
if (isset($settings['handler_settings']['target_bundles_drag_drop'])) {
$selected_bundles = array_filter($settings['handler_settings']['target_bundles_drag_drop'], function ($item) {
return $item['enabled'];
});
if (count($selected_bundles)) {
$target_bundles = array_keys($selected_bundles);
}
else {
$target_bundles = array_keys($settings['handler_settings']['target_bundles_drag_drop']);
}
}
}
$target_bundle = $target
->get('bundle');
$target_bundles = array_filter($target_bundles, function ($item) use ($target_bundle) {
return $item !== $target_bundle;
});
return $target_bundles;
}
public function updateInfo(FieldDefinitionInterface $field, $property, $value) {
$info = $field
->get('target_info');
if (!isset($info)) {
$info = new TargetInfo();
}
$res = false;
if (property_exists(TargetInfo::class, $property)) {
$info->{$property} = $value;
$field
->set('target_info', $info);
$res = true;
}
return $res;
}
public function getInfo(FieldDefinitionInterface $field, $property) {
$info = $field
->get('target_info');
if (!isset($info)) {
$info = new TargetInfo();
}
$res = null;
if (property_exists(TargetInfo::class, $property)) {
$res = $info->{$property};
}
return $res;
}
private function setFieldsInCommon(FieldDefinitionInterface &$field, array &$fields) {
foreach ($fields as $key => $other_field) {
$other_info = $other_field
->get('target_info');
$last_key = count($other_info->path) - 1;
$others_host = $other_info->path[$last_key];
$info = $field
->get('target_info');
$current_host_key = count($info->path) - 1;
$current_host = $info->path[$current_host_key];
if ($others_host['host_field'] === $current_host['host_field']) {
if (!isset($info->in_common)) {
$info->in_common = array();
}
if (!isset($other_info->in_common)) {
$other_info->in_common = array();
}
$other_field_in_common = array(
'id' => $other_field
->id(),
'name' => $other_field
->getName(),
);
$field_in_common = array(
'id' => $field
->id(),
'name' => $field
->getName(),
);
$info->in_common[] = $other_field_in_common;
$field
->set('target_info', $info);
$other_info->in_common[] = $field_in_common;
$other_field
->set('target_info', $other_info);
}
}
}
private function buildPath(FieldDefinitionInterface $field, array $first_host) {
$bundles = $this->bundleInfo
->getBundleInfo('paragraph');
foreach ($bundles as $name => $bundle) {
$bundles[$name]['name'] = $name;
$fields = $this->entityFieldManager
->getFieldDefinitions('paragraph', $name);
$fields = array_filter($fields, function ($item) {
return $item instanceof FieldConfigInterface;
});
$bundles[$name]['fields'] = $fields;
}
$field_bundle = NULL;
$getFieldBundle = function (FieldDefinitionInterface $field) use ($bundles) {
foreach ($bundles as $bundle) {
foreach ($bundle['fields'] as $b_field) {
if ($b_field
->getName() === $field
->getName()) {
return $bundle;
}
}
}
return NULL;
};
$getHost = function ($field_bundle) use ($bundles) {
foreach ($bundles as $bundle) {
foreach ($bundle['fields'] as $b_field) {
$settings = $b_field
->getSetting('handler_settings');
if (isset($settings['target_bundles'])) {
foreach ($settings['target_bundles'] as $allowed_bundle) {
if ($allowed_bundle === $field_bundle['name']) {
$allowed = array_filter($bundles, function ($item) use ($allowed_bundle) {
return $item['name'] === $allowed_bundle;
});
$allowed = array_values($allowed);
return array(
'bundle' => $allowed[0],
'host_field' => $b_field,
);
}
}
}
}
}
return NULL;
};
$path = array();
$field_bundle = $getFieldBundle($field);
while (isset($field_bundle)) {
$host = $getHost($field_bundle);
if (isset($host)) {
$new_path = array(
'bundle' => $host['bundle']['name'],
'host_field' => $host['host_field']
->getName(),
'host_field_bundle' => $host['host_field']
->get('bundle'),
'host_entity' => 'paragraph',
);
array_unshift($path, $new_path);
$field_bundle = $getFieldBundle($host['host_field']);
}
else {
$field_bundle = NULL;
}
}
array_unshift($path, $first_host);
for ($i = 0; $i < count($path); $i++) {
$path[$i]['order'] = $i;
}
return $path;
}
public function getMaxValues(FieldDefinitionInterface $target, array $configuration = null) {
$crd = (int) $target
->getFieldStorageDefinition()
->getCardinality();
if (!isset($configuration['max_values'])) {
return $crd;
}
$unlimited = $crd === -1;
$max_values = (int) $configuration['max_values'];
$valid = $max_values <= $crd && !$unlimited && !($max_values < 0 && $crd > 0) || $unlimited && $max_values >= -1;
if ($valid) {
$res = $max_values;
}
else {
$res = $crd;
}
return $res;
}
public function loadParentFields(FieldDefinitionInterface $field) {
$target_info = $field->target_info;
$parents = array();
foreach ($target_info->path as $parentI) {
$bundle = isset($parentI['host_field_bundle']) ? $parentI['host_field_bundle'] : $parentI['bundle'];
$fields = $this->entityFieldManager
->getFieldDefinitions($parentI['host_entity'], $bundle);
$parents[] = $fields[$parentI['host_field']];
}
return $parents;
}
}