diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index 5300dc8..4c8fe24 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -478,6 +478,62 @@ protected function buildBundleFieldDefinitions($entity_type_id, $bundle, array $ /** * {@inheritdoc} */ + public function getStorageFieldDefinitions($entity_type_id) { + if (!isset($this->storageFieldDefinitions[$entity_type_id])) { + // Not prepared, try to load from cache. + $cid = 'entity_storage_field_definitions:' . $entity_type_id . ':' . $this->languageManager->getCurrentLanguage()->id; + if ($cache = $this->cache->get($cid)) { + $this->storageFieldDefinitions[$entity_type_id] = $cache->data; + } + else { + // Rebuild the definitions and put it into the cache. + $this->storageFieldDefinitions[$entity_type_id] = $this->buildStorageFieldDefinitions($entity_type_id); + $this->cache->set($cid, $this->storageFieldDefinitions[$entity_type_id], Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE)); + } + } + return $this->storageFieldDefinitions[$entity_type_id]; + } + + /** + * Builds storage field definitions for an entity type. + * + * @param string $entity_type_id + * The entity type ID. Only entity types that implement + * \Drupal\Core\Entity\ContentEntityInterface are supported + * + * @return \Drupal\Core\Field\FieldStorageDefinitionInterface[] + * An array of storage field definitions, keyed by field name. + */ + protected function buildStorageFieldDefinitions($entity_type_id) { + $entity_type = $this->getDefinition($entity_type_id); + $field_definitions = array(); + + // Retrieve base field definitions from modules. + foreach ($this->moduleHandler->getImplementations('entity_storage_field_info') as $module) { + $module_definitions = $this->moduleHandler->invoke($module, 'entity_storage_field_info', array($entity_type)); + if (!empty($module_definitions)) { + // Ensure the provider key actually matches the name of the provider + // defining the field. + foreach ($module_definitions as $field_name => $definition) { + // @todo Remove this check one FieldDefinitionInterface exposes a + // proper provider setter. See https://drupal.org/node/2225961. + if ($definition instanceof FieldDefinition) { + $definition->setProvider($module); + } + $field_definitions[$field_name] = $definition; + } + } + } + + // Invoke alter hook. + $this->moduleHandler->alter('entity_storage_field_info', $field_definitions, $entity_type); + + return $field_definitions; + } + + /** + * {@inheritdoc} + */ public function clearCachedFieldDefinitions() { $this->baseFieldDefinitions = array(); $this->fieldDefinitions = array(); diff --git a/core/lib/Drupal/Core/Field/FieldDefinition.php b/core/lib/Drupal/Core/Field/FieldDefinition.php index 27e84cc..00543f0 100644 --- a/core/lib/Drupal/Core/Field/FieldDefinition.php +++ b/core/lib/Drupal/Core/Field/FieldDefinition.php @@ -68,6 +68,37 @@ public static function create($type) { } /** + * Creates a new field definition based upon a field storage definition. + * + * In cases where one needs a field storage definitions to act like full + * field definitions, this creates a new field definition based upon the + * (limited) information available. That way it is possible to use the field + * definition in places where a full field definition is required; e.g., with + * widgets or formatters. + * + * @param FieldStorageDefinitionInterface $definition + * The field storage definition to base the new field definition upon. + * + * @return $this + */ + public static function createFromFieldStorageDefinition(FieldStorageDefinitionInterface $definition) { + return static::create($definition->getType()) + ->setCardinality($definition->getCardinality()) + ->setConstraints($definition->getConstraints()) + ->setCustomStorage($definition->hasCustomStorage()) + ->setDescription($definition->getDescription()) + ->setLabel($definition->getLabel()) + ->setName($definition->getName()) + ->setProvider($definition->getProvider()) + ->setQueryable($definition->isQueryable()) + ->setRequired($definition->isRequired()) + ->setRevisionable($definition->isRevisionable()) + ->setSettings($definition->getSettings()) + ->setTargetEntityTypeId($definition->getTargetEntityTypeId()) + ->setTranslatable($definition->isTranslatable()); + } + + /** * {@inheritdoc} */ public static function createFromItemType($item_type) { diff --git a/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php b/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php index 501aa4c..a828e25 100644 --- a/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php +++ b/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php @@ -117,17 +117,4 @@ public function getDisplayOptions($display_context); */ public function getDefaultValue(EntityInterface $entity); - /** - * Returns the storage behavior for this field. - * - * Indicates whether the entity type's storage controller should take care of - * storing the field values or whether it is handled separately; e.g. by the - * module providing the field. - * - * @return bool - * FALSE if the storage controller takes care of storing the field, TRUE - * otherwise. - */ - public function hasCustomStorage(); - } diff --git a/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php b/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php index db3a4f4..7d9fd5c 100644 --- a/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php +++ b/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php @@ -263,4 +263,25 @@ public function getConstraints(); */ public function getConstraint($constraint_name); + /** + * Returns the name of the provider of this field. + * + * @return string + * The provider name; e.g., the module name. + */ + public function getProvider(); + + /** + * Returns the storage behavior for this field. + * + * Indicates whether the entity type's storage controller should take care of + * storing the field values or whether it is handled separately; e.g. by the + * module providing the field. + * + * @return bool + * FALSE if the storage controller takes care of storing the field, TRUE + * otherwise. + */ + public function hasCustomStorage(); + } diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index 68c0a7e..c11a9dd 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -730,9 +730,9 @@ function content_translation_form_field_ui_field_edit_form_submit($form, array & * Implements hook_form_FORM_ID_alter() for 'field_ui_field_instance_edit_form'. */ function content_translation_form_field_ui_field_instance_edit_form_alter(array &$form, array &$form_state, $form_id) { - if ($form['#field']->isTranslatable()) { + if ($form_state['instance']->isTranslatable()) { module_load_include('inc', 'content_translation', 'content_translation.admin'); - $element = content_translation_field_sync_widget($form['#field']); + $element = content_translation_field_sync_widget($form_state['instance']); if ($element) { $form['instance']['settings']['translation_sync'] = $element; } diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php index 3349609..5ad029a 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php +++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php @@ -10,6 +10,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Field\FieldDefinition; use Drupal\field\Field as FieldHelper; use Drupal\Core\Entity\FieldableDatabaseStorageController; use Drupal\Core\Field\FieldDefinitionInterface; @@ -40,9 +41,13 @@ class Field extends FieldPluginBase { public $items = array(); /** - * The field information as returned by field_info_field(). + * The field definition to use. * - * @var \Drupal\field\FieldConfigInterface + * A field storage definition turned into a field definition, so it can be + * used with widgets and formatters. See + * FieldDefinition::createFromFieldStorageDefinition(). + * + * @var \Drupal\Core\Field\FieldDefinitionInterface */ public $field_info; @@ -139,7 +144,8 @@ public static function create(ContainerInterface $container, array $configuratio public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { parent::init($view, $display, $options); - $this->field_info = FieldHelper::fieldInfo()->getField($this->definition['entity_type'], $this->definition['field_name']); + $storage_field_definition = FieldHelper::fieldInfo()->getField($this->definition['entity_type'], $this->definition['field_name']); + $this->field_info = FieldDefinition::createFromFieldStorageDefinition($storage_field_definition); $this->multiple = FALSE; $this->limit_values = FALSE;