Commit 5b026c38 authored by catch's avatar catch

Issue #2004626 by plach, kfritsche, vijaycs85, Pancho, penyaskito: Make...

Issue #2004626 by plach, kfritsche, vijaycs85, Pancho, penyaskito: Make non-configurable field translation settings available in the content language settings.
parent 9afeeb28
......@@ -489,13 +489,23 @@ public function getFieldDefinitions($entity_type, $bundle = NULL) {
$hooks = array('entity_field_info', $entity_type . '_field_info');
$this->moduleHandler->alter($hooks, $this->entityFieldInfo[$entity_type], $entity_type);
// Enforce fields to be multiple by default.
foreach ($this->entityFieldInfo[$entity_type]['definitions'] as &$definition) {
$definition['list'] = TRUE;
}
foreach ($this->entityFieldInfo[$entity_type]['optional'] as &$definition) {
$definition['list'] = TRUE;
// Enforce fields to be multiple and untranslatable by default.
$entity_info = $this->getDefinition($entity_type);
$keys = array_intersect_key(array_filter($entity_info['entity_keys']), array_flip(array('id', 'revision', 'uuid', 'bundle')));
$untranslatable_fields = array_flip(array('langcode') + $keys);
foreach (array('definitions', 'optional') as $key) {
foreach ($this->entityFieldInfo[$entity_type][$key] as $name => &$definition) {
$definition['list'] = TRUE;
// Ensure ids and langcode fields are never made translatable.
if (isset($untranslatable_fields[$name]) && !empty($definition['translatable'])) {
throw new \LogicException(format_string('The @field field cannot be translatable.', array('@field' => $definition['label'])));
}
if (!isset($definition['translatable'])) {
$definition['translatable'] = FALSE;
}
}
}
$this->cache->set($cid, $this->entityFieldInfo[$entity_type], CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE, 'entity_field_info' => TRUE));
}
}
......
......@@ -8,6 +8,7 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Field\FieldDefinitionInterface;
use Drupal\Core\Language\Language;
use Drupal\field\Field as FieldService;
/**
* Returns a form element to configure field synchronization.
......@@ -73,6 +74,7 @@ function _content_translation_form_language_content_settings_form_alter(array &$
$form['#attached']['js'][] = array('data' => drupal_get_path('module', 'content_translation') . '/content_translation.admin.js', 'type' => 'file');
$dependent_options_settings = array();
$entity_manager = Drupal::entityManager();
foreach ($form['#labels'] as $entity_type => $label) {
$entity_info = entity_get_info($entity_type);
foreach (entity_get_bundles($entity_type) as $bundle => $bundle_info) {
......@@ -84,31 +86,51 @@ function _content_translation_form_language_content_settings_form_alter(array &$
// Only show the checkbox to enable translation if the bundles in the
// entity might have fields and if there are fields to translate.
if (!empty($entity_info['fieldable'])) {
$instances = field_info_instances($entity_type, $bundle);
if ($instances) {
$fields = $entity_manager->getFieldDefinitions($entity_type, $bundle);
if ($fields) {
$form['settings'][$entity_type][$bundle]['translatable'] = array(
'#type' => 'checkbox',
'#title' => $bundle,
'#default_value' => content_translation_enabled($entity_type, $bundle),
);
// @todo Exploit field definitions once all core entities and field
// types are migrated to the Entity Field API.
foreach ($instances as $field_name => $instance) {
$form['settings'][$entity_type][$bundle]['fields'][$field_name] = array(
'#label' => $instance->getFieldLabel(),
'#type' => 'checkbox',
'#title' => $instance->getFieldLabel(),
'#default_value' => $instance->isFieldTranslatable(),
);
$column_element = content_translation_field_sync_widget($instance);
if ($column_element) {
$form['settings'][$entity_type][$bundle]['columns'][$field_name] = $column_element;
if (isset($column_element['#options']['file'])) {
$dependent_options_settings["settings[{$entity_type}][{$bundle}][columns][{$field_name}]"] = array('file');
$field_settings = content_translation_get_config($entity_type, $bundle, 'fields');
foreach ($fields as $field_name => $definition) {
$translatable = !empty($field_settings[$field_name]);
// We special case Field API fields as they always natively support
// translation.
// @todo Remove this special casing as soon as configurable and
// base field definitions are "unified".
if (!empty($definition['configurable']) && ($field = FieldService::fieldInfo()->getField($entity_type, $field_name))) {
$instance = FieldService::fieldInfo()->getInstance($entity_type, $bundle, $field_name);
$form['settings'][$entity_type][$bundle]['fields'][$field_name] = array(
'#label' => $instance->getFieldLabel(),
'#type' => 'checkbox',
'#title' => $instance->getFieldLabel(),
'#default_value' => $translatable,
);
$column_element = content_translation_field_sync_widget($instance);
if ($column_element) {
$form['settings'][$entity_type][$bundle]['columns'][$field_name] = $column_element;
// @todo This should not concern only files.
if (isset($column_element['#options']['file'])) {
$dependent_options_settings["settings[{$entity_type}][{$bundle}][columns][{$field_name}]"] = array('file');
}
}
}
// Instead we need to rely on field definitions to determine whether
// fields support translation. Whether they are actually enabled is
// determined through our settings. As a consequence only fields
// that support translation can be enabled or disabled.
elseif (isset($field_settings[$field_name]) || !empty($definition['translatable'])) {
$form['settings'][$entity_type][$bundle]['fields'][$field_name] = array(
'#label' => $definition['label'],
'#type' => 'checkbox',
'#default_value' => $translatable,
);
}
}
}
}
......@@ -326,11 +348,11 @@ function _content_translation_update_field_translatability($settings) {
foreach ($bundle_settings['fields'] as $field_name => $translatable) {
// If a field is enabled for translation for at least one instance we
// need to mark it as translatable.
$fields[$entity_type][$field_name] = $translatable || !empty($fields[$entity_type][$field_name]);
if (FieldService::fieldInfo()->getField($entity_type, $field_name)) {
$fields[$entity_type][$field_name] = $translatable || !empty($fields[$entity_type][$field_name]);
}
}
}
// @todo Store non-configurable field settings to be able to alter their
// definition afterwards.
}
}
......
......@@ -126,6 +126,33 @@ function content_translation_entity_bundle_info_alter(&$bundles) {
}
}
/**
* Implements hook_entity_field_info_alter().
*/
function content_translation_entity_field_info_alter(&$info, $entity_type) {
$translation_settings = config('content_translation.settings')->get($entity_type);
if ($translation_settings) {
// Currently field translatability is defined per-field but we may want to
// make it per-instance instead, so leaving the possibility open for further
// easier refactoring.
$fields = array();
foreach ($translation_settings as $bundle => $settings) {
$fields += !empty($settings['content_translation']['fields']) ? $settings['content_translation']['fields'] : array();
}
$keys = array('definitions', 'optional');
foreach ($fields as $name => $translatable) {
foreach ($keys as $key) {
if (isset($info[$key][$name])) {
$info[$key][$name]['translatable'] = (bool) $translatable;
break;
}
}
}
}
}
/**
* Implements hook_menu().
*/
......@@ -987,6 +1014,11 @@ function content_translation_save_settings($settings) {
// Store whether a bundle has translation enabled or not.
content_translation_set_config($entity_type, $bundle, 'enabled', $bundle_settings['translatable']);
// Store whether fields are translatable or not.
if (!empty($bundle_settings['fields'])) {
content_translation_set_config($entity_type, $bundle, 'fields', $bundle_settings['fields']);
}
// Store whether fields have translation enabled or not.
if (!empty($bundle_settings['columns'])) {
foreach ($bundle_settings['columns'] as $field_name => $column_settings) {
......
......@@ -20,7 +20,7 @@ class ContentTranslationSettingsTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('language', 'content_translation', 'comment', 'field_ui');
public static $modules = array('language', 'content_translation', 'node', 'comment', 'field_ui');
public static function getInfo() {
return array(
......@@ -114,6 +114,17 @@ function testSettingsUI() {
$this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
$this->drupalGet('admin/structure/types/manage/article');
$this->assertFieldChecked('edit-language-configuration-content-translation');
// Test that the title field of nodes is available in the settings form.
$edit = array(
'entity_types[node]' => TRUE,
'settings[node][article][settings][language][langcode]' => 'current_interface',
'settings[node][article][settings][language][language_show]' => TRUE,
'settings[node][article][translatable]' => TRUE,
'settings[node][article][fields][title]' => TRUE
);
$this->assertSettings('node', NULL, TRUE, $edit);
}
/**
......
......@@ -108,10 +108,13 @@ function testImageFieldSync() {
$this->assertNoFieldChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-alt');
$this->assertNoFieldChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-title');
$edit = array(
'settings[entity_test_mul][entity_test_mul][fields][field_test_et_ui_image]' => TRUE,
'settings[entity_test_mul][entity_test_mul][columns][field_test_et_ui_image][alt]' => TRUE,
'settings[entity_test_mul][entity_test_mul][columns][field_test_et_ui_image][title]' => TRUE,
);
$this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save'));
$errors = $this->xpath('//div[contains(@class, "messages--error")]');
$this->assertFalse($errors, 'Settings correctly stored.');
$this->assertFieldChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-alt');
$this->assertFieldChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-title');
$this->drupalLogin($this->translator);
......
......@@ -359,6 +359,7 @@ public static function baseFieldDefinitions($entity_type) {
'property_constraints' => array(
'value' => array('Length' => array('max' => 255)),
),
'translatable' => TRUE,
);
$properties['uid'] = array(
'label' => t('User ID'),
......
......@@ -15,11 +15,6 @@
*/
class NodeTranslationUITest extends ContentTranslationUITest {
/**
* The title of the test node.
*/
protected $title;
/**
* Modules to enable.
*
......@@ -38,7 +33,6 @@ public static function getInfo() {
function setUp() {
$this->entityType = 'node';
$this->bundle = 'article';
$this->title = $this->randomName();
parent::setUp();
$this->drupalPlaceBlock('system_help_block', array('region' => 'content'));
}
......@@ -62,8 +56,7 @@ protected function getTranslatorPermissions() {
* Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::getNewEntityValues().
*/
protected function getNewEntityValues($langcode) {
// Node title is not translatable yet, hence we use a fixed value.
return array('title' => $this->title) + parent::getNewEntityValues($langcode);
return array('title' => $this->randomName()) + parent::getNewEntityValues($langcode);
}
/**
......
......@@ -9,6 +9,7 @@
use Drupal\Core\Language\Language;
use Drupal\Core\TypedData\TranslatableInterface;
use Drupal\entity_test\Entity\EntityTestMulRev;
/**
* Tests entity translation.
......@@ -492,4 +493,42 @@ function testEntityTranslationAPI() {
$this->assertEqual($field->getLangcode(), $langcode2, 'Field object has the expected langcode.');
}
/**
* Check that field translatability is handled properly.
*/
function testFieldDefinitions() {
// Check that field translatability can be altered to be enabled or disabled
// in field definitions.
$entity_type = 'entity_test_mulrev';
$this->state->set('entity_test.field_definitions.translatable', array('name' => FALSE));
$this->entityManager->clearCachedFieldDefinitions();
$definitions = $this->entityManager->getFieldDefinitions($entity_type);
$this->assertFalse($definitions['name']['translatable'], 'Field translatability can be disabled programmatically.');
$this->state->set('entity_test.field_definitions.translatable', array('name' => TRUE));
$this->entityManager->clearCachedFieldDefinitions();
$definitions = $this->entityManager->getFieldDefinitions($entity_type);
$this->assertTrue($definitions['name']['translatable'], 'Field translatability can be enabled programmatically.');
// Check that field translatability is disabled by default.
$base_field_definitions = EntityTestMulRev::baseFieldDefinitions($entity_type);
$this->assertTrue(!isset($base_field_definitions['id']['translatable']), 'Translatability for the <em>id</em> field is not defined.');
$this->assertFalse($definitions['id']['translatable'], 'Field translatability is disabled by default.');
// Check that entity ids and langcode fields cannot be translatable.
foreach (array('id', 'uuid', 'revision_id', 'type', 'langcode') as $name) {
$this->state->set('entity_test.field_definitions.translatable', array($name => TRUE));
$this->entityManager->clearCachedFieldDefinitions();
$message = format_string('Field %field cannot be translatable.', array('%field' => $name));
try {
$definitions = $this->entityManager->getFieldDefinitions($entity_type);
$this->fail($message);
}
catch (\LogicException $e) {
$this->pass($message);
}
}
}
}
......@@ -72,6 +72,17 @@ function entity_test_entity_info_alter(&$info) {
}
}
/**
* Implements hook_entity_field_info_alter().
*/
function entity_test_entity_field_info_alter(&$info, $entity_type) {
if ($entity_type == 'entity_test_mulrev' && ($names = \Drupal::state()->get('entity_test.field_definitions.translatable'))) {
foreach ($names as $name => $value) {
$info['definitions'][$name]['translatable'] = $value;
}
}
}
/**
* Creates a new bundle for entity_test entities.
*
......
......@@ -90,9 +90,9 @@ public function testTranslationUI() {
// Make sure that no row was inserted for taxonomy vocabularies, which do
// not have translations enabled.
$rows = db_query('SELECT * FROM {content_translation}')->fetchAll();
$this->assertEqual(2, count($rows));
$this->assertEqual('taxonomy_term', $rows[0]->entity_type);
$this->assertEqual('taxonomy_term', $rows[1]->entity_type);
foreach ($rows as $row) {
$this->assertEqual('taxonomy_term', $row->entity_type);
}
}
/**
......
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