Commit bb4359a4 authored by webchick's avatar webchick

Issue #2067079 by yched, andypost: Remove the Field Language API.

parent 14b84b11
...@@ -415,28 +415,6 @@ function hook_field_attach_view_alter(&$output, $context) { ...@@ -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". * @} End of "addtogroup field_attach".
*/ */
......
...@@ -774,8 +774,7 @@ function field_attach_view(EntityInterface $entity, EntityViewDisplayInterface $ ...@@ -774,8 +774,7 @@ function field_attach_view(EntityInterface $entity, EntityViewDisplayInterface $
* $entity->getTranslation($langcode)->{$field_name} * $entity->getTranslation($langcode)->{$field_name}
*/ */
function field_get_items(EntityInterface $entity, $field_name, $langcode = NULL) { function field_get_items(EntityInterface $entity, $field_name, $langcode = NULL) {
$langcode = field_language($entity, $field_name, $langcode); return \Drupal::entityManager()->getTranslationFromContext($entity, $langcode)->{$field_name};
return isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
} }
/** /**
...@@ -828,77 +827,3 @@ function field_access($op, FieldInterface $field, $entity_type, $entity = NULL, ...@@ -828,77 +827,3 @@ function field_access($op, FieldInterface $field, $entity_type, $entity = NULL,
$items = $entity ? $entity->get($field->id()) : NULL; $items = $entity ? $entity->get($field->id()) : NULL;
return $access_controller->fieldAccess($op, $field, $account, $items); 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;
}
}
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
function field_info_cache_clear() { function field_info_cache_clear() {
drupal_static_reset('field_view_mode_settings'); drupal_static_reset('field_view_mode_settings');
drupal_static_reset('field_form_mode_settings'); drupal_static_reset('field_form_mode_settings');
drupal_static_reset('field_available_languages');
// @todo: Remove this when field_attach_*_bundle() bundle management // @todo: Remove this when field_attach_*_bundle() bundle management
// functions are moved to the entity API. // functions are moved to the entity API.
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Template\Attribute; use Drupal\Core\Template\Attribute;
use Drupal\field\FieldInterface;
use Drupal\field\FieldInstanceInterface;
/* /*
* Load all public Field API functions. Drupal currently has no * Load all public Field API functions. Drupal currently has no
...@@ -16,7 +14,6 @@ ...@@ -16,7 +14,6 @@
* every page request. * every page request.
*/ */
require_once __DIR__ . '/field.info.inc'; require_once __DIR__ . '/field.info.inc';
require_once __DIR__ . '/field.multilingual.inc';
require_once __DIR__ . '/field.attach.inc'; require_once __DIR__ . '/field.attach.inc';
require_once __DIR__ . '/field.form.inc'; require_once __DIR__ . '/field.form.inc';
require_once __DIR__ . '/field.purge.inc'; require_once __DIR__ . '/field.purge.inc';
...@@ -348,13 +345,15 @@ function field_view_value(EntityInterface $entity, $field_name, $item, $display ...@@ -348,13 +345,15 @@ function field_view_value(EntityInterface $entity, $field_name, $item, $display
$output = array(); $output = array();
if ($field = field_info_field($entity->entityType(), $field_name)) { if ($field = field_info_field($entity->entityType(), $field_name)) {
// Determine the langcode that will be used by language fallback. // Clone the entity since we are going to modify field values.
$langcode = field_language($entity, $field_name, $langcode); $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 // 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. // field_view_field() to build the render array for the whole field.
$clone = clone $entity; $clone->{$field_name}->setValue(array($item));
$clone->getTranslation($langcode)->{$field_name}->setValue(array($item));
$elements = field_view_field($clone, $field_name, $display, $langcode); $elements = field_view_field($clone, $field_name, $display, $langcode);
// Extract the part of the render array we need. // Extract the part of the render array we need.
...@@ -419,8 +418,6 @@ function field_view_value(EntityInterface $entity, $field_name, $item, $display ...@@ -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) { function field_view_field(ContentEntityInterface $entity, $field_name, $display_options = array(), $langcode = NULL) {
$output = array(); $output = array();
$bundle = $entity->bundle();
$entity_type = $entity->entityType();
// Return nothing if the field doesn't exist. // Return nothing if the field doesn't exist.
if (!$entity->hasField($field_name)) { if (!$entity->hasField($field_name)) {
...@@ -448,10 +445,11 @@ function field_view_field(ContentEntityInterface $entity, $field_name, $display_ ...@@ -448,10 +445,11 @@ function field_view_field(ContentEntityInterface $entity, $field_name, $display_
} }
if ($formatter) { 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. // Run the formatter.
$items = $entity->getTranslation($display_langcode)->get($field_name);
$formatter->prepareView(array($entity->id() => $items)); $formatter->prepareView(array($entity->id() => $items));
$result = $formatter->view($items); $result = $formatter->view($items);
...@@ -461,7 +459,7 @@ function field_view_field(ContentEntityInterface $entity, $field_name, $display_ ...@@ -461,7 +459,7 @@ function field_view_field(ContentEntityInterface $entity, $field_name, $display_
'entity' => $entity, 'entity' => $entity,
'view_mode' => $view_mode, 'view_mode' => $view_mode,
'display_options' => $display_options, 'display_options' => $display_options,
'langcode' => $display_langcode, 'langcode' => $entity->language()->id,
); );
drupal_alter('field_attach_view', $result, $context); drupal_alter('field_attach_view', $result, $context);
......
<?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']);
}
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
/** /**
* Unit test class for the multilanguage fields logic. * Unit test class for the multilanguage fields logic.
* *
* The following tests will check the multilanguage logic in field handling, and * The following tests will check the multilanguage logic in field handling.
* that only the correct values are returned by field_available_languages().
*/ */
class TranslationTest extends FieldUnitTestBase { class TranslationTest extends FieldUnitTestBase {
...@@ -113,38 +112,6 @@ function setUp() { ...@@ -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. * Test translatable fields storage/retrieval.
*/ */
...@@ -159,8 +126,6 @@ function testTranslatableFieldSaveLoad() { ...@@ -159,8 +126,6 @@ function testTranslatableFieldSaveLoad() {
field_test_entity_info_translatable($entity_type, TRUE); field_test_entity_info_translatable($entity_type, TRUE);
$entity = entity_create($entity_type, array('type' => $this->instance->bundle)); $entity = entity_create($entity_type, array('type' => $this->instance->bundle));
$field_translations = array(); $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()); $available_langcodes = array_keys(language_list());
$entity->langcode->value = reset($available_langcodes); $entity->langcode->value = reset($available_langcodes);
foreach ($available_langcodes as $langcode) { foreach ($available_langcodes as $langcode) {
......
...@@ -103,9 +103,7 @@ function testFieldFormTranslationRevisions() { ...@@ -103,9 +103,7 @@ function testFieldFormTranslationRevisions() {
// Prepare the field translations. // Prepare the field translations.
field_test_entity_info_translatable($this->entity_type, TRUE); field_test_entity_info_translatable($this->entity_type, TRUE);
$entity = entity_create($this->entity_type, array()); $entity = entity_create($this->entity_type, array());
$available_langcodes = array_flip(field_available_languages($this->entity_type, $this->field)); $available_langcodes = array_flip(array_keys(language_list()));
unset($available_langcodes[Language::LANGCODE_NOT_SPECIFIED]);
unset($available_langcodes[Language::LANGCODE_NOT_APPLICABLE]);
$field_name = $this->field->getName(); $field_name = $this->field->getName();
// Store the field translations. // Store the field translations.
......
...@@ -29,7 +29,6 @@ function field_test_entity_info_alter(&$entity_info) { ...@@ -29,7 +29,6 @@ function field_test_entity_info_alter(&$entity_info) {
* Helper function to enable entity translations. * Helper function to enable entity translations.
*/ */
function field_test_entity_info_translatable($entity_type = NULL, $translatable = NULL) { function field_test_entity_info_translatable($entity_type = NULL, $translatable = NULL) {
drupal_static_reset('field_has_translation_handler');
$stored_value = &drupal_static(__FUNCTION__, array()); $stored_value = &drupal_static(__FUNCTION__, array());
if (isset($entity_type)) { if (isset($entity_type)) {
$stored_value[$entity_type] = $translatable; $stored_value[$entity_type] = $translatable;
......
...@@ -49,19 +49,6 @@ function field_test_menu() { ...@@ -49,19 +49,6 @@ function field_test_menu() {
return $items; 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. * Store and retrieve keyed data for later verification by unit tests.
* *
......
...@@ -126,8 +126,6 @@ function setUp() { ...@@ -126,8 +126,6 @@ function setUp() {
'name' => $this->randomString(), 'name' => $this->randomString(),
)); ));
language_save($langcode); 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 // 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, // 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 // decimal 13 is binary 1101 so unit 3,2 and 0 will be added to the
......
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