Issue #1498874 by peximo, plach, Gábor Hojtsy, attiks: Provide language awareness to entity forms (introduce the form language concept).
parent
e904f789fb
commit
267eb43804
|
@ -467,12 +467,13 @@ function entity_form_id(EntityInterface $entity, $operation = 'default') {
|
|||
* @return
|
||||
* A $form_state array already filled the entity form controller.
|
||||
*/
|
||||
function entity_form_state_defaults(EntityInterface $entity, $operation = 'default') {
|
||||
function entity_form_state_defaults(EntityInterface $entity, $operation = 'default', $langcode = NULL) {
|
||||
$form_state = array();
|
||||
$controller = entity_form_controller($entity->entityType(), $operation);
|
||||
$form_state['build_info']['callback'] = array($controller, 'build');
|
||||
$form_state['build_info']['base_form_id'] = $entity->entityType() . '_form';
|
||||
$form_state['build_info']['args'] = array($entity);
|
||||
$form_state['langcode'] = $langcode;
|
||||
return $form_state;
|
||||
}
|
||||
|
||||
|
@ -506,8 +507,8 @@ function entity_form_submit(EntityInterface $entity, $operation = 'default', &$f
|
|||
* @return
|
||||
* The processed form for the given entity and operation.
|
||||
*/
|
||||
function entity_get_form(EntityInterface $entity, $operation = 'default') {
|
||||
$form_state = entity_form_state_defaults($entity, $operation);
|
||||
function entity_get_form(EntityInterface $entity, $operation = 'default', $langcode = NULL) {
|
||||
$form_state = entity_form_state_defaults($entity, $operation, $langcode);
|
||||
$form_id = entity_form_id($entity, $operation);
|
||||
return drupal_build_form($form_id, $form_state);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\entity;
|
||||
|
||||
use Drupal\Component\Uuid\Uuid;
|
||||
use Drupal\Core\Language\Language;
|
||||
|
||||
/**
|
||||
* Defines a base entity class.
|
||||
|
@ -148,9 +149,7 @@ class Entity implements EntityInterface {
|
|||
* Implements EntityInterface::language().
|
||||
*/
|
||||
public function language() {
|
||||
// @todo: Check for language.module instead, once Field API language
|
||||
// handling depends upon it too.
|
||||
return module_exists('locale') ? language_load($this->langcode) : FALSE;
|
||||
return !empty($this->langcode) ? language_load($this->langcode) : new Language(array('langcode' => LANGUAGE_NOT_SPECIFIED));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -207,12 +207,27 @@ class EntityFormController implements EntityFormControllerInterface {
|
|||
/**
|
||||
* Implements Drupal\entity\EntityFormControllerInterface::getFormLangcode().
|
||||
*/
|
||||
public function getFormLangcode($form_state) {
|
||||
// @todo Introduce a new form language type (see hook_language_types_info())
|
||||
// to be used as the default active form language, should it be missing, so
|
||||
// that entity forms can be used to submit multilingual values.
|
||||
$language = $this->getEntity($form_state)->language();
|
||||
return !empty($language->langcode) ? $language->langcode : NULL;
|
||||
public function getFormLangcode(array $form_state) {
|
||||
$entity = $this->getEntity($form_state);
|
||||
$translations = $entity->translations();
|
||||
|
||||
if (!empty($form_state['langcode'])) {
|
||||
$langcode = $form_state['langcode'];
|
||||
}
|
||||
else {
|
||||
// If no form langcode was provided we default to the current content
|
||||
// language and inspect existing translations to find a valid fallback,
|
||||
// if any.
|
||||
$langcode = language(LANGUAGE_TYPE_CONTENT)->langcode;
|
||||
$fallback = language_multilingual() ? language_fallback_get_candidates() : array();
|
||||
while (!empty($langcode) && !isset($translations[$langcode])) {
|
||||
$langcode = array_shift($fallback);
|
||||
}
|
||||
}
|
||||
|
||||
// If the site is not multilingual or no translation for the given form
|
||||
// language is available, fall back to the entity language.
|
||||
return !empty($langcode) ? $langcode : $entity->language()->langcode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,7 +49,7 @@ interface EntityFormControllerInterface {
|
|||
* @return string
|
||||
* The form language code.
|
||||
*/
|
||||
public function getFormLangcode($form_state);
|
||||
public function getFormLangcode(array $form_state);
|
||||
|
||||
/**
|
||||
* Returns the operation identifying the form controller.
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\entity\Tests\EntityTranslationFormTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\entity\Tests;
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\Core\Language\Language;
|
||||
|
||||
/**
|
||||
* Tests entity translation form.
|
||||
*/
|
||||
class EntityTranslationFormTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('entity_test', 'locale', 'node');
|
||||
|
||||
protected $langcodes;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Entity translation form',
|
||||
'description' => 'Tests entity translation form functionality.',
|
||||
'group' => 'Entity API',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
// Enable translations for the test entity type.
|
||||
variable_set('entity_test_translation', TRUE);
|
||||
|
||||
// Create test languages.
|
||||
$this->langcodes = array();
|
||||
for ($i = 0; $i < 2; ++$i) {
|
||||
$language = new Language(array(
|
||||
'langcode' => 'l' . $i,
|
||||
'name' => $this->randomString(),
|
||||
));
|
||||
$this->langcodes[$i] = $language->langcode;
|
||||
language_save($language);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests entity form language.
|
||||
*/
|
||||
function testEntityFormLanguage() {
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('create page content', 'edit own page content', 'administer content types'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Create a node with language LANGUAGE_NOT_SPECIFIED.
|
||||
$edit = array();
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$edit["title"] = $this->randomName(8);
|
||||
$edit["body[$langcode][0][value]"] = $this->randomName(16);
|
||||
|
||||
$this->drupalGet('node/add/page');
|
||||
$form_langcode = variable_get('entity_form_langcode', FALSE);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
|
||||
$node = $this->drupalGetNodeByTitle($edit["title"]);
|
||||
$this->assertTrue($node->langcode == $form_langcode, 'Form language is the same as the entity language.');
|
||||
|
||||
// Edit the node and test the form language.
|
||||
$this->drupalGet($this->langcodes[0] . '/node/' . $node->nid . '/edit');
|
||||
$form_langcode = variable_get('entity_form_langcode', FALSE);
|
||||
$this->assertTrue($node->langcode == $form_langcode, 'Form language is the same as the entity language.');
|
||||
|
||||
// Explicitly set form langcode.
|
||||
$langcode = $this->langcodes[0];
|
||||
entity_get_form($node, 'default', $langcode);
|
||||
$form_langcode = variable_get('entity_form_langcode', FALSE);
|
||||
$this->assertTrue($langcode == $form_langcode, 'Form language is the same as the language parameter.');
|
||||
|
||||
// Enable language selector.
|
||||
$this->drupalGet('admin/structure/types/manage/page');
|
||||
$edit = array('node_type_language_hidden' => FALSE, 'node_type_language_default' => LANGUAGE_NOT_SPECIFIED);
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
$this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.'));
|
||||
|
||||
// Create a node with language.
|
||||
$edit = array();
|
||||
$langcode = $this->langcodes[0];
|
||||
$field_langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$edit["title"] = $this->randomName(8);
|
||||
$edit["body[$field_langcode][0][value]"] = $this->randomName(16);
|
||||
$edit['langcode'] = $langcode;
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
$this->assertRaw(t('Basic page %title has been created.', array('%title' => $edit["title"])), t('Basic page created.'));
|
||||
|
||||
// Check to make sure the node was created.
|
||||
$node = $this->drupalGetNodeByTitle($edit["title"]);
|
||||
$this->assertTrue($node, t('Node found in database.'));
|
||||
|
||||
// Make body translatable.
|
||||
$field = field_info_field('body');
|
||||
$field['translatable'] = TRUE;
|
||||
field_update_field($field);
|
||||
$field = field_info_field('body');
|
||||
$this->assertTrue($field['translatable'], "Field body is translatable.");
|
||||
|
||||
// Create a body translation and check the form language.
|
||||
$langcode2 = $this->langcodes[1];
|
||||
$node->set('body', array(array('value' => $this->randomName(16))), $langcode2);
|
||||
$node->save();
|
||||
$this->drupalGet($langcode2 . '/node/' . $node->nid . '/edit');
|
||||
$form_langcode = variable_get('entity_form_langcode', FALSE);
|
||||
$this->assertTrue($langcode2 == $form_langcode, "Node edit form language is $langcode2.");
|
||||
}
|
||||
}
|
|
@ -66,3 +66,11 @@ function entity_test_load_multiple(array $ids = NULL, $reset = FALSE) {
|
|||
function entity_test_delete_multiple(array $ids) {
|
||||
entity_get_controller('entity_test')->delete($ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_BASE_FORM_ID_alter().
|
||||
*/
|
||||
function entity_test_form_node_form_alter(&$form, &$form_state, $form_id) {
|
||||
$langcode = $form_state['controller']->getFormLangcode($form_state);
|
||||
variable_set('entity_form_langcode', $langcode);
|
||||
}
|
||||
|
|
|
@ -337,7 +337,14 @@ class NodeFormController extends EntityFormController {
|
|||
protected function submitNodeLanguage(array $form, array &$form_state) {
|
||||
if (field_has_translation_handler('node', 'node')) {
|
||||
$bundle = $form_state['values']['type'];
|
||||
$node_language = $form_state['values']['langcode'];
|
||||
$entity = $this->getEntity($form_state);
|
||||
$form_langcode = $this->getFormLangcode($form_state);
|
||||
|
||||
// If we are editing the default language values, we use the submitted
|
||||
// entity language as the new language for fields to handle any language
|
||||
// change. Otherwise the current form language is the proper value, since
|
||||
// in this case it is not supposed to change.
|
||||
$current_langcode = $entity->language()->langcode == $form_langcode ? $form_state['values']['langcode'] : $form_langcode;
|
||||
|
||||
foreach (field_info_instances('node', $bundle) as $instance) {
|
||||
$field_name = $instance['field_name'];
|
||||
|
@ -346,8 +353,8 @@ class NodeFormController extends EntityFormController {
|
|||
|
||||
// Handle a possible language change: new language values are inserted,
|
||||
// previous ones are deleted.
|
||||
if ($field['translatable'] && $previous_langcode != $node_language) {
|
||||
$form_state['values'][$field_name][$node_language] = $form_state['values'][$field_name][$previous_langcode];
|
||||
if ($field['translatable'] && $previous_langcode != $current_langcode) {
|
||||
$form_state['values'][$field_name][$current_langcode] = $form_state['values'][$field_name][$previous_langcode];
|
||||
$form_state['values'][$field_name][$previous_langcode] = array();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue