From bb4359a428e4d8b317fd29f1d5a385ebd0198846 Mon Sep 17 00:00:00 2001
From: webchick <webchick@24967.no-reply.drupal.org>
Date: Fri, 27 Dec 2013 22:42:52 -0800
Subject: [PATCH] Issue #2067079 by yched, andypost: Remove the Field Language
 API.

---
 core/modules/field/field.api.php              |  22 ---
 core/modules/field/field.deprecated.inc       |  77 +-------
 core/modules/field/field.info.inc             |   1 -
 core/modules/field/field.module               |  24 ++-
 core/modules/field/field.multilingual.inc     | 174 ------------------
 .../Drupal/field/Tests/TranslationTest.php    |  37 +---
 .../Drupal/field/Tests/TranslationWebTest.php |   4 +-
 .../modules/field_test/field_test.entity.inc  |   1 -
 .../modules/field_test/field_test.module      |  13 --
 .../system/Tests/Entity/EntityQueryTest.php   |   2 -
 10 files changed, 14 insertions(+), 341 deletions(-)
 delete mode 100644 core/modules/field/field.multilingual.inc

diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index 8341c7a156a4..6d34707718ac 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -415,28 +415,6 @@ function hook_field_attach_view_alter(&$output, $context) {
   }
 }
 
-/**
- * Alter field_available_languages() values.
- *
- * This hook is invoked from field_available_languages() to allow modules to
- * alter the array of available language codes for the given field.
- *
- * @param $langcodes
- *   A reference to an array of language codes to be made available.
- * @param $context
- *   An associative array containing:
- *   - entity_type: The type of the entity the field is attached to.
- *   - field: A field data structure.
- */
-function hook_field_available_languages_alter(&$langcodes, $context) {
-  // Add an unavailable language code.
-  $langcodes[] = 'xx';
-
-  // Remove an available language code.
-  $index = array_search('yy', $langcodes);
-  unset($langcodes[$index]);
-}
-
 /**
  * @} End of "addtogroup field_attach".
  */
