summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcatch2012-09-06 12:11:03 (GMT)
committercatch2012-09-06 12:11:03 (GMT)
commit267eb43804e7faef7171eb19ff8299c8c9c521dc (patch)
treea14e0be535fbe928343da933a0fad76c7b4af44c
parente904f789fbdcc30b58f5118d5b3580bb9844f2a9 (diff)
Issue #1498874 by peximo, plach, Gábor Hojtsy, attiks: Provide language awareness to entity forms (introduce the form language concept).
-rw-r--r--core/modules/entity/entity.module7
-rw-r--r--core/modules/entity/lib/Drupal/entity/Entity.php5
-rw-r--r--core/modules/entity/lib/Drupal/entity/EntityFormController.php27
-rw-r--r--core/modules/entity/lib/Drupal/entity/EntityFormControllerInterface.php2
-rw-r--r--core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationFormTest.php122
-rw-r--r--core/modules/entity/tests/modules/entity_test/entity_test.module8
-rw-r--r--core/modules/node/lib/Drupal/node/NodeFormController.php13
7 files changed, 168 insertions, 16 deletions
diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module
index 2c54daa..8bd2fc1 100644
--- a/core/modules/entity/entity.module
+++ b/core/modules/entity/entity.module
@@ -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);
}
diff --git a/core/modules/entity/lib/Drupal/entity/Entity.php b/core/modules/entity/lib/Drupal/entity/Entity.php
index 9701d28..e63185d 100644
--- a/core/modules/entity/lib/Drupal/entity/Entity.php
+++ b/core/modules/entity/lib/Drupal/entity/Entity.php
@@ -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));
}
/**
diff --git a/core/modules/entity/lib/Drupal/entity/EntityFormController.php b/core/modules/entity/lib/Drupal/entity/EntityFormController.php
index 4f1263c..dabb330 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityFormController.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityFormController.php
@@ -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;
}
/**
diff --git a/core/modules/entity/lib/Drupal/entity/EntityFormControllerInterface.php b/core/modules/entity/lib/Drupal/entity/EntityFormControllerInterface.php
index 6765d85..95fb2fc 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityFormControllerInterface.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityFormControllerInterface.php
@@ -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.
diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationFormTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationFormTest.php
new file mode 100644
index 0000000..3908184
--- /dev/null
+++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationFormTest.php
@@ -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.");
+ }
+}
diff --git a/core/modules/entity/tests/modules/entity_test/entity_test.module b/core/modules/entity/tests/modules/entity_test/entity_test.module
index 02ec108..9b1b224 100644
--- a/core/modules/entity/tests/modules/entity_test/entity_test.module
+++ b/core/modules/entity/tests/modules/entity_test/entity_test.module
@@ -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);
+}
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index b99547e..b27e1a6 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -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();
}
}