Issue #2026339 by Berdir, yched: Remove text_sanitize() since we have TextProcessed as an EntityNG computed property.
parent
f7a4182e2f
commit
258d14eaee
|
@ -54,8 +54,8 @@ class NodeTokenReplaceTest extends NodeTestBase {
|
|||
$tests['[node:type]'] = 'article';
|
||||
$tests['[node:type-name]'] = 'Article';
|
||||
$tests['[node:title]'] = check_plain($node->getTitle());
|
||||
$tests['[node:body]'] = text_sanitize($instance['settings']['text_processing'], $node->language()->id, $node->body[0]->getValue(), 'value');
|
||||
$tests['[node:summary]'] = text_sanitize($instance['settings']['text_processing'], $node->language()->id, $node->body[0]->getValue(), 'summary');
|
||||
$tests['[node:body]'] = $node->body->processed;
|
||||
$tests['[node:summary]'] = $node->body->summary_processed;
|
||||
$tests['[node:langcode]'] = check_plain($node->language()->id);
|
||||
$tests['[node:url]'] = url('node/' . $node->id(), $url_options);
|
||||
$tests['[node:edit-url]'] = url('node/' . $node->id() . '/edit', $url_options);
|
||||
|
@ -97,7 +97,7 @@ class NodeTokenReplaceTest extends NodeTestBase {
|
|||
|
||||
// Generate and test sanitized token - use full body as expected value.
|
||||
$tests = array();
|
||||
$tests['[node:summary]'] = text_sanitize($instance['settings']['text_processing'], $node->language()->id, $node->body[0]->getValue(), 'value');
|
||||
$tests['[node:summary]'] = $node->body->processed;
|
||||
|
||||
// Test to make sure that we generated something for each token.
|
||||
$this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated for node without a summary.');
|
||||
|
|
|
@ -144,11 +144,11 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
|
|||
|
||||
// If the summary was requested and is not empty, use it.
|
||||
if ($name == 'summary' && !empty($item->summary)) {
|
||||
$output = $sanitize ? text_sanitize($instance['settings']['text_processing'], $field_langcode, $item->getValue(), 'summary') : $item->summary;
|
||||
$output = $sanitize ? $item->summary_processed : $item->summary;
|
||||
}
|
||||
// Attempt to provide a suitable version of the 'body' field.
|
||||
else {
|
||||
$output = $sanitize ? text_sanitize($instance['settings']['text_processing'], $field_langcode, $item->getValue(), 'value') : $item->value;
|
||||
$output = $sanitize ? $item->processed : $item->value;
|
||||
// A summary was requested.
|
||||
if ($name == 'summary') {
|
||||
// Generate an optionally trimmed summary of the body field.
|
||||
|
|
|
@ -71,22 +71,34 @@ abstract class TextItemBase extends ConfigFieldItemBase implements PrepareCacheI
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareCache() {
|
||||
// Where possible, generate the sanitized version of each textual property
|
||||
// (e.g., 'value', 'summary') within this field item early so that it is
|
||||
// cached in the field cache. This avoids the need to look up the sanitized
|
||||
// value in the filter cache separately.
|
||||
// Where possible, generate the processed (sanitized) version of each
|
||||
// textual property (e.g., 'value', 'summary') within this field item early
|
||||
// so that it is cached in the field cache. This avoids the need to look up
|
||||
// the sanitized value in the filter cache separately.
|
||||
$text_processing = $this->getFieldSetting('text_processing');
|
||||
if (!$text_processing || filter_format_allowcache($this->get('format')->getValue())) {
|
||||
$itemBC = $this->getValue();
|
||||
$langcode = $this->getParent()->getParent()->language()->id;
|
||||
// The properties that need sanitizing are the ones that are the 'text
|
||||
// source' of a TextProcessed computed property.
|
||||
// @todo Clean up this mess by making the TextProcessed property type
|
||||
// support its own cache integration: https://drupal.org/node/2026339.
|
||||
foreach ($this->getPropertyDefinitions() as $definition) {
|
||||
foreach ($this->getPropertyDefinitions() as $property => $definition) {
|
||||
if (isset($definition['class']) && ($definition['class'] == '\Drupal\text\TextProcessed')) {
|
||||
$source_property = $definition['settings']['text source'];
|
||||
$this->set('safe_' . $source_property, text_sanitize($text_processing, $langcode, $itemBC, $source_property));
|
||||
$this->get($property)->getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onChange($property_name) {
|
||||
// Notify the parent of changes.
|
||||
if (isset($this->parent)) {
|
||||
$this->parent->onChange($this->name);
|
||||
}
|
||||
|
||||
// Unset processed properties that are affected by the change.
|
||||
foreach ($this->getPropertyDefinitions() as $property => $definition) {
|
||||
if (isset($definition['class']) && ($definition['class'] == '\Drupal\text\TextProcessed')) {
|
||||
if ($property_name == 'format' || (isset($definition['settings']['text source']) && $definition['settings']['text source'] == $property_name)) {
|
||||
$this->set($property, NULL, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,11 +38,7 @@ class TextDefaultFormatter extends FormatterBase {
|
|||
$elements = array();
|
||||
|
||||
foreach ($items as $delta => $item) {
|
||||
// @todo Convert text_sanitize() to work on an NG $item. See
|
||||
// https://drupal.org/node/2026339.
|
||||
$itemBC = $item->getValue(TRUE);
|
||||
$output = text_sanitize($this->getFieldSetting('text_processing'), $langcode, $itemBC, 'value');
|
||||
$elements[$delta] = array('#markup' => $output);
|
||||
$elements[$delta] = array('#markup' => $item->processed);
|
||||
}
|
||||
|
||||
return $elements;
|
||||
|
|
|
@ -71,10 +71,10 @@ class TextTrimmedFormatter extends FormatterBase {
|
|||
$text_processing = $this->getFieldSetting('text_processing');
|
||||
foreach ($items as $delta => $item) {
|
||||
if ($this->getPluginId() == 'text_summary_or_trimmed' && !empty($item->summary)) {
|
||||
$output = text_sanitize($text_processing, $langcode, $item->getValue(TRUE), 'summary');
|
||||
$output = $item->summary_processed;
|
||||
}
|
||||
else {
|
||||
$output = text_sanitize($text_processing, $langcode, $item->getValue(TRUE), 'value');
|
||||
$output = $item->processed;
|
||||
$output = text_summary($output, $text_processing ? $item->format : NULL, $this->getSetting('trim_length'));
|
||||
}
|
||||
$elements[$delta] = array('#markup' => $output);
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\text\Tests\TextSummaryItemTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\text\Tests;
|
||||
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Entity\Field\FieldInterface;
|
||||
use Drupal\Core\Entity\Field\FieldItemInterface;
|
||||
use Drupal\field\Tests\FieldUnitTestBase;
|
||||
|
||||
/**
|
||||
* Tests for \Drupal\text\Plugin\field\field_type\TextWithSummaryItem.
|
||||
*/
|
||||
class TextWithSummaryItemTest extends FieldUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('filter');
|
||||
|
||||
/**
|
||||
* Field entity.
|
||||
*
|
||||
* @var \Drupal\field\Entity\Field.
|
||||
*/
|
||||
protected $field;
|
||||
|
||||
/**
|
||||
* Field instance.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldInstance
|
||||
*/
|
||||
protected $instance;
|
||||
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Text summary field item',
|
||||
'description' => 'Tests using entity fields of the text summary field type.',
|
||||
'group' => 'Field types',
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installSchema('entity_test', array('entity_test_rev', 'entity_test_rev_revision'));
|
||||
|
||||
// Create the necessary formats.
|
||||
$this->installConfig(array('filter'));
|
||||
entity_create('filter_format', array(
|
||||
'format' => 'no_filters',
|
||||
'filters' => array(),
|
||||
))->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.
|
||||
$entity = entity_create($entity_type, array());
|
||||
$entity->summary_field->value = $value = $this->randomName();
|
||||
$entity->summary_field->summary = $summary = $this->randomName();
|
||||
$entity->summary_field->format = NULL;
|
||||
$entity->name->value = $this->randomName();
|
||||
$entity->save();
|
||||
|
||||
$entity = entity_load($entity_type, $entity->id());
|
||||
$this->assertTrue($entity->summary_field instanceof FieldInterface, '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->processed, $value);
|
||||
$this->assertEqual($entity->summary_field->summary, $summary);
|
||||
$this->assertEqual($entity->summary_field->summary_processed, $summary);
|
||||
$this->assertNull($entity->summary_field->format);
|
||||
|
||||
// Enable text processing.
|
||||
$this->instance->settings['text_processing'] = 1;
|
||||
$this->instance->save();
|
||||
|
||||
// Re-load the entity.
|
||||
$entity = entity_load($entity_type, $entity->id(), TRUE);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the processed values are cached.
|
||||
*/
|
||||
function testProcessedCache() {
|
||||
// Use an entity type that has caching enabled.
|
||||
$entity_type = 'entity_test_rev';
|
||||
|
||||
$this->createField($entity_type);
|
||||
|
||||
// Create an entity with a summary and a text format.
|
||||
$entity = entity_create($entity_type, array());
|
||||
$entity->summary_field->value = $value = $this->randomName();
|
||||
$entity->summary_field->summary = $summary = $this->randomName();
|
||||
$entity->summary_field->format = 'plain_text';
|
||||
$entity->name->value = $this->randomName();
|
||||
$entity->save();
|
||||
|
||||
// Inject values into the cache to make sure that these are used as-is and
|
||||
// not re-calculated.
|
||||
$data = array(
|
||||
'summary_field' => array(
|
||||
Language::LANGCODE_DEFAULT => array(
|
||||
0 => array(
|
||||
'value' => $value,
|
||||
'summary' => $summary,
|
||||
'format' => 'plain_text',
|
||||
'processed' => 'Cached processed value',
|
||||
'summary_processed' => 'Cached summary processed value',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
cache('field')->set("field:$entity_type:" . $entity->id(), $data);
|
||||
|
||||
$entity = entity_load($entity_type, $entity->id());
|
||||
$this->assertEqual($entity->summary_field->processed, 'Cached processed value');
|
||||
$this->assertEqual($entity->summary_field->summary_processed, 'Cached summary processed value');
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text_with_summary field and field instance.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* Entity type for which the field should be created.
|
||||
*/
|
||||
protected function createField($entity_type) {
|
||||
// Create a field .
|
||||
$this->field = entity_create('field_entity', array(
|
||||
'name' => 'summary_field',
|
||||
'entity_type' => $entity_type,
|
||||
'type' => 'text_with_summary',
|
||||
'settings' => array(
|
||||
'max_length' => 10,
|
||||
)
|
||||
));
|
||||
$this->field->save();
|
||||
$this->instance = entity_create('field_instance', array(
|
||||
'field_name' => $this->field->name,
|
||||
'entity_type' => $entity_type,
|
||||
'bundle' => $entity_type,
|
||||
'settings' => array(
|
||||
'text_processing' => 0,
|
||||
)
|
||||
));
|
||||
$this->instance->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -21,18 +21,11 @@ use InvalidArgumentException;
|
|||
class TextProcessed extends TypedData {
|
||||
|
||||
/**
|
||||
* The text property.
|
||||
* Cached processed text.
|
||||
*
|
||||
* @var \Drupal\Core\TypedData\TypedDataInterface
|
||||
* @var string|null
|
||||
*/
|
||||
protected $text;
|
||||
|
||||
/**
|
||||
* The text format property.
|
||||
*
|
||||
* @var \Drupal\Core\TypedData\TypedDataInterface
|
||||
*/
|
||||
protected $format;
|
||||
protected $processed = NULL;
|
||||
|
||||
/**
|
||||
* Overrides TypedData::__construct().
|
||||
|
@ -45,47 +38,35 @@ class TextProcessed extends TypedData {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides TypedData::setContext().
|
||||
*/
|
||||
public function setContext($name = NULL, TypedDataInterface $parent = NULL) {
|
||||
parent::setContext($name, $parent);
|
||||
if (isset($parent)) {
|
||||
$this->text = $parent->get($this->definition['settings']['text source']);
|
||||
$this->format = $parent->get('format');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\Core\TypedData\TypedDataInterface::getValue().
|
||||
*/
|
||||
public function getValue($langcode = NULL) {
|
||||
|
||||
if (!isset($this->text)) {
|
||||
throw new InvalidArgumentException('Computed properties require context for computation.');
|
||||
if ($this->processed !== NULL) {
|
||||
return $this->processed;
|
||||
}
|
||||
|
||||
$field = $this->parent->getParent();
|
||||
$entity = $field->getParent();
|
||||
$instance = field_info_instance($entity->entityType(), $field->getName(), $entity->bundle());
|
||||
|
||||
if (!empty($instance['settings']['text_processing']) && $this->format->getValue()) {
|
||||
return check_markup($this->text->getValue(), $this->format->getValue(), $entity->language()->id);
|
||||
$item = $this->getParent();
|
||||
$text = $item->{($this->definition['settings']['text source'])};
|
||||
if ($item->getFieldDefinition()->getFieldSetting('text_processing')) {
|
||||
$this->processed = check_markup($text, $item->format, $item->getLangcode());
|
||||
}
|
||||
else {
|
||||
// If no format is available, still make sure to sanitize the text.
|
||||
return check_plain($this->text->getValue());
|
||||
// Escape all HTML and retain newlines.
|
||||
// @see \Drupal\text\Plugin\field\formatter\TextPlainFormatter
|
||||
$this->processed = nl2br(check_plain($text));
|
||||
}
|
||||
return $this->processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\Core\TypedData\TypedDataInterface::setValue().
|
||||
*/
|
||||
public function setValue($value, $notify = TRUE) {
|
||||
if (isset($value)) {
|
||||
// @todo This is triggered from DatabaseStorageController::invokeFieldMethod()
|
||||
// in the case of case of non-NG entity types.
|
||||
// throw new ReadOnlyException('Unable to set a computed property.');
|
||||
$this->processed = $value;
|
||||
// Notify the parent of any changes.
|
||||
if ($notify && isset($this->parent)) {
|
||||
$this->parent->onChange($this->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,42 +40,6 @@ function text_help($path, $arg) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the 'value' or 'summary' data of a text value.
|
||||
*
|
||||
* Depending on whether the field instance uses text processing, data is run
|
||||
* through check_plain() or check_markup().
|
||||
*
|
||||
* @param bool $text_processing
|
||||
* Whether to process the text via check_markup().
|
||||
* @param string $langcode
|
||||
* The language associated with $item.
|
||||
* @param array $item
|
||||
* The field value to sanitize.
|
||||
* @param string $column
|
||||
* The column to sanitize (either 'value' or 'summary').
|
||||
*
|
||||
* @return string
|
||||
* The sanitized string.
|
||||
*/
|
||||
function text_sanitize($text_processing, $langcode, $item, $column) {
|
||||
if (isset($item["safe_$column"])) {
|
||||
return $item["safe_$column"];
|
||||
}
|
||||
|
||||
// Optimize by opting out for the trivial 'empty string' case.
|
||||
if ($item[$column] == '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($text_processing) {
|
||||
return check_markup($item[$column], $item['format'], $langcode);
|
||||
}
|
||||
// Escape all HTML and retain newlines.
|
||||
// @see \Drupal\text\Plugin\field\formatter\TextPlainFormatter
|
||||
return nl2br(check_plain($item[$column]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a trimmed, formatted version of a text field value.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue