Issue #784672 by smustgrave, floretan, lokapujya, joegraduate, jcnventura, AndyF, joelpittet, darvanen, c960657, eiriksm, viappidu, jungle, ravi.shankar, DanielVeza, Meenakshi_j, gordon, raman.b, mohit_aghera, vsujeetkumar, aleevas, vakulrai, bruvers, larowlan, vpeltot, wjaspers, Sonal.Sangale, jan.stoeckler, jofitz, vdsh, minorOffense, LewisNyman, mgifford, Berdir, tstoeckler, Luke.Leber, Hanno, alexpott, andypost, yannickoo, hchonov, quietone, David_Rothstein, fgm, mr.baileys, MaxMendez, mpp: Allow text field to enforce a specific text format

merge-requests/3042/head
Alex Pott 2022-11-29 11:37:35 +00:00
parent e2d4dcfdf2
commit 82576b6002
No known key found for this signature in database
GPG Key ID: BDA67E7EE836E5CE
41 changed files with 403 additions and 30 deletions

View File

@ -94,7 +94,10 @@ function block_content_add_body_field($block_type_id, $label = 'Body') {
'field_storage' => FieldStorageConfig::loadByName('block_content', 'body'), 'field_storage' => FieldStorageConfig::loadByName('block_content', 'body'),
'bundle' => $block_type_id, 'bundle' => $block_type_id,
'label' => $label, 'label' => $label,
'settings' => ['display_summary' => FALSE], 'settings' => [
'display_summary' => FALSE,
'allowed_formats' => [],
],
]); ]);
$field->save(); $field->save();

View File

@ -13,6 +13,7 @@ source:
field_name: body field_name: body
label: Body label: Body
display_summary: false display_summary: false
allowed_formats: { }
ids: ids:
entity_type: entity_type:
type: string type: string

View File

@ -19,4 +19,5 @@ default_value_callback: ''
settings: settings:
display_summary: true display_summary: true
required_summary: false required_summary: false
allowed_formats: { }
field_type: text_with_summary field_type: text_with_summary

View File

@ -414,7 +414,10 @@ class ConfigTranslationListUiTest extends BrowserTestBase {
'field_storage' => FieldStorageConfig::loadByName('block_content', 'body'), 'field_storage' => FieldStorageConfig::loadByName('block_content', 'body'),
'bundle' => $block_content_type->id(), 'bundle' => $block_content_type->id(),
'label' => 'Body', 'label' => 'Body',
'settings' => ['display_summary' => FALSE], 'settings' => [
'display_summary' => FALSE,
'allowed_formats' => [],
],
]); ]);
$field->save(); $field->save();

View File

@ -15,3 +15,7 @@ editor.settings.trex:
stumpy_arms: stumpy_arms:
type: boolean type: boolean
label: 'Stumpy arms' label: 'Stumpy arms'
field.field_settings.editor_test_text_long:
label: 'Filter test text (formatted, long) settings'
type: field.field_settings.text

View File

@ -11,5 +11,6 @@ description: ''
required: false required: false
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text field_type: text

View File

@ -11,5 +11,6 @@ description: ''
required: false required: false
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text field_type: text

View File

@ -11,5 +11,6 @@ description: ''
required: false required: false
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text field_type: text

View File

@ -9,7 +9,8 @@ description: ''
required: '0' required: '0'
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text field_type: text
dependencies: dependencies:
config: config:

View File

@ -9,7 +9,8 @@ description: ''
required: '0' required: '0'
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text field_type: text
dependencies: dependencies:
config: config:

View File

@ -9,7 +9,8 @@ description: ''
required: '0' required: '0'
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text field_type: text
dependencies: dependencies:
config: config:

View File

@ -82,7 +82,9 @@ abstract class FieldConfigResourceTestBase extends ConfigEntityResourceTestBase
'label' => 'field_llama', 'label' => 'field_llama',
'langcode' => 'en', 'langcode' => 'en',
'required' => FALSE, 'required' => FALSE,
'settings' => [], 'settings' => [
'allowed_formats' => [],
],
'status' => TRUE, 'status' => TRUE,
'translatable' => TRUE, 'translatable' => TRUE,
'uuid' => $this->entity->uuid(), 'uuid' => $this->entity->uuid(),

View File

@ -33,7 +33,7 @@ class MigrateFieldInstanceTest extends MigrateDrupal6TestBase {
$field = FieldConfig::load('node.story.field_test'); $field = FieldConfig::load('node.story.field_test');
$this->assertSame('Text Field', $field->label()); $this->assertSame('Text Field', $field->label());
// field_test is a text_long field, which have no settings. // field_test is a text_long field, which have no settings.
$this->assertSame([], $field->getSettings()); $this->assertSame(['allowed_formats' => []], $field->getSettings());
$this->assertSame('text for default value', $entity->field_test->value); $this->assertSame('text for default value', $entity->field_test->value);
// Test a number field. // Test a number field.

View File

@ -16,5 +16,6 @@ required: true
translatable: true translatable: true
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text_long field_type: text_long

View File

@ -19,4 +19,5 @@ default_value_callback: ''
settings: settings:
display_summary: true display_summary: true
required_summary: false required_summary: false
allowed_formats: { }
field_type: text_with_summary field_type: text_with_summary

View File

@ -119,7 +119,7 @@ class FieldConfigTest extends ConfigEntityResourceTestBase {
'label' => 'field_llama', 'label' => 'field_llama',
'langcode' => 'en', 'langcode' => 'en',
'required' => FALSE, 'required' => FALSE,
'settings' => [], 'settings' => ['allowed_formats' => []],
'status' => TRUE, 'status' => TRUE,
'translatable' => TRUE, 'translatable' => TRUE,
'drupal_internal__id' => 'node.camelids.field_llama', 'drupal_internal__id' => 'node.camelids.field_llama',

View File

@ -277,7 +277,10 @@ function node_add_body_field(NodeTypeInterface $type, $label = 'Body') {
'field_storage' => $field_storage, 'field_storage' => $field_storage,
'bundle' => $type->id(), 'bundle' => $type->id(),
'label' => $label, 'label' => $label,
'settings' => ['display_summary' => TRUE], 'settings' => [
'display_summary' => TRUE,
'allowed_formats' => [],
],
]); ]);
$field->save(); $field->save();

View File

@ -17,4 +17,5 @@ default_value: { }
default_value_callback: '' default_value_callback: ''
settings: settings:
display_summary: true display_summary: true
allowed_formats: { }
field_type: text_with_summary field_type: text_with_summary

View File

@ -19,6 +19,12 @@ field.storage_settings.text:
field.field_settings.text: field.field_settings.text:
type: mapping type: mapping
label: 'Text (formatted) settings' label: 'Text (formatted) settings'
mapping:
allowed_formats:
type: sequence
label: 'Allowed text formats'
sequence:
type: string
field.value.text: field.value.text:
type: mapping type: mapping
@ -33,11 +39,17 @@ field.value.text:
field.storage_settings.text_long: field.storage_settings.text_long:
label: 'Text (formatted, long) settings' label: 'Text (formatted, long) settings'
type: mapping type: field.field_settings.text
field.field_settings.text_long: field.field_settings.text_long:
label: 'Text (formatted, long) settings' label: 'Text (formatted, long) settings'
type: mapping type: mapping
mapping:
allowed_formats:
type: sequence
label: 'Allowed text formats'
sequence:
type: string
field.value.text_long: field.value.text_long:
type: mapping type: mapping
@ -64,6 +76,11 @@ field.field_settings.text_with_summary:
required_summary: required_summary:
type: boolean type: boolean
label: 'Require summary' label: 'Require summary'
allowed_formats:
type: sequence
label: 'Allowed text formats'
sequence:
type: string
field.value.text_with_summary: field.value.text_with_summary:
type: mapping type: mapping

View File

@ -0,0 +1,35 @@
<?php
namespace Drupal\text\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Form\FormStateInterface;
/**
* Defines an item list class for text fields.
*/
class TextFieldItemList extends FieldItemList {
/**
* {@inheritdoc}
*/
public function defaultValuesFormValidate(array $element, array &$form, FormStateInterface $form_state) {
if ($allowed_formats = $this->getSetting('allowed_formats')) {
$field_name = $this->definition->getName();
$submitted_values = $form_state->getValue([
'default_value_input',
$field_name,
]);
foreach ($submitted_values as $delta => $value) {
if (!in_array($value['format'], $allowed_formats, TRUE)) {
$form_state->setErrorByName(
"default_value_input][{$field_name}][{$delta}][format",
$this->t("The selected text format is not allowed.")
);
}
}
}
parent::defaultValuesFormValidate($element, $form, $form_state);
}
}

View File

@ -14,7 +14,8 @@ use Drupal\Core\Form\FormStateInterface;
* description = @Translation("This field stores a text with a text format."), * description = @Translation("This field stores a text with a text format."),
* category = @Translation("Text"), * category = @Translation("Text"),
* default_widget = "text_textfield", * default_widget = "text_textfield",
* default_formatter = "text_default" * default_formatter = "text_default",
* list_class = "\Drupal\text\Plugin\Field\FieldType\TextFieldItemList"
* ) * )
*/ */
class TextItem extends TextItemBase { class TextItem extends TextItemBase {

View File

@ -6,6 +6,7 @@ use Drupal\Component\Utility\Random;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemBase; use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TypedData\DataDefinition; use Drupal\Core\TypedData\DataDefinition;
/** /**
@ -13,6 +14,62 @@ use Drupal\Core\TypedData\DataDefinition;
*/ */
abstract class TextItemBase extends FieldItemBase { abstract class TextItemBase extends FieldItemBase {
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
return ['allowed_formats' => []] + parent::defaultFieldSettings();
}
/**
* {@inheritdoc}
*/
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$element = parent::fieldSettingsForm($form, $form_state);
$settings = $this->getSettings();
$element['allowed_formats'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Allowed text formats'),
'#options' => $this->get('format')->getPossibleOptions(),
'#default_value' => !empty($settings['allowed_formats']) ? $settings['allowed_formats'] : [],
'#description' => $this->t('Select the allowed text formats. If no formats are selected, all available text formats will be displayed to the user.'),
'#element_validate' => [[static::class, 'validateAllowedFormats']],
];
return $element;
}
/**
* Render API callback: Processes the allowed formats value.
*
* Ensure the element's value is an indexed array of selected format IDs.
* This function is assigned as an #element_validate callback.
*
* @see static::fieldSettingsForm()
*/
public static function validateAllowedFormats(array &$element, FormStateInterface $form_state) {
$value = array_values(array_filter($form_state->getValue($element['#parents'])));
$form_state->setValueForElement($element, $value);
}
/**
* {@inheritdoc}
*/
public static function calculateDependencies(FieldDefinitionInterface $field_definition) {
// Add explicitly allowed formats as config dependencies.
$format_dependencies = [];
$dependencies = parent::calculateDependencies($field_definition);
if (!is_null($field_definition->getSetting('allowed_formats'))) {
$format_dependencies = array_map(function (string $format_id) {
return 'filter.format.' . $format_id;
}, $field_definition->getSetting('allowed_formats'));
}
$config = $dependencies['config'] ?? [];
$dependencies['config'] = array_merge($config, $format_dependencies);
return $dependencies;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -22,7 +79,8 @@ abstract class TextItemBase extends FieldItemBase {
->setRequired(TRUE); ->setRequired(TRUE);
$properties['format'] = DataDefinition::create('filter_format') $properties['format'] = DataDefinition::create('filter_format')
->setLabel(t('Text format')); ->setLabel(t('Text format'))
->setSetting('allowed_formats', $field_definition->getSetting('allowed_formats'));
$properties['processed'] = DataDefinition::create('string') $properties['processed'] = DataDefinition::create('string')
->setLabel(t('Processed text')) ->setLabel(t('Processed text'))

View File

@ -13,7 +13,8 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface;
* description = @Translation("This field stores a long text with a text format."), * description = @Translation("This field stores a long text with a text format."),
* category = @Translation("Text"), * category = @Translation("Text"),
* default_widget = "text_textarea", * default_widget = "text_textarea",
* default_formatter = "text_default" * default_formatter = "text_default",
* list_class = "\Drupal\text\Plugin\Field\FieldType\TextFieldItemList"
* ) * )
*/ */
class TextLongItem extends TextItemBase { class TextLongItem extends TextItemBase {

View File

@ -16,7 +16,8 @@ use Drupal\Core\StringTranslation\TranslatableMarkup;
* description = @Translation("This field stores long text with a format and an optional summary."), * description = @Translation("This field stores long text with a format and an optional summary."),
* category = @Translation("Text"), * category = @Translation("Text"),
* default_widget = "text_textarea_with_summary", * default_widget = "text_textarea_with_summary",
* default_formatter = "text_default" * default_formatter = "text_default",
* list_class = "\Drupal\text\Plugin\Field\FieldType\TextFieldItemList"
* ) * )
*/ */
class TextWithSummaryItem extends TextItemBase { class TextWithSummaryItem extends TextItemBase {
@ -87,7 +88,7 @@ class TextWithSummaryItem extends TextItemBase {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function fieldSettingsForm(array $form, FormStateInterface $form_state) { public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$element = []; $element = parent::fieldSettingsForm($form, $form_state);
$settings = $this->getSettings(); $settings = $this->getSettings();
$element['display_summary'] = [ $element['display_summary'] = [

View File

@ -34,11 +34,17 @@ class TextareaWidget extends StringTextareaWidget {
*/ */
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$main_widget = parent::formElement($items, $delta, $element, $form, $form_state); $main_widget = parent::formElement($items, $delta, $element, $form, $form_state);
$allowed_formats = $this->getFieldSetting('allowed_formats');
$element = $main_widget['value']; $element = $main_widget['value'];
$element['#type'] = 'text_format'; $element['#type'] = 'text_format';
$element['#format'] = $items[$delta]->format; $element['#format'] = $items[$delta]->format;
$element['#base_type'] = $main_widget['value']['#type']; $element['#base_type'] = $main_widget['value']['#type'];
if ($allowed_formats && !$this->isDefaultValueWidget($form_state)) {
$element['#allowed_formats'] = $allowed_formats;
}
return $element; return $element;
} }

View File

@ -25,11 +25,17 @@ class TextfieldWidget extends StringTextfieldWidget {
*/ */
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$main_widget = parent::formElement($items, $delta, $element, $form, $form_state); $main_widget = parent::formElement($items, $delta, $element, $form, $form_state);
$allowed_formats = $this->getFieldSetting('allowed_formats');
$element = $main_widget['value']; $element = $main_widget['value'];
$element['#type'] = 'text_format'; $element['#type'] = 'text_format';
$element['#format'] = $items[$delta]->format ?? NULL; $element['#format'] = $items[$delta]->format ?? NULL;
$element['#base_type'] = $main_widget['value']['#type']; $element['#base_type'] = $main_widget['value']['#type'];
if ($allowed_formats && !$this->isDefaultValueWidget($form_state)) {
$element['#allowed_formats'] = $allowed_formats;
}
return $element; return $element;
} }

View File

@ -7,6 +7,7 @@ use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Entity\FieldStorageConfig;
use Drupal\filter\Entity\FilterFormat; use Drupal\filter\Entity\FilterFormat;
use Drupal\filter\Render\FilteredMarkup;
use Drupal\Tests\field\Functional\String\StringFieldTest; use Drupal\Tests\field\Functional\String\StringFieldTest;
use Drupal\Tests\TestFileCreationTrait; use Drupal\Tests\TestFileCreationTrait;
@ -21,6 +22,11 @@ class TextFieldTest extends StringFieldTest {
getTestFiles as drupalGetTestFiles; getTestFiles as drupalGetTestFiles;
} }
/**
* {@inheritdoc}
*/
protected static $modules = ['entity_test', 'file', 'field_ui'];
/** /**
* A user with relevant administrative privileges. * A user with relevant administrative privileges.
* *
@ -39,7 +45,10 @@ class TextFieldTest extends StringFieldTest {
protected function setUp(): void { protected function setUp(): void {
parent::setUp(); parent::setUp();
$this->adminUser = $this->drupalCreateUser(['administer filters']); $this->adminUser = $this->drupalCreateUser([
'administer filters',
'administer entity_test fields',
]);
} }
// Test fields. // Test fields.
@ -157,13 +166,146 @@ class TextFieldTest extends StringFieldTest {
$this->_testTextfieldWidgetsFormatted('text_long', 'text_textarea'); $this->_testTextfieldWidgetsFormatted('text_long', 'text_textarea');
} }
/**
* Test widgets for fields with selected allowed formats.
*/
public function testTextfieldWidgetsAllowedFormats() {
// Create one text format.
$this->drupalLogin($this->adminUser);
$format1 = FilterFormat::create([
'format' => mb_strtolower($this->randomMachineName()),
'name' => $this->randomMachineName(),
]);
$format1->save();
// Create a second text format.
$format2 = FilterFormat::create([
'format' => mb_strtolower($this->randomMachineName()),
'name' => $this->randomMachineName(),
'filters' => [
'filter_html' => [
'status' => 1,
'settings' => [
'allowed_html' => '<strong>',
],
],
],
]);
$format2->save();
// Create a third text format.
$format3 = FilterFormat::create([
'format' => mb_strtolower($this->randomMachineName()),
'name' => $this->randomMachineName(),
]);
$format3->save();
// Grant access to both formats to the user.
$roles = $this->webUser->getRoles();
$rid = $roles[0];
user_role_grant_permissions($rid, [
$format1->getPermissionName(),
$format2->getPermissionName(),
$format3->getPermissionName(),
]);
// Create a field with multiple formats allowed.
$field_name = mb_strtolower($this->randomMachineName());
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test',
'type' => 'text',
]);
$field_storage->save();
$field = FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => 'entity_test',
'label' => $this->randomMachineName() . '_label',
'settings' => ['allowed_formats' => []],
]);
$field->save();
/** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository */
$entity_display_repository = $this->container->get('entity_display.repository');
$entity_display_repository->getFormDisplay('entity_test', 'entity_test', 'default')
->setComponent($field_name, [
'type' => 'text_textfield',
])
->save();
$entity_display_repository->getViewDisplay('entity_test', 'entity_test', 'full')
->setComponent($field_name)
->save();
// Display the creation form.
$this->drupalLogin($this->webUser);
$this->drupalGet('entity_test/add');
$this->assertSession()->fieldExists("{$field_name}[0][value]", NULL);
$this->assertSession()->optionExists("{$field_name}[0][format]", $format1->id());
$this->assertSession()->optionExists("{$field_name}[0][format]", $format2->id());
$this->assertSession()->optionExists("{$field_name}[0][format]", $format3->id());
$filtered_markup = FilteredMarkup::create('<div><strong><span>Hello World</span></strong></div>');
$edit = [
"{$field_name}[0][value]" => $filtered_markup,
];
$this->submitForm($edit, 'Save');
preg_match('|entity_test/manage/(\d+)|', $this->getUrl(), $match);
$id = $match[1];
$this->assertSession()->pageTextContains('entity_test ' . $id . ' has been created.');
// Display the entity.
$entity = EntityTest::load($id);
$display = $entity_display_repository->getViewDisplay($entity->getEntityTypeId(), $entity->bundle(), 'full');
$content = $display->build($entity);
$rendered_entity = \Drupal::service('renderer')->renderRoot($content);
$this->assertStringContainsString('<div><strong><span>', (string) $rendered_entity);
// Log back in as admin.
$this->drupalLogin($this->adminUser);
// Change field to allow only one format.
$path = "entity_test/structure/entity_test/fields/entity_test.entity_test.$field_name";
$this->drupalGet($path);
$this->submitForm(["settings[allowed_formats][{$format1->id()}]" => $format1->id()], 'Save settings');
$this->drupalGet($path);
// Display the creation form.
$this->drupalLogin($this->webUser);
// We shouldn't have the 'format' selector since only one format is allowed.
$this->drupalGet('entity_test/add');
$this->assertSession()->fieldExists("{$field_name}[0][value]", NULL);
$this->assertSession()->fieldNotExists("{$field_name}[0][format]");
// Retest the entity renders fine even though filter2 is disabled.
$entity = EntityTest::load($id);
$display = $entity_display_repository->getViewDisplay($entity->getEntityTypeId(), $entity->bundle(), 'full');
$content = $display->build($entity);
$rendered_entity = \Drupal::service('renderer')->renderRoot($content);
$this->assertStringContainsString('<div><strong><span>', (string) $rendered_entity);
// Test when 2 of 3 formats are selected.
$field->setSetting('allowed_formats', [$format1->id(), $format2->id()]);
$field->save();
$this->drupalGet('entity_test/add');
// We should see the 'format' selector again.
$this->assertSession()->fieldExists("{$field_name}[0][value]", NULL);
$this->assertSession()->optionExists("{$field_name}[0][format]", $format1->id());
$this->assertSession()->optionExists("{$field_name}[0][format]", $format2->id());
$this->assertSession()->optionNotExists("{$field_name}[0][format]", $format3->id());
// Change field to allow all formats by configuring none as allowed.
$field->setSetting('allowed_formats', []);
$field->save();
$this->drupalGet('entity_test/add');
// We should see the 'format' selector again.
$this->assertSession()->fieldExists("{$field_name}[0][value]", NULL);
$this->assertSession()->optionExists("{$field_name}[0][format]", $format1->id());
$this->assertSession()->optionExists("{$field_name}[0][format]", $format2->id());
$this->assertSession()->optionExists("{$field_name}[0][format]", $format3->id());
}
/** /**
* Helper function for testTextfieldWidgetsFormatted(). * Helper function for testTextfieldWidgetsFormatted().
*/ */
public function _testTextfieldWidgetsFormatted($field_type, $widget_type) { public function _testTextfieldWidgetsFormatted($field_type, $widget_type) {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container->get('renderer');
// Create a field. // Create a field.
$field_name = mb_strtolower($this->randomMachineName()); $field_name = mb_strtolower($this->randomMachineName());
$field_storage = FieldStorageConfig::create([ $field_storage = FieldStorageConfig::create([

View File

@ -3,6 +3,9 @@
namespace Drupal\Tests\text\Kernel; namespace Drupal\Tests\text\Kernel;
use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\filter\Entity\FilterFormat;
use Drupal\KernelTests\KernelTestBase; use Drupal\KernelTests\KernelTestBase;
use Drupal\text\Plugin\Field\FieldType\TextItemBase; use Drupal\text\Plugin\Field\FieldType\TextItemBase;
@ -16,7 +19,7 @@ class TextItemBaseTest extends KernelTestBase {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected static $modules = ['filter', 'text']; protected static $modules = ['filter', 'text', 'entity_test', 'field'];
/** /**
* Tests creation of sample values. * Tests creation of sample values.
@ -57,4 +60,42 @@ class TextItemBaseTest extends KernelTestBase {
]; ];
} }
/**
* @covers ::calculateDependencies
*/
public function testCalculateDependencies() {
$format = FilterFormat::create([
'format' => 'test_format',
'name' => 'Test format',
]);
$fieldName = mb_strtolower($this->randomMachineName());
$field_storage = FieldStorageConfig::create([
'field_name' => $fieldName,
'entity_type' => 'entity_test',
'type' => 'text',
]);
$field_storage->save();
$field = FieldConfig::create([
'field_name' => $fieldName,
'entity_type' => 'entity_test',
'bundle' => 'entity_test',
'settings' => [
'allowed_formats' => [$format->id()],
],
]);
$field->save();
$field->calculateDependencies();
$this->assertEquals([
'module' => [
'entity_test',
'text',
],
'config' => [
"field.storage.entity_test.$fieldName",
'filter.format.test_format',
],
], $field->getDependencies());
}
} }

View File

@ -5,6 +5,10 @@
* Contains post update hooks for the text module. * Contains post update hooks for the text module.
*/ */
use Drupal\Core\Config\Entity\ConfigEntityUpdater;
use Drupal\field\FieldConfigInterface;
use Drupal\text\Plugin\Field\FieldType\TextItemBase;
/** /**
* Implements hook_removed_post_updates(). * Implements hook_removed_post_updates().
*/ */
@ -14,3 +18,24 @@ function text_removed_post_updates() {
'text_post_update_add_required_summary_flag_form_display' => '10.0.0', 'text_post_update_add_required_summary_flag_form_display' => '10.0.0',
]; ];
} }
/**
* Add allowed_formats setting to existing text fields.
*/
function text_post_update_allowed_formats(&$sandbox = NULL) {
\Drupal::classResolver(ConfigEntityUpdater::class)
->update($sandbox, 'field_config', function (FieldConfigInterface $field_config) {
$class = get_class($field_config);
// Deal only with text fields and descendants.
if (is_a($class, TextItemBase::class, TRUE)) {
// Get the existing allowed_formats setting.
$allowed_formats = $field_config->get('settings.allowed_formats');
if (!is_array($allowed_formats) && empty($allowed_formats)) {
// Save default value if existing value not present.
$field_config->set('settings.allowed_formats', []);
return TRUE;
}
}
return FALSE;
});
}

View File

@ -80,7 +80,10 @@ class ViewEntityDependenciesTest extends ViewsKernelTestBase {
'field_storage' => FieldStorageConfig::loadByName('node', 'body'), 'field_storage' => FieldStorageConfig::loadByName('node', 'body'),
'bundle' => $content_type->id(), 'bundle' => $content_type->id(),
'label' => $this->randomMachineName() . '_body', 'label' => $this->randomMachineName() . '_body',
'settings' => ['display_summary' => TRUE], 'settings' => [
'display_summary' => TRUE,
'allowed_formats' => [],
],
])->save(); ])->save();
ViewTestData::createTestViews(static::class, ['views_test_config']); ViewTestData::createTestViews(static::class, ['views_test_config']);

