From 1ac72a9de390c0b736d2bd502e21453fe2635ef6 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Sun, 12 May 2013 20:22:44 +0100
Subject: [PATCH] Issue #1980632 by dawehner, yched: Fixed Viewing a node with
 a List field results in fatal error.

---
 core/modules/field/field.module               |  2 +
 .../formatter/OptionsDefaultFormatter.php     |  2 +-
 .../field/formatter/OptionsKeyFormatter.php   |  2 +-
 .../Drupal/options/Tests/OptionsFieldTest.php | 68 +++++----------
 .../options/Tests/OptionsFieldUITest.php      |  4 +-
 .../Tests/OptionsFieldUnitTestBase.php        | 83 +++++++++++++++++++
 .../options/Tests/OptionsFormattersTest.php   | 50 +++++++++++
 7 files changed, 159 insertions(+), 52 deletions(-)
 create mode 100644 core/modules/options/lib/Drupal/options/Tests/OptionsFieldUnitTestBase.php
 create mode 100644 core/modules/options/lib/Drupal/options/Tests/OptionsFormattersTest.php

diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 13fb22cadf53..7660f5744541 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -835,6 +835,8 @@ function field_view_field(EntityInterface $entity, $field_name, $display_options
   if ($formatter) {
     $display_langcode = field_language($entity, $field_name, $langcode);
     $items = array();
+    // Ensure the BC entity is used.
+    $entity = $entity->getBCEntity();
     if (isset($entity->{$field_name}[$display_langcode])) {
       $items = $entity->{$field_name}[$display_langcode];
     }
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php b/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php
index 48268aa74eca..01b4efb84521 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php
@@ -16,7 +16,7 @@
  * Plugin implementation of the 'list_default' formatter.
  *
  * @Plugin(
- *   id = "options_list_default",
+ *   id = "list_default",
  *   module = "options",
  *   label = @Translation("Default"),
  *   field_types = {
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsKeyFormatter.php b/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsKeyFormatter.php
index d461155328c3..94b076f0257a 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsKeyFormatter.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsKeyFormatter.php
@@ -16,7 +16,7 @@
  * Plugin implementation of the 'list_key' formatter.
  *
  * @Plugin(
- *   id = "options_list_key",
+ *   id = "list_key",
  *   module = "options",
  *   label = @Translation("Key"),
  *   field_types = {
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php
index 11ab663ef48a..13d0fbaeaea7 100644
--- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php
@@ -8,12 +8,11 @@
 namespace Drupal\options\Tests;
 
 use Drupal\field\FieldException;
-use Drupal\field\Tests\FieldUnitTestBase;
 
 /**
  * Tests for the 'Options' field types.
  */
-class OptionsFieldTest extends FieldUnitTestBase {
+class OptionsFieldTest extends OptionsFieldUnitTestBase {
 
   /**
    * Modules to enable.
@@ -30,33 +29,6 @@ public static function getInfo() {
     );
   }
 
-  function setUp() {
-    parent::setUp();
-    $this->installSchema('system', 'menu_router');
-
-
-    $this->field_name = 'test_options';
-    $this->field_definition = array(
-      'field_name' => $this->field_name,
-      'type' => 'list_integer',
-      'cardinality' => 1,
-      'settings' => array(
-        'allowed_values' => array(1 => 'One', 2 => 'Two', 3 => 'Three'),
-      ),
-    );
-    $this->field = field_create_field($this->field_definition);
-
-    $this->instance = array(
-      'field_name' => $this->field_name,
-      'entity_type' => 'entity_test',
-      'bundle' => 'entity_test',
-      'widget' => array(
-        'type' => 'options_buttons',
-      ),
-    );
-    $this->instance = field_create_instance($this->instance);
-  }
-
   /**
    * Test that allowed values can be updated.
    */
@@ -66,14 +38,14 @@ function testUpdateAllowedValues() {
     // All three options appear.
     $entity = entity_create('entity_test', array());
     $form = entity_get_form($entity);
-    $this->assertTrue(!empty($form[$this->field_name][$langcode][1]), 'Option 1 exists');
-    $this->assertTrue(!empty($form[$this->field_name][$langcode][2]), 'Option 2 exists');
-    $this->assertTrue(!empty($form[$this->field_name][$langcode][3]), 'Option 3 exists');
+    $this->assertTrue(!empty($form[$this->fieldName][$langcode][1]), 'Option 1 exists');
+    $this->assertTrue(!empty($form[$this->fieldName][$langcode][2]), 'Option 2 exists');
+    $this->assertTrue(!empty($form[$this->fieldName][$langcode][3]), 'Option 3 exists');
 
     // Use one of the values in an actual entity, and check that this value
     // cannot be removed from the list.
     $entity = entity_create('entity_test', array());
-    $entity->{$this->field_name}->value = 1;
+    $entity->{$this->fieldName}->value = 1;
     $entity->save();
     $this->field['settings']['allowed_values'] = array(2 => 'Two');
     try {
@@ -84,7 +56,7 @@ function testUpdateAllowedValues() {
       $this->pass(t('Cannot update a list field to not include keys with existing data.'));
     }
     // Empty the value, so that we can actually remove the option.
-    unset($entity->{$this->field_name});
+    unset($entity->{$this->fieldName});
     $entity->save();
 
     // Removed options do not appear.
@@ -92,26 +64,26 @@ function testUpdateAllowedValues() {
     field_update_field($this->field);
     $entity = entity_create('entity_test', array());
     $form = entity_get_form($entity);
-    $this->assertTrue(empty($form[$this->field_name][$langcode][1]), 'Option 1 does not exist');
-    $this->assertTrue(!empty($form[$this->field_name][$langcode][2]), 'Option 2 exists');
-    $this->assertTrue(empty($form[$this->field_name][$langcode][3]), 'Option 3 does not exist');
+    $this->assertTrue(empty($form[$this->fieldName][$langcode][1]), 'Option 1 does not exist');
+    $this->assertTrue(!empty($form[$this->fieldName][$langcode][2]), 'Option 2 exists');
+    $this->assertTrue(empty($form[$this->fieldName][$langcode][3]), 'Option 3 does not exist');
 
     // Completely new options appear.
     $this->field['settings']['allowed_values'] = array(10 => 'Update', 20 => 'Twenty');
     field_update_field($this->field);
     $form = entity_get_form($entity);
-    $this->assertTrue(empty($form[$this->field_name][$langcode][1]), 'Option 1 does not exist');
-    $this->assertTrue(empty($form[$this->field_name][$langcode][2]), 'Option 2 does not exist');
-    $this->assertTrue(empty($form[$this->field_name][$langcode][3]), 'Option 3 does not exist');
-    $this->assertTrue(!empty($form[$this->field_name][$langcode][10]), 'Option 10 exists');
-    $this->assertTrue(!empty($form[$this->field_name][$langcode][20]), 'Option 20 exists');
+    $this->assertTrue(empty($form[$this->fieldName][$langcode][1]), 'Option 1 does not exist');
+    $this->assertTrue(empty($form[$this->fieldName][$langcode][2]), 'Option 2 does not exist');
+    $this->assertTrue(empty($form[$this->fieldName][$langcode][3]), 'Option 3 does not exist');
+    $this->assertTrue(!empty($form[$this->fieldName][$langcode][10]), 'Option 10 exists');
+    $this->assertTrue(!empty($form[$this->fieldName][$langcode][20]), 'Option 20 exists');
 
     // Options are reset when a new field with the same name is created.
-    field_delete_field($this->field_name);
+    field_delete_field($this->fieldName);
     unset($this->field['id']);
-    field_create_field($this->field_definition);
+    field_create_field($this->fieldDefinition);
     $this->instance = array(
-      'field_name' => $this->field_name,
+      'field_name' => $this->fieldName,
       'entity_type' => 'entity_test',
       'bundle' => 'entity_test',
       'widget' => array(
@@ -121,8 +93,8 @@ function testUpdateAllowedValues() {
     field_create_instance($this->instance);
     $entity = entity_create('entity_test', array());
     $form = entity_get_form($entity);
-    $this->assertTrue(!empty($form[$this->field_name][$langcode][1]), 'Option 1 exists');
-    $this->assertTrue(!empty($form[$this->field_name][$langcode][2]), 'Option 2 exists');
-    $this->assertTrue(!empty($form[$this->field_name][$langcode][3]), 'Option 3 exists');
+    $this->assertTrue(!empty($form[$this->fieldName][$langcode][1]), 'Option 1 exists');
+    $this->assertTrue(!empty($form[$this->fieldName][$langcode][2]), 'Option 2 exists');
+    $this->assertTrue(!empty($form[$this->fieldName][$langcode][3]), 'Option 3 exists');
   }
 }
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
index 7b6c415cd717..e2314582032e 100644
--- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
@@ -321,7 +321,7 @@ function testNodeDisplay() {
     $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save and keep published'));
 
     // Check the node page and see if the values are correct.
-    $file_formatters = array('options_list_default', 'options_list_key');
+    $file_formatters = array('list_default', 'list_key');
     foreach ($file_formatters as $formatter) {
       $edit = array(
         "fields[$this->field_name][type]" => $formatter,
@@ -329,7 +329,7 @@ function testNodeDisplay() {
       $this->drupalPost('admin/structure/types/manage/' . $this->type_name . '/display', $edit, t('Save'));
       $this->drupalGet('node/' . $node->nid);
 
-      if ($formatter == 'options_list_default') {
+      if ($formatter == 'list_default') {
         $output = $on;
       }
       else {
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUnitTestBase.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUnitTestBase.php
new file mode 100644
index 000000000000..e2d4ad7af5b1
--- /dev/null
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUnitTestBase.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\options\Tests\OptionsFieldUnitTestBase.
+ */
+
+
+namespace Drupal\options\Tests;
+
+use Drupal\field\Tests\FieldUnitTestBase;
+
+/**
+ * Defines a common base test class for unit tests of the options module.
+ */
+class OptionsFieldUnitTestBase extends FieldUnitTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('options');
+
+  /**
+   * The field name used in the test.
+   *
+   * @var string
+   */
+  protected $fieldName = 'test_options';
+
+  /**
+   * The field definition used to created the field entity.
+   *
+   * @var array
+   */
+  protected $fieldDefinition;
+
+  /**
+   * The list field used in the test.
+   *
+   * @var \Drupal\field\Plugin\Core\Entity\Field
+   */
+  protected $field;
+
+  /**
+   * The list field instance used in the test.
+   *
+   * @var \Drupal\field\Plugin\Core\Entity\FieldInstance
+   */
+  protected $instance;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $this->installSchema('system', 'menu_router');
+
+    $this->fieldDefinition = array(
+      'field_name' => $this->fieldName,
+      'type' => 'list_integer',
+      'cardinality' => 1,
+      'settings' => array(
+        'allowed_values' => array(1 => 'One', 2 => 'Two', 3 => 'Three'),
+      ),
+    );
+    $this->field = entity_create('field_entity', $this->fieldDefinition);
+    $this->field->save();
+
+    $instance = array(
+      'field_name' => $this->fieldName,
+      'entity_type' => 'entity_test',
+      'bundle' => 'entity_test',
+      'widget' => array(
+        'type' => 'options_buttons',
+      ),
+    );
+    $this->instance = entity_create('field_instance', $instance);
+    $this->instance->save();
+  }
+
+}
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFormattersTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFormattersTest.php
new file mode 100644
index 000000000000..799e726359ee
--- /dev/null
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFormattersTest.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\options\Tests\OptionsFormattersTest.
+ */
+
+namespace Drupal\options\Tests;
+
+/**
+ * Tests the formatters provided by the options module.
+ *
+ * @see \Drupal\options\Plugin\field\formatter\OptionsDefaultFormatter
+ * @see \Drupal\options\Plugin\field\formatter\OptionsKeyFormatter
+ */
+class OptionsFormattersTest extends OptionsFieldUnitTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Options field formatters',
+      'description' => 'Test the Options field type formatters.',
+      'group' => 'Field types',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+  }
+
+  /**
+   * Tests the formatters.
+   */
+  public function testFormatter() {
+    $entity = entity_create('entity_test', array());
+    $entity->{$this->fieldName}->value = 1;
+
+    $build = field_view_field($entity, $this->fieldName, array());
+
+    $this->assertEqual($build['#formatter'], 'list_default', 'Ensure to fall back to the default formatter.');
+    $this->assertEqual($build[0]['#markup'], 'One');
+
+    $build = field_view_field($entity, $this->fieldName, array('type' => 'list_key'));
+    $this->assertEqual($build['#formatter'], 'list_key', 'The chosen formatter is used.');
+    $this->assertEqual($build[0]['#markup'], 1);
+  }
+
+}
-- 
GitLab