Commit ba2b8690 authored by alexpott's avatar alexpott

Issue #2275659 by fago, pgautam: Separate FieldableEntityInterface out of ContentEntityInterface.

parent 51a6720f
......@@ -12,22 +12,20 @@
/**
* Defines a common interface for all content entity objects.
*
* This interface builds upon the general interfaces provided by the typed data
* API, while extending them with content entity-specific additions. I.e., a
* content entity implements the ComplexDataInterface among others, thus is
* complex data containing fields as its data properties. The contained fields
* have to implement \Drupal\Core\Field\FieldItemListInterface,
* which builds upon typed data interfaces as well.
* Content entities use fields for all their entity properties and are
* translatable and revisionable, while translations and revisions can be
* enabled per entity type. It's best practice to always implement
* ContentEntityInterface for content-like entities that should be stored in
* some database, and enable/disable revisions and translations as desired.
*
* When implementing this interface which extends Traversable, make sure to list
* IteratorAggregate or Iterator before this interface in the implements clause.
*
* @see \Drupal\Core\TypedData\TypedDataManager
* @see \Drupal\Core\Field\FieldItemListInterface
* @see \Drupal\Core\Entity\ContentEntityBase
*
* @ingroup entity_api
*/
interface ContentEntityInterface extends \Traversable, EntityInterface, RevisionableInterface, TranslatableInterface {
interface ContentEntityInterface extends \Traversable, FieldableEntityInterface, RevisionableInterface, TranslatableInterface {
/**
* Marks the translation identified by the given language code as existing.
......@@ -40,181 +38,4 @@ interface ContentEntityInterface extends \Traversable, EntityInterface, Revision
*/
public function initTranslation($langcode);
/**
* Provides base field definitions for an entity type.
*
* Implementations typically use the class
* \Drupal\Core\Field\BaseFieldDefinition for creating the field definitions;
* for example a 'name' field could be defined as the following:
* @code
* $fields['name'] = BaseFieldDefinition::create('string')
* ->setLabel(t('Name'));
* @endcode
*
* By definition, base fields are fields that exist for every bundle. To
* provide definitions for fields that should only exist on some bundles, use
* \Drupal\Core\Entity\ContentEntityInterface::bundleFieldDefinitions().
*
* The definitions returned by this function can be overridden for all
* bundles by hook_entity_base_field_info_alter() or overridden on a
* per-bundle basis via 'base_field_override' configuration entities.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type definition. Useful when a single class is used for multiple,
* possibly dynamic entity types.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface[]
* An array of base field definitions for the entity type, keyed by field
* name.
*
* @see \Drupal\Core\Entity\EntityManagerInterface::getFieldDefinitions()
* @see \Drupal\Core\Entity\ContentEntityInterface::bundleFieldDefinitions()
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type);
/**
* Provides field definitions for a specific bundle.
*
* This function can return definitions both for bundle fields (fields that
* are not defined in $base_field_definitions, and therefore might not exist
* on some bundles) as well as bundle-specific overrides of base fields
* (fields that are defined in $base_field_definitions, and therefore exist
* for all bundles). However, bundle-specific base field overrides can also
* be provided by 'base_field_override' configuration entities, and that is
* the recommended approach except in cases where an entity type needs to
* provide a bundle-specific base field override that is decoupled from
* configuration. Note that for most entity types, the bundles themselves are
* derived from configuration (e.g., 'node' bundles are managed via
* 'node_type' configuration entities), so decoupling bundle-specific base
* field overrides from configuration only makes sense for entity types that
* also decouple their bundles from configuration. In cases where both this
* function returns a bundle-specific override of a base field and a
* 'base_field_override' configuration entity exists, the latter takes
* precedence.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type definition. Useful when a single class is used for multiple,
* possibly dynamic entity types.
* @param string $bundle
* The bundle.
* @param \Drupal\Core\Field\FieldDefinitionInterface[] $base_field_definitions
* The list of base field definitions.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface[]
* An array of bundle field definitions, keyed by field name.
*
* @see \Drupal\Core\Entity\EntityManagerInterface::getFieldDefinitions()
* @see \Drupal\Core\Entity\ContentEntityInterface::baseFieldDefinitions()
*
* @todo WARNING: This method will be changed in
* https://www.drupal.org/node/2346347.
*/
public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions);
/**
* Returns whether the entity has a field with the given name.
*
* @param string $field_name
* The field name.
*
* @return bool
* TRUE if the entity has a field with the given name. FALSE otherwise.
*/
public function hasField($field_name);
/**
* Gets the definition of a contained field.
*
* @param string $name
* The name of the field.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface|null
* The definition of the field or null if the field does not exist.
*/
public function getFieldDefinition($name);
/**
* Gets an array of field definitions of all contained fields.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface[]
* An array of field definitions, keyed by field name.
*
* @see \Drupal\Core\Entity\EntityManagerInterface::getFieldDefinitions()
*/
public function getFieldDefinitions();
/**
* Returns an array of all field values.
*
* Gets an array of plain field values, including only non-computed values.
* Note that the structure varies by entity type and bundle.
*
* @return array
* An array of field values, keyed by field name.
*/
public function toArray();
/**
* Gets a field item list.
*
* @param string $field_name
* The name of the field to get; e.g., 'title' or 'name'.
*
* @throws \InvalidArgumentException
* If an invalid field name is given.
*
* @return \Drupal\Core\Field\FieldItemListInterface
* The field item list, containing the field items.
*/
public function get($field_name);
/**
* Sets a field value.
*
* @param string $field_name
* The name of the field to set; e.g., 'title' or 'name'.
* @param mixed $value
* The value to set, or NULL to unset the field.
* @param bool $notify
* (optional) Whether to notify the entity of the change. Defaults to
* TRUE. If the update stems from the entity, set it to FALSE to avoid
* being notified again.
*
* @throws \InvalidArgumentException
* If the specified field does not exist.
*
* @return $this
*/
public function set($field_name, $value, $notify = TRUE);
/**
* Gets an array of field item lists.
*
* @param bool $include_computed
* If set to TRUE, computed fields are included. Defaults to FALSE.
*
* @return \Drupal\Core\Field\FieldItemListInterface[]
* An array of field item lists implementing, keyed by field name.
*/
public function getFields($include_computed = TRUE);
/**
* Reacts to changes to a field.
*
* Note that this is invoked after any changes have been applied.
*
* @param string $field_name
* The name of the field which is changed.
*/
public function onChange($field_name);
/**
* Validates the currently set values.
*
* @return \Symfony\Component\Validator\ConstraintViolationListInterface
* A list of constraint violations. If the list is empty, validation
* succeeded.
*/
public function validate();
}
......@@ -9,7 +9,7 @@
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -70,7 +70,7 @@ public function view(EntityInterface $_entity, $view_mode = 'full', $langcode =
// rendered title field formatter as the page title instead of the default
// plain text title. This allows attributes set on the field to propagate
// correctly (e.g. RDFa, in-place editing).
if ($_entity instanceof ContentEntityInterface) {
if ($_entity instanceof FieldableEntityInterface) {
$label_field = $_entity->getEntityType()->getKey('label');
if ($label_field && $_entity->getFieldDefinition($label_field)->getDisplayOptions('view')) {
// We must render the label field, because rendering the entity may be
......
......@@ -7,7 +7,7 @@
namespace Drupal\Core\Entity\Display;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Form\FormStateInterface;
/**
......@@ -86,7 +86,7 @@ interface EntityFormDisplayInterface extends EntityDisplayInterface {
* accessed by \Drupal\Core\Field\WidgetBaseInterface::getWidgetState() and
* \Drupal\Core\Field\WidgetBaseInterface::setWidgetState().
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity.
* @param array $form
* The form structure to fill in. This can be a full form structure, or a
......@@ -98,7 +98,7 @@ interface EntityFormDisplayInterface extends EntityDisplayInterface {
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
public function buildForm(ContentEntityInterface $entity, array &$form, FormStateInterface $form_state);
public function buildForm(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state);
/**
* Validates submitted widget values and sets the corresponding form errors.
......@@ -119,7 +119,7 @@ public function buildForm(ContentEntityInterface $entity, array &$form, FormStat
* It reports field constraint violations as form errors on the correct form
* elements.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity.
* @param array $form
* The form structure where field elements are attached to. This might be a
......@@ -127,7 +127,7 @@ public function buildForm(ContentEntityInterface $entity, array &$form, FormStat
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
public function validateFormValues(ContentEntityInterface $entity, array &$form, FormStateInterface $form_state);
public function validateFormValues(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state);
/**
* Extracts field values from the submitted widget values into the entity.
......@@ -135,7 +135,7 @@ public function validateFormValues(ContentEntityInterface $entity, array &$form,
* This accounts for drag-and-drop reordering of field values, and filtering
* of empty values.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity.
* @param array $form
* The form structure where field elements are attached to. This might be a
......@@ -149,6 +149,6 @@ public function validateFormValues(ContentEntityInterface $entity, array &$form,
* if any, do not correspond to widgets and should be extracted manually by
* the caller if needed.
*/
public function extractFormValues(ContentEntityInterface $entity, array &$form, FormStateInterface $form_state);
public function extractFormValues(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state);
}
......@@ -7,7 +7,7 @@
namespace Drupal\Core\Entity\Display;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
/**
* Provides a common interface for entity view displays.
......@@ -19,7 +19,7 @@ interface EntityViewDisplayInterface extends EntityDisplayInterface {
*
* See the buildMultiple() method for details.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity being displayed.
*
* @return array
......@@ -27,7 +27,7 @@ interface EntityViewDisplayInterface extends EntityDisplayInterface {
*
* @see \Drupal\Core\Entity\Display\EntityViewDisplayInterface::buildMultiple()
*/
public function build(ContentEntityInterface $entity);
public function build(FieldableEntityInterface $entity);
/**
* Returns a renderable array for the components of a set of entities.
......@@ -40,7 +40,7 @@ public function build(ContentEntityInterface $entity);
* hook_entity_display_build_alter() is invoked on each entity, allowing 3rd
* party code to alter the render array.
*
* @param \Drupal\Core\Entity\ContentEntityInterface[] $entities
* @param \Drupal\Core\Entity\FieldableEntityInterface[] $entities
* The entities being displayed.
*
* @return array
......
......@@ -7,7 +7,7 @@
namespace Drupal\Core\Entity\Entity;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\EntityDisplayBase;
use Drupal\Core\Form\FormStateInterface;
......@@ -50,7 +50,7 @@ class EntityFormDisplay extends EntityDisplayBase implements EntityFormDisplayIn
* party code to alter the display options held in the display before they are
* used to generate render arrays.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity for which the form is being built.
* @param string $form_mode
* The form mode.
......@@ -61,7 +61,7 @@ class EntityFormDisplay extends EntityDisplayBase implements EntityFormDisplayIn
* @see entity_get_form_display()
* @see hook_entity_form_display_alter()
*/
public static function collectRenderDisplay(ContentEntityInterface $entity, $form_mode) {
public static function collectRenderDisplay(FieldableEntityInterface $entity, $form_mode) {
$entity_type = $entity->getEntityTypeId();
$bundle = $entity->bundle();
......@@ -148,7 +148,7 @@ public function getRenderer($field_name) {
/**
* {@inheritdoc}
*/
public function buildForm(ContentEntityInterface $entity, array &$form, FormStateInterface $form_state) {
public function buildForm(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state) {
// Set #parents to 'top-level' by default.
$form += array('#parents' => array());
......@@ -197,7 +197,7 @@ public function processForm($element, FormStateInterface $form_state, $form) {
/**
* {@inheritdoc}
*/
public function extractFormValues(ContentEntityInterface $entity, array &$form, FormStateInterface $form_state) {
public function extractFormValues(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state) {
$extracted = array();
foreach ($entity as $name => $items) {
if ($widget = $this->getRenderer($name)) {
......@@ -211,7 +211,7 @@ public function extractFormValues(ContentEntityInterface $entity, array &$form,
/**
* {@inheritdoc}
*/
public function validateFormValues(ContentEntityInterface $entity, array &$form, FormStateInterface $form_state) {
public function validateFormValues(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state) {
foreach ($entity as $field_name => $items) {
// Only validate the fields that actually appear in the form, and let the
// widget assign the violations to the right form elements.
......
......@@ -9,7 +9,7 @@
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\EntityDisplayBase;
/**
......@@ -50,7 +50,7 @@ class EntityViewDisplay extends EntityDisplayBase implements EntityViewDisplayIn
* party code to alter the display options held in the display before they are
* used to generate render arrays.
*
* @param \Drupal\Core\Entity\ContentEntityInterface[] $entities
* @param \Drupal\Core\Entity\FieldableEntityInterface[] $entities
* The entities being rendered. They should all be of the same entity type.
* @param string $view_mode
* The view mode being rendered.
......@@ -142,7 +142,7 @@ public static function collectRenderDisplays($entities, $view_mode) {
*
* See the collectRenderDisplays() method for details.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity being rendered.
* @param string $view_mode
* The view mode.
......@@ -152,7 +152,7 @@ public static function collectRenderDisplays($entities, $view_mode) {
*
* @see \Drupal\entity\Entity\EntityDisplay::collectRenderDisplays()
*/
public static function collectRenderDisplay(ContentEntityInterface $entity, $view_mode) {
public static function collectRenderDisplay(FieldableEntityInterface $entity, $view_mode) {
$displays = static::collectRenderDisplays(array($entity), $view_mode);
return $displays[$entity->bundle()];
}
......@@ -196,7 +196,7 @@ public function getRenderer($field_name) {
/**
* {@inheritdoc}
*/
public function build(ContentEntityInterface $entity) {
public function build(FieldableEntityInterface $entity) {
$build = $this->buildMultiple(array($entity));
return $build[0];
}
......
......@@ -115,7 +115,7 @@ public function __construct(array $values, $entity_type) {
throw new \InvalidArgumentException('Missing required properties for an EntityDisplay entity.');
}
if (!$this->entityManager()->getDefinition($values['targetEntityType'])->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')) {
if (!$this->entityManager()->getDefinition($values['targetEntityType'])->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) {
throw new \InvalidArgumentException('EntityDisplay entities can only handle content entity types.');
}
......@@ -357,7 +357,7 @@ protected function getFieldDefinition($field_name) {
protected function getFieldDefinitions() {
// Entity displays are sometimes created for non-content entities.
// @todo Prevent this in https://drupal.org/node/2095195.
if (!\Drupal::entityManager()->getDefinition($this->targetEntityType)->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')) {
if (!\Drupal::entityManager()->getDefinition($this->targetEntityType)->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) {
return array();
}
......
......@@ -11,6 +11,8 @@
/**
* Defines a common interface for all entity objects.
*
* @ingroup entity_api
*/
interface EntityInterface extends AccessibleInterface {
......
......@@ -353,7 +353,7 @@ public function getBaseFieldDefinitions($entity_type_id) {
*
* @param string $entity_type_id
* The entity type ID. Only entity types that implement
* \Drupal\Core\Entity\ContentEntityInterface are supported.
* \Drupal\Core\Entity\FieldableEntityInterface are supported.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface[]
* An array of field definitions, keyed by field name.
......@@ -366,8 +366,8 @@ protected function buildBaseFieldDefinitions($entity_type_id) {
$entity_type = $this->getDefinition($entity_type_id);
$class = $entity_type->getClass();
// Fail with an exception for config entity types.
if (!$entity_type->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')) {
// Fail with an exception for non-fieldable entity types.
if (!$entity_type->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) {
throw new \LogicException(String::format('Getting the base fields is not supported for entity type @type.', array('@type' => $entity_type->getLabel())));
}
......@@ -456,7 +456,7 @@ public function getFieldDefinitions($entity_type_id, $bundle) {
*
* @param string $entity_type_id
* The entity type ID. Only entity types that implement
* \Drupal\Core\Entity\ContentEntityInterface are supported.
* \Drupal\Core\Entity\FieldableEntityInterface are supported.
* @param string $bundle
* The bundle.
* @param \Drupal\Core\Field\FieldDefinitionInterface[] $base_field_definitions
......@@ -568,7 +568,7 @@ public function getFieldMap() {
else {
// Rebuild the definitions and put it into the cache.
foreach ($this->getDefinitions() as $entity_type_id => $entity_type) {
if ($entity_type->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')) {
if ($entity_type->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) {
foreach ($this->getBundleInfo($entity_type_id) as $bundle => $bundle_info) {
foreach ($this->getFieldDefinitions($entity_type_id, $bundle) as $field_name => $field_definition) {
$this->fieldMap[$entity_type_id][$field_name]['type'] = $field_definition->getType();
......@@ -608,7 +608,7 @@ public function getFieldMapByFieldType($field_type) {
*
* @param string $entity_type_id
* The entity type ID. Only entity types that implement
* \Drupal\Core\Entity\ContentEntityInterface are supported
* \Drupal\Core\Entity\FieldableEntityInterface are supported
*
* @return \Drupal\Core\Field\FieldStorageDefinitionInterface[]
* An array of field storage definitions, keyed by field name.
......@@ -987,7 +987,7 @@ public function onEntityTypeCreate(EntityTypeInterface $entity_type) {
}
$this->setLastInstalledDefinition($entity_type);
if ($entity_type->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')) {
if ($entity_type->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) {
$this->setLastInstalledFieldStorageDefinitions($entity_type_id, $this->getFieldStorageDefinitions($entity_type_id));
}
}
......
......@@ -36,7 +36,7 @@ public function getEntityTypeLabels($group = FALSE);
*
* @param string $entity_type_id
* The entity type ID. Only entity types that implement
* \Drupal\Core\Entity\ContentEntityInterface are supported.
* \Drupal\Core\Entity\FieldableEntityInterface are supported.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface[]
* The array of base field definitions for the entity type, keyed by field
......@@ -52,7 +52,7 @@ public function getBaseFieldDefinitions($entity_type_id);
*
* @param string $entity_type_id
* The entity type ID. Only entity types that implement
* \Drupal\Core\Entity\ContentEntityInterface are supported.
* \Drupal\Core\Entity\FieldableEntityInterface are supported.
* @param string $bundle
* The bundle.
*
......
......@@ -247,7 +247,7 @@ public function buildMultiple(array $build_list) {
foreach ($children as $key) {
if (isset($build_list[$key][$entity_type_key])) {
$entity = $build_list[$key][$entity_type_key];
if ($entity instanceof ContentEntityInterface) {
if ($entity instanceof FieldableEntityInterface) {
$view_modes[$build_list[$key]['#view_mode']][$key] = $entity;
}
}
......
<?php
/**
* @file
* Contains \Drupal\Core\Entity\FieldableEntityInterface.
*/
namespace Drupal\Core\Entity;
use Drupal\Core\TypedData\ComplexDataInterface;
/**
* Interface for entities having fields.
*
* This interface builds upon the general interfaces provided by the typed data
* API, while extending them with entity-specific additions. I.e., fieldable
* entities implement the ComplexDataInterface among others, thus it is complex
* data containing fields as its data properties. The contained fields have to
* implement \Drupal\Core\Field\FieldItemListInterface, which builds upon typed
* data interfaces as well.
*
* When implementing this interface which extends Traversable, make sure to list
* IteratorAggregate or Iterator before this interface in the implements clause.
*
* @see \Drupal\Core\TypedData\TypedDataManager
* @see \Drupal\Core\Field\FieldItemListInterface
*
* @ingroup entity_api
*/
interface FieldableEntityInterface extends EntityInterface {
/**
* Provides base field definitions for an entity type.
*
* Implementations typically use the class
* \Drupal\Core\Field\BaseFieldDefinition for creating the field definitions;
* for example a 'name' field could be defined as the following:
* @code
* $fields['name'] = BaseFieldDefinition::create('string')
* ->setLabel(t('Name'));
* @endcode
*
* By definition, base fields are fields that exist for every bundle. To
* provide definitions for fields that should only exist on some bundles, use
* \Drupal\Core\Entity\FieldableEntityInterface::bundleFieldDefinitions().
*
* The definitions returned by this function can be overridden for all
* bundles by hook_entity_base_field_info_alter() or overridden on a
* per-bundle basis via 'base_field_override' configuration entities.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type definition. Useful when a single class is used for multiple,
* possibly dynamic entity types.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface[]
* An array of base field definitions for the entity type, keyed by field
* name.
*
* @see \Drupal\Core\Entity\EntityManagerInterface::getFieldDefinitions()
* @see \Drupal\Core\Entity\FieldableEntityInterface::bundleFieldDefinitions()
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type);
/**
* Provides field definitions for a specific bundle.
*
* This function can return definitions both for bundle fields (fields that
* are not defined in $base_field_definitions, and therefore might not exist
* on some bundles) as well as bundle-specific overrides of base fields
* (fields that are defined in $base_field_definitions, and therefore exist
* for all bundles). However, bundle-specific base field overrides can also
* be provided by 'base_field_override' configuration entities, and that is
* the recommended approach except in cases where an entity type needs to
* provide a bundle-specific base field override that is decoupled from
* configuration. Note that for most entity types, the bundles themselves are
* derived from configuration (e.g., 'node' bundles are managed via
* 'node_type' configuration entities), so decoupling bundle-specific base
* field overrides from configuration only makes sense for entity types that
* also decouple their bundles from configuration. In cases where both this
* function returns a bundle-specific override of a base field and a
* 'base_field_override' configuration entity exists, the latter takes
* precedence.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type definition. Useful when a single class is used for multiple,
* possibly dynamic entity types.
* @param string $bundle
* The bundle.
* @param \Drupal\Core\Field\FieldDefinitionInterface[] $base_field_definitions
* The list of base field definitions.
*
* @return \Drupal\Core\Field\Fi