diff --git a/core/modules/field/field.deprecated.inc b/core/modules/field/field.deprecated.inc
index 94373bcd4982..31c67580fb25 100644
--- a/core/modules/field/field.deprecated.inc
+++ b/core/modules/field/field.deprecated.inc
@@ -774,8 +774,7 @@ function field_attach_view(EntityInterface $entity, EntityViewDisplayInterface $
  *   $entity->getTranslation($langcode)->{$field_name}
  */
 function field_get_items(EntityInterface $entity, $field_name, $langcode = NULL) {
-  $langcode = field_language($entity, $field_name, $langcode);
-  return isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
+  return \Drupal::entityManager()->getTranslationFromContext($entity, $langcode)->{$field_name};
 }
 
 /**
@@ -828,77 +827,3 @@ function field_access($op, FieldInterface $field, $entity_type, $entity = NULL,
   $items = $entity ? $entity->get($field->id()) : NULL;
   return $access_controller->fieldAccess($op, $field, $account, $items);
 }
-
-/**
- * Ensures that a given language code is valid.
- *
- * Checks whether the given language code is one of the enabled language codes.
- * Otherwise, it returns the current, global language code; or the site's
- * default language code, if the additional parameter $default is TRUE.
- *
- * @param $langcode
- *   The language code to validate.
- * @param $default
- *   Whether to return the default language code or the current language code in
- *   case $langcode is invalid.
- *
- * @return
- *   A valid language code.
- *
- * @deprecated This has been deprecated in favor of the Entity Field API.
- */
-function field_valid_language($langcode, $default = TRUE) {
-  $languages = field_content_languages();
-  if (in_array($langcode, $languages)) {
-    return $langcode;
-  }
-  return $default ? language_default()->id : language(Language::TYPE_CONTENT)->id;
-}
-
-/**
- * Returns the display language code for the fields attached to the given
- * entity.
- *
- * The actual language code for each given field is determined based on the
- * requested language code and the actual data available in the fields
- * themselves.
- * If there is no registered translation handler for the given entity type, the
- * display language code to be used is just Language::LANGCODE_NOT_SPECIFIED, as
- * no other language code is allowed by field_available_languages().
- *
- * If translation handlers are found, we let modules provide alternative display
- * language codes for fields not having the requested language code available.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- *   The entity to be displayed.
- * @param $field_name
- *   (optional) The name of the field to be displayed. Defaults to NULL. If
- *   no value is specified, the display language codes for every field attached
- *   to the given entity will be returned.
- * @param $langcode
- *   (optional) The language code $entity has to be displayed in. Defaults to
- *   NULL. If no value is given the current language will be used.
- *
- * @return
- *   A language code if a field name is specified, an array of language codes
- *   keyed by field name otherwise.
- *
- * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates()
- * @see \Drupal\Core\Entity\EntityInterface::getFieldLangcode()
- *
- * @deprecated This has been deprecated in favor of the Entity Field API.
- */
-function field_language(EntityInterface $entity, $field_name = NULL, $langcode = NULL) {
-  $langcode = \Drupal::entityManager()->getTranslationFromContext($entity, $langcode)->language()->id;
-  $translatable = field_has_translation_handler($entity->entityType());
-  if (!isset($field_name)) {
-    $display_langcodes = array();
-    foreach ($entity->getPropertyDefinitions() as $name => $definition) {
-      $display_langcodes[$name] = $translatable ? $langcode : Language::LANGCODE_NOT_SPECIFIED;
-    }
-    return $display_langcodes;
-  }
-  else {
-    return $translatable ? $langcode : Language::LANGCODE_NOT_SPECIFIED;
-  }
-}
diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc
index d33b2df11a4b..119f6faf1235 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -29,7 +29,6 @@
 function field_info_cache_clear() {
   drupal_static_reset('field_view_mode_settings');
   drupal_static_reset('field_form_mode_settings');
-  drupal_static_reset('field_available_languages');
 
   // @todo: Remove this when field_attach_*_bundle() bundle management
   // functions are moved to the entity API.
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index e19408cabf5b..8b80c56bd872 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -7,8 +7,6 @@
 use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Template\Attribute;
-use Drupal\field\FieldInterface;
-use Drupal\field\FieldInstanceInterface;
 
 /*
  * Load all public Field API functions. Drupal currently has no
@@ -16,7 +14,6 @@
  * every page request.
  */
 require_once __DIR__ . '/field.info.inc';
-require_once __DIR__ . '/field.multilingual.inc';
 require_once __DIR__ . '/field.attach.inc';
 require_once __DIR__ . '/field.form.inc';
 require_once __DIR__ . '/field.purge.inc';
@@ -348,13 +345,15 @@ function field_view_value(EntityInterface $entity, $field_name, $item, $display
   $output = array();
 
   if ($field = field_info_field($entity->entityType(), $field_name)) {
-    // Determine the langcode that will be used by language fallback.
-    $langcode = field_language($entity, $field_name, $langcode);
+    // Clone the entity since we are going to modify field values.
+    $clone = clone $entity;
+
+    // Apply language fallback.
+    $clone = \Drupal::entityManager()->getTranslationFromContext($clone, $langcode);
 
     // Push the item as the single value for the field, and defer to
     // field_view_field() to build the render array for the whole field.
-    $clone = clone $entity;
-    $clone->getTranslation($langcode)->{$field_name}->setValue(array($item));
+    $clone->{$field_name}->setValue(array($item));
     $elements = field_view_field($clone, $field_name, $display, $langcode);
 
     // Extract the part of the render array we need.
@@ -419,8 +418,6 @@ function field_view_value(EntityInterface $entity, $field_name, $item, $display
  */
 function field_view_field(ContentEntityInterface $entity, $field_name, $display_options = array(), $langcode = NULL) {
   $output = array();
-  $bundle = $entity->bundle();
-  $entity_type = $entity->entityType();
 
   // Return nothing if the field doesn't exist.
   if (!$entity->hasField($field_name)) {
@@ -448,10 +445,11 @@ function field_view_field(ContentEntityInterface $entity, $field_name, $display_
   }
 
   if ($formatter) {
-    $display_langcode = field_language($entity, $field_name, $langcode);
+    // Apply language fallback.
+    $entity = \Drupal::entityManager()->getTranslationFromContext($entity, $langcode);
+    $items = $entity->get($field_name);
 
-    // Invoke the formatter's prepareView() and view() methods.
-    $items = $entity->getTranslation($display_langcode)->get($field_name);
+    // Run the formatter.
     $formatter->prepareView(array($entity->id() => $items));
     $result = $formatter->view($items);
 
@@ -461,7 +459,7 @@ function field_view_field(ContentEntityInterface $entity, $field_name, $display_
       'entity' => $entity,
       'view_mode' => $view_mode,
       'display_options' => $display_options,
-      'langcode' => $display_langcode,
+      'langcode' => $entity->language()->id,
     );
     drupal_alter('field_attach_view', $result, $context);
 
diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc
deleted file mode 100644
index d5d058acc64c..000000000000
--- a/core/modules/field/field.multilingual.inc
+++ /dev/null
@@ -1,174 +0,0 @@
-<?php
-
-/**
- * @file
- * Functions implementing Field API multilingual support.
- */
-
-use Drupal\Core\Language\Language;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\field\FieldInterface;
-
-/**
- * @defgroup field_language Field Language API
- * @{
- * Handles multilingual fields.
- *
- * Fields natively implement multilingual support, and all fields use the
- * following structure:
- * @code
- * $entity->{$field_name}[$langcode][$delta][$column_name]
- * @endcode
- * Every field can hold a single or multiple value for each language code
- * belonging to the available language codes set:
- * - For untranslatable fields this set is only Language::LANGCODE_DEFAULT.
- * - For translatable fields this set can contain any language code. By default
- *   it is the list returned by field_content_languages(), which contains all
- *   installed languages with the addition of Language::LANGCODE_NOT_SPECIFIED.
- *   This default can be altered by modules implementing
- *   hook_field_available_languages_alter().
- *
- * The available language codes for a particular field are returned by
- * field_available_languages(). Whether a field is translatable is determined by
- * calling $field_definition->isTranslatable().
- *
- * By default, field_invoke_method() processes a field in all available
- * languages, unless it is given a language code suggestion. Based on that
- * suggestion, _field_language_suggestion() determines the languages to act on.
- *
- * Most field_attach_*() functions act on all available language codes, except
- * for the following:
- * - field_attach_form() only takes a single language code, specifying which
- *   language the field values will be submitted in.
- * - field_attach_view() requires the language the entity will be displayed in.
- *   Since it is unknown whether a field translation exists for the requested
- *   language, the translation handler is responsible for performing one of the
- *   following actions:
- *   - Ignore missing translations, i.e. do not show any field values for the
- *     requested language. For example, see field_field_language_alter().
- *   - Provide a value in a different language as fallback. By default, the
- *     fallback logic is applied separately to each field to ensure that there
- *     is a value for each field to display.
- *   The field language fallback logic relies on the global language fallback
- *   configuration. Therefore, the displayed field values can be in the
- *   requested language, but may be different if no values for the requested
- *   language are available. The default language fallback rules inspect all the
- *   enabled languages ordered by their weight. This behavior can be altered or
- *   even disabled by modules implementing hook_field_language_alter(), making
- *   it possible to choose the first approach. The display language for each
- *   field is returned by field_language().
- *
- * See @link field Field API @endlink for information about the other parts of
- * the Field API.
- */
-
-
-/**
- * Collects the available language codes for the given entity type and field.
- *
- * If the given field has language support enabled, an array of available
- * language codes will be returned, otherwise only Language::LANGCODE_DEFAULT
- * will be returned. Since the default value for a 'translatable' entity
- * property is FALSE, we ensure that only entities that are able to handle
- * translations actually get translatable fields.
- *
- * @param $entity_type
- *   The type of the entity the field is attached to, e.g. 'node' or 'user'.
- * @param $field
- *   A field structure.
- *
- * @return
- *   An array of valid language codes.
- */
-function field_available_languages($entity_type, FieldInterface $field) {
-  static $drupal_static_fast;
-  if (!isset($drupal_static_fast)) {
-    $drupal_static_fast['field_langcodes'] = &drupal_static(__FUNCTION__);
-  }
-  $field_langcodes = &$drupal_static_fast['field_langcodes'];
-  $field_name = $field->getName();
-
-  if (!isset($field_langcodes[$entity_type][$field_name])) {
-    // If the field has language support enabled we retrieve an (alterable) list
-    // of enabled languages, otherwise we return Language::LANGCODE_DEFAULT.
-    if ($field->isTranslatable()) {
-      $langcodes = field_content_languages();
-      // Let other modules alter the available languages.
-      $context = array('entity_type' => $entity_type, 'field' => $field);
-      drupal_alter('field_available_languages', $langcodes, $context);
-      $field_langcodes[$entity_type][$field_name] = $langcodes;
-    }
-    else {
-      $field_langcodes[$entity_type][$field_name] = array(Language::LANGCODE_DEFAULT);
-    }
-  }
-
-  return $field_langcodes[$entity_type][$field_name];
-}
-
-/**
- * Process the language code suggestion based on the available language codes.
- *
- * If a non-empty language code suggestion is provided it must appear among the
- * available language codes, otherwise it will be ignored.
- *
- * @param $available_langcodes
- *   An array of valid language codes.
- * @param $langcode_suggestion
- *   A language code or an array of language codes keyed by field name.
- * @param $field_name
- *   The name of the field being processed.
- *
- * @return
- *   An array of valid language codes.
- */
-function _field_language_suggestion($available_langcodes, $langcode_suggestion, $field_name) {
-  // Handle possible language suggestions.
-  if (!empty($langcode_suggestion)) {
-    // We might have an array of language suggestions keyed by field name.
-    if (is_array($langcode_suggestion) && isset($langcode_suggestion[$field_name])) {
-      $langcode_suggestion = $langcode_suggestion[$field_name];
-    }
-
-    // If we have a single language code suggestion and it is available, we just
-    // return it.
-    if (in_array($langcode_suggestion, $available_langcodes)) {
-      $available_langcodes = array($langcode_suggestion);
-    }
-  }
-
-  return $available_langcodes;
-}
-
-/**
- * Returns available content language codes.
- *
- * @return
- *   An array of language codes.
- */
-function field_content_languages() {
-  return array_keys(language_list(Language::STATE_ALL));
-}
-
-/**
- * Checks if a module is registered as a translation handler for a given entity.
- *
- * If no handler is passed, the function simply checks if there is any
- * translation handler enabled for the given entity type.
- *
- * @param $entity_type
- *   The type of the entity whose fields are to be translated.
- * @param $handler
- *   (optional) The name of the handler to be checked. Defaults to NULL.
- *
- * @return
- *   TRUE, if the given handler is allowed to manage field translations. If no
- *   handler is passed, TRUE means there is at least one registered translation
- *   handler.
- *
- * @todo Remove this once the migration to the Entity Field API is complete.
- */
-function field_has_translation_handler($entity_type, $handler = NULL) {
-  $info = entity_get_info($entity_type);
-  return !empty($info['translatable']);
-}
diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
index c87802f92f04..b30625beda10 100644
--- a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
@@ -12,8 +12,7 @@
 /**
  * Unit test class for the multilanguage fields logic.
  *
- * The following tests will check the multilanguage logic in field handling, and
- * that only the correct values are returned by field_available_languages().
+ * The following tests will check the multilanguage logic in field handling.
  */
 class TranslationTest extends FieldUnitTestBase {
 
@@ -113,38 +112,6 @@ function setUp() {
     }
   }
 
-  /**
-   * Ensures that only valid values are returned by field_available_languages().
-   */
-  function testFieldAvailableLanguages() {
-    // Test 'translatable' fieldable info.
-    field_test_entity_info_translatable('entity_test', FALSE);
-    $field = clone($this->field);
-    $field->field_name .= '_untranslatable';
-    $field->save();
-
-    // Enable field translations for the entity.
-    field_test_entity_info_translatable('entity_test', TRUE);
-
-    // Test hook_field_languages() invocation on a translatable field.
-    \Drupal::state()->set('field_test.field_available_languages_alter', TRUE);
-    $langcodes = field_content_languages();
-    $available_langcodes = field_available_languages($this->entity_type, $this->field);
-    foreach ($available_langcodes as $langcode) {
-      if ($langcode != 'xx' && $langcode != 'en') {
-        $this->assertTrue(in_array($langcode, $langcodes), format_string('%language is an enabled language.', array('%language' => $langcode)));
-      }
-    }
-    $this->assertTrue(in_array('xx', $available_langcodes), format_string('%language was made available.', array('%language' => 'xx')));
-    $this->assertFalse(in_array('en', $available_langcodes), format_string('%language was made unavailable.', array('%language' => 'en')));
-
-    // Test field_available_languages() behavior for untranslatable fields.
-    $this->field->translatable = FALSE;
-    $this->field->save();
-    $available_langcodes = field_available_languages($this->entity_type, $this->field);
-    $this->assertTrue(count($available_langcodes) == 1 && $available_langcodes[0] === Language::LANGCODE_DEFAULT, 'For untranslatable fields only Language::LANGCODE_DEFAULT is available.');
-  }
-
   /**
    * Test translatable fields storage/retrieval.
    */
@@ -159,8 +126,6 @@ function testTranslatableFieldSaveLoad() {
     field_test_entity_info_translatable($entity_type, TRUE);
     $entity = entity_create($entity_type, array('type' => $this->instance->bundle));
     $field_translations = array();
-    $available_langcodes = field_available_languages($entity_type, $this->field);
-    $this->assertTrue(count($available_langcodes) > 1, 'Field is translatable.');
     $available_langcodes = array_keys(language_list());
     $entity->langcode->value = reset($available_langcodes);
     foreach ($available_langcodes as $langcode) {
diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
index 349ee4c681db..4b2bb9587d38 100644
--- a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
@@ -103,9 +103,7 @@ function testFieldFormTranslationRevisions() {
     // Prepare the field translations.
     field_test_entity_info_translatable($this->entity_type, TRUE);
     $entity = entity_create($this->entity_type, array());
-    $available_langcodes = array_flip(field_available_languages($this->entity_type, $this->field));
-    unset($available_langcodes[Language::LANGCODE_NOT_SPECIFIED]);
-    unset($available_langcodes[Language::LANGCODE_NOT_APPLICABLE]);
+    $available_langcodes = array_flip(array_keys(language_list()));
     $field_name = $this->field->getName();
 
     // Store the field translations.
diff --git a/core/modules/field/tests/modules/field_test/field_test.entity.inc b/core/modules/field/tests/modules/field_test/field_test.entity.inc
index 880636ebf6e5..a642b856241c 100644
--- a/core/modules/field/tests/modules/field_test/field_test.entity.inc
+++ b/core/modules/field/tests/modules/field_test/field_test.entity.inc
@@ -29,7 +29,6 @@ function field_test_entity_info_alter(&$entity_info) {
  * Helper function to enable entity translations.
  */
 function field_test_entity_info_translatable($entity_type = NULL, $translatable = NULL) {
-  drupal_static_reset('field_has_translation_handler');
   $stored_value = &drupal_static(__FUNCTION__, array());
   if (isset($entity_type)) {
     $stored_value[$entity_type] = $translatable;
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index d1817c6bd43e..8215416b7873 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -49,19 +49,6 @@ function field_test_menu() {
   return $items;
 }
 
-/**
- * Implements hook_field_available_languages_alter().
- */
-function field_test_field_available_languages_alter(&$langcodes, $context) {
-  if (\Drupal::state()->get('field_test.field_available_languages_alter')) {
-    // Add an unavailable language code.
-    $langcodes[] = 'xx';
-    // Remove an available language code.
-    $index = array_search('en', $langcodes);
-    unset($langcodes[$index]);
-  }
-}
-
 /**
  * Store and retrieve keyed data for later verification by unit tests.
  *
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php
index e0463f6bda84..f97a44f0d521 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php
@@ -126,8 +126,6 @@ function setUp() {
       'name' => $this->randomString(),
     ));
     language_save($langcode);
-    $field_langcodes = &drupal_static('field_available_languages');
-    $field_langcodes['entity_test_mulrev'][$greetings] = array('tr', 'pl');
     // Calculate the cartesian product of the unit array by looking at the
     // bits of $i and add the unit at the bits that are 1. For example,
     // decimal 13 is binary 1101 so unit 3,2 and 0 will be added to the
-- 
GitLab