From 36bc91215cd3269565cd4f7f1994ef3da439bc14 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Thu, 27 Oct 2016 22:25:24 -0700
Subject: [PATCH] Issue #2811725 by mpdonadio, paulanders, jhedstrom: Error
 when render Datetime Range field: Error: Unsupported operand types

---
 .../DateRangeDefaultFormatter.php             | 13 ++++----
 .../src/Tests/DateRangeFieldTest.php          | 30 +++++++++++++++++++
 .../modules/entity_test/entity_test.module    | 13 +++++++-
 3 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeDefaultFormatter.php b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeDefaultFormatter.php
index f5ebb8ceaa83..c0feed2cd8bd 100644
--- a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeDefaultFormatter.php
+++ b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeDefaultFormatter.php
@@ -58,13 +58,12 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
         }
         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);
+          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);
+          }
         }
       }
     }
diff --git a/core/modules/datetime_range/src/Tests/DateRangeFieldTest.php b/core/modules/datetime_range/src/Tests/DateRangeFieldTest.php
index 2afb5f5ec9eb..759352e8de16 100644
--- a/core/modules/datetime_range/src/Tests/DateRangeFieldTest.php
+++ b/core/modules/datetime_range/src/Tests/DateRangeFieldTest.php
@@ -140,6 +140,11 @@ public function testDateRangeField() {
       ]));
       $this->assertText(' THESEPARATOR ', 'Found proper separator');
 
+      // Verify that hook_entity_prepare_view can add attributes.
+      // @see entity_test_entity_prepare_view()
+      $this->drupalGet('entity_test/' . $id);
+      $this->assertFieldByXPath('//div[@data-field-item-attr="foobar"]');
+
       // Verify that the plain formatter works.
       $this->displayOptions['type'] = 'daterange_plain';
       $this->displayOptions['settings'] = $this->defaultSettings;
@@ -203,6 +208,11 @@ public function testDateRangeField() {
       ]));
       $this->assertNoText(' THESEPARATOR ', 'Separator not found on page');
 
+      // Verify that hook_entity_prepare_view can add attributes.
+      // @see entity_test_entity_prepare_view()
+      $this->drupalGet('entity_test/' . $id);
+      $this->assertFieldByXPath('//time[@data-field-item-attr="foobar"]');
+
       $this->displayOptions['type'] = 'daterange_plain';
       $this->displayOptions['settings'] = $this->defaultSettings;
       entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
@@ -289,6 +299,11 @@ public function testDatetimeRangeField() {
     $this->assertFieldByXPath('//time[@datetime="' . $end_expected_iso . '"]', $end_expected, new FormattableMarkup('Formatted date field using %value format displayed as %expected with %expected_iso attribute.', ['%value' => 'long', '%expected' => $end_expected, '%expected_iso' => $end_expected_iso]));
     $this->assertText(' THESEPARATOR ', 'Found proper separator');
 
+    // Verify that hook_entity_prepare_view can add attributes.
+    // @see entity_test_entity_prepare_view()
+    $this->drupalGet('entity_test/' . $id);
+    $this->assertFieldByXPath('//div[@data-field-item-attr="foobar"]');
+
     // Verify that the plain formatter works.
     $this->displayOptions['type'] = 'daterange_plain';
     $this->displayOptions['settings'] = $this->defaultSettings;
@@ -360,6 +375,11 @@ public function testDatetimeRangeField() {
     $this->assertFieldByXPath('//time[@datetime="' . $start_expected_iso . '"]', $start_expected, new FormattableMarkup('Formatted date field using %value format displayed as %expected with %expected_iso attribute.', ['%value' => 'long', '%expected' => $start_expected, '%expected_iso' => $start_expected_iso]));
     $this->assertNoText(' THESEPARATOR ', 'Separator not found on page');
 
+    // Verify that hook_entity_prepare_view can add attributes.
+    // @see entity_test_entity_prepare_view()
+    $this->drupalGet('entity_test/' . $id);
+    $this->assertFieldByXPath('//time[@data-field-item-attr="foobar"]');
+
     $this->displayOptions['type'] = 'daterange_plain';
     $this->displayOptions['settings'] = $this->defaultSettings;
     entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
@@ -440,6 +460,11 @@ public function testAlldayRangeField() {
     $this->assertFieldByXPath('//time[@datetime="' . $end_expected_iso . '"]', $end_expected, new FormattableMarkup('Formatted date field using %value format displayed as %expected with %expected_iso attribute.', ['%value' => 'long', '%expected' => $end_expected, '%expected_iso' => $end_expected_iso]));
     $this->assertText(' THESEPARATOR ', 'Found proper separator');
 
+    // Verify that hook_entity_prepare_view can add attributes.
+    // @see entity_test_entity_prepare_view()
+    $this->drupalGet('entity_test/' . $id);
+    $this->assertFieldByXPath('//div[@data-field-item-attr="foobar"]');
+
     // Verify that the plain formatter works.
     $this->displayOptions['type'] = 'daterange_plain';
     $this->displayOptions['settings'] = $this->defaultSettings;
@@ -513,6 +538,11 @@ public function testAlldayRangeField() {
     $this->assertFieldByXPath('//time[@datetime="' . $end_expected_iso . '"]', $end_expected, new FormattableMarkup('Formatted date field using %value format displayed as %expected with %expected_iso attribute.', ['%value' => 'long', '%expected' => $end_expected, '%expected_iso' => $end_expected_iso]));
     $this->assertText(' THESEPARATOR ', 'Found proper separator');
 
+    // Verify that hook_entity_prepare_view can add attributes.
+    // @see entity_test_entity_prepare_view()
+    $this->drupalGet('entity_test/' . $id);
+    $this->assertFieldByXPath('//div[@data-field-item-attr="foobar"]');
+
     $this->displayOptions['type'] = 'daterange_plain';
     entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
       ->setComponent($field_name, $this->displayOptions)
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 453bdf11441c..b0c8cbf4dccd 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -674,14 +674,25 @@ function _entity_test_record_hooks($hook, $data) {
  * Implements hook_entity_prepare_view().
  */
 function entity_test_entity_prepare_view($entity_type, array $entities, array $displays) {
-  // Add a dummy field item attribute on field_test_text if it exists.
   if ($entity_type == 'entity_test') {
     foreach ($entities as $entity) {
+      /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
+
+      // Add a dummy field item attribute on field_test_text if it exists.
       if ($entity->hasField('field_test_text') && $displays[$entity->bundle()]->getComponent('field_test_text')) {
         foreach ($entity->get('field_test_text') as $item) {
           $item->_attributes += array('data-field-item-attr' => 'foobar');
         }
       }
+
+      // Add a dummy field item attribute on daterange fields if they exist.
+      $fields = $entity->getFieldDefinitions();
+      foreach ($fields as $field) {
+        if ($field->getType() === 'daterange') {
+          $item = $entity->get($field->getName());
+          $item->_attributes += array('data-field-item-attr' => 'foobar');
+        }
+      }
     }
   }
 }
-- 
GitLab