View File

@ -19,4 +19,5 @@ default_value_callback: ''
settings: settings:
display_summary: false display_summary: false
required_summary: false required_summary: false
allowed_formats: { }
field_type: text_with_summary field_type: text_with_summary

View File

@ -16,5 +16,6 @@ required: false
translatable: true translatable: true
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text_long field_type: text_long

View File

@ -16,5 +16,6 @@ required: false
translatable: true translatable: true
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text_long field_type: text_long

View File

@ -19,4 +19,5 @@ default_value_callback: ''
settings: settings:
display_summary: true display_summary: true
required_summary: false required_summary: false
allowed_formats: { }
field_type: text_with_summary field_type: text_with_summary

View File

@ -19,4 +19,5 @@ default_value_callback: ''
settings: settings:
display_summary: true display_summary: true
required_summary: false required_summary: false
allowed_formats: { }
field_type: text_with_summary field_type: text_with_summary

View File

@ -16,5 +16,6 @@ required: true
translatable: true translatable: true
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text_long field_type: text_long

View File

@ -16,5 +16,6 @@ required: true
translatable: true translatable: true
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text_long field_type: text_long

View File

@ -19,4 +19,5 @@ default_value_callback: ''
settings: settings:
display_summary: false display_summary: false
required_summary: false required_summary: false
allowed_formats: { }
field_type: text_with_summary field_type: text_with_summary

View File

@ -16,5 +16,6 @@ required: true
translatable: true translatable: true
default_value: { } default_value: { }
default_value_callback: '' default_value_callback: ''
settings: { } settings:
allowed_formats: { }
field_type: text_long field_type: text_long

View File

@ -19,4 +19,5 @@ default_value_callback: ''
settings: settings:
display_summary: true display_summary: true
required_summary: false required_summary: false
allowed_formats: { }
field_type: text_with_summary field_type: text_with_summary

View File

@ -19,4 +19,5 @@ default_value_callback: ''
settings: settings:
display_summary: true display_summary: true
required_summary: false required_summary: false
allowed_formats: { }
field_type: text_with_summary field_type: text_with_summary