Commit 73fcf586 authored by alexpott's avatar alexpott

Issue #2489472 by cilefen, amateescu, bircher, saki007ster, swentel, andypost,...

Issue #2489472 by cilefen, amateescu, bircher, saki007ster, swentel, andypost, alexpott, Bojhan: Field-based module dependency uninstall message is unhelpful and not grammatically correct
parent 867bf59f
......@@ -3,5 +3,5 @@ services:
class: Drupal\field\FieldUninstallValidator
tags:
- { name: module_install.uninstall_validator }
arguments: ['@entity.manager', '@string_translation']
arguments: ['@entity_type.manager', '@string_translation', '@plugin.manager.field.field_type']
lazy: true
......@@ -7,8 +7,9 @@
namespace Drupal\field;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
......@@ -26,17 +27,27 @@ class FieldUninstallValidator implements ModuleUninstallValidatorInterface {
*/
protected $fieldStorageConfigStorage;
/**
* The field type plugin manager.
*
* @var \Drupal\Core\Field\FieldTypePluginManagerInterface
*/
protected $fieldTypeManager;
/**
* Constructs a new FieldUninstallValidator.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity manager.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service.
* @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
* The field type plugin manager.
*/
public function __construct(EntityManagerInterface $entity_manager, TranslationInterface $string_translation) {
$this->fieldStorageConfigStorage = $entity_manager->getStorage('field_storage_config');
public function __construct(EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation, FieldTypePluginManagerInterface $field_type_manager) {
$this->fieldStorageConfigStorage = $entity_type_manager->getStorage('field_storage_config');
$this->stringTranslation = $string_translation;
$this->fieldTypeManager = $field_type_manager;
}
/**
......@@ -47,15 +58,17 @@ public function validate($module) {
if ($field_storages = $this->getFieldStoragesByModule($module)) {
// Provide an explanation message (only mention pending deletions if there
// remain no actual, non-deleted fields.)
$non_deleted = FALSE;
$fields_in_use = [];
foreach ($field_storages as $field_storage) {
if (!$field_storage->isDeleted()) {
$non_deleted = TRUE;
break;
$fields_in_use[$field_storage->getType()][] = $field_storage->getLabel();
}
}
if (!empty($fields_in_use)) {
foreach ($fields_in_use as $field_type => $field_storages) {
$field_type_label = $this->getFieldTypeLabel($field_type);
$reasons[] = $this->formatPlural(count($fields_in_use[$field_type]), 'The %field_type_label field type is used in the following field: @fields', 'The %field_type_label field type is used in the following fields: @fields', ['%field_type_label' => $field_type_label, '@fields' => implode(', ', $field_storages)]);
}
if ($non_deleted) {
$reasons[] = $this->t('Fields type(s) in use');
}
else {
$reasons[] = $this->t('Fields pending deletion');
......@@ -77,4 +90,18 @@ protected function getFieldStoragesByModule($module) {
return $this->fieldStorageConfigStorage->loadByProperties(['module' => $module, 'include_deleted' => TRUE]);
}
/**
* Returns the label for a specified field type.
*
* @param string $field_type
* The field type.
*
* @return string
* The field type label.
*/
protected function getFieldTypeLabel($field_type) {
return $this->fieldTypeManager->getDefinitions()[$field_type]['label'];
}
}
......@@ -93,14 +93,35 @@ function testReEnabledField() {
$admin_user = $this->drupalCreateUser(array('access administration pages', 'administer modules'));
$this->drupalLogin($admin_user);
$this->drupalGet('admin/modules/uninstall');
$this->assertText('Fields type(s) in use');
$this->assertText("The Telephone number field type is used in the following field: node.field_telephone");
// Add another telephone field to a different entity type in order to test
// the message for the case when multiple fields are blocking the
// uninstallation of a module.
$field_storage2 = entity_create('field_storage_config', array(
'field_name' => 'field_telephone_2',
'entity_type' => 'user',
'type' => 'telephone',
));
$field_storage2->save();
entity_create('field_config', array(
'field_storage' => $field_storage2,
'bundle' => 'user',
'label' => 'User Telephone Number',
))->save();
$this->drupalGet('admin/modules/uninstall');
$this->assertText("The Telephone number field type is used in the following fields: node.field_telephone, user.field_telephone_2");
// Delete both fields.
$field_storage->delete();
$field_storage2->delete();
$this->drupalGet('admin/modules/uninstall');
$this->assertText('Fields pending deletion');
$this->cronRun();
$this->assertNoText('Fields type(s) in use');
$this->assertNoText("The Telephone number field type is used in the following field: node.field_telephone");
$this->assertNoText('Fields pending deletion');
}
}
......@@ -7,6 +7,7 @@
namespace Drupal\Tests\field\Unit;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\simpletest\AssertHelperTrait;
use Drupal\Tests\UnitTestCase;
......@@ -23,6 +24,13 @@ class FieldUninstallValidatorTest extends UnitTestCase {
*/
protected $fieldUninstallValidator;
/**
* The mock field type plugin manager;
*
* @var \Drupal\Core\Field\FieldTypePluginManagerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $fieldTypePluginManager;
/**
* {@inheritdoc}
*/
......@@ -30,7 +38,7 @@ protected function setUp() {
parent::setUp();
$this->fieldUninstallValidator = $this->getMockBuilder('Drupal\field\FieldUninstallValidator')
->disableOriginalConstructor()
->setMethods(['getFieldStoragesByModule'])
->setMethods(['getFieldStoragesByModule', 'getFieldTypeLabel'])
->getMock();
$this->fieldUninstallValidator->setStringTranslation($this->getStringTranslationStub());
}
......@@ -79,12 +87,24 @@ public function testValidateNoDeleted() {
$field_storage->expects($this->once())
->method('isDeleted')
->willReturn(FALSE);
$field_type = $this->randomMachineName();
$field_storage->expects($this->once())
->method('getType')
->willReturn($field_type);
$field_name = $this->randomMachineName();
$field_storage->expects($this->once())
->method('getLabel')
->willReturn($field_name);
$this->fieldUninstallValidator->expects($this->once())
->method('getFieldStoragesByModule')
->willReturn([$field_storage]);
$field_type_label = $this->randomMachineName();
$this->fieldUninstallValidator->expects($this->once())
->method('getFieldTypeLabel')
->willReturn($field_type_label);
$module = $this->randomMachineName();
$expected = ['Fields type(s) in use'];
$expected = ["The <em class=\"placeholder\">$field_type_label</em> field type is used in the following field: $field_name"];
$reasons = $this->fieldUninstallValidator->validate($module);
$this->assertSame($expected, $this->castSafeStrings($reasons));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment