Commit 1fb7dc9c authored by xjm's avatar xjm

Issue #2775669 by jhedstrom, denutkarsh, xjm, mpdonadio: Clean up redundant...

Issue #2775669 by jhedstrom, denutkarsh, xjm, mpdonadio: Clean up redundant methods in datetime field formatters
parent f572d837
...@@ -32,30 +32,18 @@ public static function defaultSettings() { ...@@ -32,30 +32,18 @@ public static function defaultSettings() {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function viewElements(FieldItemListInterface $items, $langcode) { public function viewElements(FieldItemListInterface $items, $langcode) {
// @todo Evaluate removing this method in
// https://www.drupal.org/node/2793143 to determine if the behavior and
// markup in the base class implementation can be used instead.
$elements = array(); $elements = array();
foreach ($items as $delta => $item) { foreach ($items as $delta => $item) {
$output = '';
if (!empty($item->date)) { if (!empty($item->date)) {
/** @var \Drupal\Core\Datetime\DrupalDateTime $date */ /** @var \Drupal\Core\Datetime\DrupalDateTime $date */
$date = $item->date; $date = $item->date;
if ($this->getFieldSetting('datetime_type') == 'date') { $elements[$delta] = $this->buildDate($date);
// A date without time will pick up the current time, use the default.
datetime_date_default_time($date);
}
$this->setTimeZone($date);
$output = $this->formatDate($date);
} }
$elements[$delta] = [
'#markup' => $output,
'#cache' => [
'contexts' => [
'timezone',
],
],
];
} }
return $elements; return $elements;
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
namespace Drupal\datetime\Plugin\Field\FieldFormatter; namespace Drupal\datetime\Plugin\Field\FieldFormatter;
use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
/** /**
...@@ -28,59 +27,6 @@ public static function defaultSettings() { ...@@ -28,59 +27,6 @@ public static function defaultSettings() {
) + parent::defaultSettings(); ) + parent::defaultSettings();
} }
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = array();
foreach ($items as $delta => $item) {
$output = '';
$iso_date = '';
if ($item->date) {
/** @var \Drupal\Core\Datetime\DrupalDateTime $date */
$date = $item->date;
if ($this->getFieldSetting('datetime_type') == 'date') {
// A date without time will pick up the current time, use the default.
datetime_date_default_time($date);
}
// Create the ISO date in Universal Time.
$iso_date = $date->format("Y-m-d\TH:i:s") . 'Z';
$this->setTimeZone($date);
$output = $this->formatDate($date);
}
// Display the date using theme datetime.
$elements[$delta] = array(
'#cache' => [
'contexts' => [
'timezone',
],
],
'#theme' => 'time',
'#text' => $output,
'#html' => FALSE,
'#attributes' => array(
'datetime' => $iso_date,
),
);
if (!empty($item->_attributes)) {
$elements[$delta]['#attributes'] += $item->_attributes;
// Unset field item attributes since they have been included in the
// formatter output and should not be rendered in the field template.
unset($item->_attributes);
}
}
return $elements;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase; use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
...@@ -117,6 +118,30 @@ public function settingsSummary() { ...@@ -117,6 +118,30 @@ public function settingsSummary() {
return $summary; return $summary;
} }
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = array();
foreach ($items as $delta => $item) {
if ($item->date) {
/** @var \Drupal\Core\Datetime\DrupalDateTime $date */
$date = $item->date;
$elements[$delta] = $this->buildDateWithIsoAttribute($date);
if (!empty($item->_attributes)) {
$elements[$delta]['#attributes'] += $item->_attributes;
// Unset field item attributes since they have been included in the
// formatter output and should not be rendered in the field template.
unset($item->_attributes);
}
}
}
return $elements;
}
/** /**
* Creates a formatted date value as a string. * Creates a formatted date value as a string.
* *
...@@ -167,4 +192,69 @@ protected function getFormatSettings() { ...@@ -167,4 +192,69 @@ protected function getFormatSettings() {
return $settings; return $settings;
} }
/**
* Creates a render array from a date object.
*
* @param \Drupal\Core\Datetime\DrupalDateTime $date
* A date object.
*
* @return array
* A render array.
*/
protected function buildDate(DrupalDateTime $date) {
if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) {
// A date without time will pick up the current time, use the default.
datetime_date_default_time($date);
}
$this->setTimeZone($date);
$build = [
'#markup' => $this->formatDate($date),
'#cache' => [
'contexts' => [
'timezone',
],
],
];
return $build;
}
/**
* Creates a render array from a date object with ISO date attribute.
*
* @param \Drupal\Core\Datetime\DrupalDateTime $date
* A date object.
*
* @return array
* A render array.
*/
protected function buildDateWithIsoAttribute(DrupalDateTime $date) {
if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) {
// A date without time will pick up the current time, use the default.
datetime_date_default_time($date);
}
// Create the ISO date in Universal Time.
$iso_date = $date->format("Y-m-d\TH:i:s") . 'Z';
$this->setTimeZone($date);
$build = [
'#theme' => 'time',
'#text' => $this->formatDate($date),
'#html' => FALSE,
'#attributes' => [
'datetime' => $iso_date,
],
'#cache' => [
'contexts' => [
'timezone',
],
],
];
return $build;
}
} }
...@@ -25,27 +25,12 @@ public function viewElements(FieldItemListInterface $items, $langcode) { ...@@ -25,27 +25,12 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = array(); $elements = array();
foreach ($items as $delta => $item) { foreach ($items as $delta => $item) {
$output = '';
if (!empty($item->date)) { if (!empty($item->date)) {
/** @var \Drupal\Core\Datetime\DrupalDateTime $date */ /** @var \Drupal\Core\Datetime\DrupalDateTime $date */
$date = $item->date; $date = $item->date;
if ($this->getFieldSetting('datetime_type') == 'date') { $elements[$delta] = $this->buildDate($date);
// A date without time will pick up the current time, use the default.
datetime_date_default_time($date);
}
$this->setTimeZone($date);
$output = $this->formatDate($date);
} }
$elements[$delta] = [
'#cache' => [
'contexts' => [
'timezone',
],
],
'#markup' => $output,
];
} }
return $elements; return $elements;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace Drupal\datetime\Tests; namespace Drupal\datetime\Tests;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Unicode; use Drupal\Component\Utility\Unicode;
use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Datetime\DrupalDateTime;
...@@ -139,6 +140,16 @@ function testDateField() { ...@@ -139,6 +140,16 @@ function testDateField() {
$this->renderTestEntity($id); $this->renderTestEntity($id);
$this->assertText($expected, SafeMarkup::format('Formatted date field using datetime_custom format displayed as %expected.', array('%expected' => $expected))); $this->assertText($expected, SafeMarkup::format('Formatted date field using datetime_custom format displayed as %expected.', array('%expected' => $expected)));
// Test that allowed markup in custom format is preserved and XSS is
// removed.
$this->displayOptions['settings']['date_format'] = '\\<\\s\\t\\r\\o\\n\\g\\>m/d/Y\\<\\/\\s\\t\\r\\o\\n\\g\\>\\<\\s\\c\\r\\i\\p\\t\\>\\a\\l\\e\\r\\t\\(\\S\\t\\r\\i\\n\\g\\.\\f\\r\\o\\m\\C\\h\\a\\r\\C\\o\\d\\e\\(\\8\\8\\,\\8\\3\\,\\8\\3\\)\\)\\<\\/\\s\\c\\r\\i\\p\\t\\>';
entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
->setComponent($field_name, $this->displayOptions)
->save();
$expected = '<strong>' . $date->format('m/d/Y') . '</strong>alert(String.fromCharCode(88,83,83))';
$this->renderTestEntity($id);
$this->assertRaw($expected, new FormattableMarkup('Formatted date field using daterange_custom format displayed as %expected.', array('%expected' => $expected)));
// Verify that the 'datetime_time_ago' formatter works for intervals in the // Verify that the 'datetime_time_ago' formatter works for intervals in the
// past. First update the test entity so that the date difference always // past. First update the test entity so that the date difference always
// has the same interval. Since the database always stores UTC, and the // has the same interval. Since the database always stores UTC, and the
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
namespace Drupal\datetime_range; namespace Drupal\datetime_range;
use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Field\FieldItemListInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
/** /**
* Provides friendly methods for datetime range. * Provides friendly methods for datetime range.
...@@ -11,68 +10,40 @@ ...@@ -11,68 +10,40 @@
trait DateTimeRangeTrait { trait DateTimeRangeTrait {
/** /**
* Creates a render array from a date object. * {@inheritdoc}
*
* @param \Drupal\Core\Datetime\DrupalDateTime $date
* A date object.
*
* @return array
* A render array.
*/ */
protected function buildDate(DrupalDateTime $date) { public function viewElements(FieldItemListInterface $items, $langcode) {
if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) { $elements = [];
// A date without time will pick up the current time, use the default. $separator = $this->getSetting('separator');
datetime_date_default_time($date);
foreach ($items as $delta => $item) {
if (!empty($item->start_date) && !empty($item->end_date)) {
/** @var \Drupal\Core\Datetime\DrupalDateTime $start_date */
$start_date = $item->start_date;
/** @var \Drupal\Core\Datetime\DrupalDateTime $end_date */
$end_date = $item->end_date;
if ($start_date->format('U') !== $end_date->format('U')) {
$elements[$delta] = [
'start_date' => $this->buildDateWithIsoAttribute($start_date),
'separator' => ['#plain_text' => ' ' . $separator . ' '],
'end_date' => $this->buildDateWithIsoAttribute($end_date),
];
}
else {
$elements[$delta] = $this->buildDateWithIsoAttribute($start_date);
if (!empty($item->_attributes)) {
$elements[$delta]['#attributes'] += $item->_attributes;
// Unset field item attributes since they have been included in the
// formatter output and should not be rendered in the field template.
unset($item->_attributes);
}
}
}
} }
$this->setTimeZone($date);
$build = [ return $elements;
'#plain_text' => $this->formatDate($date),
'#cache' => [
'contexts' => [
'timezone',
],
],
];
return $build;
}
/**
* Creates a render array from a date object with ISO date attribute.
*
* @param \Drupal\Core\Datetime\DrupalDateTime $date
* A date object.
*
* @return array
* A render array.
*/
protected function buildDateWithIsoAttribute(DrupalDateTime $date) {
if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) {
// A date without time will pick up the current time, use the default.
datetime_date_default_time($date);
}
// Create the ISO date in Universal Time.
$iso_date = $date->format("Y-m-d\TH:i:s") . 'Z';
$this->setTimeZone($date);
$build = [
'#theme' => 'time',
'#text' => $this->formatDate($date),
'#html' => FALSE,
'#attributes' => [
'datetime' => $iso_date,
],
'#cache' => [
'contexts' => [
'timezone',
],
],
];
return $build;
} }
} }
...@@ -38,6 +38,9 @@ public static function defaultSettings() { ...@@ -38,6 +38,9 @@ public static function defaultSettings() {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function viewElements(FieldItemListInterface $items, $langcode) { public function viewElements(FieldItemListInterface $items, $langcode) {
// @todo Evaluate removing this method in
// https://www.drupal.org/node/2793143 to determine if the behavior and
// markup in the base class implementation can be used instead.
$elements = []; $elements = [];
$separator = $this->getSetting('separator'); $separator = $this->getSetting('separator');
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
namespace Drupal\datetime_range\Plugin\Field\FieldFormatter; namespace Drupal\datetime_range\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\datetime\Plugin\Field\FieldFormatter\DateTimeDefaultFormatter; use Drupal\datetime\Plugin\Field\FieldFormatter\DateTimeDefaultFormatter;
use Drupal\datetime_range\DateTimeRangeTrait; use Drupal\datetime_range\DateTimeRangeTrait;
...@@ -35,42 +34,6 @@ public static function defaultSettings() { ...@@ -35,42 +34,6 @@ public static function defaultSettings() {
] + parent::defaultSettings(); ] + parent::defaultSettings();
} }
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
$separator = $this->getSetting('separator');
foreach ($items as $delta => $item) {
if (!empty($item->start_date) && !empty($item->end_date)) {
/** @var \Drupal\Core\Datetime\DrupalDateTime $start_date */
$start_date = $item->start_date;
/** @var \Drupal\Core\Datetime\DrupalDateTime $end_date */
$end_date = $item->end_date;
if ($start_date->getTimestamp() !== $end_date->getTimestamp()) {
$elements[$delta] = [
'start_date' => $this->buildDateWithIsoAttribute($start_date),
'separator' => ['#plain_text' => ' ' . $separator . ' '],
'end_date' => $this->buildDateWithIsoAttribute($end_date),
];
}
else {
$elements[$delta] = $this->buildDateWithIsoAttribute($start_date);
if (!empty($item->_attributes)) {
$elements[$delta]['#attributes'] += $item->_attributes;
// Unset field item attributes since they have been included in the
// formatter output and should not be rendered in the field template.
unset($item->_attributes);
}
}
}
}
return $elements;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
......
...@@ -48,7 +48,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) { ...@@ -48,7 +48,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
/** @var \Drupal\Core\Datetime\DrupalDateTime $end_date */ /** @var \Drupal\Core\Datetime\DrupalDateTime $end_date */
$end_date = $item->end_date; $end_date = $item->end_date;
if ($start_date->getTimestamp() !== $end_date->getTimestamp()) { if ($start_date->format('U') !== $end_date->format('U')) {
$elements[$delta] = [ $elements[$delta] = [
'start_date' => $this->buildDate($start_date), 'start_date' => $this->buildDate($start_date),
'separator' => ['#plain_text' => ' ' . $separator . ' '], 'separator' => ['#plain_text' => ' ' . $separator . ' '],
...@@ -57,6 +57,13 @@ public function viewElements(FieldItemListInterface $items, $langcode) { ...@@ -57,6 +57,13 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
} }
else { else {
$elements[$delta] = $this->buildDate($start_date); $elements[$delta] = $this->buildDate($start_date);
if (!empty($item->_attributes)) {
$elements[$delta]['#attributes'] += $item->_attributes;
// Unset field item attributes since they have been included in the
// formatter output and should not be rendered in the field template.
unset($item->_attributes);
}
} }
} }
} }
......
...@@ -165,6 +165,16 @@ public function testDateRangeField() { ...@@ -165,6 +165,16 @@ public function testDateRangeField() {
$this->renderTestEntity($id); $this->renderTestEntity($id);
$this->assertText($expected, new FormattableMarkup('Formatted date field using daterange_custom format displayed as %expected.', array('%expected' => $expected))); $this->assertText($expected, new FormattableMarkup('Formatted date field using daterange_custom format displayed as %expected.', array('%expected' => $expected)));
// Test that allowed markup in custom format is preserved and XSS is
// removed.
$this->displayOptions['settings']['date_format'] = '\\<\\s\\t\\r\\o\\n\\g\\>m/d/Y\\<\\/\\s\\t\\r\\o\\n\\g\\>\\<\\s\\c\\r\\i\\p\\t\\>\\a\\l\\e\\r\\t\\(\\S\\t\\r\\i\\n\\g\\.\\f\\r\\o\\m\\C\\h\\a\\r\\C\\o\\d\\e\\(\\8\\8\\,\\8\\3\\,\\8\\3\\)\\)\\<\\/\\s\\c\\r\\i\\p\\t\\>';
entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
->setComponent($field_name, $this->displayOptions)
->save();
$expected = '<strong>' . $start_date->format('m/d/Y') . '</strong>alert(String.fromCharCode(88,83,83)) - <strong>' . $end_date->format('m/d/Y') . '</strong>alert(String.fromCharCode(88,83,83))';
$this->renderTestEntity($id);
$this->assertRaw($expected, new FormattableMarkup('Formatted date field using daterange_custom format displayed as %expected.', array('%expected' => $expected)));
// Test formatters when start date and end date are the same // Test formatters when start date and end date are the same
$this->drupalGet('entity_test/add'); $this->drupalGet('entity_test/add');
$value = '2012-12-31 00:00:00'; $value = '2012-12-31 00:00:00';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment