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
parent
e2d4dcfdf2
commit
82576b6002
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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'))
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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'] = [
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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([
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -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']);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue