diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php index 7e9bc5a..34f5ee8 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php @@ -550,53 +550,30 @@ public function save(EntityInterface $entity) { // with $isDefaultRevision = FALSE? $return = FALSE; } + // Ensure the appropriate langcodes are stored in the property data. if ($this->dataTable) { - // Ensure the appropriate langcodes are stored in the property data. $entity->default_langcode = $entity->langcode; $entity->langcode = $langcode; } if ($this->revisionKey) { $this->saveRevision($entity); } - if ($this->dataTable) { - // @todo find a nicer way to do this. - $query = db_select($this->entityInfo['data table']) - ->condition($this->idKey, $entity->id()) - ->condition('langcode', $entity->langcode); - $query->addExpression('1'); - if ($query->execute()->fetchField()) { - $primary_keys = array( - $this->idKey, - $this->revisionKey, - 'langcode', - ); - $primary_keys = array($this->idKey); - $primary_keys[] = 'langcode'; - // Update existing property row. - drupal_write_record($this->entityInfo['data table'], $entity, $primary_keys); - } - else { - // Insert new property row. - drupal_write_record($this->entityInfo['data table'], $entity); - } - } $this->resetCache(array($entity->id())); $this->postSave($entity, TRUE); $this->invokeHook('update', $entity); } else { $return = drupal_write_record($this->entityInfo['base table'], $entity); + // Ensure the appropriate langcodes are stored in the property data. + // @todo clarify if it wouldn't be better to rename the column in the base + // table default_langcode as well. if ($this->dataTable) { - // Ensure the appropriate langcodes are stored in the property data. $entity->default_langcode = $entity->langcode; $entity->langcode = $langcode; } if ($this->revisionKey) { $this->saveRevision($entity); } - if ($this->dataTable) { - drupal_write_record($this->entityInfo['data table'], $entity); - } // Reset general caches, but keep caches specific to certain entities. $this->resetCache(array()); @@ -625,14 +602,14 @@ public function save(EntityInterface $entity) { * The entity object. */ protected function saveRevision(EntityInterface $entity) { - // When saving properties in a new language create a new revision. - // @todo find a nicer way to do this. - if ($this->dataTable) { + // Ensure when saving properties in a new language a new revision is created. + // @todo try to find a nicer/unified way to do this. + if ($this->dataTable && !$entity->isNewRevision()) { $query = db_select($this->revisionTable) ->condition($this->idKey, $entity->id()) ->condition('langcode', $entity->langcode); $query->addExpression('1'); - if (!$query->execute()->fetchField() && !$entity->isNewRevision()) { + if (!$query->execute()->fetchField()) { $entity->setNewRevision(); } } @@ -680,11 +657,32 @@ protected function preSave(EntityInterface $entity) { } * Used after the entity is saved, but before invoking the insert or update * hook. * - * @param $update + * @param boolean $update * (bool) TRUE if the entity has been updated, or FALSE if it has been * inserted. */ - protected function postSave(EntityInterface $entity, $update) { } + protected function postSave(EntityInterface $entity, $update) { + // Write the data into the property data table if one is available. + if ($this->dataTable) { + // @todo try to find a better way to deal with updates. + $query = db_select($this->entityInfo['data table']) + ->condition($this->idKey, $entity->id()) + ->condition('langcode', $entity->langcode); + $query->addExpression('1'); + if ($update && $query->execute()->fetchField()) { + // Update existing property data row. + $primary_keys = array( + $this->idKey, + 'langcode', + ); + drupal_write_record($this->entityInfo['data table'], $entity, $primary_keys); + } + else { + // Insert new property data row. + drupal_write_record($this->entityInfo['data table'], $entity); + } + } + } /** * Acts on entities before they are deleted. diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php index ec1425e..1d999c3 100644 --- a/core/modules/node/lib/Drupal/node/NodeStorageController.php +++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php @@ -120,6 +120,8 @@ protected function preSaveRevision(array &$record, EntityInterface $entity) { * Overrides Drupal\Core\Entity\DatabaseStorageController::postSave(). */ protected function postSave(EntityInterface $node, $update) { + parent::postSave($node, $update); + // Update the node access table for this node, but only if it is the // default revision. There's no need to delete existing records if the node // is new. diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php index c80b339..c512825 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php @@ -142,65 +142,4 @@ function testMultilingualDisplaySettings() { $this->assertEqual(current($body), $node->body['en'][0]['value'], 'Node body found.'); } - /** - * Test property translation. - */ - public function testMultilingualProperties() { - $title_values = array( - 'en' => $this->randomName(8), - 'it' => $this->randomName(8), - ); - $node = $this->drupalCreateNode(array( - 'title' => $title_values['en'], - 'body' => array('en' => array(array($this->randomString(30)))), - 'langcode' => 'en', - )); - - // Save properties in a different language. - $node->title = $title_values['it']; - $node->langcode = 'it'; - $node->save(); - - $node_property_data = db_select('node_property_data') - ->fields('node_property_data') - ->condition('nid', $node->id()) - ->execute() - ->fetchAll(); - $this->assertEqual(2, count($node_property_data), 'Two property items found.'); - $property_languages = array(); - $property_default_languages = array(); - foreach ($node_property_data as $node_property_data_raw) { - $property_languages[$node_property_data_raw->langcode] = $node_property_data_raw->langcode; - $property_default_languages[$node_property_data_raw->default_langcode] = $node_property_data_raw->default_langcode; - - $this->assertEqual($title_values[$node_property_data_raw->langcode], $node_property_data_raw->title, $node_property_data_raw->langcode . ': Language specific title found.'); - } - $this->assertEqual(array('en' => 'en', 'it' => 'it'), $property_languages, 'Expected property languages found.'); - $this->assertEqual(array('en' => 'en'), $property_default_languages, 'Default language of properties is consistent.'); - - $node_property_revision = db_select('node_property_revision') - ->fields('node_property_revision') - ->condition('nid', $node->id()) - ->orderBy('vid') - ->execute() - ->fetchAll(); - $this->assertEqual(2, count($node_property_revision), 'Two property revision rows found.'); - $revision_languages = array(); - $revision_default_languages = array(); - foreach ($node_property_revision as $node_property_revision_raw) { - $revision_languages[$node_property_revision_raw->langcode] = $node_property_revision_raw->langcode; - $revision_default_languages[$node_property_revision_raw->default_langcode] = $node_property_revision_raw->default_langcode; - - $this->assertEqual($title_values[$node_property_revision_raw->langcode], $node_property_revision_raw->title, $node_property_revision_raw->langcode . ': Language specific title found.'); - } - $this->assertEqual(array('en' => 'en', 'it' => 'it'), $revision_languages, 'Expected property revision languages found.'); - $this->assertEqual(array('en' => 'en'), $revision_default_languages, 'Default language of revisions is consistent.'); - - $node_raw_data = db_select('node') - ->fields('node') - ->condition('nid', $node->id()) - ->execute() - ->fetchAll(); - $this->assertEqual('en', $node_raw_data[0]->langcode, 'Default language unchanged.'); - } } diff --git a/core/modules/node/lib/Drupal/node/Tests/NodePropertyMultilingualTestCase.php b/core/modules/node/lib/Drupal/node/Tests/NodePropertyMultilingualTestCase.php new file mode 100644 index 0000000..22437f9 --- /dev/null +++ b/core/modules/node/lib/Drupal/node/Tests/NodePropertyMultilingualTestCase.php @@ -0,0 +1,196 @@ + 'Multilingual properties', + 'description' => 'Test multilingual support for properties.', + 'group' => 'Node', + ); + } + + public function setUp() { + parent::setUp(); + + // Create Basic page node type. + $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); + + // Setup users. + $admin_user = $this->drupalCreateUser(array( + 'administer languages', + 'administer content types', + 'access administration pages', + 'create page content', + 'edit own page content', + )); + $this->drupalLogin($admin_user); + + // Add a new languages. + $language = new Language(array( + 'langcode' => 'it', + 'name' => 'Italian', + )); + language_save($language); + $language = new Language(array( + 'langcode' => 'de', + 'name' => 'German', + )); + language_save($language); + + // Enable URL language detection and selection. + $edit = array('language_interface[enabled][language-url]' => '1'); + $this->drupalPost('admin/config/regional/language/detection', $edit, t('Save settings')); + + // Set "Basic page" content type to use multilingual support. + $edit = array( + 'language_configuration[language_hidden]' => FALSE, + ); + $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')), 'Basic page content type has been updated.'); + + // Make node body translatable. + $field = field_info_field('body'); + $field['translatable'] = TRUE; + field_update_field($field); + } + + /** + * Test property translation. + */ + public function testMultilingualProperties() { + $available_langcodes = array('en', 'it', 'de'); + // Create different nodes with different default langcodes. + foreach ($available_langcodes as $default_langcode) { + // Create base node. + $title_values = array( + $default_langcode => $this->randomName(8), + ); + $node = $this->drupalCreateNode(array( + 'title' => $title_values[$default_langcode], + 'body' => array($default_langcode => array(array($this->randomString(30)))), + 'langcode' => $default_langcode, + )); + + $property_langcodes = array_diff($available_langcodes, array($default_langcode)); + + // Create properties in different languages. + $property_count = 1; + $expected_languages = array($default_langcode); + foreach ($property_langcodes as $langcode) { + $property_count++; + $expected_languages[] = $langcode; + $title_values[$langcode] = $this->randomName(8); + + // Save properties in a different language. + $node->title = $title_values[$langcode]; + $node->langcode = $langcode; + $node->save(); + + // Check consistency of property data. + $node_property_data = db_select('node_property_data') + ->fields('node_property_data') + ->condition('nid', $node->id()) + ->execute() + ->fetchAll(); + $this->assertEqual($property_count, count($node_property_data), 'Expected ' . $property_count . ' property rows found.'); + $found_property_languages = array(); + $found_property_default_languages = array(); + foreach ($node_property_data as $node_property_data_raw) { + $found_property_languages[] = $node_property_data_raw->langcode; + $found_property_default_languages[$node_property_data_raw->default_langcode] = $node_property_data_raw->default_langcode; + $this->assertEqual($title_values[$node_property_data_raw->langcode], $node_property_data_raw->title, $node_property_data_raw->langcode . ': Language specific title found.'); + } + $this->assertEqual($expected_languages, $found_property_languages, 'Expected property languages found.'); + $this->assertEqual(array($default_langcode => $default_langcode), $found_property_default_languages, 'Default language of properties is consistent.'); + + // Check consistency of revisions. + $node_property_revision = db_select('node_property_revision') + ->fields('node_property_revision') + ->condition('nid', $node->id()) + ->orderBy('vid') + ->execute() + ->fetchAll(); + $this->assertEqual($property_count, count($node_property_revision), 'Expected ' . $property_count . ' property revision rows found.'); + $found_revision_languages = array(); + $found_revision_default_languages = array(); + foreach ($node_property_revision as $node_property_revision_raw) { + $found_revision_languages[] = $node_property_revision_raw->langcode; + $found_revision_default_languages[$node_property_revision_raw->default_langcode] = $node_property_revision_raw->default_langcode; + $this->assertEqual($title_values[$node_property_revision_raw->langcode], $node_property_revision_raw->title, $node_property_revision_raw->langcode . ': Language specific title found.'); + } + $this->assertEqual($expected_languages, $found_revision_languages, 'Expected property revision languages found.'); + $this->assertEqual(array($default_langcode => $default_langcode), $found_revision_default_languages, 'Default language of revisions is consistent.'); + } + + // Check revisioning. + $title_revision_values = array(); + foreach ($available_langcodes as $langcode) { + $title_revision_values[$langcode] = $this->randomName(8); + // Create new revision in the same language. + $old_revision_id = $node->getRevisionId(); + $node->title = $title_revision_values[$langcode]; + $node->langcode = $langcode; + $node->setNewRevision(); + $node->save(); + + // Check consistency of property data. + $node_property_data = db_select('node_property_data') + ->fields('node_property_data') + ->condition('nid', $node->id()) + ->condition('langcode', $node->langcode) + ->execute() + ->fetchAll(); + if ($this->assertEqual(1, count($node_property_data), 'Two property rows found.')) { + $this->assertNotEqual($old_revision_id, $node_property_data[0]->vid, $node_property_data_raw->langcode . ': New Revision id set.'); + $this->assertEqual($title_revision_values[$langcode], $node_property_data[0]->title, $node_property_data_raw->langcode . ': Revisioned title found.'); + } + + $node_property_revision = db_select('node_property_revision') + ->fields('node_property_revision') + ->condition('nid', $node->id()) + ->condition('langcode', $node->langcode) + ->orderBy('vid') + ->execute() + ->fetchAll(); + $this->assertEqual(2, count($node_property_revision), 'Two property revision rows found.'); + foreach ($node_property_revision as $node_property_revision_raw) { + if ($node_property_revision_raw->vid == $node->getRevisionId()) { + $this->assertEqual($title_revision_values[$langcode], $node_property_revision_raw->title, $node_property_revision_raw->langcode . ': title of new revision found.'); + } + else { + $this->assertEqual($title_values[$langcode], $node_property_revision_raw->title, $node_property_revision_raw->langcode . ': title of old revision found.'); + } + } + } + + // Check if the default language is untouched. + $node_raw_data = db_select('node') + ->fields('node') + ->condition('nid', $node->id()) + ->execute() + ->fetchAll(); + $this->assertEqual($default_langcode, $node_raw_data[0]->langcode, 'Default language unchanged.'); + } + } +}