diff --git a/core/modules/field/src/BaseFieldStorageConfigWrapper.php b/core/modules/field/src/BaseFieldStorageConfigWrapper.php new file mode 100644 index 0000000000..05bcf6df68 --- /dev/null +++ b/core/modules/field/src/BaseFieldStorageConfigWrapper.php @@ -0,0 +1,111 @@ +toArray(); + $values['type'] = $base_field_definition->getType(); + $values['module'] = static::lookupTypeProvider($values['type']); + return new static($values); + } + + /** + * Returns the field type provider. + * + * @param string $type + * The field type. + * + * @return string + * The field type provider. + */ + protected static function lookupTypeProvider($type) { + /** @var \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager */ + $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); + try { + $field_type = $field_type_manager->getDefinition($type); + return $field_type['provider']; + } + catch (PluginNotFoundException $e) { + return NULL; + } + } + + /** + * Returns field bundles for the specified entity type. + * + * @param string $entity_type_id + * The entity type ID. + * + * @return string[][] + * An associative array of bundle IDs keyed by field name. + */ + public static function getFieldBundles($entity_type_id) { + $field_bundles = &static::$field_bundle_ids[$entity_type_id]; + if (!isset($field_bundles)) { + $field_bundles = []; + /** @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info */ + $bundle_info = \Drupal::service('entity_type.bundle.info')->getBundleInfo($entity_type_id); + /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager */ + $entity_field_manager = \Drupal::service('entity_field.manager'); + foreach ($bundle_info as $bundle_id => $info) { + /** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */ + foreach ($entity_field_manager->getFieldDefinitions($entity_type_id, $bundle_id) as $field_name => $field_definition) { + // Filter out Field module's field definitions. + if (!($field_definition instanceof FieldConfigInterface) && $field_definition instanceof FieldStorageDefinitionInterface && !$field_definition->isBaseField()) { + $field_bundles[$field_name][] = $bundle_id; + } + } + } + } + return $field_bundles; + } + + /** + * {@inheritdoc} + */ + public function getBundles() { + $field_bundles = static::getFieldBundles($this->entity_type); + return isset($field_bundles[$this->field_name]) ? $field_bundles[$this->field_name] : []; + } + + /** + * {@inheritdoc} + */ + public function preSave(EntityStorageInterface $storage) { + throw new \BadMethodCallException('BaseFieldStorageConfigWrapper instances cannot be persisted.'); + } + +} diff --git a/core/modules/views/src/EntityViewsData.php b/core/modules/views/src/EntityViewsData.php index 079ee3bb3d..4fdb28e4e1 100644 --- a/core/modules/views/src/EntityViewsData.php +++ b/core/modules/views/src/EntityViewsData.php @@ -9,9 +9,12 @@ use Drupal\Core\Entity\Sql\SqlEntityStorageInterface; use Drupal\Core\Entity\Sql\TableMappingInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; +use Drupal\field\BaseFieldStorageConfigWrapper; +use Drupal\field\Entity\FieldStorageConfigWrapper; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -321,6 +324,19 @@ public function getViewsData() { $table_data['table']['entity type'] = $entity_type_id; }); + // Add any bundle fields defined in code. + // @todo Here we are assuming that hard-coded bundle field definitions + // extend BaseFieldDefinition, which is a common case. Revisit this logic + // in https://www.drupal.org/project/drupal/issues/2930736. + $storage_definitions = $this->entityManager->getFieldStorageDefinitions($this->entityType->id()); + foreach (BaseFieldStorageConfigWrapper::getFieldBundles($this->entityType->id()) as $field_name => $bundles) { + $storage_definition = isset($storage_definitions[$field_name]) ? $storage_definitions[$field_name] : NULL; + if (!$storage_definition->isBaseField() && $storage_definition instanceof BaseFieldDefinition) { + $field_storage = BaseFieldStorageConfigWrapper::createFromBaseFieldDefinition($storage_definition); + views_collect_field_view_data($field_storage, $data); + } + } + return $data; } diff --git a/core/modules/views/views.views.inc b/core/modules/views/views.views.inc index 633ce9b9da..15acd107a8 100644 --- a/core/modules/views/views.views.inc +++ b/core/modules/views/views.views.inc @@ -171,31 +171,44 @@ function views_views_data() { } } - // Field modules can implement hook_field_views_data() to override the default - // behavior for adding fields. - $module_handler = \Drupal::moduleHandler(); - $entity_manager = \Drupal::entityManager(); if ($entity_manager->hasDefinition('field_storage_config')) { /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */ foreach ($entity_manager->getStorage('field_storage_config')->loadMultiple() as $field_storage) { - if (_views_field_get_entity_type_storage($field_storage)) { - $result = (array) $module_handler->invoke($field_storage->getTypeProvider(), 'field_views_data', [$field_storage]); - if (empty($result)) { - $result = views_field_default_views_data($field_storage); - } - $module_handler->alter('field_views_data', $result, $field_storage); - - if (is_array($result)) { - $data = NestedArray::mergeDeep($result, $data); - } - } + views_collect_field_view_data($field_storage, $data); } } return $data; } +/** + * Collects view data for the specified Field module field. + * + * @param \Drupal\field\FieldStorageConfigInterface $field_storage + * The field storage definition. + * @param array $data + * A reference to a view data array. + * + * @internal + */ +function views_collect_field_view_data(FieldStorageConfigInterface $field_storage, array &$data) { + // Field modules can implement hook_field_views_data() to override the default + // behavior for adding fields. + $module_handler = \Drupal::moduleHandler(); + if (_views_field_get_entity_type_storage($field_storage)) { + $result = (array) $module_handler->invoke($field_storage->getTypeProvider(), 'field_views_data', [$field_storage]); + if (empty($result)) { + $result = views_field_default_views_data($field_storage); + } + $module_handler->alter('field_views_data', $result, $field_storage); + + if (is_array($result)) { + $data = NestedArray::mergeDeep($result, $data); + } + } +} + /** * Implements hook_views_data_alter(). * @@ -361,7 +374,7 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora $untranslatable_config_bundles = []; foreach ($bundles_names as $bundle) { - $fields[$bundle] = FieldConfig::loadByName($entity_type->id(), $bundle, $field_name); + $fields[$bundle] = $entity_manager->getFieldDefinitions($entity_type->id(), $bundle)[$field_name]; } foreach ($fields as $bundle => $config_entity) { if (!empty($config_entity)) {