summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwebchick2013-11-18 19:24:48 (GMT)
committerwebchick2013-11-18 19:24:48 (GMT)
commit4f00351eeda05d031de094c020cdb9f1975578e7 (patch)
tree09f7c08d74275a84f432bf3701e0d552d7382523
parent3cf0801b28593ea1aff76f04019d5db59a126572 (diff)
Issue #2129039 by plach, jthorson, pfrenssen, nyirocsaba, Gábor Hojtsy: Integrity constraint violation when translating body field.
-rw-r--r--core/lib/Drupal/Core/Entity/ContentEntityBase.php15
-rw-r--r--core/lib/Drupal/Core/Entity/EntityFormController.php4
-rw-r--r--core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php9
-rw-r--r--core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php59
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php11
5 files changed, 82 insertions, 16 deletions
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 5447e90..7291e8d 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -904,9 +904,18 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
// Avoid deep-cloning when we are initializing a translation object, since
// it will represent the same entity, only with a different active language.
if (!$this->translationInitialize) {
- foreach ($this->fields as $name => $properties) {
- foreach ($properties as $langcode => $property) {
- $this->fields[$name][$langcode] = clone $property;
+ $definitions = $this->getPropertyDefinitions();
+ foreach ($this->fields as $name => $values) {
+ $this->fields[$name] = array();
+ // Untranslatable fields may have multiple references for the same field
+ // object keyed by language. To avoid creating different field objects
+ // we retain just the original value, as references will be recreated
+ // later as needed.
+ if (empty($definitions[$name]['translatable']) && count($values) > 1) {
+ $values = array_intersect_key($values, array(Language::LANGCODE_DEFAULT => TRUE));
+ }
+ foreach ($values as $langcode => $items) {
+ $this->fields[$name][$langcode] = clone $items;
$this->fields[$name][$langcode]->setContext($name, $this);
}
}
diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index 54ee489..1e75646 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -176,6 +176,10 @@ class EntityFormController extends FormBase implements EntityFormControllerInter
* @see \Drupal\Core\Entity\EntityFormController::form()
*/
public function processForm($element, $form_state, $form) {
+ // If the form is cached, process callbacks may not have a valid reference
+ // to the entity object, hence we must restore it.
+ $this->entity = $form_state['controller']->getEntity();
+
// Assign the weights configured in the form display.
foreach ($this->getFormDisplay($form_state)->getComponents() as $name => $options) {
if (isset($element[$name])) {
diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php
index 8bd4876..d1485d2 100644
--- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php
+++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php
@@ -125,12 +125,19 @@ abstract class ContentTranslationTestBase extends WebTestBase {
}
/**
+ * Returns an array of permissions needed for the administrator.
+ */
+ protected function getAdministratorPermissions() {
+ return array_merge($this->getEditorPermissions(), $this->getTranslatorPermissions(), array('administer content translation'));
+ }
+
+ /**
* Creates and activates translator, editor and admin users.
*/
protected function setupUsers() {
$this->translator = $this->drupalCreateUser($this->getTranslatorPermissions(), 'translator');
$this->editor = $this->drupalCreateUser($this->getEditorPermissions(), 'editor');
- $this->administrator = $this->drupalCreateUser(array_merge($this->getEditorPermissions(), $this->getTranslatorPermissions()), 'administrator');
+ $this->administrator = $this->drupalCreateUser($this->getAdministratorPermissions(), 'administrator');
$this->drupalLogin($this->translator);
}
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php
index bab9996..25cce23 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php
@@ -22,6 +22,13 @@ class NodeTranslationUITest extends ContentTranslationUITest {
*/
public static $modules = array('block', 'language', 'content_translation', 'node', 'datetime', 'field_ui');
+ /**
+ * The profile to install as a basis for testing.
+ *
+ * @var string
+ */
+ protected $profile = 'standard';
+
public static function getInfo() {
return array(
'name' => 'Node translation UI',
@@ -34,15 +41,15 @@ class NodeTranslationUITest extends ContentTranslationUITest {
$this->entityType = 'node';
$this->bundle = 'article';
parent::setUp();
+
+ // Ensure the help message is shown even with prefixed paths.
$this->drupalPlaceBlock('system_help_block', array('region' => 'content'));
- }
- /**
- * Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::setupBundle().
- */
- protected function setupBundle() {
- parent::setupBundle();
- $this->drupalCreateContentType(array('type' => $this->bundle, 'name' => $this->bundle));
+ // Display the language selector.
+ $this->drupalLogin($this->administrator);
+ $edit = array('language_configuration[language_show]' => TRUE);
+ $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
+ $this->drupalLogin($this->translator);
}
/**
@@ -53,6 +60,20 @@ class NodeTranslationUITest extends ContentTranslationUITest {
}
/**
+ * {@inheritdoc}
+ */
+ protected function getEditorPermissions() {
+ return array('administer nodes', 'create article content');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getAdministratorPermissions() {
+ return array_merge(parent::getAdministratorPermissions(), array('access administration pages', 'administer content types', 'administer node fields', 'access content overview', 'bypass node access'));
+ }
+
+ /**
* Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::getNewEntityValues().
*/
protected function getNewEntityValues($langcode) {
@@ -60,6 +81,22 @@ class NodeTranslationUITest extends ContentTranslationUITest {
}
/**
+ * {@inheritdoc}
+ */
+ protected function createEntity($values, $langcode, $bundle_name = NULL) {
+ $this->drupalLogin($this->editor);
+ $edit = array(
+ 'title' => $values['title'],
+ "{$this->fieldName}[0][value]" => $values[$this->fieldName][0]['value'],
+ 'langcode' => $langcode,
+ );
+ $this->drupalPostForm('node/add/article', $edit,t('Save and publish'));
+ $this->drupalLogin($this->translator);
+ $node = $this->drupalGetNodeByTitle($values['title']);
+ return $node->id();
+ }
+
+ /**
* Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::getFormSubmitAction().
*/
protected function getFormSubmitAction(EntityInterface $entity) {
@@ -136,11 +173,10 @@ class NodeTranslationUITest extends ContentTranslationUITest {
* Tests translate link on content admin page.
*/
function testTranslateLinkContentAdminPage() {
- $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'access content overview', 'administer nodes', 'bypass node access'));
- $this->drupalLogin($this->admin_user);
+ $this->drupalLogin($this->administrator);
$page = $this->drupalCreateNode(array('type' => 'page'));
- $article = $this->drupalCreateNode(array('type' => 'article'));
+ $article = $this->drupalCreateNode(array('type' => 'article', 'langcode' => $this->langcodes[0]));
// Verify translation links.
$this->drupalGet('admin/content');
@@ -153,8 +189,7 @@ class NodeTranslationUITest extends ContentTranslationUITest {
* Tests field translation form.
*/
function testFieldTranslationForm() {
- $admin_user = $this->drupalCreateUser(array_merge($this->getTranslatorPermissions(), array('access administration pages', 'bypass node access', 'administer node fields')));
- $this->drupalLogin($admin_user);
+ $this->drupalLogin($this->administrator);
$article = $this->drupalCreateNode(array('type' => 'article', 'langcode' => 'en'));
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
index bc0e195..11903c1 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
@@ -483,6 +483,17 @@ class EntityTranslationTest extends EntityUnitTestBase {
$translation = $cloned->getTranslation($langcode);
$this->assertNotIdentical($entity, $translation->getUntranslated(), 'A cloned entity object has no reference to the original one.');
+ // Check that untranslatable field references keep working after serializing
+ // and cloning the entity.
+ $entity = $this->reloadEntity($entity);
+ $type = $this->randomName();
+ $entity->getTranslation($langcode)->type->value = $type;
+ $entity = unserialize(serialize($entity));
+ $cloned = clone $entity;
+ $translation = $cloned->getTranslation($langcode);
+ $translation->type->value = strrev($type);
+ $this->assertEqual($cloned->type->value, $translation->type->value, 'Untranslatable field references keep working after serializing and cloning the entity.');
+
// Check that per-language defaults are properly populated.
$entity = $this->reloadEntity($entity);
$instance_id = implode('.', array($entity->entityType(), $entity->bundle(), $this->field_name));