Update to Drupal 8.0.0-beta15. For more information, see: https://www.drupal.org/node/2563023

This commit is contained in:
Pantheon Automation 2015-09-04 13:20:09 -07:00 committed by Greg Anderson
parent 2720a9ec4b
commit f3791f1da3
1898 changed files with 54300 additions and 11481 deletions

View file

@ -6,12 +6,13 @@
namespace Drupal\Core\Field;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Xss;
/**
* Useful methods when dealing with displaying allowed tags.
*
* @deprecated in Drupal 8.0.x, will be removed before Drupal 9.0.0. Use
* \Drupal\Core\Field\FieldFilteredString instead.
*
* @see \Drupal\Core\Field\FieldFilteredString
*/
trait AllowedTagsXssTrait {
@ -33,30 +34,21 @@ trait AllowedTagsXssTrait {
* valid UTF-8.
*/
public function fieldFilterXss($string) {
// All known XSS vectors are filtered out by
// \Drupal\Component\Utility\Xss::filter(), all tags in the markup are
// allowed intentionally by the trait, and no danger is added in by
// \Drupal\Component\Utility\HTML::normalize(). Since the normalized value
// is essentially the same markup, designate this string as safe as well.
// This method is an internal part of field sanitization, so the resultant,
// sanitized string should be printable as is.
//
// @todo Free this memory in https://www.drupal.org/node/2505963.
return SafeMarkup::set(Html::normalize(Xss::filter($string, $this->allowedTags())));
return FieldFilteredString::create($string);
}
/**
* Returns a list of tags allowed by AllowedTagsXssTrait::fieldFilterXss().
*/
public function allowedTags() {
return array('a', 'b', 'big', 'code', 'del', 'em', 'i', 'ins', 'pre', 'q', 'small', 'span', 'strong', 'sub', 'sup', 'tt', 'ol', 'ul', 'li', 'p', 'br', 'img');
return FieldFilteredString::allowedTags();
}
/**
* Returns a human-readable list of allowed tags for display in help texts.
*/
public function displayAllowedTags() {
return '<' . implode('> <', $this->allowedTags()) . '>';
return FieldFilteredString::displayAllowedTags();
}
}

View file

@ -20,7 +20,7 @@ use Drupal\Core\Field\FieldException;
* @ConfigEntityType(
* id = "base_field_override",
* label = @Translation("Base field override"),
* controllers = {
* handlers = {
* "storage" = "Drupal\Core\Field\BaseFieldOverrideStorage"
* },
* config_prefix = "base_field_override",

View file

@ -248,15 +248,10 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn
// @see \Drupal\Core\Field\FieldItemInterface::calculateDependencies()
$this->addDependencies($definition['class']::calculateDependencies($this));
// If the target entity type uses entities to manage its bundles then
// depend on the bundle entity.
$bundle_entity_type_id = $this->entityManager()->getDefinition($this->entity_type)->getBundleEntityType();
if ($bundle_entity_type_id != 'bundle') {
if (!$bundle_entity = $this->entityManager()->getStorage($bundle_entity_type_id)->load($this->bundle)) {
throw new \LogicException("Missing bundle entity, entity type {$bundle_entity_type_id}, entity id {$this->bundle}.");
}
$this->addDependency('config', $bundle_entity->getConfigDependencyName());
}
// Create dependency on the bundle.
$bundle_config_dependency = $this->entityManager()->getDefinition($this->entity_type)->getBundleConfigDependency($this->bundle);
$this->addDependency($bundle_config_dependency['type'], $bundle_config_dependency['name']);
return $this->dependencies;
}

View file

@ -0,0 +1,78 @@
<?php
/**
* @file
* Contains \Drupal\Core\Field\FieldFilteredString.
*/
namespace Drupal\Core\Field;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\SafeStringInterface;
use Drupal\Component\Utility\SafeStringTrait;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\Xss;
/**
* Defines an object that passes safe strings through the Field system.
*
* This object filters the string using a very restrictive tag list when it is
* created.
*
* @internal
* This object is marked as internal because it should only be used by the
* Field module and field-related plugins.
*
* @see \Drupal\Core\Render\SafeString
*/
final class FieldFilteredString implements SafeStringInterface, \Countable {
use SafeStringTrait;
/**
* Overrides \Drupal\Component\Utility\SafeStringTrait::create().
*
* @return string|\Drupal\Component\Utility\SafeStringInterface
* A safe string filtered with the allowed tag list and normalized.
*
* @see \Drupal\Core\Field\FieldFilteredString::allowedTags()
* @see \Drupal\Component\Utility\Xss::filter()
* @see \Drupal\Component\Utility\Html::normalize()
*/
public static function create($string) {
$string = (string) $string;
if ($string === '') {
return '';
}
$safe_string = new static();
// All known XSS vectors are filtered out by
// \Drupal\Component\Utility\Xss::filter(), all tags in the markup are
// allowed intentionally by the trait, and no danger is added in by
// \Drupal\Component\Utility\HTML::normalize(). Since the normalized value
// is essentially the same markup, designate this string as safe as well.
// This method is an internal part of field sanitization, so the resultant,
// sanitized string should be printable as is.
$safe_string->string = Html::normalize(Xss::filter($string, static::allowedTags()));
return $safe_string;
}
/**
* Returns the allowed tag list.
*
* @return string[]
* A list of allowed tags.
*/
public static function allowedTags() {
return ['a', 'b', 'big', 'code', 'del', 'em', 'i', 'ins', 'pre', 'q', 'small', 'span', 'strong', 'sub', 'sup', 'tt', 'ol', 'ul', 'li', 'p', 'br', 'img'];
}
/**
* Returns a human-readable list of allowed tags for display in help texts.
*
* @return string
* A human-readable list of allowed tags for display in help texts.
*/
public static function displayAllowedTags() {
return '<' . implode('> <', static::allowedTags()) . '>';
}
}

View file

@ -7,7 +7,7 @@
namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Field\FieldItemListInterface;
@ -37,7 +37,7 @@ class BasicStringFormatter extends FormatterBase {
foreach ($items as $delta => $item) {
// The text value has no text format assigned to it, so the user input
// should equal the output, including newlines.
$elements[$delta] = array('#markup' => nl2br(SafeMarkup::checkPlain($item->value)));
$elements[$delta] = array('#markup' => nl2br(Html::escape($item->value)));
}
return $elements;

View file

@ -8,7 +8,6 @@
namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Component\Utility\SafeMarkup;
/**
* Plugin implementation of the 'entity reference ID' formatter.
@ -33,7 +32,7 @@ class EntityReferenceIdFormatter extends EntityReferenceFormatterBase {
foreach ($this->getEntitiesToView($items) as $delta => $entity) {
if ($entity->id()) {
$elements[$delta] = array(
'#markup' => SafeMarkup::checkPlain($entity->id()),
'#plain_text' => $entity->id(),
// Create a cache tag entry for the referenced entity. In the case
// that the referenced entity is deleted, the cache for referring
// entities must be cleared.

View file

@ -7,7 +7,6 @@
namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Entity\Exception\UndefinedLinkTemplateException;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
@ -98,7 +97,7 @@ class EntityReferenceLabelFormatter extends EntityReferenceFormatterBase {
}
}
else {
$elements[$delta] = array('#markup' => SafeMarkup::checkPlain($label));
$elements[$delta] = array('#plain_text' => $label);
}
$elements[$delta]['#cache']['tags'] = $entity->getCacheTags();
}

View file

@ -7,11 +7,11 @@
namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -121,8 +121,10 @@ class LanguageFormatter extends StringFormatter {
// either displayed in its configured form (loaded directly from config
// storage by LanguageManager::getLanguages()) or in its native language
// name. That only depends on formatter settings and no language condition.
$languages = $this->getSetting('native_language') ? $this->languageManager->getNativeLanguages() : $this->languageManager->getLanguages();
return $item->language ? SafeMarkup::checkPlain($languages[$item->language->getId()]->getName()) : '';
$languages = $this->getSetting('native_language') ? $this->languageManager->getNativeLanguages(LanguageInterface::STATE_ALL) : $this->languageManager->getLanguages(LanguageInterface::STATE_ALL);
return [
'#plain_text' => $item->language && isset($languages[$item->language->getId()]) ? $languages[$item->language->getId()]->getName() : ''
];
}
}

View file

@ -75,8 +75,8 @@ abstract class NumericFormatterBase extends FormatterBase {
// Account for prefix and suffix.
if ($this->getSetting('prefix_suffix')) {
$prefixes = isset($settings['prefix']) ? array_map(array($this, 'fieldFilterXss'), explode('|', $settings['prefix'])) : array('');
$suffixes = isset($settings['suffix']) ? array_map(array($this, 'fieldFilterXss'), explode('|', $settings['suffix'])) : array('');
$prefixes = isset($settings['prefix']) ? array_map(array('Drupal\Core\Field\FieldFilteredString', 'create'), explode('|', $settings['prefix'])) : array('');
$suffixes = isset($settings['suffix']) ? array_map(array('Drupal\Core\Field\FieldFilteredString', 'create'), explode('|', $settings['suffix'])) : array('');
$prefix = (count($prefixes) > 1) ? $this->formatPlural($item->value, $prefixes[0], $prefixes[1]) : $prefixes[0];
$suffix = (count($suffixes) > 1) ? $this->formatPlural($item->value, $suffixes[0], $suffixes[1]) : $suffixes[0];
$output = $prefix . $output . $suffix;

View file

@ -7,7 +7,7 @@
namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\RevisionableInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
@ -128,16 +128,16 @@ class StringFormatter extends FormatterBase implements ContainerFactoryPluginInt
}
foreach ($items as $delta => $item) {
$string = $this->viewValue($item);
$view_value = $this->viewValue($item);
if ($url) {
$elements[$delta] = [
'#type' => 'link',
'#title' => $string,
'#title' => $view_value,
'#url' => $url,
];
}
else {
$elements[$delta] = ['#markup' => $string];
$elements[$delta] = is_array($view_value) ? $view_value : ['#markup' => $view_value];
}
}
return $elements;
@ -149,13 +149,15 @@ class StringFormatter extends FormatterBase implements ContainerFactoryPluginInt
* @param \Drupal\Core\Field\FieldItemInterface $item
* One field item.
*
* @return string
* The textual output generated.
* @return array
* The textual output generated as a render array.
*/
protected function viewValue(FieldItemInterface $item) {
// The text value has no text format assigned to it, so the user input
// should equal the output, including newlines.
return nl2br(SafeMarkup::checkPlain($item->value));
return [
'#markup' => nl2br(Html::escape($item->value))
];
}
}

View file

@ -40,10 +40,10 @@ class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPlu
protected $dateFormatter;
/**
* The current Request object.
*
* @var \Symfony\Component\HttpFoundation\Request
*/
* The current Request object.
*
* @var \Symfony\Component\HttpFoundation\Request
*/
protected $request;
/**

View file

@ -13,6 +13,7 @@ use Drupal\Core\Entity\TypedData\EntityDataDefinition;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\StringTranslation\TranslationWrapper;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\DataReferenceDefinition;
@ -82,19 +83,19 @@ class EntityReferenceItem extends FieldItemBase {
if ($target_id_data_type === 'integer') {
$target_id_definition = DataDefinition::create('integer')
->setLabel(t('@label ID', array($target_type_info->getLabel())))
->setLabel(new TranslationWrapper('@label ID', ['@label' => $target_type_info->getLabel()]))
->setSetting('unsigned', TRUE);
}
else {
$target_id_definition = DataDefinition::create('string')
->setLabel(t('@label ID', array($target_type_info->getLabel())));
->setLabel(new TranslationWrapper('@label ID', ['@label' => $target_type_info->getLabel()]));
}
$target_id_definition->setRequired(TRUE);
$properties['target_id'] = $target_id_definition;
$properties['entity'] = DataReferenceDefinition::create('entity')
->setLabel($target_type_info->getLabel())
->setDescription(t('The referenced entity'))
->setDescription(new TranslationWrapper('The referenced entity'))
// The entity object is computed out of the entity ID.
->setComputed(TRUE)
->setReadOnly(FALSE)

View file

@ -63,4 +63,16 @@ class PasswordItem extends StringItem {
}
}
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
// We cannot use the parent implementation from StringItem as it does not
// consider the additional 'existing' property that PasswordItem contains.
$value = $this->get('value')->getValue();
$existing = $this->get('existing')->getValue();
return $value === NULL && $existing === NULL;
}
}

View file

@ -40,4 +40,12 @@ abstract class StringItemBase extends FieldItemBase {
return $properties;
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
$value = $this->get('value')->getValue();
return $value === NULL || $value === '';
}
}

View file

@ -23,6 +23,7 @@ use Drupal\Core\TypedData\DataDefinition;
* description = @Translation("An entity field containing a URI."),
* no_ui = TRUE,
* default_formatter = "uri_link",
* default_widget = "uri",
* )
*/
class UriItem extends StringItem {
@ -31,9 +32,11 @@ class UriItem extends StringItem {
* {@inheritdoc}
*/
public static function defaultStorageSettings() {
return array(
'max_length' => 2048,
) + parent::defaultStorageSettings();
$storage_settings = parent::defaultStorageSettings();
// is_ascii doesn't make sense for URIs.
unset($storage_settings['is_ascii']);
$storage_settings['max_length'] = 2048;
return $storage_settings;
}
/**

View file

@ -7,6 +7,7 @@
namespace Drupal\Core\Field\Plugin\Field\FieldWidget;
use Drupal\Core\Field\FieldFilteredString;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
@ -17,7 +18,7 @@ use Symfony\Component\Validator\ConstraintViolationInterface;
*
* @FieldWidget(
* id = "number",
* label = @Translation("Text field"),
* label = @Translation("Number field"),
* field_types = {
* "integer",
* "decimal",
@ -101,11 +102,11 @@ class NumberWidget extends WidgetBase {
// Add prefix and suffix.
if ($field_settings['prefix']) {
$prefixes = explode('|', $field_settings['prefix']);
$element['#field_prefix'] = $this->fieldFilterXss(array_pop($prefixes));
$element['#field_prefix'] = FieldFilteredString::create(array_pop($prefixes));
}
if ($field_settings['suffix']) {
$suffixes = explode('|', $field_settings['suffix']);
$element['#field_suffix'] = $this->fieldFilterXss(array_pop($suffixes));
$element['#field_suffix'] = FieldFilteredString::create(array_pop($suffixes));
}
return array('value' => $element);

View file

@ -9,6 +9,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldWidget;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldFilteredString;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
@ -190,7 +191,7 @@ abstract class OptionsWidgetBase extends WidgetBase {
*/
protected function sanitizeLabel(&$label) {
// Allow a limited set of HTML tags.
$label = $this->fieldFilterXss($label);
$label = FieldFilteredString::create($label);
}
/**

View file

@ -10,7 +10,6 @@ namespace Drupal\Core\Field;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\SortArray;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Symfony\Component\Validator\ConstraintViolationInterface;
@ -85,8 +84,8 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface
if ($this->handlesMultipleValues() || isset($get_delta)) {
$delta = isset($get_delta) ? $get_delta : 0;
$element = array(
'#title' => SafeMarkup::checkPlain($this->fieldDefinition->getLabel()),
'#description' => $this->fieldFilterXss(\Drupal::token()->replace($this->fieldDefinition->getDescription())),
'#title' => $this->fieldDefinition->getLabel(),
'#description' => FieldFilteredString::create(\Drupal::token()->replace($this->fieldDefinition->getDescription())),
);
$element = $this->formSingleElement($items, $delta, $element, $form, $form_state);
@ -128,9 +127,9 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface
'#parents' => array_merge($parents, array($field_name . '_wrapper')),
'#attributes' => array(
'class' => array(
'field-type-' . Html::getClass($this->fieldDefinition->getType()),
'field-name-' . Html::getClass($field_name),
'field-widget-' . Html::getClass($this->getPluginId()),
'field--type-' . Html::getClass($this->fieldDefinition->getType()),
'field--name-' . Html::getClass($field_name),
'field--widget-' . Html::getClass($this->getPluginId()),
),
),
'widget' => $elements,
@ -164,8 +163,8 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface
break;
}
$title = SafeMarkup::checkPlain($this->fieldDefinition->getLabel());
$description = $this->fieldFilterXss(\Drupal::token()->replace($this->fieldDefinition->getDescription()));
$title = $this->fieldDefinition->getLabel();
$description = FieldFilteredString::create(\Drupal::token()->replace($this->fieldDefinition->getDescription()));
$elements = array();
@ -179,7 +178,7 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface
// table.
if ($is_multiple) {
$element = [
'#title' => $title . ' ' . $this->t('(value @number)', ['@number' => $delta + 1]),
'#title' => $this->t('@title (value @number)', ['@title' => $title, '@number' => $delta + 1]),
'#title_display' => 'invisible',
'#description' => '',
];