datafield-1.x-dev/src/Plugin/DataField/FieldType/EntityReferenceItem.php
src/Plugin/DataField/FieldType/EntityReferenceItem.php
<?php
namespace Drupal\datafield\Plugin\DataField\FieldType;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityTypeRepositoryInterface;
use Drupal\Core\Field\EntityReferenceFieldItemList;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\datafield\Attribute\DataFieldType;
use Drupal\datafield\TypedData\EntityDataDefinition;
use Drupal\views\Views;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Defines the 'entity_reference' entity field type.
*
* Supported settings (below the definition's 'settings' key) are:
* - target_type: The entity type to reference. Required.
*/
#[DataFieldType(
id: 'entity_reference',
label: new TranslatableMarkup('Entity reference'),
description: new TranslatableMarkup('An data field containing an entity reference.'),
category: 'reference',
default_widget: 'entity_reference_autocomplete',
default_formatter: 'entity_reference_label',
list_class: EntityReferenceFieldItemList::class
)]
class EntityReferenceItem extends IntegerItem implements ContainerFactoryPluginInterface {
use StringTranslationTrait;
/**
* Constructs a EntityReferenceAutocompleteWidget object.
*
* @param string $plugin_id
* The plugin_id for the formatter.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param mixed $field_definition
* The definition of the field to which the formatter is associated.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Entity\EntityTypeRepositoryInterface $entityTypeRepository
* The entity type repository.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entityTypeBundleInfo
* The entity type bundle info service.
* @param \Drupal\Core\Session\AccountInterface $currentUser
* The current user service.
*/
public function __construct($plugin_id, $plugin_definition, $field_definition, protected EntityTypeManagerInterface $entityTypeManager, protected EntityTypeRepositoryInterface $entityTypeRepository, protected EntityTypeBundleInfoInterface $entityTypeBundleInfo, protected AccountInterface $currentUser) {
unset($plugin_id, $plugin_definition, $field_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, $configuration, $plugin_id, $plugin_definition) {
return new static(
$plugin_id,
$plugin_definition,
$configuration,
$container->get('entity_type.manager'),
$container->get('entity_type.repository'),
$container->get('entity_type.bundle.info'),
$container->get('current_user'),
);
}
/**
* {@inheritdoc}
*/
public function getLabel() {
return $this->t('Entity Reference');
}
/**
* {@inheritdoc}
*/
public function fieldSettingsForm(array $field_settings, array $settings) {
$field_settings += [
'entity_reference_type' => 'node',
'target_bundles' => 'page',
];
if ($field_settings["entity_reference_type"] == 'user') {
$field_settings["target_bundles"] = 'user';
}
$repository = $this->entityTypeRepository->getEntityTypeLabels(TRUE);
$contentType = [];
if (isset($repository["Configuration"])) {
unset($repository["Configuration"]);
}
if (isset($repository["Content"])) {
$contentType = $repository["Content"];
unset($repository["Content"]);
}
foreach ($repository as $repo) {
$contentType += $repo;
}
$contentType['image'] = $this->t('Image');
$entity_reference_type = $field_settings['entity_reference_type'];
$field_form = [
'label' => [
'#type' => 'textfield',
'#title' => $this->t('Label'),
'#default_value' => $field_settings['label'] ?? ucfirst($settings["name"]),
],
'required' => [
'#type' => 'checkbox',
'#title' => $this->t('Required'),
'#default_value' => $field_settings['required'] ?? FALSE,
],
'entity_reference_type' => [
'#type' => 'select',
'#title' => $this->t('Entity reference type'),
'#options' => $contentType,
'#empty_option' => $this->t('- Select a field type -'),
'#default_value' => $entity_reference_type,
'#description' => $this->t('Save and back again to select bundle'),
],
];
if (!empty($entity_reference_type)) {
$view_storage = $this->entityTypeManager->getStorage('view');
$displaysViewsRef = Views::getApplicableViews('entity_reference_display');
$explode = explode(':', $entity_reference_type);
$entity_type_id = end($explode);
if ($entity_type_id == 'image') {
$entity_type_id = 'file';
}
$entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
$titleBundle = $entity_type->getBundleLabel() ?? $this->t('Wait after select type');
$bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id);
if (!empty($bundles)) {
$bundle_options = [];
foreach ($bundles as $bundle_name => $bundle_info) {
$bundle_options[$bundle_name] = $bundle_info['label'];
}
}
if (!empty($displaysViewsRef)) {
// Filter views that list the entity type we want, and group
// the separate displays by view.
$optionsViewRef = [];
foreach ($displaysViewsRef as $data) {
[$view_id, $display_id] = $data;
$view = $view_storage->load($view_id);
if (in_array($view->get('base_table'), [
$entity_type->getBaseTable(),
$entity_type->getDataTable(),
])) {
$display = $view->get('display');
$optionsViewRef[$view_id . ':' . $display_id] = $view_id . ' - ' . $display[$display_id]['display_title'];
}
}
if (!empty($optionsViewRef)) {
$bundle_options['views'] = $optionsViewRef;
}
}
$field_form['target_bundles'] = [
'#type' => 'select',
'#title' => $titleBundle,
'#options' => $bundle_options ?? [],
'#empty_option' => $this->t('- Select a bundle -'),
'#default_value' => $field_settings['target_bundles'] ?? '',
];
$tmp = explode(':', $field_settings['target_bundles']);
// Check if the entity type is a view reference.
if (count($tmp) > 1) {
$field_form['view_arguments'] = [
'#type' => 'textfield',
'#title' => $this->t('View arguments'),
'#default_value' => $field_settings['view_arguments'] ?? '',
'#description' => $this->t('Provide a comma separated list of arguments to pass to the view.'),
];
}
}
return $field_form;
}
/**
* Get constraints.
*
* {@inheritdoc}
*/
public function getConstraints(array $settings) {
$constraints = [];
if ($settings['required']) {
$constraints['NotBlank'] = [];
}
return $constraints;
}
/**
* Process widget form.
*
* {@inheritdoc}
*/
public function setWidgetForm(&$widget, $field_settings, $entity) {
$explode = explode(':', $field_settings["entity_reference_type"] ?? '');
$reference_type = end($explode);
if (empty($reference_type)) {
$reference_type = 'node';
}
$widget['#target_type'] = $reference_type;
$widget['#entity_type'] = $field_settings["entity_reference_type"] ?? 'node';
$widget['#empty_option'] = $this->t('- Select -');
$widget['#selection_handler'] = 'default';
$bundle = $field_settings["target_bundles"] ?? '';
$widget['#placeholder'] = implode(' ', [
$this->t('Typing'),
$field_settings["label"] ?? '',
]);
$checkView = explode(':', $bundle);
if (!empty($bundle)) {
$widget['#bundle'] = $bundle;
if (!empty($widget["#widget_settings"]["autocreate"])) {
$widget['#autocreate']['bundle'] = $bundle;
$widget['#autocreate']['uid'] = $this->currentUser->id();
}
}
$optionsView = [
'target_type' => $reference_type,
'entity' => $entity,
];
$widget['#selection_settings'] = ['target_bundles' => [$bundle]];
if ($field_settings["entity_reference_type"] == 'user') {
$widget['#selection_settings'] = ['include_anonymous' => FALSE];
}
if ($reference_type != 'user') {
$optionsView['target_bundles'] = [$bundle];
}
if (isset($widget['#default_value']) && empty($widget['#default_value'])) {
unset($widget['#default_value']);
}
if (count($checkView) > 1) {
[$view_name, $display_name] = $checkView;
$view_arguments = $field_settings["view_arguments"] ?? '';
$view = [
'view_name' => $view_name,
'display_name' => $display_name,
'arguments' => explode(',', str_replace(' ', '', $view_arguments)),
];
$widget['#selection_handler'] = 'views';
$widget['#selection_settings']['view'] = $view;
// Check if is views reference.
$optionsView += [
'handler' => 'views',
'view' => $view,
];
// If it is view and autocreate.
if (!empty($widget["#widget_settings"]["autocreate"])) {
$view = Views::getView($view_name);
$view->setDisplay($display_name);
$displayHandler = $view->display_handler;
$filters = $displayHandler->getHandlers('filter');
foreach ($filters as $filter) {
$pluginId = $filter->getPluginId();
if ($pluginId == 'bundle') {
$bundle = array_key_first($filter->value);
$widget['#autocreate']['bundle'] = $bundle;
$widget["#selection_settings"]["target_bundles"] = [$bundle => $bundle];
break;
}
}
}
}
$widget['#selection_settings']['options_view'] = $optionsView;
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(array $settings) {
$name = $settings['name'];
$data_type = 'entity_datafield';
return EntityDataDefinition::create($data_type)
->setLabel(new TranslatableMarkup('%name value', ['%name' => $name]))
->setRequired(FALSE);
}
}
