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) {
}
}
/**
* 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".
*/
......
......@@ -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;
}
}
......@@ -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.
......
......@@ -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);
......
<?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 @@
/**
* 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) {
......
......@@ -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.
......
......@@ -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;
......
......@@ -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.
*
......
......@@ -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
......
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