From f4bb9d10cb4bd382791fc9fdbf92e0055e08efa2 Mon Sep 17 00:00:00 2001 From: jagilpe Date: Thu, 13 Nov 2014 09:52:28 +0100 Subject: [PATCH] Issue #1344672 by jagilpe: Added Entity Translation support and tests. --- field_collection.module | 123 ++++++++-- field_collection.test | 627 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 734 insertions(+), 16 deletions(-) diff --git a/field_collection.module b/field_collection.module index 3a8f9e9..42d36bd 100644 --- a/field_collection.module +++ b/field_collection.module @@ -57,7 +57,8 @@ function field_collection_entity_info() { ), 'access callback' => 'field_collection_item_access', 'deletion callback' => 'field_collection_item_delete', - 'metadata controller class' => 'FieldCollectionItemMetadataController' + 'metadata controller class' => 'FieldCollectionItemMetadataController', + 'language callback' => 'field_collection_get_entity_language' ); // Add info about the bundles. We do not use field_info_fields() but directly @@ -972,7 +973,7 @@ function field_collection_field_update($host_entity_type, $host_entity, $field, $items_original = !empty($host_entity->original->{$field['field_name']}[$langcode]) ? $host_entity->original->{$field['field_name']}[$langcode] : array(); $original_by_id = array_flip(field_collection_field_item_to_ids($items_original)); - foreach ($items as &$item) { + foreach ($items as $delta => &$item) { // In case the entity has been changed / created, save it and set the id. // If the host entity creates a new revision, save new item-revisions as // well. @@ -1010,6 +1011,7 @@ function field_collection_field_update($host_entity_type, $host_entity, $field, ); } } + unset($original_by_id[$item['value']]); } @@ -1456,26 +1458,47 @@ function field_collection_field_widget_form(&$form, &$form_state, $field, $insta $field_state['items_count'] = 1; } - if (isset($field_state['entity'][$delta])) { - $field_collection_item = $field_state['entity'][$delta]; - } - else { + // Check if this is an Entity Translation Source Form + if (module_exists('entity_translation') && isset($form['#entity_translation_source_form']) && $form['#entity_translation_source_form']) { if (isset($items[$delta])) { $field_collection_item = field_collection_field_get_entity($items[$delta], $field_name); + // This is the source form for a translation with field translation, therefore we must clone the field collection item + $new_entity = clone $field_collection_item; + $new_entity->item_id = NULL; + $new_entity->revision_id = NULL; + $new_entity->is_new = TRUE; + $field_state['entity'][$delta] = $new_entity; + $new_entity->setHostEntity($element['#entity_type'], $element['#entity'], 'de', FALSE); + + $new_entity->check = 'delta_' . $delta; + + $field_state['entity'][$delta] = $new_entity; + field_form_set_state($field_parents, $field_name, $language, $form_state, $field_state); + field_attach_form('field_collection_item', $new_entity, $element, $form_state, LANGUAGE_NONE); } - // Show an empty collection if we have no existing one or it does not - // load. - if (empty($field_collection_item)) { - $field_collection_item = entity_create('field_collection_item', array('field_name' => $field_name)); - $field_collection_item->setHostEntity($element['#entity_type'], $element['#entity']); + } + else { + if (isset($field_state['entity'][$delta])) { + $field_collection_item = $field_state['entity'][$delta]; + } + else { + if (isset($items[$delta])) { + $field_collection_item = field_collection_field_get_entity($items[$delta], $field_name); + } + // Show an empty collection if we have no existing one or it does not + // load. + if (empty($field_collection_item)) { + $field_collection_item = entity_create('field_collection_item', array('field_name' => $field_name)); + } + + // Put our entity in the form state, so FAPI callbacks can access it. + $field_state['entity'][$delta] = $field_collection_item; } - // Put our entity in the form state, so FAPI callbacks can access it. - $field_state['entity'][$delta] = $field_collection_item; + field_form_set_state($field_parents, $field_name, $language, $form_state, $field_state); + field_attach_form('field_collection_item', $field_collection_item, $element, $form_state, LANGUAGE_NONE); } - field_form_set_state($field_parents, $field_name, $language, $form_state, $field_state); - field_attach_form('field_collection_item', $field_collection_item, $element, $form_state, $language); if (empty($element['#required'])) { $element['#after_build'][] = 'field_collection_field_widget_embed_delay_required_validation'; @@ -1736,7 +1759,20 @@ function field_collection_field_widget_embed_validate($element, &$form_state, $c $language = $element['#language']; $field_state = field_form_get_state($field_parents, $field_name, $language, $form_state); - $field_collection_item = $field_state['entity'][$element['#delta']]; + + // Check if this is a translation with Entity Translation + if (isset($form_state['entity_translation']) && $form_state['entity_translation']['is_translation']) { + // Check if it's the translation creation + if (!isset($field_state['entity'][$element['#delta']]) && $field_state['entity'][0]->is_new) { + $field_collection_item = $element['#entity']; + } + else { + $field_collection_item = $field_state['entity'][$element['#delta']]; + } + } + else { + $field_collection_item = $field_state['entity'][$element['#delta']]; + } // Attach field API validation of the embedded form. field_attach_form_validate('field_collection_item', $field_collection_item, $element, $form_state); @@ -1764,6 +1800,9 @@ function field_collection_field_widget_embed_validate($element, &$form_state, $c } } + + + // Only if the form is being submitted, finish the collection entity and // prepare it for saving. if ($form_state['submitted'] && !form_get_errors()) { @@ -1785,6 +1824,7 @@ function field_collection_field_widget_embed_validate($element, &$form_state, $c $item['entity'] = $field_collection_item; form_set_value($element, $item, $form_state); } + } /** @@ -1996,3 +2036,54 @@ function field_collection_devel_generate($object, $field, $instance, $bundle) { function field_collection_hide_blank_items($field) { return !empty($field['settings']['hide_blank_items']) && $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED; } + +/* + * Language callback for the Entity Metadata Wrapper + * + * @param string $entity_type + * The entity type. + * @param unknown $entity + * The entity to get the language from + */ +function field_collection_get_entity_language($entity_type, $entity) { + return isset($entity->language) ? $entity->language : LANGUAGE_NONE; +} + +/** + * implements hook_entity_translation_insert + */ +function field_collection_entity_translation_insert($entity_type, $entity, $translation, $values = array()) { + // Check if some of the values inserted are of a field_collection field + if (!empty($values)) { + foreach ($values as $field_name => $value) { + $field = field_info_field($field_name); + + if ($field['type'] == 'field_collection') { + // We have found a field collection + $language = $translation['language']; + $source_language = $translation['source']; + + if (!empty($value[$language])) { + $source_items = !empty($entity->{$field_name}[$source_language]) ? field_collection_field_item_to_ids($entity->{$field_name}[$source_language]) : array(); + foreach ($value[$language] as $delta => $field_value) { + if (!isset($field_value['entity'])) { + if ($fc_entity = field_collection_field_get_entity($field_value)) { + // Check if this field collection item belongs to the source language + if (in_array($fc_entity->item_id, $source_items)) { + // Clone the field collection item + $new_fc_entity = clone $fc_entity; + $new_fc_entity->item_id = NULL; + $new_fc_entity->revision_id = NULL; + $new_fc_entity->is_new = TRUE; + + // Set the new entity for saving it later + $entity->{$field_name}[$language][$delta]['entity'] = $new_fc_entity; + } + } + } + } + } + } + } + } +} diff --git a/field_collection.test b/field_collection.test index a2fd734..feda2b1 100644 --- a/field_collection.test +++ b/field_collection.test @@ -578,3 +578,630 @@ class FieldCollectionContentTranslationTestCase extends DrupalWebTestCase { } } + +/** + * Test using field collection with content that gets translated with Entity Translation. + */ +class FieldCollectionEntityTranslationTestCase extends DrupalWebTestCase { + const TRANS_FIELD_EN = 'Translatable EN'; + const TRANS_FIELD_DE = 'Translatable DE'; + const TRANS_FIELD_DE_MOD = 'Translatable DE Mod'; + const UNTRANS_FIELD_EN = 'Untranslatable EN'; + const UNTRANS_FIELD_DE = 'Untranslatable DE'; + const UNTRANS_FIELD_DE_MOD = 'Untranslatable DE Mod'; + const NUM_VALUES = 4; + + public static function getInfo() { + return array( + 'name' => 'Field collection entity translation', + 'description' => 'Tests using content under translation with Entity Translation.', + 'group' => 'Field types', + 'dependencies' => array('entity_translation'), + ); + } + + /** + * Login the given user only if she has not changed. + */ + function login($user) { + if (!isset($this->current_user) || $this->current_user->uid != $user->uid) { + $this->current_user = $user; + $this->drupalLogin($user); + } + } + + /** + * Returns a user with administration rights. + * + * @param $permissions + * Additional permissions for administrative user. + */ + function getAdminUser(array $permissions = array()) { + if (!isset($this->admin_user)) { + $this->admin_user = $this->drupalCreateUser(array_merge(array( + 'bypass node access', + 'administer nodes', + 'administer languages', + 'administer content types', + 'administer blocks', + 'access administration pages', + 'administer site configuration', + ), $permissions)); + } + return $this->admin_user; + } + + /** + * Returns a user with minimal translation rights. + * + * @param $permissions + * Additional permissions for administrative user. + */ + function getTranslatorUser(array $permissions = array()) { + if (!isset($this->translator_user)) { + $this->translator_user = $this->drupalCreateUser(array_merge(array( + 'create page content', + 'edit own page content', + 'delete own page content', + 'translate any entity', + ), $permissions)); + } + return $this->translator_user; + } + + /** + * Install a specified language if it has not been already, otherwise make sure that the language is enabled. + * + * @param $langcode + * The language code to check. + */ + function addLanguage($langcode) { + // Check to make sure that language has not already been installed. + $this->drupalGet('admin/config/regional/language'); + + if (strpos($this->drupalGetContent(), 'enabled[' . $langcode . ']') === FALSE) { + // Doesn't have language installed so add it. + $edit = array(); + $edit['langcode'] = $langcode; + $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language')); + + // Make sure we are not using a stale list. + drupal_static_reset('language_list'); + $languages = language_list('language'); + $this->assertTrue(array_key_exists($langcode, $languages), t('Language was installed successfully.')); + + if (array_key_exists($langcode, $languages)) { + $this->assertRaw(t('The language %language has been created and can now be used. More information is available on the help screen.', array('%language' => $languages[$langcode]->name, '@locale-help' => url('admin/help/locale'))), t('Language has been created.')); + } + } + elseif ($this->xpath('//input[@type="checkbox" and @name=:name and @checked="checked"]', array(':name' => 'enabled[' . $langcode . ']'))) { + // It is installed and enabled. No need to do anything. + $this->assertTrue(TRUE, 'Language [' . $langcode . '] already installed and enabled.'); + } + else { + // It is installed but not enabled. Enable it. + $this->assertTrue(TRUE, 'Language [' . $langcode . '] already installed.'); + $this->drupalPost(NULL, array('enabled[' . $langcode . ']' => TRUE), t('Save configuration')); + $this->assertRaw(t('Configuration saved.'), t('Language successfully enabled.')); + } + } + + public function setUp() { + parent::setUp(array('field_collection', 'entity_translation')); + $language_none = LANGUAGE_NONE; + // Login with an admin user + $this->login($this->getAdminUser()); + // Add English and German languages + $this->addLanguage('en'); + $this->addLanguage('de'); + + // Set "Article" content type to use multilingual support with translation. + $edit = array(); + $edit['language_content_type'] = ENTITY_TRANSLATION_ENABLED; + $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 field collection field to use for the tests. + $this->field_name = 'field_test_collection'; + $this->field_base = "{$this->field_name}[$language_none]"; + $this->field = array( + 'field_name' => $this->field_name, + 'type' => 'field_collection', + 'cardinality' => -1, + 'translatable' => TRUE, + ); + $this->field = field_create_field($this->field); + $this->field_id = $this->field['id']; + + $this->instance = array( + 'field_name' => $this->field_name, + 'entity_type' => 'node', + 'bundle' => 'page', + 'label' => $this->randomName() . '_label', + 'description' => $this->randomName() . '_description', + 'weight' => mt_rand(0, 127), + 'settings' => array(), + 'widget' => array( + 'type' => 'field_collection_embed', + 'label' => 'Test', + 'settings' => array(), + ), + ); + $this->instance = field_create_instance($this->instance); + + // Add an untraslatable field to the collection + $this->field_untrans_name = 'field_text_untrans'; + $this->field_untrans_base = "[{$this->field_untrans_name}][$language_none][0][value]"; + $field = array( + 'field_name' => $this->field_untrans_name, + 'type' => 'text', + 'cardinality' => 1, + 'translatable' => FALSE, + ); + field_create_field($field); + $instance = array( + 'entity_type' => 'field_collection_item', + 'field_name' => $this->field_untrans_name, + 'bundle' => $this->field_name, + 'label' => 'Test untranslatable text field', + 'widget' => array( + 'type' => 'text_textfield', + ), + ); + field_create_instance($instance); + + // Add a translatable field to the collection + $this->field_trans_name = 'field_text_trans'; + $this->field_trans_base = "[{$this->field_trans_name}][$language_none][0][value]"; + $field = array( + 'field_name' => $this->field_trans_name, + 'type' => 'text', + 'cardinality' => 1, + 'translatable' => TRUE, + ); + field_create_field($field); + $instance = array( + 'entity_type' => 'field_collection_item', + 'field_name' => $this->field_trans_name, + 'bundle' => $this->field_name, + 'label' => 'Test translatable text field', + 'widget' => array( + 'type' => 'text_textfield', + ), + ); + field_create_instance($instance); + + $this->login($this->getTranslatorUser()); + } + + /** + * Creates a basic page in the specified language with only a value in the field collection + * + * @param integer $num_values + * The number of values to include in the field collection + */ + protected function createPage($num_values, $langcode = 'en') { + // Check if num_values is greater than the field cardinality + if ($num_values > self::NUM_VALUES) { + $num_values = self::NUM_VALUES; + } + + $title = $this->randomName(); + + $this->drupalGet('node/add/page'); + + $edit = array(); + $edit["title"] = $title; + for ($i = 0; $i < $num_values; $i++) { + if ($i != 0) { + $this->drupalPost(NULL, array(), t('Add another item')); + } + $edit[$this->field_base . '[' . $i . ']' . $this->field_untrans_base] = self::UNTRANS_FIELD_EN . '_' . $i; + $edit[$this->field_base . '[' . $i . ']' . $this->field_trans_base] = self::TRANS_FIELD_EN . '_' . $i; + } + + $edit['language'] = $langcode; + $this->drupalPost(NULL, $edit, t('Save')); + $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), t('Basic page created.')); + + // Check to make sure the node was created. + $node = $this->drupalGetNodeByTitle($title); + $this->assertTrue($node, t('Node found in database.')); + + return $node; + + } + + /** + * Create a translation using the Entity Translation Form + * + * @param $node + * Node of the basic page to create translation for. + * @param $langcode + * The language code of the translation. + * @param $source_langcode + * The original language code. + */ + protected function createTranslationForm($node, $langcode, $source_langcode = 'en') { + $language_none = LANGUAGE_NONE; + $edit = array(); + + $this->drupalGet('node/' . $node->nid . '/edit/add/' . $source_langcode . '/' .$langcode); + + // Get the field collection in the original language + $fc_values = $node->{$this->field_name}[$source_langcode]; + + // Check if all the fields were well populated and fill it later with the new value + foreach ($fc_values as $delta => $fc_value) { + // Load the field collection item + $fc_item = reset(entity_load('field_collection_item', array($fc_value['value']))); + $fc_untrans_key = "{$this->field_name}[$langcode][$delta]{$this->field_untrans_base}"; + $fc_trans_key = "{$this->field_name}[$langcode][$delta]{$this->field_trans_base}"; + $this->assertFieldByXPath( + "//input[@name='$fc_untrans_key']", + $fc_item->{$this->field_untrans_name}[LANGUAGE_NONE][0]['value'], + 'Original value of untranslatable field correctly populated' + ); + $this->assertFieldByXPath( + "//input[@name='$fc_trans_key']", + $fc_item->{$this->field_trans_name}[LANGUAGE_NONE][0]['value'], + 'Original value of translatable field correctly populated' + ); + + $edit[$fc_untrans_key] = self::UNTRANS_FIELD_DE . '_' . $delta; + $edit[$fc_trans_key] = self::TRANS_FIELD_DE . '_' . $delta; + } + + // Save the translation + $this->drupalPost(NULL, $edit, t('Save')); + $this->drupalGet('node/' . $node->nid . '/translate'); + $this->assertLinkByHref('node/' . $node->nid . '/edit/' . $langcode, 0, t('Translation edit link found. Translation created.')); + + // Reload the node + $node = node_load($node->nid, NULL, TRUE); + + // Check the values of the translated field + $this->checkFieldCollectionContent($node, $langcode); + + // Check the values of the field in the original language + $this->checkFieldCollectionContent($node, $source_langcode); + + return $node; + } + + /** + * Removes a translation using the entity translation form + * + * @param mixed $node + * The node to remove the translation from + * @param unknown $langcode + * The language of the translation to remove + * @param unknown $source_langcode + * The source language of the node + */ + protected function removeTranslationForm($node, $langcode, $source_langcode) { + // Number of field collection items in the source language + $num_original_fc_items = count($node->{$this->field_name}[$source_langcode]); + // Get the field_collection items of the translation + $fc_item_ids = array(); + foreach ($node->{$this->field_name}[$langcode] as $delta => $value) { + $fc_item_ids[] = $value['value']; + } + + // Fetch the translation edition form + $this->drupalGet('node/' . $node->nid . '/edit/' . $langcode); + + // Remove the translation + $this->drupalPost(NULL, array(), t('Delete translation')); + // Confirm deletion + $this->drupalPost(NULL, array(), t('Delete')); + + // Reload the node + $node = node_load($node->nid, NULL, TRUE); + + // Check that the translation is removed + $this->drupalGet('node/' . $node->nid . '/translate'); + $this->assertLinkByHref('node/' . $node->nid . '/edit/add/' . $source_langcode . '/' . $langcode, 0, 'The add translation link appears'); + $this->assert(empty($node->{$this->field_name}[$langcode])); + + // Check that the field collection items of the translation are removed + // This test fails and it not really clear if it'a problem of field_collection or of + // Entity Translation that does not fires field_attach_update +// $fc_items = entity_load('field_collection_item', $fc_item_ids); +// $this->assert(empty($fc_items), t('The field collection item has been removed from the database.')); + + // Check that the field collection in the original language has not changed + $num_fc_items = count($node->{$this->field_name}[$source_langcode]); + $this->assertEqual($num_original_fc_items, $num_fc_items, 'The number of field collection items in the original language has not changed.'); + $this->checkFieldCollectionContent($node, $source_langcode); + } + + /** + * Creates a translation programmatically using Entity Translation + * + * @param $node + * Node of the basic page to create translation for. + * @param $langcode + * The language code of the translation. + * @param $source_langcode + * The source language code. + */ + protected function createTranslation($node, $langcode) { + $source_langcode = $node->language; + + // Get the Entity Translation Handler + $handler = entity_translation_get_handler('node', $node, TRUE); + // Variable to hold the fields values + $values = array(); + // Translation settings + $translation = array( + 'translate' => 0, + 'status' => 1, + 'language' => $langcode, + 'source' => $source_langcode, + 'uid' => $node->uid, + ); + // Copy field values + foreach (field_info_instances('node', $node->type) as $instance) { + $field_name = $instance['field_name']; + $field = field_info_field($field_name); + $field_value = array(); + // Copy the value of the translated field if it's translatable + if ($field['translatable']) { + if (isset($node->{$field_name}[$node->language])) { + $field_value = $node->{$field_name}[$source_langcode]; + $values[$field_name][$langcode] = $field_value; + $node->{$field_name}[$langcode] = $field_value; + } + } + } + + $handler->setTranslation($translation, $values); + $handler->saveTranslations(); + field_attach_update('node', $node); + + // Reload an return the node + $node = node_load($node->nid, null, TRUE); + return $node; + } + + /** + * Removes a translation programmatically using the entity translation api + * + * @param mixed $node + * The node to remove the translation from + * @param unknown $langcode + * The language of the translation to remove + */ + protected function removeTranslation($node, $langcode) { + // Get a translation entity handler + $handler = entity_translation_get_handler('node', $node, TRUE); + + // Remove the translation + $handler->removeTranslation($langcode); + node_save($node); + + // Reload and return the node + $node = node_load($node->nid, null, TRUE); + + return $node; + } + + /** + * Creates a new revision of the node and checks the result + * + * @param $node + * @param $langcode + * @param $source_langcode + * @return + * The new revision of the node + */ + protected function createRevision($node, $langcode, $source_langcode) { + $node_original_revision = $node->vid; + // The original entries of the translated field + $original_fc_item_ids = $node->{$this->field_name}[$langcode]; + + // Create the revision + $node->revision = TRUE; + node_save($node); + + // The new entries of the translated field + $new_fc_item_ids = $node->{$this->field_name}[$langcode]; + + // Check that the field collection items are the same and a new revision of each one has been created + foreach ($original_fc_item_ids as $delta => $value) { + $this->assertEqual($value['value'], $new_fc_item_ids[$delta]['value'], t('We have the same field collection item')); + $this->assertNotEqual($value['revision_id'], $new_fc_item_ids[$delta]['revision_id'], t('We have a new revision of the field collection item')); + } + + return $node; + } + + /** + * Check the content of the field collection for a specified language + * + * @param mixed $node + * The node to check + * @param string $langcode + * The language to check + */ + protected function checkFieldCollectionContent($node, $langcode) { + switch($langcode) { + case 'en': + $untrans_field = self::UNTRANS_FIELD_EN; + $trans_field = self::TRANS_FIELD_EN; + break; + case 'de': + $untrans_field = self::UNTRANS_FIELD_DE; + $trans_field = self::TRANS_FIELD_DE; + break; + } + // Get the field collection in the specified language + $fc_values = $node->{$this->field_name}[$langcode]; + + foreach ($fc_values as $delta => $fc_value) { + // Load the field collection item + $fc_item = reset(entity_load('field_collection_item', array($fc_value['value']))); + $fc_untrans_key = "{$this->field_name}[$langcode][$delta]{$this->field_untrans_base}"; + $fc_trans_key = "{$this->field_name}[$langcode][$delta]{$this->field_trans_base}"; + + $this->assertEqual($untrans_field . '_' . $delta, $fc_item->{$this->field_untrans_name}[LANGUAGE_NONE][0]['value']); + $this->assertEqual($trans_field . '_' . $delta, $fc_item->{$this->field_trans_name}[LANGUAGE_NONE][0]['value']); + } + } + + /** + * Returns the text field values of an specified node, language and delta + * + * @param mixed $node + * @param string $langcode + * @param integer $delta + * @return array + */ + protected function getFieldValues($node, $langcode, $delta) { + $return = array(); + + if (isset($node->{$this->field_name}[$langcode][$delta]['value'])) { + $fc_item_id = $node->{$this->field_name}[$langcode][$delta]['value']; + // Load the field collection + $fc_item = reset(entity_load('field_collection_item', array($fc_item_id))); + + $return = array( + 'field_untrans' => $fc_item->{$this->field_untrans_name}[LANGUAGE_NONE][0]['value'], + 'field_trans' => $fc_item->{$this->field_trans_name}[LANGUAGE_NONE][0]['value'], + ); + } + + return $return; + } + + /** + * Ensures that field collections has the right behaviour in all Entity Translation use cases + */ + public function testEntityTranslation() { + $source_langcode = 'en'; + $translation_langcode = 'de'; + + /* + * Tests with a page with only one value in the field collection + */ + // Create an article in the original language with only one field collection value + $node = $this->createPage(1, $source_langcode); + + // Create a traslation of the page through the entity translation form + $node = $this->createTranslationForm($node, $translation_langcode, $source_langcode); + + /* + * Test with a page with multiple values in the field collection + */ + $num_values = 4; + // Create a page in the original language with multiple field collection values + $node = $this->createPage($num_values, $source_langcode); + + // Create a traslation of the page through the entity translation form + $node = $this->createTranslationForm($node, $translation_langcode, $source_langcode); + + // Assign a new field collection item to an existing node + $values = array(); + $values['field_name'] = $this->field_name; + $fc_entity = entity_create('field_collection_item', $values); + $fc_entity->setHostEntity('node', $node, $translation_langcode); + $fc_wrapper = entity_metadata_wrapper('field_collection_item', $fc_entity); + $fc_wrapper->{$this->field_untrans_name}->set(self::UNTRANS_FIELD_DE_MOD); + $fc_wrapper->{$this->field_trans_name}->set(self::TRANS_FIELD_DE_MOD); + $fc_wrapper->save(TRUE); + node_save($node); + + // Reload the node to check it + $node = node_load($node->nid, NULL, TRUE); + // Check that there is a new element in the translation + $this->assertEqual($num_values + 1, count($node->{$this->field_name}[$translation_langcode]), t('We have one item more in translation.')); + // Check that the new element is correctly saved + $fc_item_values = $this->getFieldValues($node, $translation_langcode, $num_values); + $this->assertEqual($fc_item_values['field_untrans'], self::UNTRANS_FIELD_DE_MOD); + $this->assertEqual($fc_item_values['field_trans'], self::TRANS_FIELD_DE_MOD); + // Check that we have the same items in the original language + $this->assertEqual($num_values, count($node->{$this->field_name}[$source_langcode]), t('We have same items in the original language.')); + + // Remove a field collection item from the translation + $fc_item_id = $node->{$this->field_name}[$translation_langcode][0]['value']; + unset($node->{$this->field_name}[$translation_langcode][0]); + node_save($node); + // Reload the node + $node = node_load($node->nid, NULL, TRUE); + // Check that we have one item less in the translation + // We should take into account that we added a field one step before + $this->assertEqual($num_values, count($node->{$this->field_name}[$translation_langcode]), t('We have one item less in translation.')); + // Check that we have the same items in the original language + $this->assertEqual($num_values, count($node->{$this->field_name}[$source_langcode]), t('We have same items in the original language.')); + // Check that the field collection is removed from the database + $fc_items = entity_load('field_collection_item', array($fc_item_id)); + $this->assert(empty($fc_items), t('The field collection item has been removed from the database.')); + + // Delete the translation + $this->removeTranslationForm($node, $translation_langcode, $source_langcode); + + /* + * Check the revisioning of an entity with translations + */ + $num_values = 4; + // Create a page in the original language with multiple field collection values + $node_rev = $this->createPage($num_values, $source_langcode); + + // Create a traslation of the page + $node_rev = $this->createTranslationForm($node_rev, $translation_langcode, $source_langcode); + + $original_revision = $node_rev->vid; + + // Create a new revision of the node + $node_rev = $this->createRevision($node_rev, $translation_langcode, $source_langcode); + + /* + * Test creating programmatically + */ + $num_values = 4; + // Create a page in the original language + $node_prog = $this->createPage($num_values, $source_langcode); + + // Create programmatically a translation of the page + $node_prog = $this->createTranslation($node_prog, $translation_langcode); + + $orig_fc_items = $node_prog->{$this->field_name}[$source_langcode]; + $trans_fc_items = $node_prog->{$this->field_name}[$translation_langcode]; + + $orig_fc_item_ids = array(); + $trans_fc_item_ids = array(); + + // Check each item + foreach ($orig_fc_items as $delta => $value) { + $orig_fc_item_ids[] = $value['value']; + $trans_fc_item_ids[] = $trans_fc_items[$delta]['value']; + + // Check if we have new items for the translation + $this->assertNotEqual($value['value'], $trans_fc_items[$delta]['value'], t('New item generated for translation.')); + } + + // Check that the original item still exists in the database + $fc_items = entity_load('field_collection_item', $orig_fc_item_ids); + $this->assert(!empty($fc_items), t('Field Collections in the source language still exist.')); + // Check that the translated item exists in the database + $fc_items = entity_load('field_collection_item', $trans_fc_item_ids); + $this->assert(!empty($fc_items), t('Translations for the Field Collection exist.')); + + // Remove the translation and check that the original field collection items are still there + $node_prog = $this->removeTranslation($node, $translation_langcode); + + // Check the content in the source language + $this->checkFieldCollectionContent($node_prog, $source_langcode); + + // Check that the field translated content has been removed + $this->assert(empty($node->{$this->field_name}[$translation_langcode]), t('Translated content removed.')); + + // Check that the field collection items have been removed from the database + // This test fails and it not really clear if it'a problem of field_collection or of + // Entity Translation that does not fires field_attach_update +// $fc_items = entity_load('field_collection_item', $trans_fc_item_ids); +// $this->assert(empty($fc_items), t('Translations for the Field Collection removed from the database.')); + } + +} -- 1.7.10.4