class DynamicEntityReferenceItem in Dynamic Entity Reference 8
Same name and namespace in other branches
- 8.2 src/Plugin/Field/FieldType/DynamicEntityReferenceItem.php \Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceItem
Defines the 'dynamic_entity_reference' entity field type.
Supported settings (below the definition's 'settings' key) are:
- exclude_entity_types: Allow user to include or exclude entity_types.
- entity_type_ids: The entity type ids that can or cannot be referenced.
@property int target_id @property string target_type @property \Drupal\Core\Entity\ContentEntityInterface entity
Plugin annotation
@FieldType(
id = "dynamic_entity_reference",
label = @Translation("Dynamic entity reference"),
description = @Translation("An entity field containing a dynamic entity reference."),
category = @Translation("Dynamic Reference"),
no_ui = FALSE,
list_class = "\Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceFieldItemList",
default_widget = "dynamic_entity_reference_default",
default_formatter = "dynamic_entity_reference_label"
)
Hierarchy
- class \Drupal\Core\TypedData\TypedData implements PluginInspectionInterface, TypedDataInterface uses DependencySerializationTrait, StringTranslationTrait, TypedDataTrait
- class \Drupal\Core\TypedData\Plugin\DataType\Map implements \Drupal\Core\TypedData\Plugin\DataType\IteratorAggregate, ComplexDataInterface
- class \Drupal\Core\Field\FieldItemBase implements FieldItemInterface
- class \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem implements PreconfiguredFieldUiOptionsInterface, OptionsProviderInterface
- class \Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceItem
- class \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem implements PreconfiguredFieldUiOptionsInterface, OptionsProviderInterface
- class \Drupal\Core\Field\FieldItemBase implements FieldItemInterface
- class \Drupal\Core\TypedData\Plugin\DataType\Map implements \Drupal\Core\TypedData\Plugin\DataType\IteratorAggregate, ComplexDataInterface
Expanded class hierarchy of DynamicEntityReferenceItem
8 files declare their use of DynamicEntityReferenceItem
- DynamicEntityReferenceEntityFormatter.php in src/
Plugin/ Field/ FieldFormatter/ DynamicEntityReferenceEntityFormatter.php - DynamicEntityReferenceItemNormalizer.php in src/
Normalizer/ DynamicEntityReferenceItemNormalizer.php - DynamicEntityReferenceOptionsTrait.php in src/
Plugin/ Field/ FieldWidget/ DynamicEntityReferenceOptionsTrait.php - DynamicEntityReferenceTest.php in tests/
src/ Functional/ DynamicEntityReferenceTest.php - DynamicEntityReferenceWidget.php in src/
Plugin/ Field/ FieldWidget/ DynamicEntityReferenceWidget.php
File
- src/
Plugin/ Field/ FieldType/ DynamicEntityReferenceItem.php, line 41
Namespace
Drupal\dynamic_entity_reference\Plugin\Field\FieldTypeView source
class DynamicEntityReferenceItem extends EntityReferenceItem {
/**
* {@inheritdoc}
*/
public static function defaultStorageSettings() {
return [
'exclude_entity_types' => TRUE,
'entity_type_ids' => [],
];
}
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
$default_settings = [];
$labels = \Drupal::service('entity_type.repository')
->getEntityTypeLabels(TRUE);
$options = $labels[(string) t('Content', [], [
'context' => 'Entity type group',
])];
// Field storage settings are not accessible here so we are assuming that
// all the entity types are referenceable by default.
// See https://www.drupal.org/node/2346273#comment-9385179 for more details.
foreach (array_keys($options) as $entity_type_id) {
$default_settings[$entity_type_id] = [
'handler' => "default:{$entity_type_id}",
'handler_settings' => [],
];
}
return $default_settings;
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['target_id'] = DataReferenceTargetDefinition::create('integer')
->setLabel(t('Entity ID'))
->setSetting('unsigned', TRUE)
->setRequired(TRUE);
$properties['target_type'] = DataReferenceTargetDefinition::create('string')
->setLabel(new TranslatableMarkup('Target Entity Type'))
->setRequired(TRUE);
$properties['entity'] = DataDynamicReferenceDefinition::create('entity')
->setLabel(t('Entity'))
->setDescription(new TranslatableMarkup('The referenced entity'))
->setComputed(TRUE)
->setReadOnly(FALSE);
return $properties;
}
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
$columns = [
'target_id' => [
'description' => 'The ID of the target entity.',
'type' => 'int',
'unsigned' => TRUE,
],
'target_type' => [
'description' => 'The Entity Type ID of the target entity.',
'type' => 'varchar',
'length' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
],
];
$schema = [
'columns' => $columns,
'indexes' => [
'target_id' => [
'target_id',
'target_type',
],
],
];
return $schema;
}
/**
* {@inheritdoc}
*/
public function onChange($property_name, $notify = TRUE) {
/** @var \Drupal\dynamic_entity_reference\Plugin\DataType\DynamicEntityReference $entity_property */
$entity_property = $this
->get('entity');
if ($property_name == 'target_type' && !$entity_property
->getValue()) {
$entity_property
->getTargetDefinition()
->setEntityTypeId($this
->get('target_type')
->getValue());
}
elseif ($property_name == 'entity') {
$this
->writePropertyValue('target_type', $entity_property
->getValue()
->getEntityTypeId());
}
elseif ($property_name == 'target_id') {
// Just in case target_id is set before target_type then set it to empty
// string instead of NULL so that
// \Drupal\Core\Entity\Plugin\DataType\EntityReference::setValue
// doesn't throw "InvalidArgumentException: Value is not a valid entity".
$entity_property
->getTargetDefinition()
->setEntityTypeId($this
->get('target_type')
->getValue() ?: '');
}
parent::onChange($property_name, $notify);
}
/**
* {@inheritdoc}
*
* To select both target_type and target_id the option value is
* changed from target_id to target_type-target_id.
*
* @see \Drupal\dynamic_entity_reference\Plugin\Field\FieldWidget\DynamicEntityReferenceOptionsTrait::massageFormValues()
*/
public function getSettableOptions(AccountInterface $account = NULL) {
$field_definition = $this
->getFieldDefinition();
$entity_type_manager = \Drupal::entityTypeManager();
$entity_type_bundles_info = \Drupal::service('entity_type.bundle.info');
$selection_manager = \Drupal::service('plugin.manager.dynamic_entity_reference_selection');
$options = [];
$settings = $this
->getSettings();
$target_types = static::getTargetTypes($settings);
foreach ($target_types as $target_type) {
$options[$target_type] = $selection_manager
->getSelectionHandler($field_definition, $this
->getEntity(), $target_type)
->getReferenceableEntities();
}
if (empty($options)) {
return [];
}
$return = [];
foreach ($options as $target_type => $referenceable_entities) {
$target_type_info = $entity_type_manager
->getDefinition($target_type);
$target_type_label = $target_type_info
->getLabel();
// Rebuild the array by changing the bundle key into the bundle label.
$bundles = $entity_type_bundles_info
->getBundleInfo($target_type);
foreach ($referenceable_entities as $bundle => $entities) {
// The label does not need sanitizing since it is used as an optgroup
// which is only supported by select elements and auto-escaped.
$bundle_label = $bundles[$bundle]['label'];
foreach ($entities as $id => $entity_label) {
if (count($target_types) > 1) {
if ($target_type_info
->hasKey('bundle')) {
$return[(string) $target_type_label . ': ' . (string) $bundle_label]["{$target_type}-{$id}"] = "{$entity_label} ({$target_type_label}:{$id})";
}
else {
$return[(string) $target_type_label]["{$target_type}-{$id}"] = "{$entity_label} ({$target_type_label}:{$id})";
}
}
else {
$return[(string) $bundle_label]["{$target_type}-{$id}"] = "{$entity_label} ({$target_type_label}:{$id})";
}
}
}
}
return $return;
}
/**
* {@inheritdoc}
*/
public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
// @todo inject this.
$labels = \Drupal::service('entity_type.repository')
->getEntityTypeLabels(TRUE);
$options = $labels[(string) t('Content', [], [
'context' => 'Entity type group',
])];
foreach (array_keys($options) as $entity_type_id) {
if (!static::entityHasIntegerId($entity_type_id)) {
unset($options[$entity_type_id]);
}
}
$element['exclude_entity_types'] = [
'#type' => 'checkbox',
'#title' => t('Exclude the selected items'),
'#default_value' => $this
->getSetting('exclude_entity_types'),
'#disabled' => $has_data,
];
$element['entity_type_ids'] = [
'#type' => 'select',
'#title' => t('Select items'),
'#options' => $options,
'#default_value' => $this
->getSetting('entity_type_ids'),
'#disabled' => $has_data,
'#multiple' => TRUE,
'#element_validate' => [
[
DynamicEntityReferenceItem::class,
'storageSettingsFormValidate',
],
],
];
return $element;
}
/**
* Form element validation for storage settings.
*
* @param array $element
* The form element .
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param array $form
* The complete form.
*/
public static function storageSettingsFormValidate(array &$element, FormStateInterface $form_state, array $form) {
$labels = \Drupal::service('entity_type.repository')
->getEntityTypeLabels(TRUE);
$options = array_filter(array_keys($labels[(string) t('Content', [], [
'context' => 'Entity type group',
])]), function ($entity_type_id) {
return static::entityHasIntegerId($entity_type_id);
});
$exclude_entity_types = $form_state
->getValue([
'settings',
'exclude_entity_types',
], 0);
$entity_type_ids = $form_state
->getValue([
'settings',
'entity_type_ids',
], []);
$diff = array_diff($options, $entity_type_ids);
if (!$exclude_entity_types && empty($entity_type_ids) || $exclude_entity_types && empty($diff)) {
$form_state
->setError($element, t('Select at least one entity type ID.'));
}
}
/**
* {@inheritdoc}
*/
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$settings_form = [];
$settings = $this
->getSettings();
foreach (static::getTargetTypes($settings) as $target_type) {
$entity_type = \Drupal::entityTypeManager()
->getDefinition($target_type);
$settings_form[$target_type] = $this
->targetTypeFieldSettingsForm($form, $form_state, $target_type);
$settings_form[$target_type]['handler']['#title'] = t('Reference type for @target_type', [
'@target_type' => $entity_type
->getLabel(),
]);
}
return $settings_form;
}
/**
* Returns a form for single target type settings.
*
* This is same as
* \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::fieldSettingsForm()
* but it uses dynamic_entity_reference_selection plugin manager instead of
* entity_reference_selection plugin manager.
*
* @param array $form
* The form where the settings form is being included in.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state of the (entire) configuration form.
* @param string $target_type
* The target entity type id.
*
* @return array
* The form definition for the field settings.
*/
protected function targetTypeFieldSettingsForm(array $form, FormStateInterface $form_state, $target_type) {
/** @var \Drupal\field\FieldConfigInterface $field */
$field = $form_state
->getFormObject()
->getEntity();
$field_settings = $field
->getSettings();
/** @var \Drupal\dynamic_entity_reference\SelectionPluginManager $manager */
$manager = \Drupal::service('plugin.manager.dynamic_entity_reference_selection');
// Get all selection plugins for this entity type.
$selection_plugins = $manager
->getSelectionGroups($target_type);
$handlers_options = [];
foreach (array_keys($selection_plugins) as $selection_group_id) {
// We only display base plugins (e.g. 'default', 'views', ...) and not
// entity type specific plugins (e.g. 'default:node', 'default:user',
// ...).
if (array_key_exists($selection_group_id, $selection_plugins[$selection_group_id])) {
$handlers_options[$selection_group_id] = Html::escape($selection_plugins[$selection_group_id][$selection_group_id]['label']);
}
elseif (array_key_exists($selection_group_id . ':' . $target_type, $selection_plugins[$selection_group_id])) {
$selection_group_plugin = $selection_group_id . ':' . $target_type;
$handlers_options[$selection_group_plugin] = Html::escape($selection_plugins[$selection_group_id][$selection_group_plugin]['base_plugin_label']);
}
}
$form = [
'#type' => 'container',
'#process' => [
[
EntityReferenceItem::class,
'fieldSettingsAjaxProcess',
],
],
'#element_validate' => [
[
DynamicEntityReferenceItem::class,
'fieldSettingsFormValidate',
],
],
];
$form['handler'] = [
'#type' => 'details',
'#title' => t('Reference type'),
'#open' => TRUE,
'#tree' => TRUE,
'#process' => [
[
EntityReferenceItem::class,
'formProcessMergeParent',
],
],
];
$form['handler']['handler'] = [
'#type' => 'select',
'#title' => t('Reference method'),
'#options' => $handlers_options,
'#default_value' => $field_settings[$target_type]['handler'],
'#required' => TRUE,
'#ajax' => TRUE,
'#limit_validation_errors' => [],
];
$form['handler']['handler_submit'] = [
'#type' => 'submit',
'#value' => t('Change handler'),
'#limit_validation_errors' => [],
'#attributes' => [
'class' => [
'js-hide',
],
],
'#submit' => [
'entity_reference_settings_ajax_submit',
],
];
$form['handler']['handler_settings'] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'entity_reference-settings',
],
],
];
$handler = $manager
->getSelectionHandler($field, NULL, $target_type);
$form['handler']['handler_settings'] += $handler
->buildConfigurationForm([], $form_state);
return $form;
}
/**
* Form element validation handler; Stores the new values in the form state.
*
* @param array $form
* The form where the settings form is being included in.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state of the (entire) configuration form.
*/
public static function fieldSettingsFormValidate(array $form, FormStateInterface $form_state) {
/** @var \Drupal\field\Entity\FieldConfig $field */
$field = $form_state
->getFormObject()
->getEntity();
foreach (static::getTargetTypes($field
->getSettings()) as $target_type) {
// If no checkboxes were checked for 'target_bundles', store NULL ("all
// bundles are referenceable") rather than empty array ("no bundle is
// referenceable" - typically happens when all referenceable bundles have
// been deleted).
if ($form_state
->getValue([
'settings',
$target_type,
'handler_settings',
'target_bundles',
]) === []) {
$form_state
->setValue([
'settings',
$target_type,
'handler_settings',
'target_bundles',
], NULL);
}
// Don't store the 'target_bundles_update' button value into the field
// config settings.
$form_state
->unsetValue([
'settings',
$target_type,
'handler_settings',
'target_bundles_update',
]);
$form_state
->unsetValue([
'settings',
$target_type,
'handler_submit',
]);
}
}
/**
* {@inheritdoc}
*/
public static function mainPropertyName() {
// Dynamic entity reference field has two main properties i.e. target_type
// and target_id but for entity field query to evaluate the relationship
// specifier correctly the main property is needed. It is also needed to
// render the correct field value in views.
return 'target_id';
}
/**
* {@inheritdoc}
*/
public function setValue($values, $notify = TRUE) {
// If either a scalar or an object was passed as the value for the item,
// assign it to the 'entity' property since that works for both cases.
if (isset($values) && !is_array($values)) {
$this
->set('entity', $values, $notify);
}
else {
if (empty($values['target_type']) && !empty($values['target_id']) && !(isset($values['entity']) && $values['entity'] instanceof EntityInterface)) {
throw new \InvalidArgumentException('No entity type was provided, value is not a valid entity.');
}
// We have to bypass the EntityReferenceItem::setValue() here because we
// also want to invoke onChange for target_type.
FieldItemBase::setValue($values, FALSE);
// Support setting the field item with only one property, but make sure
// values stay in sync if only property is passed.
// NULL is a valid value, so we use array_key_exists().
if (is_array($values) && array_key_exists('target_id', $values) && array_key_exists('target_type', $values) && !isset($values['entity'])) {
$this
->onChange('target_type', FALSE);
$this
->onChange('target_id', FALSE);
}
elseif (is_array($values) && !array_key_exists('target_id', $values) && !array_key_exists('target_type', $values) && isset($values['entity'])) {
$this
->onChange('entity', FALSE);
}
elseif (is_array($values) && array_key_exists('target_id', $values) && array_key_exists('target_type', $values) && isset($values['entity'])) {
/** @var \Drupal\dynamic_entity_reference\Plugin\DataType\DynamicEntityReference $entity_property */
$entity_property = $this
->get('entity');
$entity_id = $entity_property
->getTargetIdentifier();
/** @var \Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface $target_definition */
$target_definition = $entity_property
->getTargetDefinition();
$entity_type = $target_definition
->getEntityTypeId();
if (!$this->entity
->isNew() && $values['target_id'] !== NULL && ($entity_id !== $values['target_id'] || $entity_type !== $values['target_type'])) {
throw new \InvalidArgumentException('The target id, target type and entity passed to the dynamic entity reference item do not match.');
}
}
// Notify the parent if necessary.
if ($notify && $this->parent) {
$this->parent
->onChange($this
->getName());
}
}
}
/**
* {@inheritdoc}
*/
public function getValue() {
$values = parent::getValue();
if (!empty($values['target_type'])) {
$this
->get('entity')
->getTargetDefinition()
->setEntityTypeId($values['target_type']);
}
return $values;
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
// Avoid loading the entity by first checking the 'target_id'.
if ($this->target_id !== NULL && $this->target_type !== NULL) {
return FALSE;
}
if ($this->entity && $this->entity instanceof EntityInterface) {
return FALSE;
}
return TRUE;
}
/**
* {@inheritdoc}
*/
public function preSave() {
if ($this
->hasNewEntity()) {
// Save the entity if it has not already been saved by some other code.
if ($this->entity
->isNew()) {
$this->entity
->save();
}
// Make sure the parent knows we are updating this property so it can
// react properly.
$this->target_id = $this->entity
->id();
$this->target_type = $this->entity
->getEntityTypeId();
}
if (!$this
->isEmpty() && $this->target_id === NULL) {
$this->target_id = $this->entity
->id();
}
}
/**
* {@inheritdoc}
*/
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
/** @var \Drupal\dynamic_entity_reference\SelectionPluginManager $manager */
$manager = \Drupal::service('plugin.manager.dynamic_entity_reference_selection');
$settings = $field_definition
->getSettings();
foreach (static::getTargetTypes($settings) as $target_type) {
$values['target_type'] = $target_type;
if ($referenceable = $manager
->getSelectionHandler($field_definition, NULL, $target_type)
->getReferenceableEntities()) {
$group = array_rand($referenceable);
$values['target_id'] = array_rand($referenceable[$group]);
return $values;
}
}
}
/**
* {@inheritdoc}
*/
public static function calculateDependencies(FieldDefinitionInterface $field_definition) {
$dependencies = FieldItemBase::calculateDependencies($field_definition);
$entity_repository = \Drupal::service('entity.repository');
if ($default_value = $field_definition
->getDefaultValueLiteral()) {
foreach ($default_value as $value) {
if (is_array($value) && isset($value['target_uuid']) && isset($value['target_type'])) {
$entity = $entity_repository
->loadEntityByUuid($value['target_type'], $value['target_uuid']);
// If the entity does not exist do not create the dependency.
// @see \Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceFieldItemList::processDefaultValue()
if ($entity) {
$dependencies[$entity
->getEntityType()
->getConfigDependencyKey()][] = $entity
->getConfigDependencyName();
}
}
}
}
// Depend on target bundle configurations. Dependencies for 'target_bundles'
// also covers the 'auto_create_bundle' setting, if any, because its value
// is included in the 'target_bundles' list.
$entity_type_manager = \Drupal::entityTypeManager();
$settings = $field_definition
->getSettings();
foreach (static::getTargetTypes($settings) as $target_type) {
$handler = $settings[$target_type]['handler_settings'];
if (!empty($handler['target_bundles'])) {
$target_entity_type = $entity_type_manager
->getDefinition($target_type);
if ($bundle_entity_type_id = $target_entity_type
->getBundleEntityType()) {
if ($storage = $entity_type_manager
->getStorage($bundle_entity_type_id)) {
foreach ($storage
->loadMultiple($handler['target_bundles']) as $bundle) {
$dependencies[$bundle
->getConfigDependencyKey()][] = $bundle
->getConfigDependencyName();
}
}
}
}
}
return $dependencies;
}
/**
* {@inheritdoc}
*/
public static function onDependencyRemoval(FieldDefinitionInterface $field_definition, array $dependencies) {
$changed = FALSE;
if ($default_value = $field_definition
->getDefaultValueLiteral()) {
foreach ($default_value as $key => $value) {
if (is_array($value) && isset($value['target_uuid']) && isset($value['target_type'])) {
$entity = \Drupal::service('entity.repository')
->loadEntityByUuid($value['target_type'], $value['target_uuid']);
// @see \Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceFieldItemList::processDefaultValue()
if ($entity && isset($dependencies[$entity
->getConfigDependencyKey()][$entity
->getConfigDependencyName()])) {
unset($default_value[$key]);
$changed = TRUE;
}
}
}
if ($changed) {
$field_definition
->setDefaultValue($default_value);
}
}
$entity_type_manager = \Drupal::entityTypeManager();
// Update the 'target_bundles' handler setting if a bundle config dependency
// has been removed.
$settings = $field_definition
->getSettings();
foreach (static::getTargetTypes($settings) as $target_type) {
$bundles_changed = FALSE;
$handler_settings = $settings[$target_type]['handler_settings'];
if (!empty($handler_settings['target_bundles'])) {
$target_entity_type = $entity_type_manager
->getDefinition($target_type);
if ($bundle_entity_type_id = $target_entity_type
->getBundleEntityType()) {
if ($storage = $entity_type_manager
->getStorage($bundle_entity_type_id)) {
foreach ($storage
->loadMultiple($handler_settings['target_bundles']) as $bundle) {
if (isset($dependencies[$bundle
->getConfigDependencyKey()][$bundle
->getConfigDependencyName()])) {
unset($handler_settings['target_bundles'][$bundle
->id()]);
// If this bundle is also used in the 'auto_create_bundle'
// setting, disable the auto-creation feature completely.
$auto_create_bundle = !empty($handler_settings['auto_create_bundle']) ? $handler_settings['auto_create_bundle'] : FALSE;
if ($auto_create_bundle && $auto_create_bundle == $bundle
->id()) {
$handler_settings['auto_create'] = FALSE;
$handler_settings['auto_create_bundle'] = NULL;
}
$bundles_changed = TRUE;
// In case we deleted the only target bundle allowed by the
// field we have to log a critical message because the field
// will not function correctly anymore.
if ($handler_settings['target_bundles'] === []) {
\Drupal::logger('dynamic_entity_reference')
->critical('The %target_bundle bundle (entity type: %target_entity_type) was deleted. As a result, the %field_name dynamic entity reference field (entity_type: %entity_type, bundle: %bundle) no longer has any valid bundle it can reference. The field is not working correctly anymore and has to be adjusted.', [
'%target_bundle' => $bundle
->label(),
'%target_entity_type' => $bundle
->getEntityType()
->getBundleOf(),
'%field_name' => $field_definition
->getName(),
'%entity_type' => $field_definition
->getTargetEntityTypeId(),
'%bundle' => $field_definition
->getTargetBundle(),
]);
}
}
}
}
}
}
if ($bundles_changed) {
$settings[$target_type]['handler_settings'] = $handler_settings;
$field_definition
->setSettings($settings);
}
$changed |= $bundles_changed;
}
return $changed;
}
/**
* Helper function to get all the entity type ids that can be referenced.
*
* @param array $settings
* The settings of the field storage.
*
* @return string[]
* All the target entity type ids that can be referenced.
*/
public static function getTargetTypes(array $settings) {
$labels = \Drupal::service('entity_type.repository')
->getEntityTypeLabels(TRUE);
$options = array_filter(array_keys($labels[(string) t('Content', [], [
'context' => 'Entity type group',
])]), function ($entity_type_id) {
return static::entityHasIntegerId($entity_type_id);
});
if (!empty($settings['exclude_entity_types'])) {
return array_diff($options, $settings['entity_type_ids'] ?: []);
}
else {
return array_intersect($options, $settings['entity_type_ids'] ?: []);
}
}
/**
* Determines if an entity type has an integer-based ID definition.
*
* @param string $entity_type_id
* The ID the represents the entity type.
*
* @return bool
* Returns TRUE if the entity type has an integer-based ID definition and
* FALSE otherwise.
*/
public static function entityHasIntegerId($entity_type_id) {
$entity_type = \Drupal::entityTypeManager()
->getDefinition($entity_type_id);
// Make sure entity type is a content entity type.
if (!$entity_type instanceof ContentEntityTypeInterface) {
return FALSE;
}
// Make sure entity type has an id.
if (!$entity_type
->hasKey('id')) {
return FALSE;
}
/** @var \Drupal\Core\Field\FieldDefinitionInterface[] $field_definitions */
$field_definitions = \Drupal::service('entity_field.manager')
->getBaseFieldDefinitions($entity_type_id);
$entity_type_id_definition = $field_definitions[$entity_type
->getKey('id')];
return $entity_type_id_definition
->getType() === 'integer';
}
/**
* {@inheritdoc}
*/
public static function calculateStorageDependencies(FieldStorageDefinitionInterface $field_definition) {
$dependencies = FieldItemBase::calculateStorageDependencies($field_definition);
$entity_manager = \Drupal::entityTypeManager();
foreach (static::getTargetTypes($field_definition
->getSettings()) as $entity_type_id) {
if ($entity_manager
->hasDefinition($entity_type_id) && ($target_entity_type = $entity_manager
->getDefinition($entity_type_id))) {
$dependencies['module'][] = $target_entity_type
->getProvider();
}
}
return $dependencies;
}
/**
* {@inheritdoc}
*/
public static function getPreconfiguredOptions() {
$options = [];
// Add all the commonly referenced entity types as distinct pre-configured
// options.
$entity_types = \Drupal::entityTypeManager()
->getDefinitions();
$common_references = array_filter($entity_types, function (EntityTypeInterface $entity_type) {
return $entity_type
->isCommonReferenceTarget();
});
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
foreach ($common_references as $entity_type) {
$options[$entity_type
->id()] = [
'label' => $entity_type
->getLabel(),
'field_storage_config' => [
'settings' => [
'exclude_entity_types' => FALSE,
'entity_type_ids' => [
$entity_type
->id(),
],
],
],
];
}
return $options;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
DynamicEntityReferenceItem:: |
public static | function |
Calculates dependencies for field items. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function |
Calculates dependencies for field items on the storage level. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function |
Defines the field-level settings for this plugin. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function |
Defines the storage-level settings for this plugin. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function | Determines if an entity type has an integer-based ID definition. | |
DynamicEntityReferenceItem:: |
public | function |
Returns a form for the field-level settings. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function |
Form element validation handler; Stores the new values in the form state. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function |
Generates placeholder field values. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function |
Returns preconfigured field options for a field type. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public | function |
To select both target_type and target_id the option value is
changed from target_id to target_type-target_id. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function | Helper function to get all the entity type ids that can be referenced. | |
DynamicEntityReferenceItem:: |
public | function |
Gets the data value. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public | function |
Determines whether the data structure is empty. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function |
Returns the name of the main property, if any. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public | function |
React to changes to a child property or item. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function |
Informs the plugin that a dependency of the field will be deleted. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public | function |
Defines custom presave behavior for field values. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function |
Defines field item properties. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function |
Returns the schema for the field. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public | function |
Sets the data value. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public | function |
Returns a form for the storage-level settings. Overrides EntityReferenceItem:: |
|
DynamicEntityReferenceItem:: |
public static | function | Form element validation for storage settings. | |
DynamicEntityReferenceItem:: |
protected | function | Returns a form for single target type settings. | |
EntityReferenceItem:: |
public static | function | Render API callback: Processes the field settings form and allows access to the form state. | |
EntityReferenceItem:: |
public static | function | Adds entity_reference specific properties to AJAX form elements from the field settings form. | |
EntityReferenceItem:: |
public static | function | Render API callback: Moves entity_reference specific Form API elements (i.e. 'handler_settings') up a level for easier processing by the validation and submission handlers. | |
EntityReferenceItem:: |
public | function |
Gets a list of validation constraints. Overrides TypedData:: |
|
EntityReferenceItem:: |
public | function |
Returns an array of possible values with labels for display. Overrides OptionsProviderInterface:: |
|
EntityReferenceItem:: |
public | function |
Returns an array of possible values. Overrides OptionsProviderInterface:: |
|
EntityReferenceItem:: |
protected static | function | Gets a bundle for a given entity type and selection options. | |
EntityReferenceItem:: |
public | function |
Returns an array of settable values. Overrides OptionsProviderInterface:: |
|
EntityReferenceItem:: |
public | function | Determines whether the item holds an unsaved entity. | |
EntityReferenceItem:: |
public static | function | Ajax callback for the handler settings form. | |
EntityReferenceItem:: |
public static | function | Submit handler for the non-JS case. | |
FieldItemBase:: |
public | function |
Defines custom delete behavior for field values. Overrides FieldItemInterface:: |
2 |
FieldItemBase:: |
public | function |
Defines custom revision delete behavior for field values. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
public static | function |
Returns a settings array in the field type's canonical representation. Overrides FieldItemInterface:: |
1 |
FieldItemBase:: |
public static | function |
Returns a settings array that can be stored as a configuration value. Overrides FieldItemInterface:: |
1 |
FieldItemBase:: |
public | function |
Gets the entity that field belongs to. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
public | function |
Gets the field definition. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
public | function |
Gets the langcode of the field values held in the object. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
protected | function | Returns the value of a field setting. | |
FieldItemBase:: |
protected | function | Returns the array of field settings. | |
FieldItemBase:: |
public | function |
Defines custom post-save behavior for field values. Overrides FieldItemInterface:: |
2 |
FieldItemBase:: |
public static | function |
Returns a settings array in the field type's canonical representation. Overrides FieldItemInterface:: |
2 |
FieldItemBase:: |
public static | function |
Returns a settings array that can be stored as a configuration value. Overrides FieldItemInterface:: |
2 |
FieldItemBase:: |
public | function |
Returns a renderable array for a single field item. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
protected | function |
Different to the parent Map class, we avoid creating property objects as
far as possible in order to optimize performance. Thus we just update
$this->values if no property object has been created yet. Overrides Map:: |
|
FieldItemBase:: |
public | function |
Constructs a TypedData object given its definition and context. Overrides TypedData:: |
1 |
FieldItemBase:: |
public | function |
Magic method: Gets a property value. Overrides FieldItemInterface:: |
2 |
FieldItemBase:: |
public | function |
Magic method: Determines whether a property is set. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
public | function |
Magic method: Sets a property value. Overrides FieldItemInterface:: |
1 |
FieldItemBase:: |
public | function |
Magic method: Unsets a property. Overrides FieldItemInterface:: |
|
Map:: |
protected | property |
The data definition. Overrides TypedData:: |
|
Map:: |
protected | property | The array of properties. | |
Map:: |
protected | property | An array of values for the contained properties. | |
Map:: |
public | function |
Applies the default value. Overrides TypedData:: |
4 |
Map:: |
public | function |
Gets a property object. Overrides ComplexDataInterface:: |
|
Map:: |
public | function | ||
Map:: |
public | function |
Gets an array of property objects. Overrides ComplexDataInterface:: |
|
Map:: |
public | function |
Returns a string representation of the data. Overrides TypedData:: |
|
Map:: |
public | function |
Sets a property value. Overrides ComplexDataInterface:: |
|
Map:: |
public | function |
Returns an array of all property values. Overrides ComplexDataInterface:: |
1 |
Map:: |
public | function | Magic method: Implements a deep clone. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
TypedData:: |
protected | property | The property name. | |
TypedData:: |
protected | property | The parent typed data object. | |
TypedData:: |
public static | function |
Constructs a TypedData object given its definition and context. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Gets the data definition. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Returns the name of a property or item. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Returns the parent data structure; i.e. either complex data or a list. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
|
TypedData:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
TypedData:: |
public | function |
Returns the property path of the data. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Returns the root of the typed data tree. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Sets the context of a property or item via a context aware parent. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Validates the currently set data value. Overrides TypedDataInterface:: |
|
TypedDataTrait:: |
protected | property | The typed data manager used for creating the data types. | |
TypedDataTrait:: |
public | function | Gets the typed data manager. | 2 |
TypedDataTrait:: |
public | function | Sets the typed data manager. | 2 |