Move all files to 2017/
This commit is contained in:
parent
ac7370f67f
commit
2875863330
15717 changed files with 0 additions and 0 deletions
|
@ -0,0 +1 @@
|
|||
default_summary_length: 600
|
133
2017/web/core/modules/text/config/schema/text.schema.yml
Normal file
133
2017/web/core/modules/text/config/schema/text.schema.yml
Normal file
|
@ -0,0 +1,133 @@
|
|||
# Schema for the configuration files of the text module.
|
||||
|
||||
text.settings:
|
||||
type: config_object
|
||||
label: 'Text settings'
|
||||
mapping:
|
||||
default_summary_length:
|
||||
type: integer
|
||||
label: 'Default summary length'
|
||||
|
||||
field.storage_settings.text:
|
||||
type: mapping
|
||||
label: 'Text (formatted) settings'
|
||||
mapping:
|
||||
max_length:
|
||||
type: integer
|
||||
label: 'Maximum length'
|
||||
|
||||
field.field_settings.text:
|
||||
type: mapping
|
||||
label: 'Text (formatted) settings'
|
||||
|
||||
field.value.text:
|
||||
type: mapping
|
||||
label: 'Default value'
|
||||
mapping:
|
||||
value:
|
||||
type: label
|
||||
label: 'Value'
|
||||
format:
|
||||
type: string
|
||||
label: 'Text format'
|
||||
|
||||
field.storage_settings.text_long:
|
||||
label: 'Text (formatted, long) settings'
|
||||
type: mapping
|
||||
|
||||
field.field_settings.text_long:
|
||||
label: 'Text (formatted, long) settings'
|
||||
type: mapping
|
||||
|
||||
field.value.text_long:
|
||||
type: mapping
|
||||
label: 'Default value'
|
||||
mapping:
|
||||
value:
|
||||
type: text
|
||||
label: 'Value'
|
||||
format:
|
||||
type: string
|
||||
label: 'Text format'
|
||||
|
||||
field.storage_settings.text_with_summary:
|
||||
label: 'Text (formatted, long, with summary) settings'
|
||||
type: mapping
|
||||
|
||||
field.field_settings.text_with_summary:
|
||||
type: mapping
|
||||
label: 'Text (formatted, long, with summary) settings'
|
||||
mapping:
|
||||
display_summary:
|
||||
type: boolean
|
||||
label: 'Summary input'
|
||||
|
||||
field.value.text_with_summary:
|
||||
type: mapping
|
||||
label: 'Default value'
|
||||
mapping:
|
||||
value:
|
||||
type: text
|
||||
label: 'Body'
|
||||
summary:
|
||||
type: string
|
||||
label: 'Summary'
|
||||
format:
|
||||
type: string
|
||||
label: 'Text format'
|
||||
|
||||
field.formatter.settings.text_default:
|
||||
type: mapping
|
||||
label: 'Formatted text default display format settings'
|
||||
|
||||
field.formatter.settings.text_summary_or_trimmed:
|
||||
type: mapping
|
||||
label: 'Summary or trimmed formatted text display format settings'
|
||||
mapping:
|
||||
trim_length:
|
||||
type: integer
|
||||
label: 'Trim length'
|
||||
|
||||
field.formatter.settings.text_trimmed:
|
||||
type: mapping
|
||||
label: 'Trimmed text display format settings'
|
||||
mapping:
|
||||
trim_length:
|
||||
type: integer
|
||||
label: 'Trim length'
|
||||
|
||||
field.widget.settings.text_textarea:
|
||||
type: mapping
|
||||
label: 'Text area (multiple rows) display format settings'
|
||||
mapping:
|
||||
rows:
|
||||
type: integer
|
||||
label: 'Rows'
|
||||
placeholder:
|
||||
type: label
|
||||
label: 'Placeholder'
|
||||
|
||||
field.widget.settings.text_textarea_with_summary:
|
||||
type: mapping
|
||||
label: 'Text area with a summary display format settings'
|
||||
mapping:
|
||||
rows:
|
||||
type: integer
|
||||
label: 'Rows'
|
||||
summary_rows:
|
||||
type: integer
|
||||
label: 'Number of summary rows'
|
||||
placeholder:
|
||||
type: label
|
||||
label: 'Placeholder'
|
||||
|
||||
field.widget.settings.text_textfield:
|
||||
type: mapping
|
||||
label: 'Text field display format settings'
|
||||
mapping:
|
||||
size:
|
||||
type: integer
|
||||
label: 'Size of textfield'
|
||||
placeholder:
|
||||
type: label
|
||||
label: 'Placeholder'
|
16
2017/web/core/modules/text/migrations/text_settings.yml
Normal file
16
2017/web/core/modules/text/migrations/text_settings.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
id: text_settings
|
||||
label: Drupal teaser length configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- teaser_length
|
||||
source_module: text
|
||||
process:
|
||||
default_summary_length: teaser_length
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: text.settings
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\Field\FieldFormatter;
|
||||
|
||||
use Drupal\Core\Field\FormatterBase;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'text_default' formatter.
|
||||
*
|
||||
* @FieldFormatter(
|
||||
* id = "text_default",
|
||||
* label = @Translation("Default"),
|
||||
* field_types = {
|
||||
* "text",
|
||||
* "text_long",
|
||||
* "text_with_summary",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class TextDefaultFormatter extends FormatterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function viewElements(FieldItemListInterface $items, $langcode) {
|
||||
$elements = [];
|
||||
|
||||
// The ProcessedText element already handles cache context & tag bubbling.
|
||||
// @see \Drupal\filter\Element\ProcessedText::preRenderText()
|
||||
foreach ($items as $delta => $item) {
|
||||
$elements[$delta] = [
|
||||
'#type' => 'processed_text',
|
||||
'#text' => $item->value,
|
||||
'#format' => $item->format,
|
||||
'#langcode' => $item->getLangcode(),
|
||||
];
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\Field\FieldFormatter;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'text_summary_or_trimmed' formatter.
|
||||
*
|
||||
* @FieldFormatter(
|
||||
* id = "text_summary_or_trimmed",
|
||||
* label = @Translation("Summary or trimmed"),
|
||||
* field_types = {
|
||||
* "text_with_summary"
|
||||
* },
|
||||
* quickedit = {
|
||||
* "editor" = "form"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class TextSummaryOrTrimmedFormatter extends TextTrimmedFormatter {}
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\Field\FieldFormatter;
|
||||
|
||||
use Drupal\Core\Field\FormatterBase;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'text_trimmed' formatter.
|
||||
*
|
||||
* Note: This class also contains the implementations used by the
|
||||
* 'text_summary_or_trimmed' formatter.
|
||||
*
|
||||
* @see \Drupal\text\Field\Formatter\TextSummaryOrTrimmedFormatter
|
||||
*
|
||||
* @FieldFormatter(
|
||||
* id = "text_trimmed",
|
||||
* label = @Translation("Trimmed"),
|
||||
* field_types = {
|
||||
* "text",
|
||||
* "text_long",
|
||||
* "text_with_summary"
|
||||
* },
|
||||
* quickedit = {
|
||||
* "editor" = "form"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class TextTrimmedFormatter extends FormatterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultSettings() {
|
||||
return [
|
||||
'trim_length' => '600',
|
||||
] + parent::defaultSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm(array $form, FormStateInterface $form_state) {
|
||||
$element['trim_length'] = [
|
||||
'#title' => t('Trimmed limit'),
|
||||
'#type' => 'number',
|
||||
'#field_suffix' => t('characters'),
|
||||
'#default_value' => $this->getSetting('trim_length'),
|
||||
'#description' => t('If the summary is not set, the trimmed %label field will end at the last full sentence before this character limit.', ['%label' => $this->fieldDefinition->getLabel()]),
|
||||
'#min' => 1,
|
||||
'#required' => TRUE,
|
||||
];
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsSummary() {
|
||||
$summary = [];
|
||||
$summary[] = t('Trimmed limit: @trim_length characters', ['@trim_length' => $this->getSetting('trim_length')]);
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function viewElements(FieldItemListInterface $items, $langcode) {
|
||||
$elements = [];
|
||||
|
||||
$render_as_summary = function (&$element) {
|
||||
// Make sure any default #pre_render callbacks are set on the element,
|
||||
// because text_pre_render_summary() must run last.
|
||||
$element += \Drupal::service('element_info')->getInfo($element['#type']);
|
||||
// Add the #pre_render callback that renders the text into a summary.
|
||||
$element['#pre_render'][] = [TextTrimmedFormatter::class, 'preRenderSummary'];
|
||||
// Pass on the trim length to the #pre_render callback via a property.
|
||||
$element['#text_summary_trim_length'] = $this->getSetting('trim_length');
|
||||
};
|
||||
|
||||
// The ProcessedText element already handles cache context & tag bubbling.
|
||||
// @see \Drupal\filter\Element\ProcessedText::preRenderText()
|
||||
foreach ($items as $delta => $item) {
|
||||
$elements[$delta] = [
|
||||
'#type' => 'processed_text',
|
||||
'#text' => NULL,
|
||||
'#format' => $item->format,
|
||||
'#langcode' => $item->getLangcode(),
|
||||
];
|
||||
|
||||
if ($this->getPluginId() == 'text_summary_or_trimmed' && !empty($item->summary)) {
|
||||
$elements[$delta]['#text'] = $item->summary;
|
||||
}
|
||||
else {
|
||||
$elements[$delta]['#text'] = $item->value;
|
||||
$render_as_summary($elements[$delta]);
|
||||
}
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-render callback: Renders a processed text element's #markup as a summary.
|
||||
*
|
||||
* @param array $element
|
||||
* A structured array with the following key-value pairs:
|
||||
* - #markup: the filtered text (as filtered by filter_pre_render_text())
|
||||
* - #format: containing the machine name of the filter format to be used to
|
||||
* filter the text. Defaults to the fallback format. See
|
||||
* filter_fallback_format().
|
||||
* - #text_summary_trim_length: the desired character length of the summary
|
||||
* (used by text_summary())
|
||||
*
|
||||
* @return array
|
||||
* The passed-in element with the filtered text in '#markup' trimmed.
|
||||
*
|
||||
* @see filter_pre_render_text()
|
||||
* @see text_summary()
|
||||
*/
|
||||
public static function preRenderSummary(array $element) {
|
||||
$element['#markup'] = text_summary($element['#markup'], $element['#format'], $element['#text_summary_trim_length']);
|
||||
return $element;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\Field\FieldType;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'text' field type.
|
||||
*
|
||||
* @FieldType(
|
||||
* id = "text",
|
||||
* label = @Translation("Text (formatted)"),
|
||||
* description = @Translation("This field stores a text with a text format."),
|
||||
* category = @Translation("Text"),
|
||||
* default_widget = "text_textfield",
|
||||
* default_formatter = "text_default"
|
||||
* )
|
||||
*/
|
||||
class TextItem extends TextItemBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultStorageSettings() {
|
||||
return [
|
||||
'max_length' => 255,
|
||||
] + parent::defaultStorageSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function schema(FieldStorageDefinitionInterface $field_definition) {
|
||||
return [
|
||||
'columns' => [
|
||||
'value' => [
|
||||
'type' => 'varchar',
|
||||
'length' => $field_definition->getSetting('max_length'),
|
||||
],
|
||||
'format' => [
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
'format' => ['format'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConstraints() {
|
||||
$constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
|
||||
$constraints = parent::getConstraints();
|
||||
|
||||
if ($max_length = $this->getSetting('max_length')) {
|
||||
$constraints[] = $constraint_manager->create('ComplexData', [
|
||||
'value' => [
|
||||
'Length' => [
|
||||
'max' => $max_length,
|
||||
'maxMessage' => t('%name: the text may not be longer than @max characters.', ['%name' => $this->getFieldDefinition()->getLabel(), '@max' => $max_length]),
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
return $constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
|
||||
$element = [];
|
||||
|
||||
$element['max_length'] = [
|
||||
'#type' => 'number',
|
||||
'#title' => t('Maximum length'),
|
||||
'#default_value' => $this->getSetting('max_length'),
|
||||
'#required' => TRUE,
|
||||
'#description' => t('The maximum length of the field in characters.'),
|
||||
'#min' => 1,
|
||||
'#disabled' => $has_data,
|
||||
];
|
||||
$element += parent::storageSettingsForm($form, $form_state, $has_data);
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\Field\FieldType;
|
||||
|
||||
use Drupal\Component\Utility\Random;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldItemBase;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\TypedData\DataDefinition;
|
||||
|
||||
/**
|
||||
* Base class for 'text' configurable field types.
|
||||
*/
|
||||
abstract class TextItemBase extends FieldItemBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
|
||||
$properties['value'] = DataDefinition::create('string')
|
||||
->setLabel(t('Text'))
|
||||
->setRequired(TRUE);
|
||||
|
||||
$properties['format'] = DataDefinition::create('filter_format')
|
||||
->setLabel(t('Text format'));
|
||||
|
||||
$properties['processed'] = DataDefinition::create('string')
|
||||
->setLabel(t('Processed text'))
|
||||
->setDescription(t('The text with the text format applied.'))
|
||||
->setComputed(TRUE)
|
||||
->setClass('\Drupal\text\TextProcessed')
|
||||
->setSetting('text source', 'value')
|
||||
->setInternal(FALSE);
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applyDefaultValue($notify = TRUE) {
|
||||
// @todo: Add in the filter default format here.
|
||||
$this->setValue(['format' => NULL], $notify);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEmpty() {
|
||||
$value = $this->get('value')->getValue();
|
||||
return $value === NULL || $value === '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onChange($property_name, $notify = TRUE) {
|
||||
// Unset processed properties that are affected by the change.
|
||||
foreach ($this->definition->getPropertyDefinitions() as $property => $definition) {
|
||||
if ($definition->getClass() == '\Drupal\text\TextProcessed') {
|
||||
if ($property_name == 'format' || ($definition->getSetting('text source') == $property_name)) {
|
||||
$this->writePropertyValue($property, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
parent::onChange($property_name, $notify);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
|
||||
$random = new Random();
|
||||
$settings = $field_definition->getSettings();
|
||||
|
||||
if (empty($settings['max_length'])) {
|
||||
// Textarea handling
|
||||
$value = $random->paragraphs();
|
||||
}
|
||||
else {
|
||||
// Textfield handling.
|
||||
$value = substr($random->sentences(mt_rand(1, $settings['max_length'] / 3), FALSE), 0, $settings['max_length']);
|
||||
}
|
||||
|
||||
$values = [
|
||||
'value' => $value,
|
||||
'summary' => $value,
|
||||
'format' => filter_fallback_format(),
|
||||
];
|
||||
return $values;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\Field\FieldType;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'text_long' field type.
|
||||
*
|
||||
* @FieldType(
|
||||
* id = "text_long",
|
||||
* label = @Translation("Text (formatted, long)"),
|
||||
* description = @Translation("This field stores a long text with a text format."),
|
||||
* category = @Translation("Text"),
|
||||
* default_widget = "text_textarea",
|
||||
* default_formatter = "text_default"
|
||||
* )
|
||||
*/
|
||||
class TextLongItem extends TextItemBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function schema(FieldStorageDefinitionInterface $field_definition) {
|
||||
return [
|
||||
'columns' => [
|
||||
'value' => [
|
||||
'type' => 'text',
|
||||
'size' => 'big',
|
||||
],
|
||||
'format' => [
|
||||
'type' => 'varchar_ascii',
|
||||
'length' => 255,
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
'format' => ['format'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\Field\FieldType;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\TypedData\DataDefinition;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'text_with_summary' field type.
|
||||
*
|
||||
* @FieldType(
|
||||
* id = "text_with_summary",
|
||||
* label = @Translation("Text (formatted, long, with summary)"),
|
||||
* description = @Translation("This field stores long text with a format and an optional summary."),
|
||||
* category = @Translation("Text"),
|
||||
* default_widget = "text_textarea_with_summary",
|
||||
* default_formatter = "text_default"
|
||||
* )
|
||||
*/
|
||||
class TextWithSummaryItem extends TextItemBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultFieldSettings() {
|
||||
return [
|
||||
'display_summary' => 0,
|
||||
] + parent::defaultFieldSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
|
||||
$properties = parent::propertyDefinitions($field_definition);
|
||||
|
||||
$properties['summary'] = DataDefinition::create('string')
|
||||
->setLabel(t('Summary'));
|
||||
|
||||
$properties['summary_processed'] = DataDefinition::create('string')
|
||||
->setLabel(t('Processed summary'))
|
||||
->setDescription(t('The summary text with the text format applied.'))
|
||||
->setComputed(TRUE)
|
||||
->setClass('\Drupal\text\TextProcessed')
|
||||
->setSetting('text source', 'summary');
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function schema(FieldStorageDefinitionInterface $field_definition) {
|
||||
return [
|
||||
'columns' => [
|
||||
'value' => [
|
||||
'type' => 'text',
|
||||
'size' => 'big',
|
||||
],
|
||||
'summary' => [
|
||||
'type' => 'text',
|
||||
'size' => 'big',
|
||||
],
|
||||
'format' => [
|
||||
'type' => 'varchar_ascii',
|
||||
'length' => 255,
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
'format' => ['format'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEmpty() {
|
||||
$value = $this->get('summary')->getValue();
|
||||
return parent::isEmpty() && ($value === NULL || $value === '');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
|
||||
$element = [];
|
||||
$settings = $this->getSettings();
|
||||
|
||||
$element['display_summary'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Summary input'),
|
||||
'#default_value' => $settings['display_summary'],
|
||||
'#description' => t('This allows authors to input an explicit summary, to be displayed instead of the automatically trimmed text when using the "Summary or trimmed" display type.'),
|
||||
];
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\Field\FieldWidget;
|
||||
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldWidget\StringTextareaWidget;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'text_textarea' widget.
|
||||
*
|
||||
* @FieldWidget(
|
||||
* id = "text_textarea",
|
||||
* label = @Translation("Text area (multiple rows)"),
|
||||
* field_types = {
|
||||
* "text_long"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class TextareaWidget extends StringTextareaWidget {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm(array $form, FormStateInterface $form_state) {
|
||||
$element = parent::settingsForm($form, $form_state);
|
||||
$element['rows']['#description'] = $this->t('Text editors (like CKEditor) may override this setting.');
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
|
||||
$main_widget = parent::formElement($items, $delta, $element, $form, $form_state);
|
||||
|
||||
$element = $main_widget['value'];
|
||||
$element['#type'] = 'text_format';
|
||||
$element['#format'] = $items[$delta]->format;
|
||||
$element['#base_type'] = $main_widget['value']['#type'];
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
|
||||
if ($violation->arrayPropertyPath == ['format'] && isset($element['format']['#access']) && !$element['format']['#access']) {
|
||||
// Ignore validation errors for formats if formats may not be changed,
|
||||
// i.e. when existing formats become invalid. See filter_process_format().
|
||||
return FALSE;
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\Field\FieldWidget;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'text_textarea_with_summary' widget.
|
||||
*
|
||||
* @FieldWidget(
|
||||
* id = "text_textarea_with_summary",
|
||||
* label = @Translation("Text area with a summary"),
|
||||
* field_types = {
|
||||
* "text_with_summary"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class TextareaWithSummaryWidget extends TextareaWidget {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultSettings() {
|
||||
return [
|
||||
'rows' => '9',
|
||||
'summary_rows' => '3',
|
||||
'placeholder' => '',
|
||||
] + parent::defaultSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm(array $form, FormStateInterface $form_state) {
|
||||
$element = parent::settingsForm($form, $form_state);
|
||||
$element['summary_rows'] = [
|
||||
'#type' => 'number',
|
||||
'#title' => t('Summary rows'),
|
||||
'#default_value' => $this->getSetting('summary_rows'),
|
||||
'#description' => $element['rows']['#description'],
|
||||
'#required' => TRUE,
|
||||
'#min' => 1,
|
||||
];
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsSummary() {
|
||||
$summary = parent::settingsSummary();
|
||||
|
||||
$summary[] = t('Number of summary rows: @rows', ['@rows' => $this->getSetting('summary_rows')]);
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
|
||||
$element = parent::formElement($items, $delta, $element, $form, $form_state);
|
||||
|
||||
$display_summary = $items[$delta]->summary || $this->getFieldSetting('display_summary');
|
||||
$element['summary'] = [
|
||||
'#type' => $display_summary ? 'textarea' : 'value',
|
||||
'#default_value' => $items[$delta]->summary,
|
||||
'#title' => t('Summary'),
|
||||
'#rows' => $this->getSetting('summary_rows'),
|
||||
'#description' => t('Leave blank to use trimmed value of full text as the summary.'),
|
||||
'#attached' => [
|
||||
'library' => ['text/drupal.text'],
|
||||
],
|
||||
'#attributes' => ['class' => ['js-text-summary', 'text-summary']],
|
||||
'#prefix' => '<div class="js-text-summary-wrapper text-summary-wrapper">',
|
||||
'#suffix' => '</div>',
|
||||
'#weight' => -10,
|
||||
];
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
|
||||
$element = parent::errorElement($element, $violation, $form, $form_state);
|
||||
return ($element === FALSE) ? FALSE : $element[$violation->arrayPropertyPath[0]];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\Field\FieldWidget;
|
||||
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldWidget\StringTextfieldWidget;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'text_textfield' widget.
|
||||
*
|
||||
* @FieldWidget(
|
||||
* id = "text_textfield",
|
||||
* label = @Translation("Text field"),
|
||||
* field_types = {
|
||||
* "text"
|
||||
* },
|
||||
* )
|
||||
*/
|
||||
class TextfieldWidget extends StringTextfieldWidget {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
|
||||
$main_widget = parent::formElement($items, $delta, $element, $form, $form_state);
|
||||
|
||||
$element = $main_widget['value'];
|
||||
$element['#type'] = 'text_format';
|
||||
$element['#format'] = isset($items[$delta]->format) ? $items[$delta]->format : NULL;
|
||||
$element['#base_type'] = $main_widget['value']['#type'];
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
|
||||
if ($violation->arrayPropertyPath == ['format'] && isset($element['format']['#access']) && !$element['format']['#access']) {
|
||||
// Ignore validation errors for formats if formats may not be changed,
|
||||
// i.e. when existing formats become invalid. See filter_process_format().
|
||||
return FALSE;
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\migrate\cckfield;
|
||||
|
||||
@trigger_error('TextField is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\text\Plugin\migrate\field\d6\TextField or \Drupal\text\Plugin\migrate\field\d7\TextField instead.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\cckfield\CckFieldPluginBase;
|
||||
|
||||
/**
|
||||
* @MigrateCckField(
|
||||
* id = "text",
|
||||
* type_map = {
|
||||
* "text" = "text",
|
||||
* "text_long" = "text_long",
|
||||
* "text_with_summary" = "text_with_summary"
|
||||
* },
|
||||
* core = {6,7},
|
||||
* source_module = "text",
|
||||
* destination_module = "text",
|
||||
* )
|
||||
*
|
||||
* @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use
|
||||
* \Drupal\text\Plugin\migrate\field\d6\TextField or
|
||||
* \Drupal\text\Plugin\migrate\field\d7\TextField instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2751897
|
||||
*/
|
||||
class TextField extends CckFieldPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldWidgetMap() {
|
||||
return [
|
||||
'text_textfield' => 'text_textfield',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldFormatterMap() {
|
||||
return [
|
||||
'default' => 'text_default',
|
||||
'trimmed' => 'text_trimmed',
|
||||
'plain' => 'basic_string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processCckFieldValues(MigrationInterface $migration, $field_name, $field_info) {
|
||||
$widget_type = isset($field_info['widget_type']) ? $field_info['widget_type'] : $field_info['widget']['type'];
|
||||
|
||||
if ($widget_type == 'optionwidgets_onoff') {
|
||||
$process = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
$checked_value = explode("\n", $field_info['global_settings']['allowed_values'])[1];
|
||||
if (strpos($checked_value, '|') !== FALSE) {
|
||||
$checked_value = substr($checked_value, 0, strpos($checked_value, '|'));
|
||||
}
|
||||
$process['value']['map'][$checked_value] = 1;
|
||||
}
|
||||
else {
|
||||
// See \Drupal\migrate_drupal\Plugin\migrate\source\d6\User::baseFields(),
|
||||
// signature_format for an example of the YAML that represents this
|
||||
// process array.
|
||||
$process = [
|
||||
'value' => 'value',
|
||||
'format' => [
|
||||
[
|
||||
'plugin' => 'static_map',
|
||||
'bypass' => TRUE,
|
||||
'source' => 'format',
|
||||
'map' => [0 => NULL],
|
||||
],
|
||||
[
|
||||
'plugin' => 'skip_on_empty',
|
||||
'method' => 'process',
|
||||
],
|
||||
[
|
||||
'plugin' => 'migration',
|
||||
'migration' => [
|
||||
'd6_filter_format',
|
||||
'd7_filter_format',
|
||||
],
|
||||
'source' => 'format',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$process = [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => $field_name,
|
||||
'process' => $process,
|
||||
];
|
||||
$migration->setProcessOfProperty($field_name, $process);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldType(Row $row) {
|
||||
$widget_type = $row->getSourceProperty('widget_type');
|
||||
$settings = $row->getSourceProperty('global_settings');
|
||||
|
||||
if ($widget_type == 'text_textfield') {
|
||||
$field_type = $settings['text_processing'] ? 'text' : 'string';
|
||||
if (empty($settings['max_length']) || $settings['max_length'] > 255) {
|
||||
$field_type .= '_long';
|
||||
}
|
||||
return $field_type;
|
||||
}
|
||||
|
||||
if ($widget_type == 'text_textarea') {
|
||||
$field_type = $settings['text_processing'] ? 'text_long' : 'string_long';
|
||||
return $field_type;
|
||||
}
|
||||
|
||||
switch ($widget_type) {
|
||||
case 'optionwidgets_buttons':
|
||||
case 'optionwidgets_select':
|
||||
return 'list_string';
|
||||
case 'optionwidgets_onoff':
|
||||
return 'boolean';
|
||||
default:
|
||||
return parent::getFieldType($row);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\migrate\field\d6;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
|
||||
|
||||
/**
|
||||
* @MigrateField(
|
||||
* id = "d6_text",
|
||||
* type_map = {
|
||||
* "text" = "text",
|
||||
* "text_long" = "text_long",
|
||||
* "text_with_summary" = "text_with_summary"
|
||||
* },
|
||||
* core = {6},
|
||||
* source_module = "text",
|
||||
* destination_module = "text",
|
||||
* )
|
||||
*/
|
||||
class TextField extends FieldPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldWidgetMap() {
|
||||
return [
|
||||
'text_textfield' => 'text_textfield',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldFormatterMap() {
|
||||
return [
|
||||
'default' => 'text_default',
|
||||
'trimmed' => 'text_trimmed',
|
||||
'plain' => 'basic_string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defineValueProcessPipeline(MigrationInterface $migration, $field_name, $field_info) {
|
||||
$widget_type = isset($field_info['widget_type']) ? $field_info['widget_type'] : $field_info['widget']['type'];
|
||||
|
||||
if ($widget_type == 'optionwidgets_onoff') {
|
||||
$process = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
$checked_value = explode("\n", $field_info['global_settings']['allowed_values'])[1];
|
||||
if (strpos($checked_value, '|') !== FALSE) {
|
||||
$checked_value = substr($checked_value, 0, strpos($checked_value, '|'));
|
||||
}
|
||||
$process['value']['map'][$checked_value] = 1;
|
||||
}
|
||||
else {
|
||||
// See \Drupal\migrate_drupal\Plugin\migrate\source\d6\User::baseFields(),
|
||||
// signature_format for an example of the YAML that represents this
|
||||
// process array.
|
||||
$process = [
|
||||
'value' => 'value',
|
||||
'format' => [
|
||||
[
|
||||
'plugin' => 'static_map',
|
||||
'bypass' => TRUE,
|
||||
'source' => 'format',
|
||||
'map' => [0 => NULL],
|
||||
],
|
||||
[
|
||||
'plugin' => 'skip_on_empty',
|
||||
'method' => 'process',
|
||||
],
|
||||
[
|
||||
'plugin' => 'migration',
|
||||
'migration' => [
|
||||
'd6_filter_format',
|
||||
'd7_filter_format',
|
||||
],
|
||||
'source' => 'format',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$process = [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => $field_name,
|
||||
'process' => $process,
|
||||
];
|
||||
$migration->setProcessOfProperty($field_name, $process);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldType(Row $row) {
|
||||
$widget_type = $row->getSourceProperty('widget_type');
|
||||
$settings = $row->getSourceProperty('global_settings');
|
||||
|
||||
if ($widget_type == 'text_textfield') {
|
||||
$field_type = $settings['text_processing'] ? 'text' : 'string';
|
||||
if (empty($settings['max_length']) || $settings['max_length'] > 255) {
|
||||
$field_type .= '_long';
|
||||
}
|
||||
return $field_type;
|
||||
}
|
||||
|
||||
if ($widget_type == 'text_textarea') {
|
||||
$field_type = $settings['text_processing'] ? 'text_long' : 'string_long';
|
||||
return $field_type;
|
||||
}
|
||||
|
||||
switch ($widget_type) {
|
||||
case 'optionwidgets_buttons':
|
||||
case 'optionwidgets_select':
|
||||
return 'list_string';
|
||||
case 'optionwidgets_onoff':
|
||||
return 'boolean';
|
||||
default:
|
||||
return parent::getFieldType($row);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text\Plugin\migrate\field\d7;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate\MigrateSkipRowException;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
|
||||
|
||||
/**
|
||||
* @MigrateField(
|
||||
* id = "d7_text",
|
||||
* type_map = {
|
||||
* "text" = "text",
|
||||
* "text_long" = "text_long",
|
||||
* "text_with_summary" = "text_with_summary"
|
||||
* },
|
||||
* core = {7},
|
||||
* source_module = "text",
|
||||
* destination_module = "text",
|
||||
* )
|
||||
*/
|
||||
class TextField extends FieldPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldFormatterType(Row $row) {
|
||||
$field_type = $this->getFieldType($row);
|
||||
$formatter_type = $row->getSourceProperty('formatter/type');
|
||||
|
||||
switch ($field_type) {
|
||||
case 'string':
|
||||
$formatter_type = str_replace('text_default', 'string', $formatter_type);
|
||||
break;
|
||||
case 'string_long':
|
||||
$formatter_type = str_replace('text_default', 'basic_string', $formatter_type);
|
||||
break;
|
||||
}
|
||||
|
||||
return $formatter_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldWidgetType(Row $row) {
|
||||
$field_type = $this->getFieldType($row);
|
||||
$widget_type = $row->getSourceProperty('widget/type');
|
||||
|
||||
switch ($field_type) {
|
||||
case 'string':
|
||||
$widget_type = str_replace('text_textfield', 'string_textfield', $widget_type);
|
||||
break;
|
||||
case 'string_long':
|
||||
$widget_type = str_replace('text_textarea', 'string_textarea', $widget_type);
|
||||
break;
|
||||
}
|
||||
|
||||
return $widget_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldType(Row $row) {
|
||||
$type = $row->getSourceProperty('type');
|
||||
$plain_text = FALSE;
|
||||
$filtered_text = FALSE;
|
||||
|
||||
foreach ($row->getSourceProperty('instances') as $instance) {
|
||||
// Check if this field has plain text instances, filtered text instances,
|
||||
// or both.
|
||||
$data = unserialize($instance['data']);
|
||||
switch ($data['settings']['text_processing']) {
|
||||
case '0':
|
||||
$plain_text = TRUE;
|
||||
break;
|
||||
case '1':
|
||||
$filtered_text = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($type, ['text', 'text_long'])) {
|
||||
// If a text or text_long field has only plain text instances, migrate it
|
||||
// to a string or string_long field.
|
||||
if ($plain_text && !$filtered_text) {
|
||||
$type = str_replace(['text', 'text_long'], ['string', 'string_long'], $type);
|
||||
}
|
||||
// If a text or text_long field has both plain text and filtered text
|
||||
// instances, skip the row.
|
||||
elseif ($plain_text && $filtered_text) {
|
||||
$field_name = $row->getSourceProperty('field_name');
|
||||
throw new MigrateSkipRowException("Can't migrate source field $field_name configured with both plain text and filtered text processing. See https://www.drupal.org/docs/8/upgrade/known-issues-when-upgrading-from-drupal-6-or-7-to-drupal-8#plain-text");
|
||||
}
|
||||
}
|
||||
elseif ($type == 'text_with_summary' && $plain_text) {
|
||||
// If a text_with_summary field has plain text instances, skip the row
|
||||
// since there's no such thing as a string_with_summary field.
|
||||
$field_name = $row->getSourceProperty('field_name');
|
||||
throw new MigrateSkipRowException("Can't migrate source field $field_name of type text_with_summary configured with plain text processing. See https://www.drupal.org/docs/8/upgrade/known-issues-when-upgrading-from-drupal-6-or-7-to-drupal-8#plain-text");
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
}
|
112
2017/web/core/modules/text/src/TextProcessed.php
Normal file
112
2017/web/core/modules/text/src/TextProcessed.php
Normal file
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\text;
|
||||
|
||||
use Drupal\Core\Cache\CacheableDependencyInterface;
|
||||
use Drupal\Core\TypedData\DataDefinitionInterface;
|
||||
use Drupal\Core\TypedData\TypedDataInterface;
|
||||
use Drupal\Core\TypedData\TypedData;
|
||||
use Drupal\filter\FilterProcessResult;
|
||||
use Drupal\filter\Render\FilteredMarkup;
|
||||
|
||||
/**
|
||||
* A computed property for processing text with a format.
|
||||
*
|
||||
* Required settings (below the definition's 'settings' key) are:
|
||||
* - text source: The text property containing the to be processed text.
|
||||
*/
|
||||
class TextProcessed extends TypedData implements CacheableDependencyInterface {
|
||||
|
||||
/**
|
||||
* Cached processed text.
|
||||
*
|
||||
* @var \Drupal\filter\FilterProcessResult|null
|
||||
*/
|
||||
protected $processed = NULL;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) {
|
||||
parent::__construct($definition, $name, $parent);
|
||||
|
||||
if ($definition->getSetting('text source') === NULL) {
|
||||
throw new \InvalidArgumentException("The definition's 'text source' key has to specify the name of the text property to be processed.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getValue() {
|
||||
if ($this->processed !== NULL) {
|
||||
return FilteredMarkup::create($this->processed->getProcessedText());
|
||||
}
|
||||
|
||||
$item = $this->getParent();
|
||||
$text = $item->{($this->definition->getSetting('text source'))};
|
||||
|
||||
// Avoid doing unnecessary work on empty strings.
|
||||
if (!isset($text) || $text === '') {
|
||||
$this->processed = new FilterProcessResult('');
|
||||
}
|
||||
else {
|
||||
$build = [
|
||||
'#type' => 'processed_text',
|
||||
'#text' => $text,
|
||||
'#format' => $item->format,
|
||||
'#filter_types_to_skip' => [],
|
||||
'#langcode' => $item->getLangcode(),
|
||||
];
|
||||
// Capture the cacheability metadata associated with the processed text.
|
||||
$processed_text = $this->getRenderer()->renderPlain($build);
|
||||
$this->processed = FilterProcessResult::createFromRenderArray($build)->setProcessedText((string) $processed_text);
|
||||
}
|
||||
return FilteredMarkup::create($this->processed->getProcessedText());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setValue($value, $notify = TRUE) {
|
||||
$this->processed = $value;
|
||||
// Notify the parent of any changes.
|
||||
if ($notify && isset($this->parent)) {
|
||||
$this->parent->onChange($this->name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheTags() {
|
||||
$this->getValue();
|
||||
return $this->processed->getCacheTags();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheContexts() {
|
||||
$this->getValue();
|
||||
return $this->processed->getCacheContexts();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheMaxAge() {
|
||||
$this->getValue();
|
||||
return $this->processed->getCacheMaxAge();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the renderer service.
|
||||
*
|
||||
* @return \Drupal\Core\Render\RendererInterface
|
||||
*/
|
||||
protected function getRenderer() {
|
||||
return \Drupal::service('renderer');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Functional;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\Tests\field\Functional\String\StringFieldTest;
|
||||
use Drupal\Tests\TestFileCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests the creation of text fields.
|
||||
*
|
||||
* @group text
|
||||
*/
|
||||
class TextFieldTest extends StringFieldTest {
|
||||
|
||||
use TestFileCreationTrait {
|
||||
getTestFiles as drupalGetTestFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* A user with relevant administrative privileges.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser(['administer filters']);
|
||||
}
|
||||
|
||||
// Test fields.
|
||||
|
||||
/**
|
||||
* Test text field validation.
|
||||
*/
|
||||
public function testTextFieldValidation() {
|
||||
// Create a field with settings to validate.
|
||||
$max_length = 3;
|
||||
$field_name = mb_strtolower($this->randomMachineName());
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'text',
|
||||
'settings' => [
|
||||
'max_length' => $max_length,
|
||||
],
|
||||
]);
|
||||
$field_storage->save();
|
||||
FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => 'entity_test',
|
||||
])->save();
|
||||
|
||||
// Test validation with valid and invalid values.
|
||||
$entity = EntityTest::create();
|
||||
for ($i = 0; $i <= $max_length + 2; $i++) {
|
||||
$entity->{$field_name}->value = str_repeat('x', $i);
|
||||
$violations = $entity->{$field_name}->validate();
|
||||
if ($i <= $max_length) {
|
||||
$this->assertEqual(count($violations), 0, "Length $i does not cause validation error when max_length is $max_length");
|
||||
}
|
||||
else {
|
||||
$this->assertEqual(count($violations), 1, "Length $i causes validation error when max_length is $max_length");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test required long text with file upload.
|
||||
*/
|
||||
public function testRequiredLongTextWithFileUpload() {
|
||||
// Create a text field.
|
||||
$text_field_name = 'text_long';
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $text_field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'text_with_summary',
|
||||
]);
|
||||
$field_storage->save();
|
||||
FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => 'entity_test',
|
||||
'label' => $this->randomMachineName() . '_label',
|
||||
'required' => TRUE,
|
||||
])->save();
|
||||
|
||||
// Create a file field.
|
||||
$file_field_name = 'file_field';
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $file_field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'file',
|
||||
]);
|
||||
$field_storage->save();
|
||||
FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => 'entity_test',
|
||||
'label' => $this->randomMachineName() . '_label',
|
||||
])->save();
|
||||
|
||||
entity_get_form_display('entity_test', 'entity_test', 'default')
|
||||
->setComponent($text_field_name, [
|
||||
'type' => 'text_textarea_with_summary',
|
||||
])
|
||||
->setComponent($file_field_name, [
|
||||
'type' => 'file_generic',
|
||||
])
|
||||
->save();
|
||||
entity_get_display('entity_test', 'entity_test', 'full')
|
||||
->setComponent($text_field_name)
|
||||
->setComponent($file_field_name)
|
||||
->save();
|
||||
|
||||
$test_file = current($this->drupalGetTestFiles('text'));
|
||||
$edit['files[file_field_0]'] = \Drupal::service('file_system')->realpath($test_file->uri);
|
||||
$this->drupalPostForm('entity_test/add', $edit, 'Upload');
|
||||
$this->assertResponse(200);
|
||||
$edit = [
|
||||
'text_long[0][value]' => 'Long text',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, 'Save');
|
||||
$this->assertResponse(200);
|
||||
$this->drupalGet('entity_test/1');
|
||||
$this->assertText('Long text');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test widgets.
|
||||
*/
|
||||
public function testTextfieldWidgets() {
|
||||
$this->_testTextfieldWidgets('text', 'text_textfield');
|
||||
$this->_testTextfieldWidgets('text_long', 'text_textarea');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test widgets + 'formatted_text' setting.
|
||||
*/
|
||||
public function testTextfieldWidgetsFormatted() {
|
||||
$this->_testTextfieldWidgetsFormatted('text', 'text_textfield');
|
||||
$this->_testTextfieldWidgetsFormatted('text_long', 'text_textarea');
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for testTextfieldWidgetsFormatted().
|
||||
*/
|
||||
public function _testTextfieldWidgetsFormatted($field_type, $widget_type) {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = $this->container->get('renderer');
|
||||
|
||||
// Create a field.
|
||||
$field_name = mb_strtolower($this->randomMachineName());
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => $field_type,
|
||||
]);
|
||||
$field_storage->save();
|
||||
FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => 'entity_test',
|
||||
'label' => $this->randomMachineName() . '_label',
|
||||
])->save();
|
||||
entity_get_form_display('entity_test', 'entity_test', 'default')
|
||||
->setComponent($field_name, [
|
||||
'type' => $widget_type,
|
||||
])
|
||||
->save();
|
||||
entity_get_display('entity_test', 'entity_test', 'full')
|
||||
->setComponent($field_name)
|
||||
->save();
|
||||
|
||||
// Disable all text formats besides the plain text fallback format.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
foreach (filter_formats() as $format) {
|
||||
if (!$format->isFallbackFormat()) {
|
||||
$this->drupalPostForm('admin/config/content/formats/manage/' . $format->id() . '/disable', [], t('Disable'));
|
||||
}
|
||||
}
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
// Display the creation form. Since the user only has access to one format,
|
||||
// no format selector will be displayed.
|
||||
$this->drupalGet('entity_test/add');
|
||||
$this->assertFieldByName("{$field_name}[0][value]", '', 'Widget is displayed');
|
||||
$this->assertNoFieldByName("{$field_name}[0][format]", '', 'Format selector is not displayed');
|
||||
|
||||
// Submit with data that should be filtered.
|
||||
$value = '<em>' . $this->randomMachineName() . '</em>';
|
||||
$edit = [
|
||||
"{$field_name}[0][value]" => $value,
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
preg_match('|entity_test/manage/(\d+)|', $this->getUrl(), $match);
|
||||
$id = $match[1];
|
||||
$this->assertText(t('entity_test @id has been created.', ['@id' => $id]), 'Entity was created');
|
||||
|
||||
// Display the entity.
|
||||
$entity = EntityTest::load($id);
|
||||
$display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
|
||||
$content = $display->build($entity);
|
||||
$rendered_entity = \Drupal::service('renderer')->renderRoot($content);
|
||||
$this->assertNotContains($value, (string) $rendered_entity);
|
||||
$this->assertContains(Html::escape($value), (string) $rendered_entity);
|
||||
|
||||
// Create a new text format that does not escape HTML, and grant the user
|
||||
// access to it.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$edit = [
|
||||
'format' => mb_strtolower($this->randomMachineName()),
|
||||
'name' => $this->randomMachineName(),
|
||||
];
|
||||
$this->drupalPostForm('admin/config/content/formats/add', $edit, t('Save configuration'));
|
||||
filter_formats_reset();
|
||||
$format = FilterFormat::load($edit['format']);
|
||||
$format_id = $format->id();
|
||||
$permission = $format->getPermissionName();
|
||||
$roles = $this->webUser->getRoles();
|
||||
$rid = $roles[0];
|
||||
user_role_grant_permissions($rid, [$permission]);
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
// Display edition form.
|
||||
// We should now have a 'text format' selector.
|
||||
$this->drupalGet('entity_test/manage/' . $id . '/edit');
|
||||
$this->assertFieldByName("{$field_name}[0][value]", NULL, 'Widget is displayed');
|
||||
$this->assertFieldByName("{$field_name}[0][format]", NULL, 'Format selector is displayed');
|
||||
|
||||
// Edit and change the text format to the new one that was created.
|
||||
$edit = [
|
||||
"{$field_name}[0][format]" => $format_id,
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$this->assertText(t('entity_test @id has been updated.', ['@id' => $id]), 'Entity was updated');
|
||||
|
||||
// Display the entity.
|
||||
$this->container->get('entity.manager')->getStorage('entity_test')->resetCache([$id]);
|
||||
$entity = EntityTest::load($id);
|
||||
$display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
|
||||
$content = $display->build($entity);
|
||||
$rendered_entity = \Drupal::service('renderer')->renderRoot($content);
|
||||
$this->assertContains($value, (string) $rendered_entity);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\FunctionalJavascript;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
|
||||
|
||||
/**
|
||||
* Tests the JavaScript functionality of the text_textarea_with_summary widget.
|
||||
*
|
||||
* @group text
|
||||
*/
|
||||
class TextareaWithSummaryTest extends WebDriverTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['text', 'node'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
|
||||
$account = $this->drupalCreateUser(['create page content', 'edit own page content']);
|
||||
$this->drupalLogin($account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to test toggling the summary area.
|
||||
*/
|
||||
protected function assertSummaryToggle() {
|
||||
$this->drupalGet('node/add/page');
|
||||
$widget = $this->getSession()->getPage()->findById('edit-body-wrapper');
|
||||
$summary_field = $widget->findField('edit-body-0-summary');
|
||||
|
||||
$this->assertEquals(FALSE, $summary_field->isVisible(), 'Summary field is hidden by default.');
|
||||
$this->assertEquals(FALSE, $widget->hasButton('Hide summary'), 'No Hide summary link by default.');
|
||||
|
||||
$widget->pressButton('Edit summary');
|
||||
$this->assertEquals(FALSE, $widget->hasButton('Edit summary'), 'Edit summary link is removed after clicking.');
|
||||
$this->assertEquals(TRUE, $summary_field->isVisible(), 'Summary field is shown.');
|
||||
|
||||
$widget->pressButton('Hide summary');
|
||||
$this->assertEquals(FALSE, $widget->hasButton('Hide summary'), 'Hide summary link is removed after clicking.');
|
||||
$this->assertEquals(FALSE, $summary_field->isVisible(), 'Summary field is hidden again.');
|
||||
$this->assertEquals(TRUE, $widget->hasButton('Edit summary'), 'Edit summary link is visible again.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the textSummary javascript behavior.
|
||||
*/
|
||||
public function testTextSummaryBehavior() {
|
||||
// Test with field defaults.
|
||||
$this->assertSummaryToggle();
|
||||
|
||||
// Repeat test with non-empty field description.
|
||||
$body_field = FieldConfig::loadByName('node', 'page', 'body');
|
||||
$body_field->set('description', 'Text with Summary field description.');
|
||||
$body_field->save();
|
||||
|
||||
$this->assertSummaryToggle();
|
||||
|
||||
// Test summary is shown when non-empty.
|
||||
$node = $this->createNode([
|
||||
'body' => [
|
||||
[
|
||||
'value' => $this->randomMachineName(32),
|
||||
'summary' => $this->randomMachineName(32),
|
||||
'format' => filter_default_format(),
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$page = $this->getSession()->getPage();
|
||||
$summary_field = $page->findField('edit-body-0-summary');
|
||||
|
||||
$this->assertEquals(TRUE, $summary_field->isVisible(), 'Non-empty summary field is shown by default.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Kernel\Migrate;
|
||||
|
||||
use Drupal\Tests\SchemaCheckTestTrait;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Upgrade variables to text.settings.yml.
|
||||
*
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateTextConfigsTest extends MigrateDrupal6TestBase {
|
||||
|
||||
use SchemaCheckTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->executeMigration('text_settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests migration of text variables to text.settings.yml.
|
||||
*/
|
||||
public function testTextSettings() {
|
||||
$config = $this->config('text.settings');
|
||||
$this->assertIdentical(456, $config->get('default_summary_length'));
|
||||
$this->assertConfigSchema(\Drupal::service('config.typed'), 'text.settings', $config->get());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Kernel;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
||||
/**
|
||||
* Tests the text formatters functionality.
|
||||
*
|
||||
* @group text
|
||||
*/
|
||||
class TextFormatterTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* The entity type used in this test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $entityType = 'entity_test';
|
||||
|
||||
/**
|
||||
* The bundle used in this test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $bundle = 'entity_test';
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['text'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
FilterFormat::create([
|
||||
'format' => 'my_text_format',
|
||||
'name' => 'My text format',
|
||||
'filters' => [
|
||||
'filter_autop' => [
|
||||
'module' => 'filter',
|
||||
'status' => TRUE,
|
||||
],
|
||||
],
|
||||
])->save();
|
||||
|
||||
FieldStorageConfig::create([
|
||||
'field_name' => 'formatted_text',
|
||||
'entity_type' => $this->entityType,
|
||||
'type' => 'text',
|
||||
'settings' => [],
|
||||
])->save();
|
||||
FieldConfig::create([
|
||||
'entity_type' => $this->entityType,
|
||||
'bundle' => $this->bundle,
|
||||
'field_name' => 'formatted_text',
|
||||
'label' => 'Filtered text',
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests all text field formatters.
|
||||
*/
|
||||
public function testFormatters() {
|
||||
$formatters = [
|
||||
'text_default',
|
||||
'text_trimmed',
|
||||
'text_summary_or_trimmed',
|
||||
];
|
||||
|
||||
// Create the entity to be referenced.
|
||||
$entity = $this->container->get('entity_type.manager')
|
||||
->getStorage($this->entityType)
|
||||
->create(['name' => $this->randomMachineName()]);
|
||||
$entity->formatted_text = [
|
||||
'value' => 'Hello, world!',
|
||||
'format' => 'my_text_format',
|
||||
];
|
||||
$entity->save();
|
||||
|
||||
foreach ($formatters as $formatter) {
|
||||
// Verify the text field formatter's render array.
|
||||
$build = $entity->get('formatted_text')->view(['type' => $formatter]);
|
||||
\Drupal::service('renderer')->renderRoot($build[0]);
|
||||
$this->assertEqual($build[0]['#markup'], "<p>Hello, world!</p>\n");
|
||||
$this->assertEqual($build[0]['#cache']['tags'], FilterFormat::load('my_text_format')->getCacheTags(), format_string('The @formatter formatter has the expected cache tags when formatting a formatted text field.', ['@formatter' => $formatter]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
230
2017/web/core/modules/text/tests/src/Kernel/TextSummaryTest.php
Normal file
230
2017/web/core/modules/text/tests/src/Kernel/TextSummaryTest.php
Normal file
|
@ -0,0 +1,230 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Kernel;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
|
||||
/**
|
||||
* Tests text_summary() with different strings and lengths.
|
||||
*
|
||||
* @group text
|
||||
*/
|
||||
class TextSummaryTest extends KernelTestBase {
|
||||
|
||||
public static $modules = ['system', 'user', 'filter', 'text'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installConfig(['text']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an edge case where the first sentence is a question and
|
||||
* subsequent sentences are not. This edge case is documented at
|
||||
* https://www.drupal.org/node/180425.
|
||||
*/
|
||||
public function testFirstSentenceQuestion() {
|
||||
$text = 'A question? A sentence. Another sentence.';
|
||||
$expected = 'A question? A sentence.';
|
||||
$this->assertTextSummary($text, $expected, NULL, 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test summary with long example.
|
||||
*/
|
||||
public function testLongSentence() {
|
||||
// 125.
|
||||
$text =
|
||||
'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' .
|
||||
// 108.
|
||||
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' .
|
||||
// 103.
|
||||
'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. ' .
|
||||
// 110.
|
||||
'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
|
||||
$expected = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' .
|
||||
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' .
|
||||
'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.';
|
||||
// First three sentences add up to: 336, so add one for space and then 3 to get half-way into next word.
|
||||
$this->assertTextSummary($text, $expected, NULL, 340);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test various summary length edge cases.
|
||||
*/
|
||||
public function testLength() {
|
||||
FilterFormat::create([
|
||||
'format' => 'autop',
|
||||
'filters' => [
|
||||
'filter_autop' => [
|
||||
'status' => 1,
|
||||
],
|
||||
],
|
||||
])->save();
|
||||
FilterFormat::create([
|
||||
'format' => 'autop_correct',
|
||||
'filters' => [
|
||||
'filter_autop' => [
|
||||
'status' => 1,
|
||||
],
|
||||
'filter_htmlcorrector' => [
|
||||
'status' => 1,
|
||||
],
|
||||
],
|
||||
])->save();
|
||||
|
||||
// This string tests a number of edge cases.
|
||||
$text = "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>";
|
||||
|
||||
// The summaries we expect text_summary() to return when $size is the index
|
||||
// of each array item.
|
||||
// Using no text format:
|
||||
$format = NULL;
|
||||
$i = 0;
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\n", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nH", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n<", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
|
||||
// Using a text format with filter_autop enabled.
|
||||
$format = 'autop';
|
||||
$i = 0;
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
|
||||
// Using a text format with filter_autop and filter_htmlcorrector enabled.
|
||||
$format = 'autop_correct';
|
||||
$i = 0;
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p></p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p></p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p></p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p></p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p></p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
$this->assertTextSummary($text, "<p>\nHi\n</p>\n<p>\nfolks\n<br />\n!\n</p>", $format, $i++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test text_summary() returns an empty string without any error when called
|
||||
* with an invalid format.
|
||||
*/
|
||||
public function testInvalidFilterFormat() {
|
||||
|
||||
$this->assertTextSummary($this->randomString(100), '', 'non_existent_format');
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls text_summary() and asserts that the expected teaser is returned.
|
||||
*/
|
||||
public function assertTextSummary($text, $expected, $format = NULL, $size = NULL) {
|
||||
$summary = text_summary($text, $format, $size);
|
||||
$this->assertIdentical($summary, $expected, format_string('<pre style="white-space: pre-wrap">@actual</pre> is identical to <pre style="white-space: pre-wrap">@expected</pre>', [
|
||||
'@actual' => $summary,
|
||||
'@expected' => $expected,
|
||||
]));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Kernel;
|
||||
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Field\FieldItemInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\Tests\field\Kernel\FieldKernelTestBase;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
|
||||
/**
|
||||
* Tests using entity fields of the text summary field type.
|
||||
*
|
||||
* @group text
|
||||
*/
|
||||
class TextWithSummaryItemTest extends FieldKernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['filter'];
|
||||
|
||||
/**
|
||||
* Field storage entity.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldStorageConfig
|
||||
*/
|
||||
protected $fieldStorage;
|
||||
|
||||
/**
|
||||
* Field entity.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldConfig
|
||||
*/
|
||||
protected $field;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('entity_test_rev');
|
||||
|
||||
// Create the necessary formats.
|
||||
$this->installConfig(['filter']);
|
||||
FilterFormat::create([
|
||||
'format' => 'no_filters',
|
||||
'filters' => [],
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests processed properties.
|
||||
*/
|
||||
public function testCrudAndUpdate() {
|
||||
$entity_type = 'entity_test';
|
||||
$this->createField($entity_type);
|
||||
|
||||
// Create an entity with a summary and no text format.
|
||||
$storage = $this->container->get('entity_type.manager')
|
||||
->getStorage($entity_type);
|
||||
$entity = $storage->create();
|
||||
$entity->summary_field->value = $value = $this->randomMachineName();
|
||||
$entity->summary_field->summary = $summary = $this->randomMachineName();
|
||||
$entity->summary_field->format = NULL;
|
||||
$entity->name->value = $this->randomMachineName();
|
||||
$entity->save();
|
||||
|
||||
$entity = $storage->load($entity->id());
|
||||
$this->assertTrue($entity->summary_field instanceof FieldItemListInterface, 'Field implements interface.');
|
||||
$this->assertTrue($entity->summary_field[0] instanceof FieldItemInterface, 'Field item implements interface.');
|
||||
$this->assertEqual($entity->summary_field->value, $value);
|
||||
$this->assertEqual($entity->summary_field->summary, $summary);
|
||||
$this->assertNull($entity->summary_field->format);
|
||||
// Even if no format is given, if text processing is enabled, the default
|
||||
// format is used.
|
||||
$this->assertEqual($entity->summary_field->processed, "<p>$value</p>\n");
|
||||
$this->assertEqual($entity->summary_field->summary_processed, "<p>$summary</p>\n");
|
||||
|
||||
// Change the format, this should update the processed properties.
|
||||
$entity->summary_field->format = 'no_filters';
|
||||
$this->assertEqual($entity->summary_field->processed, $value);
|
||||
$this->assertEqual($entity->summary_field->summary_processed, $summary);
|
||||
|
||||
// Test the generateSampleValue() method.
|
||||
$entity = $this->container->get('entity_type.manager')
|
||||
->getStorage($entity_type)
|
||||
->create();
|
||||
$entity->summary_field->generateSampleItems();
|
||||
$this->entityValidateAndSave($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text_with_summary field storage and field.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* Entity type for which the field should be created.
|
||||
*/
|
||||
protected function createField($entity_type) {
|
||||
// Create a field .
|
||||
$this->fieldStorage = FieldStorageConfig::create([
|
||||
'field_name' => 'summary_field',
|
||||
'entity_type' => $entity_type,
|
||||
'type' => 'text_with_summary',
|
||||
'settings' => [
|
||||
'max_length' => 10,
|
||||
],
|
||||
]);
|
||||
$this->fieldStorage->save();
|
||||
$this->field = FieldConfig::create([
|
||||
'field_storage' => $this->fieldStorage,
|
||||
'bundle' => $entity_type,
|
||||
]);
|
||||
$this->field->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Unit\Migrate;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\text\Plugin\migrate\cckfield\TextField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\text\Plugin\migrate\cckfield\TextField
|
||||
* @group text
|
||||
* @group legacy
|
||||
*/
|
||||
class TextCckTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new TextField([], 'text', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's processCckFieldValues() method will call
|
||||
// setProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to setProcessOfProperty().
|
||||
$migration->setProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processCckFieldValues
|
||||
*/
|
||||
public function testProcessFilteredTextFieldValues() {
|
||||
$field_info = [
|
||||
'widget_type' => 'text_textfield',
|
||||
];
|
||||
$this->plugin->processCckFieldValues($this->migration, 'body', $field_info);
|
||||
|
||||
$process = $this->migration->getProcess();
|
||||
$this->assertSame('sub_process', $process['plugin']);
|
||||
$this->assertSame('body', $process['source']);
|
||||
$this->assertSame('value', $process['process']['value']);
|
||||
|
||||
// Ensure that filter format IDs will be looked up in the filter format
|
||||
// migrations.
|
||||
$lookup = $process['process']['format'][2];
|
||||
$this->assertSame('migration', $lookup['plugin']);
|
||||
$this->assertContains('d6_filter_format', $lookup['migration']);
|
||||
$this->assertContains('d7_filter_format', $lookup['migration']);
|
||||
$this->assertSame('format', $lookup['source']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processCckFieldValues
|
||||
*/
|
||||
public function testProcessBooleanTextImplicitValues() {
|
||||
$info = [
|
||||
'widget_type' => 'optionwidgets_onoff',
|
||||
'global_settings' => [
|
||||
'allowed_values' => "foo\nbar",
|
||||
],
|
||||
];
|
||||
$this->plugin->processCckFieldValues($this->migration, 'field', $info);
|
||||
|
||||
$expected = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
'map' => [
|
||||
'bar' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess()['process']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processCckFieldValues
|
||||
*/
|
||||
public function testProcessBooleanTextExplicitValues() {
|
||||
$info = [
|
||||
'widget_type' => 'optionwidgets_onoff',
|
||||
'global_settings' => [
|
||||
'allowed_values' => "foo|Foo\nbaz|Baz",
|
||||
],
|
||||
];
|
||||
$this->plugin->processCckFieldValues($this->migration, 'field', $info);
|
||||
|
||||
$expected = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
'map' => [
|
||||
'baz' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess()['process']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetFieldType().
|
||||
*/
|
||||
public function getFieldTypeProvider() {
|
||||
return [
|
||||
['string_long', 'text_textfield', ['text_processing' => FALSE]],
|
||||
['string', 'text_textfield', [
|
||||
'text_processing' => FALSE,
|
||||
'max_length' => 128,
|
||||
],
|
||||
],
|
||||
['string_long', 'text_textfield', [
|
||||
'text_processing' => FALSE,
|
||||
'max_length' => 4096,
|
||||
],
|
||||
],
|
||||
['text_long', 'text_textfield', ['text_processing' => TRUE]],
|
||||
['text', 'text_textfield', [
|
||||
'text_processing' => TRUE,
|
||||
'max_length' => 128,
|
||||
],
|
||||
],
|
||||
['text_long', 'text_textfield', [
|
||||
'text_processing' => TRUE,
|
||||
'max_length' => 4096,
|
||||
],
|
||||
],
|
||||
['list_string', 'optionwidgets_buttons'],
|
||||
['list_string', 'optionwidgets_select'],
|
||||
['boolean', 'optionwidgets_onoff'],
|
||||
['text_long', 'text_textarea', ['text_processing' => TRUE]],
|
||||
['string_long', 'text_textarea', ['text_processing' => FALSE]],
|
||||
[NULL, 'undefined'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldType
|
||||
* @dataProvider getFieldTypeProvider
|
||||
*/
|
||||
public function testGetFieldType($expected_type, $widget_type, array $settings = []) {
|
||||
$row = new Row(['widget_type' => $widget_type], ['widget_type' => []]);
|
||||
$row->setSourceProperty('global_settings', $settings);
|
||||
$this->assertSame($expected_type, $this->plugin->getFieldType($row));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Unit\Migrate\d6;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\text\Plugin\migrate\field\d6\TextField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\text\Plugin\migrate\field\d6\TextField
|
||||
* @group text
|
||||
* @group legacy
|
||||
*/
|
||||
class TextFieldTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new TextField([], 'text', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's defineValueProcessPipeline() method will call
|
||||
// setProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to setProcessOfProperty().
|
||||
$migration->setProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the deprecated processFieldValues() method to test BC.
|
||||
*
|
||||
* @covers ::processFieldValues
|
||||
*
|
||||
* @depends testFilteredTextValueProcessPipeline
|
||||
*/
|
||||
public function testProcessFilteredTextFieldValues() {
|
||||
$field_info = [
|
||||
'widget_type' => 'text_textfield',
|
||||
];
|
||||
$this->plugin->processFieldValues($this->migration, 'body', $field_info);
|
||||
|
||||
$process = $this->migration->getProcess();
|
||||
$this->assertSame('sub_process', $process['plugin']);
|
||||
$this->assertSame('body', $process['source']);
|
||||
$this->assertSame('value', $process['process']['value']);
|
||||
|
||||
// Ensure that filter format IDs will be looked up in the filter format
|
||||
// migrations.
|
||||
$lookup = $process['process']['format'][2];
|
||||
$this->assertSame('migration', $lookup['plugin']);
|
||||
$this->assertContains('d6_filter_format', $lookup['migration']);
|
||||
$this->assertContains('d7_filter_format', $lookup['migration']);
|
||||
$this->assertSame('format', $lookup['source']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::defineValueProcessPipeline
|
||||
*/
|
||||
public function testFilteredTextValueProcessPipeline() {
|
||||
$field_info = [
|
||||
'widget_type' => 'text_textfield',
|
||||
];
|
||||
$this->plugin->defineValueProcessPipeline($this->migration, 'body', $field_info);
|
||||
|
||||
$process = $this->migration->getProcess();
|
||||
$this->assertSame('sub_process', $process['plugin']);
|
||||
$this->assertSame('body', $process['source']);
|
||||
$this->assertSame('value', $process['process']['value']);
|
||||
|
||||
// Ensure that filter format IDs will be looked up in the filter format
|
||||
// migrations.
|
||||
$lookup = $process['process']['format'][2];
|
||||
$this->assertSame('migration', $lookup['plugin']);
|
||||
$this->assertContains('d6_filter_format', $lookup['migration']);
|
||||
$this->assertContains('d7_filter_format', $lookup['migration']);
|
||||
$this->assertSame('format', $lookup['source']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the deprecated processFieldValues() method to test BC.
|
||||
*
|
||||
* @covers ::processFieldValues
|
||||
*
|
||||
* @depends testBooleanTextImplicitValueProcessPipeline
|
||||
*/
|
||||
public function testProcessBooleanTextImplicitValues() {
|
||||
$info = [
|
||||
'widget_type' => 'optionwidgets_onoff',
|
||||
'global_settings' => [
|
||||
'allowed_values' => "foo\nbar",
|
||||
],
|
||||
];
|
||||
$this->plugin->processFieldValues($this->migration, 'field', $info);
|
||||
|
||||
$expected = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
'map' => [
|
||||
'bar' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess()['process']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::defineValueProcessPipeline
|
||||
*/
|
||||
public function testBooleanTextImplicitValueProcessPipeline() {
|
||||
$info = [
|
||||
'widget_type' => 'optionwidgets_onoff',
|
||||
'global_settings' => [
|
||||
'allowed_values' => "foo\nbar",
|
||||
],
|
||||
];
|
||||
$this->plugin->defineValueProcessPipeline($this->migration, 'field', $info);
|
||||
|
||||
$expected = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
'map' => [
|
||||
'bar' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess()['process']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the deprecated processFieldValues() method to test BC.
|
||||
*
|
||||
* @covers ::processFieldValues
|
||||
*
|
||||
* @depends testBooleanTextExplicitValueProcessPipeline
|
||||
*/
|
||||
public function testProcessBooleanTextExplicitValues() {
|
||||
$info = [
|
||||
'widget_type' => 'optionwidgets_onoff',
|
||||
'global_settings' => [
|
||||
'allowed_values' => "foo|Foo\nbaz|Baz",
|
||||
],
|
||||
];
|
||||
$this->plugin->processFieldValues($this->migration, 'field', $info);
|
||||
|
||||
$expected = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
'map' => [
|
||||
'baz' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess()['process']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::defineValueProcessPipeline
|
||||
*/
|
||||
public function testBooleanTextExplicitValueProcessPipeline() {
|
||||
$info = [
|
||||
'widget_type' => 'optionwidgets_onoff',
|
||||
'global_settings' => [
|
||||
'allowed_values' => "foo|Foo\nbaz|Baz",
|
||||
],
|
||||
];
|
||||
$this->plugin->defineValueProcessPipeline($this->migration, 'field', $info);
|
||||
|
||||
$expected = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
'map' => [
|
||||
'baz' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess()['process']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetFieldType().
|
||||
*/
|
||||
public function getFieldTypeProvider() {
|
||||
return [
|
||||
['string_long', 'text_textfield', ['text_processing' => FALSE]],
|
||||
['string', 'text_textfield', [
|
||||
'text_processing' => FALSE,
|
||||
'max_length' => 128,
|
||||
],
|
||||
],
|
||||
['string_long', 'text_textfield', [
|
||||
'text_processing' => FALSE,
|
||||
'max_length' => 4096,
|
||||
],
|
||||
],
|
||||
['text_long', 'text_textfield', ['text_processing' => TRUE]],
|
||||
['text', 'text_textfield', [
|
||||
'text_processing' => TRUE,
|
||||
'max_length' => 128,
|
||||
],
|
||||
],
|
||||
['text_long', 'text_textfield', [
|
||||
'text_processing' => TRUE,
|
||||
'max_length' => 4096,
|
||||
],
|
||||
],
|
||||
['list_string', 'optionwidgets_buttons'],
|
||||
['list_string', 'optionwidgets_select'],
|
||||
['boolean', 'optionwidgets_onoff'],
|
||||
['text_long', 'text_textarea', ['text_processing' => TRUE]],
|
||||
['string_long', 'text_textarea', ['text_processing' => FALSE]],
|
||||
[NULL, 'undefined'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldType
|
||||
* @dataProvider getFieldTypeProvider
|
||||
*/
|
||||
public function testGetFieldType($expected_type, $widget_type, array $settings = []) {
|
||||
$row = new Row();
|
||||
$row->setSourceProperty('widget_type', $widget_type);
|
||||
$row->setSourceProperty('global_settings', $settings);
|
||||
$this->assertSame($expected_type, $this->plugin->getFieldType($row));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Unit\Migrate\d7;
|
||||
|
||||
use Drupal\Tests\text\Unit\Migrate\d6\TextFieldTest as D6TextFieldTest;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\text\Plugin\migrate\field\d7\TextField
|
||||
* @group text
|
||||
* @group legacy
|
||||
*/
|
||||
class TextFieldTest extends D6TextFieldTest {}
|
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Unit\Plugin\migrate\cckfield;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\text\Plugin\migrate\cckfield\TextField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\text\Plugin\migrate\cckfield\TextField
|
||||
* @group text
|
||||
* @group legacy
|
||||
*/
|
||||
class TextCckTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new TextField([], 'text', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's processCckFieldValues() method will call
|
||||
// setProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to setProcessOfProperty().
|
||||
$migration->setProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processCckFieldValues
|
||||
*/
|
||||
public function testProcessFilteredTextFieldValues() {
|
||||
$field_info = [
|
||||
'widget_type' => 'text_textfield',
|
||||
];
|
||||
$this->plugin->processCckFieldValues($this->migration, 'body', $field_info);
|
||||
|
||||
$process = $this->migration->getProcess();
|
||||
$this->assertSame('sub_process', $process['plugin']);
|
||||
$this->assertSame('body', $process['source']);
|
||||
$this->assertSame('value', $process['process']['value']);
|
||||
|
||||
// Ensure that filter format IDs will be looked up in the filter format
|
||||
// migrations.
|
||||
$lookup = $process['process']['format'][2];
|
||||
$this->assertSame('migration', $lookup['plugin']);
|
||||
$this->assertContains('d6_filter_format', $lookup['migration']);
|
||||
$this->assertContains('d7_filter_format', $lookup['migration']);
|
||||
$this->assertSame('format', $lookup['source']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processCckFieldValues
|
||||
*/
|
||||
public function testProcessBooleanTextImplicitValues() {
|
||||
$info = [
|
||||
'widget_type' => 'optionwidgets_onoff',
|
||||
'global_settings' => [
|
||||
'allowed_values' => "foo\nbar",
|
||||
],
|
||||
];
|
||||
$this->plugin->processCckFieldValues($this->migration, 'field', $info);
|
||||
|
||||
$expected = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
'map' => [
|
||||
'bar' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess()['process']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processCckFieldValues
|
||||
*/
|
||||
public function testProcessBooleanTextExplicitValues() {
|
||||
$info = [
|
||||
'widget_type' => 'optionwidgets_onoff',
|
||||
'global_settings' => [
|
||||
'allowed_values' => "foo|Foo\nbaz|Baz",
|
||||
],
|
||||
];
|
||||
$this->plugin->processCckFieldValues($this->migration, 'field', $info);
|
||||
|
||||
$expected = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
'map' => [
|
||||
'baz' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess()['process']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetFieldType().
|
||||
*/
|
||||
public function getFieldTypeProvider() {
|
||||
return [
|
||||
['string_long', 'text_textfield', ['text_processing' => FALSE]],
|
||||
['string', 'text_textfield', [
|
||||
'text_processing' => FALSE,
|
||||
'max_length' => 128,
|
||||
],
|
||||
],
|
||||
['string_long', 'text_textfield', [
|
||||
'text_processing' => FALSE,
|
||||
'max_length' => 4096,
|
||||
],
|
||||
],
|
||||
['text_long', 'text_textfield', ['text_processing' => TRUE]],
|
||||
['text', 'text_textfield', [
|
||||
'text_processing' => TRUE,
|
||||
'max_length' => 128,
|
||||
],
|
||||
],
|
||||
['text_long', 'text_textfield', [
|
||||
'text_processing' => TRUE,
|
||||
'max_length' => 4096,
|
||||
],
|
||||
],
|
||||
['list_string', 'optionwidgets_buttons'],
|
||||
['list_string', 'optionwidgets_select'],
|
||||
['boolean', 'optionwidgets_onoff'],
|
||||
['text_long', 'text_textarea', ['text_processing' => TRUE]],
|
||||
['string_long', 'text_textarea', ['text_processing' => FALSE]],
|
||||
[NULL, 'undefined'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldType
|
||||
* @dataProvider getFieldTypeProvider
|
||||
*/
|
||||
public function testGetFieldType($expected_type, $widget_type, array $settings = []) {
|
||||
$row = new Row(['widget_type' => $widget_type], ['widget_type' => []]);
|
||||
$row->setSourceProperty('global_settings', $settings);
|
||||
$this->assertSame($expected_type, $this->plugin->getFieldType($row));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Unit\Plugin\migrate\field\d6;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\text\Plugin\migrate\field\d6\TextField
|
||||
* @group text
|
||||
* @group legacy
|
||||
*/
|
||||
class TextFieldLegacyTest extends TextFieldTest {
|
||||
|
||||
/**
|
||||
* @covers ::processFieldValues
|
||||
* @expectedDeprecation Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use defineValueProcessPipeline() instead. See https://www.drupal.org/node/2944598.
|
||||
*/
|
||||
public function testProcessFilteredTextFieldValues($method = 'processFieldValues') {
|
||||
parent::testProcessFilteredTextFieldValues($method);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processFieldValues
|
||||
* @expectedDeprecation Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use defineValueProcessPipeline() instead. See https://www.drupal.org/node/2944598.
|
||||
*/
|
||||
public function testProcessBooleanTextImplicitValues($method = 'processFieldValues') {
|
||||
parent::testProcessBooleanTextImplicitValues($method);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processFieldValues
|
||||
* @expectedDeprecation Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use defineValueProcessPipeline() instead. See https://www.drupal.org/node/2944598.
|
||||
*/
|
||||
public function testProcessBooleanTextExplicitValues($method = 'processFieldValues') {
|
||||
parent::testProcessBooleanTextExplicitValues($method);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Unit\Plugin\migrate\field\d6;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\text\Plugin\migrate\field\d6\TextField;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\text\Plugin\migrate\field\d6\TextField
|
||||
* @group text
|
||||
*/
|
||||
class TextFieldTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigrationInterface
|
||||
*/
|
||||
protected $migration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->plugin = new TextField([], 'text', []);
|
||||
|
||||
$migration = $this->prophesize(MigrationInterface::class);
|
||||
|
||||
// The plugin's defineValueProcessPipeline() method will call
|
||||
// setProcessOfProperty() and return nothing. So, in order to examine the
|
||||
// process pipeline created by the plugin, we need to ensure that
|
||||
// getProcess() always returns the last input to setProcessOfProperty().
|
||||
$migration->setProcessOfProperty(Argument::type('string'), Argument::type('array'))
|
||||
->will(function ($arguments) use ($migration) {
|
||||
$migration->getProcess()->willReturn($arguments[1]);
|
||||
});
|
||||
|
||||
$this->migration = $migration->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::defineValueProcessPipeline
|
||||
*/
|
||||
public function testProcessFilteredTextFieldValues($method = 'defineValueProcessPipeline') {
|
||||
$field_info = [
|
||||
'widget_type' => 'text_textfield',
|
||||
];
|
||||
$this->plugin->$method($this->migration, 'body', $field_info);
|
||||
|
||||
$process = $this->migration->getProcess();
|
||||
$this->assertSame('sub_process', $process['plugin']);
|
||||
$this->assertSame('body', $process['source']);
|
||||
$this->assertSame('value', $process['process']['value']);
|
||||
|
||||
// Ensure that filter format IDs will be looked up in the filter format
|
||||
// migrations.
|
||||
$lookup = $process['process']['format'][2];
|
||||
$this->assertSame('migration', $lookup['plugin']);
|
||||
$this->assertContains('d6_filter_format', $lookup['migration']);
|
||||
$this->assertContains('d7_filter_format', $lookup['migration']);
|
||||
$this->assertSame('format', $lookup['source']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::defineValueProcessPipeline
|
||||
*/
|
||||
public function testProcessBooleanTextImplicitValues($method = 'defineValueProcessPipeline') {
|
||||
$info = [
|
||||
'widget_type' => 'optionwidgets_onoff',
|
||||
'global_settings' => [
|
||||
'allowed_values' => "foo\nbar",
|
||||
],
|
||||
];
|
||||
$this->plugin->$method($this->migration, 'field', $info);
|
||||
|
||||
$expected = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
'map' => [
|
||||
'bar' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess()['process']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::defineValueProcessPipeline
|
||||
*/
|
||||
public function testProcessBooleanTextExplicitValues($method = 'defineValueProcessPipeline') {
|
||||
$info = [
|
||||
'widget_type' => 'optionwidgets_onoff',
|
||||
'global_settings' => [
|
||||
'allowed_values' => "foo|Foo\nbaz|Baz",
|
||||
],
|
||||
];
|
||||
$this->plugin->$method($this->migration, 'field', $info);
|
||||
|
||||
$expected = [
|
||||
'value' => [
|
||||
'plugin' => 'static_map',
|
||||
'source' => 'value',
|
||||
'default_value' => 0,
|
||||
'map' => [
|
||||
'baz' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->migration->getProcess()['process']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetFieldType().
|
||||
*/
|
||||
public function getFieldTypeProvider() {
|
||||
return [
|
||||
['string_long', 'text_textfield', ['text_processing' => FALSE]],
|
||||
['string', 'text_textfield', [
|
||||
'text_processing' => FALSE,
|
||||
'max_length' => 128,
|
||||
],
|
||||
],
|
||||
['string_long', 'text_textfield', [
|
||||
'text_processing' => FALSE,
|
||||
'max_length' => 4096,
|
||||
],
|
||||
],
|
||||
['text_long', 'text_textfield', ['text_processing' => TRUE]],
|
||||
['text', 'text_textfield', [
|
||||
'text_processing' => TRUE,
|
||||
'max_length' => 128,
|
||||
],
|
||||
],
|
||||
['text_long', 'text_textfield', [
|
||||
'text_processing' => TRUE,
|
||||
'max_length' => 4096,
|
||||
],
|
||||
],
|
||||
['list_string', 'optionwidgets_buttons'],
|
||||
['list_string', 'optionwidgets_select'],
|
||||
['boolean', 'optionwidgets_onoff'],
|
||||
['text_long', 'text_textarea', ['text_processing' => TRUE]],
|
||||
['string_long', 'text_textarea', ['text_processing' => FALSE]],
|
||||
[NULL, 'undefined'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldType
|
||||
* @dataProvider getFieldTypeProvider
|
||||
*/
|
||||
public function testGetFieldType($expected_type, $widget_type, array $settings = []) {
|
||||
$row = new Row();
|
||||
$row->setSourceProperty('widget_type', $widget_type);
|
||||
$row->setSourceProperty('global_settings', $settings);
|
||||
$this->assertSame($expected_type, $this->plugin->getFieldType($row));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\text\Unit\Plugin\migrate\field\d7;
|
||||
|
||||
use Drupal\Tests\text\Unit\Plugin\migrate\field\d6\TextFieldTest as D6TextFieldTest;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\text\Plugin\migrate\field\d7\TextField
|
||||
* @group text
|
||||
*/
|
||||
class TextFieldTest extends D6TextFieldTest {}
|
65
2017/web/core/modules/text/text.es6.js
Normal file
65
2017/web/core/modules/text/text.es6.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* @file
|
||||
* Text behaviors.
|
||||
*/
|
||||
|
||||
(function($, Drupal) {
|
||||
/**
|
||||
* Auto-hide summary textarea if empty and show hide and unhide links.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches auto-hide behavior on `text-summary` events.
|
||||
*/
|
||||
Drupal.behaviors.textSummary = {
|
||||
attach(context, settings) {
|
||||
$(context)
|
||||
.find('.js-text-summary')
|
||||
.once('text-summary')
|
||||
.each(function() {
|
||||
const $widget = $(this).closest('.js-text-format-wrapper');
|
||||
|
||||
const $summary = $widget.find('.js-text-summary-wrapper');
|
||||
const $summaryLabel = $summary.find('label').eq(0);
|
||||
const $full = $widget.children('.js-form-type-textarea');
|
||||
let $fullLabel = $full.find('label').eq(0);
|
||||
|
||||
// Create a placeholder label when the field cardinality is greater
|
||||
// than 1.
|
||||
if ($fullLabel.length === 0) {
|
||||
$fullLabel = $('<label></label>').prependTo($full);
|
||||
}
|
||||
|
||||
// Set up the edit/hide summary link.
|
||||
const $link = $(
|
||||
`<span class="field-edit-link"> (<button type="button" class="link link-edit-summary">${Drupal.t(
|
||||
'Hide summary',
|
||||
)}</button>)</span>`,
|
||||
);
|
||||
const $button = $link.find('button');
|
||||
let toggleClick = true;
|
||||
$link
|
||||
.on('click', e => {
|
||||
if (toggleClick) {
|
||||
$summary.hide();
|
||||
$button.html(Drupal.t('Edit summary'));
|
||||
$link.appendTo($fullLabel);
|
||||
} else {
|
||||
$summary.show();
|
||||
$button.html(Drupal.t('Hide summary'));
|
||||
$link.appendTo($summaryLabel);
|
||||
}
|
||||
e.preventDefault();
|
||||
toggleClick = !toggleClick;
|
||||
})
|
||||
.appendTo($summaryLabel);
|
||||
|
||||
// If no summary is set, hide the summary field.
|
||||
if ($widget.find('.js-text-summary').val() === '') {
|
||||
$link.trigger('click');
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
})(jQuery, Drupal);
|
9
2017/web/core/modules/text/text.info.yml
Normal file
9
2017/web/core/modules/text/text.info.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
name: Text
|
||||
type: module
|
||||
description: 'Defines simple text field types.'
|
||||
package: Field types
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- drupal:field
|
||||
- drupal:filter
|
46
2017/web/core/modules/text/text.js
Normal file
46
2017/web/core/modules/text/text.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* See the following change record for more information,
|
||||
* https://www.drupal.org/node/2815083
|
||||
* @preserve
|
||||
**/
|
||||
|
||||
(function ($, Drupal) {
|
||||
Drupal.behaviors.textSummary = {
|
||||
attach: function attach(context, settings) {
|
||||
$(context).find('.js-text-summary').once('text-summary').each(function () {
|
||||
var $widget = $(this).closest('.js-text-format-wrapper');
|
||||
|
||||
var $summary = $widget.find('.js-text-summary-wrapper');
|
||||
var $summaryLabel = $summary.find('label').eq(0);
|
||||
var $full = $widget.children('.js-form-type-textarea');
|
||||
var $fullLabel = $full.find('label').eq(0);
|
||||
|
||||
if ($fullLabel.length === 0) {
|
||||
$fullLabel = $('<label></label>').prependTo($full);
|
||||
}
|
||||
|
||||
var $link = $('<span class="field-edit-link"> (<button type="button" class="link link-edit-summary">' + Drupal.t('Hide summary') + '</button>)</span>');
|
||||
var $button = $link.find('button');
|
||||
var toggleClick = true;
|
||||
$link.on('click', function (e) {
|
||||
if (toggleClick) {
|
||||
$summary.hide();
|
||||
$button.html(Drupal.t('Edit summary'));
|
||||
$link.appendTo($fullLabel);
|
||||
} else {
|
||||
$summary.show();
|
||||
$button.html(Drupal.t('Hide summary'));
|
||||
$link.appendTo($summaryLabel);
|
||||
}
|
||||
e.preventDefault();
|
||||
toggleClick = !toggleClick;
|
||||
}).appendTo($summaryLabel);
|
||||
|
||||
if ($widget.find('.js-text-summary').val() === '') {
|
||||
$link.trigger('click');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
})(jQuery, Drupal);
|
8
2017/web/core/modules/text/text.libraries.yml
Normal file
8
2017/web/core/modules/text/text.libraries.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
drupal.text:
|
||||
version: VERSION
|
||||
js:
|
||||
text.js: {}
|
||||
dependencies:
|
||||
- core/jquery
|
||||
- core/jquery.once
|
||||
- core/drupal
|
160
2017/web/core/modules/text/text.module
Normal file
160
2017/web/core/modules/text/text.module
Normal file
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines simple text field types.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function text_help($route_name, RouteMatchInterface $route_match) {
|
||||
switch ($route_name) {
|
||||
case 'help.page.text':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Text module allows you to create short and long text fields with optional summaries. See the <a href=":field">Field module help</a> and the <a href=":field_ui">Field UI help</a> pages for general information on fields and how to create and manage them. For more information, see the <a href=":text_documentation">online documentation for the Text module</a>.', [':field' => \Drupal::url('help.page', ['name' => 'field']), ':field_ui' => (\Drupal::moduleHandler()->moduleExists('field_ui')) ? \Drupal::url('help.page', ['name' => 'field_ui']) : '#', ':text_documentation' => 'https://www.drupal.org/documentation/modules/text']) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Managing and displaying text fields') . '</dt>';
|
||||
$output .= '<dd>' . t('The <em>settings</em> and <em>display</em> of the text field can be configured separately. See the <a href=":field_ui">Field UI help</a> for more information on how to manage fields and their display.', [':field_ui' => (\Drupal::moduleHandler()->moduleExists('field_ui')) ? \Drupal::url('help.page', ['name' => 'field_ui']) : '#']) . '</dd>';
|
||||
$output .= '<dt>' . t('Creating short text fields') . '</dt>';
|
||||
$output .= '<dd>' . t('If you choose <em>Text (plain)</em> or <em>Text (formatted)</em> as the field type on the <em>Manage fields</em> page, then a field with a single row is displayed. You can change the maximum text length in the <em>Field settings</em> when you set up the field.') . '</dd>';
|
||||
$output .= '<dt>' . t('Creating long text fields') . '</dt>';
|
||||
$output .= '<dd>' . t('If you choose <em>Text (plain, long)</em>, <em>Text (formatted, long)</em>, or <em>Text (formatted, long, with summary)</em> on the <em>Manage fields</em> page, then users can insert text of unlimited length. On the <em>Manage form display</em> page, you can set the number of rows that are displayed to users.') . '</dd>';
|
||||
$output .= '<dt>' . t('Trimming the text length') . '</dt>';
|
||||
$output .= '<dd>' . t('On the <em>Manage display</em> page you can choose to display a trimmed version of the text, and if so, where to cut off the text.') . '</dd>';
|
||||
$output .= '<dt>' . t('Displaying summaries instead of trimmed text') . '</dt>';
|
||||
$output .= '<dd>' . t('As an alternative to using a trimmed version of the text, you can enter a separate summary by choosing the <em>Text (formatted, long, with summary)</em> field type on the <em>Manage fields</em> page. Even when <em>Summary input</em> is enabled, and summaries are provided, you can display <em>trimmed</em> text nonetheless by choosing the appropriate format on the <em>Manage display</em> page.') . '</dd>';
|
||||
$output .= '<dt>' . t('Using text formats and editors') . '</dt>';
|
||||
$output .= '<dd>' . t('If you choose <em>Text (plain)</em> or <em>Text (plain, long)</em> you restrict the input to <em>Plain text</em> only. If you choose <em>Text (formatted)</em>, <em>Text (formatted, long)</em>, or <em>Text (formatted, long with summary)</em> you allow users to write formatted text. Which options are available to individual users depends on the settings on the <a href=":formats">Text formats and editors page</a>.', [':formats' => \Drupal::url('filter.admin_overview')]) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a trimmed, formatted version of a text field value.
|
||||
*
|
||||
* If the end of the summary is not indicated using the <!--break--> delimiter
|
||||
* then we generate the summary automatically, trying to end it at a sensible
|
||||
* place such as the end of a paragraph, a line break, or the end of a sentence
|
||||
* (in that order of preference).
|
||||
*
|
||||
* @param $text
|
||||
* The content for which a summary will be generated.
|
||||
* @param $format
|
||||
* The format of the content. If the line break filter is present then we
|
||||
* treat newlines embedded in $text as line breaks. If the htmlcorrector
|
||||
* filter is present, it will be run on the generated summary (if different
|
||||
* from the incoming $text).
|
||||
* @param $size
|
||||
* The desired character length of the summary. If omitted, the default value
|
||||
* will be used. Ignored if the special delimiter is present in $text.
|
||||
*
|
||||
* @return
|
||||
* The generated summary.
|
||||
*/
|
||||
function text_summary($text, $format = NULL, $size = NULL) {
|
||||
|
||||
if (!isset($size)) {
|
||||
$size = \Drupal::config('text.settings')->get('default_summary_length');
|
||||
}
|
||||
|
||||
// Find where the delimiter is in the body
|
||||
$delimiter = strpos($text, '<!--break-->');
|
||||
|
||||
// If the size is zero, and there is no delimiter, the entire body is the summary.
|
||||
if ($size == 0 && $delimiter === FALSE) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
// If a valid delimiter has been specified, use it to chop off the summary.
|
||||
if ($delimiter !== FALSE) {
|
||||
return substr($text, 0, $delimiter);
|
||||
}
|
||||
|
||||
// Retrieve the filters of the specified text format, if any.
|
||||
if (isset($format)) {
|
||||
$filter_format = FilterFormat::load($format);
|
||||
// If the specified format does not exist, return nothing. $text is already
|
||||
// filtered text, but the remainder of this function will not be able to
|
||||
// ensure a sane and secure summary.
|
||||
if (!$filter_format || !($filters = $filter_format->filters())) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a short body, the entire body is the summary.
|
||||
if (mb_strlen($text) <= $size) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
// If the delimiter has not been specified, try to split at paragraph or
|
||||
// sentence boundaries.
|
||||
|
||||
// The summary may not be longer than maximum length specified. Initial slice.
|
||||
$summary = Unicode::truncate($text, $size);
|
||||
|
||||
// Store the actual length of the UTF8 string -- which might not be the same
|
||||
// as $size.
|
||||
$max_rpos = strlen($summary);
|
||||
|
||||
// How much to cut off the end of the summary so that it doesn't end in the
|
||||
// middle of a paragraph, sentence, or word.
|
||||
// Initialize it to maximum in order to find the minimum.
|
||||
$min_rpos = $max_rpos;
|
||||
|
||||
// Store the reverse of the summary. We use strpos on the reversed needle and
|
||||
// haystack for speed and convenience.
|
||||
$reversed = strrev($summary);
|
||||
|
||||
// Build an array of arrays of break points grouped by preference.
|
||||
$break_points = [];
|
||||
|
||||
// A paragraph near the end of sliced summary is most preferable.
|
||||
$break_points[] = ['</p>' => 0];
|
||||
|
||||
// If no complete paragraph then treat line breaks as paragraphs.
|
||||
$line_breaks = ['<br />' => 6, '<br>' => 4];
|
||||
// Newline only indicates a line break if line break converter
|
||||
// filter is present.
|
||||
if (isset($format) && $filters->has('filter_autop') && $filters->get('filter_autop')->status) {
|
||||
$line_breaks["\n"] = 1;
|
||||
}
|
||||
$break_points[] = $line_breaks;
|
||||
|
||||
// If the first paragraph is too long, split at the end of a sentence.
|
||||
$break_points[] = ['. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1];
|
||||
|
||||
// Iterate over the groups of break points until a break point is found.
|
||||
foreach ($break_points as $points) {
|
||||
// Look for each break point, starting at the end of the summary.
|
||||
foreach ($points as $point => $offset) {
|
||||
// The summary is already reversed, but the break point isn't.
|
||||
$rpos = strpos($reversed, strrev($point));
|
||||
if ($rpos !== FALSE) {
|
||||
$min_rpos = min($rpos + $offset, $min_rpos);
|
||||
}
|
||||
}
|
||||
|
||||
// If a break point was found in this group, slice and stop searching.
|
||||
if ($min_rpos !== $max_rpos) {
|
||||
// Don't slice with length 0. Length must be <0 to slice from RHS.
|
||||
$summary = ($min_rpos === 0) ? $summary : substr($summary, 0, 0 - $min_rpos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the htmlcorrector filter is present, apply it to the generated summary.
|
||||
if (isset($format) && $filters->has('filter_htmlcorrector') && $filters->get('filter_htmlcorrector')->status) {
|
||||
$summary = Html::normalize($summary);
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
Reference in a new issue