Commit 7a6fb338 authored by alexpott's avatar alexpott

Issue #2114707 by Berdir, yched, amateescu, effulgentsia, fago: Allow...

Issue #2114707 by Berdir, yched, amateescu, effulgentsia, fago: Allow per-bundle overrides of field definitions.
parent eeefed73
......@@ -213,9 +213,7 @@ public function preSaveRevision(EntityStorageControllerInterface $storage_contro
*/
public function getDataDefinition() {
$definition = EntityDataDefinition::create($this->getEntityTypeId());
if ($this->bundle() != $this->getEntityTypeId()) {
$definition->setBundles(array($this->bundle()));
}
$definition->setBundles(array($this->bundle()));
return $definition;
}
......@@ -485,8 +483,7 @@ public function getFieldDefinition($name) {
*/
public function getFieldDefinitions() {
if (!isset($this->fieldDefinitions)) {
$bundle = $this->bundle != $this->entityTypeId ? $this->bundle : NULL;
$this->fieldDefinitions = \Drupal::entityManager()->getFieldDefinitions($this->entityTypeId, $bundle);
$this->fieldDefinitions = \Drupal::entityManager()->getFieldDefinitions($this->entityTypeId, $this->bundle());
}
return $this->fieldDefinitions;
}
......@@ -987,4 +984,11 @@ public function referencedEntities() {
return $referenced_entities;
}
/**
* {@inheritdoc}
*/
public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
return array();
}
}
......@@ -40,7 +40,7 @@ interface ContentEntityInterface extends EntityInterface, RevisionableInterface,
public function initTranslation($langcode);
/**
* Defines the base fields of the entity type.
* Provides base field definitions for an entity type.
*
* Implementations typically use the class \Drupal\Core\Field\FieldDefinition
* for creating the field definitions; for example a 'name' field could be
......@@ -50,16 +50,47 @@ public function initTranslation($langcode);
* ->setLabel(t('Name'));
* @endcode
*
* @param string $entity_type
* The entity type to return properties for. Useful when a single class is
* used for multiple, possibly dynamic entity types.
* If some elements in a field definition need to vary by bundle, use
* \Drupal\Core\Entity\ContentEntityInterface::bundleFieldDefinitions().
*
* @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 or alters field definitions for a specific bundle.
*
* The field definitions returned here for the bundle take precedence on the
* base field definitions specified by baseFieldDefinitions() for the entity
* type.
*
* @todo Provide a better DX for field overrides.
* See https://drupal.org/node/2145115.
*
* @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 entity field definitions, keyed by field name.
* An array of bundle field definitions, keyed by field name.
*
* @see \Drupal\Core\Entity\EntityManagerInterface::getFieldDefinitions()
* @see \Drupal\Core\Entity\ContentEntityInterface::baseFieldDefinitions()
*/
public static function baseFieldDefinitions($entity_type);
public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions);
/**
* Returns whether the entity has a field with the given name.
......
......@@ -23,23 +23,38 @@ interface EntityManagerInterface extends PluginManagerInterface {
public function getEntityTypeLabels();
/**
* Gets an array of content entity field definitions.
* Gets the base field definitions for a content entity type.
*
* If a bundle is passed, fields specific to this bundle are included.
* Only fields that are not specific to a given bundle or set of bundles are
* returned. This excludes configurable fields, as they are always attached
* to a specific bundle.
*
* @param string $entity_type_id
* The entity type to get field definitions for. Only entity types that
* implement \Drupal\Core\Entity\ContentEntityInterface are supported.
* @param string $bundle
* (optional) The entity bundle for which to get field definitions. If NULL
* is passed, no bundle-specific fields are included. Defaults to NULL.
* The entity type ID. Only entity types that implement
* \Drupal\Core\Entity\ContentEntityInterface are supported.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface[]
* An array of entity field definitions, keyed by field name.
* The array of base field definitions for the entity type, keyed by field
* name.
*
* @throws \LogicException
* Thrown if one of the entity keys is flagged as translatable.
*/
public function getBaseFieldDefinitions($entity_type_id);
/**
* Gets the field definitions for a specific bundle.
*
* @see \Drupal\Core\TypedData\TypedDataManager::create()
* @param string $entity_type_id
* The entity type ID. Only entity types that implement
* \Drupal\Core\Entity\ContentEntityInterface are supported.
* @param string $bundle
* The bundle.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface[]
* The array of field definitions for the bundle, keyed by field name.
*/
public function getFieldDefinitions($entity_type_id, $bundle = NULL);
public function getFieldDefinitions($entity_type_id, $bundle);
/**
* Creates a new access controller instance.
......
......@@ -268,7 +268,7 @@ protected function attachPropertyData(array &$entities) {
}
$data = $query->execute();
$field_definitions = \Drupal::entityManager()->getFieldDefinitions($this->entityTypeId);
$field_definitions = \Drupal::entityManager()->getBaseFieldDefinitions($this->entityTypeId);
$translations = array();
if ($this->revisionDataTable) {
$data_column_names = array_flip(array_diff(drupal_schema_fields_sql($this->entityType->getRevisionDataTable()), drupal_schema_fields_sql($this->entityType->getBaseTable())));
......@@ -1187,7 +1187,7 @@ public static function _fieldSqlSchema(FieldConfigInterface $field, array $schem
$entity_type_id = $field->entity_type;
$entity_manager = \Drupal::entityManager();
$entity_type = $entity_manager->getDefinition($entity_type_id);
$definitions = $entity_manager->getFieldDefinitions($entity_type_id);
$definitions = $entity_manager->getBaseFieldDefinitions($entity_type_id);
// Define the entity ID schema based on the field definitions.
$id_definition = $definitions[$entity_type->getKey('id')];
......
......@@ -60,8 +60,12 @@ public function getPropertyDefinitions() {
// @todo: Add support for handling multiple bundles.
// See https://drupal.org/node/2169813.
$bundles = $this->getBundles();
$bundle = is_array($bundles) && count($bundles) == 1 ? reset($bundles) : NULL;
$this->propertyDefinitions = \Drupal::entityManager()->getFieldDefinitions($entity_type_id, $bundle);
if (is_array($bundles) && count($bundles) == 1) {
$this->propertyDefinitions = \Drupal::entityManager()->getFieldDefinitions($entity_type_id, reset($bundles));
}
else {
$this->propertyDefinitions = \Drupal::entityManager()->getBaseFieldDefinitions($entity_type_id);
}
}
else {
// No entity type given.
......
......@@ -7,60 +7,16 @@
namespace Drupal\Core\Field;
use Drupal\field\FieldInstanceConfigInterface;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\field\Field;
/**
* Represents a configurable entity field item list.
*/
class ConfigFieldItemList extends FieldItemList implements ConfigFieldItemListInterface {
/**
* The Field instance definition.
*
* @var \Drupal\field\FieldInstanceConfigInterface
*/
protected $instance;
/**
* {@inheritdoc}
*/
public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) {
parent::__construct($definition, $name, $parent);
// Definition can be the field config or field instance.
if ($definition instanceof FieldInstanceConfigInterface) {
$this->instance = $definition;
}
}
/**
* {@inheritdoc}
*/
public function getFieldDefinition() {
// Configurable fields have the field_config entity injected as definition,
// but we want to return the more specific field instance here.
// @todo: Overhaul this once we have per-bundle field definitions injected,
// see https://drupal.org/node/2114707.
if (!isset($this->instance)) {
$entity = $this->getEntity();
$instances = Field::fieldInfo()->getBundleInstances($entity->getEntityTypeId(), $entity->bundle());
if (isset($instances[$this->getName()])) {
$this->instance = $instances[$this->getName()];
}
else {
// For base fields, fall back to return the general definition.
return parent::getFieldDefinition();
}
}
return $this->instance;
}
/**
* {@inheritdoc}
*/
public function getConstraints() {
$constraints = array();
$constraints = parent::getConstraints();
// Check that the number of values doesn't exceed the field cardinality. For
// form submitted values, this can only happen with 'multiple value'
// widgets.
......
......@@ -437,4 +437,13 @@ public function getConstraints(DataDefinitionInterface $definition) {
return $constraints;
}
/**
* {@inheritdoc}
*/
public function clearCachedDefinitions() {
parent::clearCachedDefinitions();
$this->prototypes = array();
}
}
......@@ -8,6 +8,7 @@
namespace Drupal\aggregator\Entity;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldDefinition;
use Symfony\Component\DependencyInjection\Container;
use Drupal\Core\Entity\EntityStorageControllerInterface;
......@@ -120,7 +121,7 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions($entity_type) {
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['fid'] = FieldDefinition::create('integer')
->setLabel(t('Feed ID'))
->setDescription(t('The ID of the aggregator feed.'))
......
......@@ -10,6 +10,7 @@
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\aggregator\ItemInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldDefinition;
/**
......@@ -60,7 +61,7 @@ public function postCreate(EntityStorageControllerInterface $storage_controller)
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions($entity_type) {
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['iid'] = FieldDefinition::create('integer')
->setLabel(t('Aggregator item ID'))
->setDescription(t('The ID of the feed item.'))
......
......@@ -9,6 +9,7 @@
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldDefinition;
use Drupal\custom_block\CustomBlockInterface;
......@@ -163,7 +164,7 @@ public function delete() {
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions($entity_type) {
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['id'] = FieldDefinition::create('integer')
->setLabel(t('Custom block ID'))
->setDescription(t('The custom block ID.'))
......
......@@ -11,6 +11,7 @@
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\comment\CommentInterface;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldDefinition;
use Drupal\Core\Language\Language;
use Drupal\Core\TypedData\DataDefinition;
......@@ -210,7 +211,7 @@ public function permalink() {
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions($entity_type) {
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['cid'] = FieldDefinition::create('integer')
->setLabel(t('Comment ID'))
->setDescription(t('The comment ID.'))
......
......@@ -69,6 +69,7 @@ public function testValidation() {
'entity_id' => $node->id(),
'entity_type' => 'node',
'field_name' => 'comment',
'comment_body' => $this->randomName(),
));
$violations = $comment->validate();
......
......@@ -9,6 +9,7 @@
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\contact\MessageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldDefinition;
/**
......@@ -139,7 +140,7 @@ public function getPersonalRecipient() {
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions($entity_type) {
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['category'] = FieldDefinition::create('entity_reference')
->setLabel(t('Category ID'))
->setDescription(t('The ID of the associated category.'))
......
......@@ -9,6 +9,8 @@
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityFormControllerInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldDefinition;
use Drupal\Core\Language\Language;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\TranslatableInterface;
......@@ -143,27 +145,23 @@ function content_translation_entity_bundle_info_alter(&$bundles) {
}
/**
* Implements hook_entity_field_info_alter().
* Implements hook_entity_base_field_info_alter().
*/
function content_translation_entity_field_info_alter(&$info, $entity_type) {
$translation_settings = \Drupal::config('content_translation.settings')->get($entity_type);
function content_translation_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
$translation_settings = \Drupal::config('content_translation.settings')->get($entity_type->id());
if ($translation_settings) {
// Currently field translatability is defined per-field but we may want to
// make it per-instance instead, so leaving the possibility open for further
// easier refactoring.
$fields = array();
// make it per-instance instead. In that case, we will need to implement
// hook_bundle_field_info_alter() instead.
$field_settings = array();
foreach ($translation_settings as $bundle => $settings) {
$fields += !empty($settings['content_translation']['fields']) ? $settings['content_translation']['fields'] : array();
$field_settings += !empty($settings['content_translation']['fields']) ? $settings['content_translation']['fields'] : array();
}
$keys = array('definitions', 'optional');
foreach ($fields as $name => $translatable) {
foreach ($keys as $key) {
if (isset($info[$key][$name])) {
$info[$key][$name]->setTranslatable((bool) $translatable);
break;
}
foreach ($field_settings as $name => $translatable) {
if (isset($fields[$name]) && $fields[$name] instanceof FieldDefinition) {
$fields[$name]->setTranslatable((bool) $translatable);
}
}
}
......
......@@ -10,7 +10,6 @@
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldDefinition;
use Drupal\Core\Entity\Display\EntityDisplayInterface;
/**
......@@ -325,20 +324,14 @@ protected function getFieldDefinition($field_name) {
* Returns the definitions of the fields that are candidate for display.
*/
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')) {
return array();
}
if (!isset($this->fieldDefinitions)) {
// @todo Replace this with \Drupal::entityManager()->getFieldDefinition()
// when it can hand the $instance objects (and then reconsider the
// $this->fieldDefinitions static cache ?)
// https://drupal.org/node/2114707
$entity_manager = \Drupal::entityManager();
$entity_type = $entity_manager->getDefinition($this->targetEntityType);
$definitions = array();
if ($entity_type->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')) {
$entity = _field_create_entity_from_ids((object) array('entity_type' => $this->targetEntityType, 'bundle' => $this->bundle, 'entity_id' => NULL));
foreach ($entity as $field_name => $items) {
$definitions[$field_name] = $items->getFieldDefinition();
}
}
$definitions = \Drupal::entityManager()->getFieldDefinitions($this->targetEntityType, $this->bundle);
// The display only cares about fields that specify display options.
// Discard base fields that are not rendered through formatters / widgets.
......
......@@ -23,14 +23,14 @@ class EntityReferenceAutocompleteTest extends EntityUnitTestBase {
*
* @var string
*/
protected $entityType = 'entity_test_label';
protected $entityType = 'entity_test';
/**
* The bundle used in this test.
*
* @var string
*/
protected $bundle = 'entity_test_label';
protected $bundle = 'entity_test';
/**
* The name of the field used in this test.
......
......@@ -124,31 +124,18 @@ function field_invoke_method($method, $target_function, EntityInterface $entity,
* @param $options
* An associative array of options, as provided to field_invoke_method(). Only
* the following keys are considered:
* - deleted
* - field_name
* - field_id
* See field_invoke_method() for details.
*
* @return
* The array of selected field definitions.
*/
function _field_invoke_get_field_definitions($entity_type, $bundle, $options) {
// @todo Replace with \Drupal::entityManager()->getFieldDefinition() after
// [#2047229] lands.
$entity = _field_create_entity_from_ids((object) array('entity_type' => $entity_type, 'bundle' => $bundle, 'entity_id' => NULL));
$field_definitions = array();
$definitions = \Drupal::entityManager()->getFieldDefinitions($entity_type, $bundle);
if (isset($options['field_name'])) {
if ($entity->hasField($options['field_name'])) {
$field_definitions[] = $entity->get($options['field_name'])->getFieldDefinition();
}
}
else {
foreach ($entity as $items) {
$field_definitions[] = $items->getFieldDefinition();
}
$definitions = array_intersect_key($definitions, array($options['field_name'] => TRUE));
}
return $field_definitions;
return $definitions;
}
/**
......
......@@ -7,8 +7,10 @@
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Template\Attribute;
use Drupal\entity\Entity\EntityViewDisplay;
use Drupal\field\Field;
/*
* Load all public Field API functions. Drupal currently has no
......@@ -189,29 +191,14 @@ function field_system_info_alter(&$info, $file, $type) {
}
/**
* Implements hook_entity_field_info() to define all configured fields.
* Implements hook_entity_bundle_field_info().
*/
function field_entity_field_info($entity_type) {
$property_info = array();
foreach (field_info_instances($entity_type) as $bundle_name => $instances) {
$optional = $bundle_name != $entity_type;
// @todo: Improve hook_entity_field_info() to allow per-bundle field
// definitions, such that we can pass on field instances as field
// definitions here. See https://drupal.org/node/2114707.
foreach ($instances as $field_name => $instance) {
if ($optional) {
$property_info['optional'][$field_name] = $instance->getField();
$property_info['bundle map'][$bundle_name][] = $field_name;
}
else {
$property_info['definitions'][$field_name] = $instance->getField();
}
}
function field_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
if ($entity_type->isFieldable()) {
// Configurable fields, which are always attached to a specific bundle, are
// added 'by bundle'.
return Field::fieldInfo()->getBundleInstances($entity_type->id(), $bundle);
}
return $property_info;
}
/**
......
......@@ -162,7 +162,7 @@ function testEntityDisplayViewMultiple() {
// Create two entities.
$entity1 = entity_create('entity_test', array('id' => 1, 'type' => 'entity_test'));
$entity1->{$this->field_name}->setValue($this->_generateTestFieldValues(1));
$entity2 = entity_create('entity_test', array('id' => 2, 'type' => 'test_bundle'));
$entity2 = entity_create('entity_test', array('id' => 2, 'type' => 'entity_test'));
$entity2->{$this->field_name}->setValue($this->_generateTestFieldValues(1));
// Run buildMultiple(), and check that the entities come out as expected.
......
......@@ -104,17 +104,8 @@ public function getRegions() {
* The array of field definitions
*/
protected function getFieldDefinitions() {
// @todo Replace this entire implementation with
// \Drupal::entityManager()->getFieldDefinition() when it can hand the
// $instance objects - https://drupal.org/node/2114707
$entity = _field_create_entity_from_ids((object) array('entity_type' => $this->entity_type, 'bundle' => $this->bundle, 'entity_id' => NULL));
$field_definitions = array();
foreach ($entity as $field_name => $items) {
$field_definitions[$field_name] = $items->getFieldDefinition();
}
$context = $this->displayContext;
return array_filter($field_definitions, function(FieldDefinitionInterface $field_definition) use ($context) {
return array_filter($this->entityManager->getFieldDefinitions($this->entity_type, $this->bundle), function(FieldDefinitionInterface $field_definition) use ($context) {
return $field_definition->isDisplayConfigurable($context);
});
}
......
......@@ -9,6 +9,7 @@
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldDefinition;
use Drupal\Core\Language\Language;
use Drupal\file\FileInterface;
......@@ -240,7 +241,7 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions($entity_type) {
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['fid'] = FieldDefinition::create('integer')
->setLabel(t('File ID'))
->setDescription(t('The file ID.'))
......
......@@ -9,6 +9,7 @@
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldDefinition;
use Drupal\Core\Language\Language;
use Drupal\Core\Session\AccountInterface;
......@@ -351,7 +352,7 @@ public function setRevisionAuthorId($uid) {
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions($entity_type) {
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['nid'] = FieldDefinition::create('integer')
->setLabel(t('Node ID'))
->setDescription(t('The node ID.'))
......@@ -378,11 +379,8 @@ public static function baseFieldDefinitions($entity_type) {
->setDescription(t('The node language code.'));
$fields['title'] = FieldDefinition::create('text')
// @todo Account for $node_type->title_label when per-bundle overrides are
// possible - https://drupal.org/node/2114707.
->setLabel(t('Title'))
->setDescription(t('The title of this node, always treated as non-markup plain text.'))
->setClass('\Drupal\node\NodeTitleItemList')
->setRequired(TRUE)
->setTranslatable(TRUE)
->setSettings(array(
......@@ -451,4 +449,17 @@ public static function baseFieldDefinitions($entity_type) {
return $fields;
}
/**
* {@inheritdoc}
*/
public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
$node_type = node_type_load($bundle);
$fields = array();
if (isset($node_type->title_label)) {
$fields['title'] = clone $base_field_definitions['title'];
$fields['title']->setLabel($node_type->title_label);
}
return $fields;
}
}
<?php
/**
* @file
* Contains \Drupal\node\NodeTitleItemList.
*/
namespace Drupal\node;
use Drupal\Core\Field\FieldDefinition;
use Drupal\Core\Field\FieldItemList;
/**
* @todo This class is a temporary hack for allowing the label of the node title
* field to vary by node type. Remove it when https://drupal.org/node/2114707
* is solved.
*/
class NodeTitleItemList extends FieldItemList {
/**
* {@inheritdoc}
*
* The typehint for $definition is a class rather than an interface, because
* there is no interface for setLabel().
*/
public function __construct(FieldDefinition $definition, $name, NodeInterface $node) {
$node_type = node_type_load($node->getType());
if (isset($node_type->title_label)) {
$definition->setLabel($node_type->title_label);
}
parent::__construct($definition, $name, $node);
}
}
......@@ -9,6 +9,7 @@
* a special 'node test view' permission.
*/
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldDefinition;
use Drupal\node\NodeInterface;
......@@ -78,15 +79,15 @@ function node_access_test_permission() {
}
/**
* Implements hook_entity_field_info().
* Implements hook_entity_base_field_info().
*/
function node_access_test_entity_field_info($entity_type) {
if ($entity_type === 'node') {
$info['definitions']['private'] = FieldDefinition::create('boolean')
->setLabel(t('Private'))
->setComputed(TRUE);
function node_access_test_entity_base_field_info(EntityTypeInterface $entity_type) {
if ($entity_type->id() === 'node') {
$fields['private'] = FieldDefinition::create('boolean')
->setLabel(t('Private'))
->setComputed(TRUE);
return $info;
return $fields;
}