diff --git a/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php b/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php index a5a9a94..9aaf35e 100644 --- a/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php +++ b/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php @@ -20,7 +20,8 @@ * * For example, configurable fields defined and exposed by field.module. */ -interface DynamicallyFieldableEntityStorageInterface extends EntityStorageInterface, FieldStorageDefinitionListenerInterface { +interface DynamicallyFieldableEntityStorageInterface extends FieldableEntityStorageInterface, FieldStorageDefinitionListenerInterface { + /** * Reacts to the creation of a field. * @@ -68,31 +69,6 @@ public function onFieldDefinitionDelete(FieldDefinitionInterface $field_definiti public function purgeFieldData(FieldDefinitionInterface $field_definition, $batch_size); /** - * Determines the number of entities with values for a given field. - * - * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition - * The field for which to count data records. - * @param bool $as_bool - * (Optional) Optimises the query for checking whether there are any records - * or not. Defaults to FALSE. - * - * @return bool|int - * The number of entities. If $as_bool parameter is TRUE then the - * value will either be TRUE or FALSE. - * - * @see \Drupal\Core\Entity\FieldableEntityStorageInterface::purgeFieldData() - */ - public function countFieldData($storage_definition, $as_bool = FALSE); - - /** - * Determines if the storage contains any data. - * - * @return bool - * TRUE if the storage contains data, FALSE if not. - */ - public function hasData(); - - /** * Performs final cleanup after all data of a field has been purged. * * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition diff --git a/core/lib/Drupal/Core/Entity/FieldableEntityInterface.php b/core/lib/Drupal/Core/Entity/FieldableEntityInterface.php index 24a74be..5330ad5 100644 --- a/core/lib/Drupal/Core/Entity/FieldableEntityInterface.php +++ b/core/lib/Drupal/Core/Entity/FieldableEntityInterface.php @@ -7,8 +7,6 @@ namespace Drupal\Core\Entity; -use Drupal\Core\TypedData\ComplexDataInterface; - /** * Interface for entities having fields. * diff --git a/core/lib/Drupal/Core/Entity/FieldableEntityStorageInterface.php b/core/lib/Drupal/Core/Entity/FieldableEntityStorageInterface.php new file mode 100644 index 0000000..dc35ff7 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/FieldableEntityStorageInterface.php @@ -0,0 +1,46 @@ +entityManager->getDefinitions(); $reasons = array(); - foreach ($entity_types as $entity_type_id => $entity_type) { + + foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) { // We skip entity types defined by the module as there may be no content // for being able to uninstall them anyway. // See \Drupal\Core\Entity\ContentUninstallValidator. @@ -47,10 +47,7 @@ public function validate($module_name) { foreach ($this->entityManager->getFieldStorageDefinitions($entity_type_id) as $storage_definition) { if ($storage_definition->getProvider() == $module_name) { $storage = $this->entityManager->getStorage($entity_type_id); - // If the content is not dynamically fieldable, fallback to checking - // whether the entity has content in general. - $fieldable = $storage instanceof DynamicallyFieldableEntityStorageInterface; - if (($fieldable && $storage->countFieldData($storage_definition, TRUE)) || (!$fieldable && $storage->hasData())) { + if ($storage instanceof FieldableEntityStorageInterface && $storage->countFieldData($storage_definition, TRUE)) { $reasons[] = $this->t('There is content for the field @field-name on entity type @entity_type.', array( '@field-name' => $storage_definition->getName(), '@entity_type' => $entity_type->getLabel(), @@ -60,6 +57,7 @@ public function validate($module_name) { } } } + return $reasons; } diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 143e8c5..9264d31 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -118,40 +118,6 @@ function field_cron() { } /** - * Implements hook_system_info_alter(). - * - * Goes through a list of all modules that provide a field type and makes them - * required if there are any active fields of that type. - */ -function field_system_info_alter(&$info, Extension $file, $type) { - // It is not safe to call entity_load_multiple_by_properties() during - // maintenance mode. - if ($type == 'module' && !defined('MAINTENANCE_MODE')) { - $field_storages = entity_load_multiple_by_properties('field_storage_config', array('module' => $file->getName(), 'include_deleted' => TRUE)); - if ($field_storages) { - $info['required'] = TRUE; - - // Provide an explanation message (only mention pending deletions if there - // remains no actual, non-deleted fields) - $non_deleted = FALSE; - foreach ($field_storages as $field_storage) { - if (empty($field_storage->deleted)) { - $non_deleted = TRUE; - break; - } - } - if ($non_deleted) { - $explanation = t('Fields type(s) in use'); - } - else { - $explanation = t('Fields pending deletion'); - } - $info['explanation'] = $explanation; - } - } -} - -/** * Implements hook_entity_field_storage_info(). */ function field_entity_field_storage_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) { diff --git a/core/modules/field/field.services.yml b/core/modules/field/field.services.yml new file mode 100644 index 0000000..7c33168 --- /dev/null +++ b/core/modules/field/field.services.yml @@ -0,0 +1,6 @@ +services: + field_module_uninstall_validator: + class: Drupal\field\ModuleUninstallValidator + tags: + - { name: module_install.uninstall_validator } + arguments: ['@entity.manager', '@string_translation'] diff --git a/core/modules/field/src/ModuleUninstallValidator.php b/core/modules/field/src/ModuleUninstallValidator.php new file mode 100644 index 0000000..90f917e --- /dev/null +++ b/core/modules/field/src/ModuleUninstallValidator.php @@ -0,0 +1,67 @@ +entityManager = $entity_manager; + $this->stringTranslation = $string_translation; + } + + /** + * {@inheritdoc} + */ + public function validate($module_name) { + $reasons = array(); + + // It is not safe to call entity_load_multiple_by_properties() during + // maintenance mode. + if (!defined('MAINTENANCE_MODE')) { + $field_storages = $this->entityManager + ->getStorage('field_storage_config') + ->loadByProperties(array('module' => $module_name, 'include_deleted' => TRUE)); + + if ($field_storages) { + // Provide an explanation message (only mention pending deletions if there + // remains no actual, non-deleted fields) + $non_deleted = FALSE; + foreach ($field_storages as $field_storage) { + if (empty($field_storage->deleted)) { + $non_deleted = TRUE; + break; + } + } + + $reasons[] = $non_deleted ? $this->t('Fields type(s) in use') : $this->t('Fields pending deletion'); + } + } + + return $reasons; + } + +}