diff --git a/mappers/locale.inc b/mappers/locale.inc index d23ad93..bc0799b 100644 --- a/mappers/locale.inc +++ b/mappers/locale.inc @@ -17,7 +17,7 @@ function locale_feeds_processor_targets_alter(array &$targets, $entity_type, $bu } /** - * Preprocess callback that set's the configured mapping language. + * Preprocess callback that sets the configured mapping language. */ function locale_feeds_preprocess_callback(FeedsSource $source, $target_item, array $target, array &$mapping) { if (empty($mapping['field_language'])) { @@ -36,9 +36,19 @@ function locale_feeds_summary_callback(array $mapping, array $target, array $for $mapping += array('field_language' => LANGUAGE_NONE); - // This is an invalid configuration that can come from disabling - // entity_translation. - $error = $mapping['field_language'] !== LANGUAGE_NONE && !$translatable; + $language_options = array(LANGUAGE_NONE => t('Language neutral')) + locale_language_list('name'); + + $error = NULL; + if ($mapping['field_language'] !== LANGUAGE_NONE && !$translatable) { + // This is an invalid configuration that can come from disabling + // entity_translation. + $error = t('Field not translatable'); + } + if (!isset($language_options[$mapping['field_language']])) { + // This is an invalid configuration that can be caused by disabling or + // removing the language in question. + $error = t('Language @lang not available', array('@lang' => $mapping['field_language'])); + } // Nothing to see here. if (!$error && !$translatable) { @@ -46,11 +56,9 @@ function locale_feeds_summary_callback(array $mapping, array $target, array $for } if ($error) { - return t('Language: @error', array('@error' => t('Error'))); + return t('Language: Error: @error', array('@error' => $error)); } - $language_options = array(LANGUAGE_NONE => t('Language neutral')) + locale_language_list('name'); - return t('Language: %lang', array('%lang' => $language_options[$mapping['field_language']])); } diff --git a/plugins/FeedsProcessor.inc b/plugins/FeedsProcessor.inc index 12f2e65..9e9d081 100644 --- a/plugins/FeedsProcessor.inc +++ b/plugins/FeedsProcessor.inc @@ -786,6 +786,13 @@ abstract class FeedsProcessor extends FeedsPlugin { if (empty($mapping['language'])) { $mapping['language'] = LANGUAGE_NONE; } + else { + // Check if the configured language is available. If not, fallback to LANGUAGE_NONE. + $languages = language_list('enabled'); + if (!isset($languages[1][$mapping['language']])) { + $mapping['language'] = LANGUAGE_NONE; + } + } // Map the source element's value to the target. // If the mapping specifies a callback method, use the callback instead of diff --git a/tests/feeds/multilingual.csv b/tests/feeds/multilingual.csv deleted file mode 100644 index 8bf5b99..0000000 --- a/tests/feeds/multilingual.csv +++ /dev/null @@ -1 +0,0 @@ -"guid","title_en","title_fr","body_en","body_fr","date_en","date_fr","datestamp_en","datestamp_fr","datetime_en","datetime_fr","image_en","image_fr","image_alt_en","image_alt_fr","image_title_en","image_title_fr","link_en","link_fr","number_decimal_en","number_decimal_fr","number_float_en","number_float_fr","number_integer_en","number_integer_fr","term_en","term_fr","text_en","text_fr" 1,"Testing Multilingual Feeds 1","Teste Feeds Multilingue 1","This is the body","Ceci est la corps","21-10-2015","05-11-1955",1445470140,-446731187,"21-10-2015 23:29","1955-11-05 12:00:13","public://images/foosball.jpeg","public://images/la fayette.jpeg","Foosball","La Fayette","Foosball played by two guys","la Fayette dans les bois","http://google.ca","http://google.fr",4.2,1.2,3.1416,5.6295,1000,2000,"News","Nouvelles","Carrots","Carottes" \ No newline at end of file diff --git a/tests/feeds/multilingual_empty.csv b/tests/feeds/multilingual_empty.csv new file mode 100644 index 0000000..33e5706 --- /dev/null +++ b/tests/feeds/multilingual_empty.csv @@ -0,0 +1,2 @@ +"guid","title","body","date","datestamp","datetime","image","image_alt","image_title","link","number_decimal","number_float","number_integer","term","text" +1,,,,,,,,,,,,,, \ No newline at end of file diff --git a/tests/feeds/multilingual_en_fr.csv b/tests/feeds/multilingual_en_fr.csv new file mode 100644 index 0000000..8bf5b99 --- /dev/null +++ b/tests/feeds/multilingual_en_fr.csv @@ -0,0 +1 @@ +"guid","title_en","title_fr","body_en","body_fr","date_en","date_fr","datestamp_en","datestamp_fr","datetime_en","datetime_fr","image_en","image_fr","image_alt_en","image_alt_fr","image_title_en","image_title_fr","link_en","link_fr","number_decimal_en","number_decimal_fr","number_float_en","number_float_fr","number_integer_en","number_integer_fr","term_en","term_fr","text_en","text_fr" 1,"Testing Multilingual Feeds 1","Teste Feeds Multilingue 1","This is the body","Ceci est la corps","21-10-2015","05-11-1955",1445470140,-446731187,"21-10-2015 23:29","1955-11-05 12:00:13","public://images/foosball.jpeg","public://images/la fayette.jpeg","Foosball","La Fayette","Foosball played by two guys","la Fayette dans les bois","http://google.ca","http://google.fr",4.2,1.2,3.1416,5.6295,1000,2000,"News","Nouvelles","Carrots","Carottes" \ No newline at end of file diff --git a/tests/feeds/multilingual_en_fr_empty.csv b/tests/feeds/multilingual_en_fr_empty.csv new file mode 100644 index 0000000..223548e --- /dev/null +++ b/tests/feeds/multilingual_en_fr_empty.csv @@ -0,0 +1 @@ +"guid","title_en","title_fr","body_en","body_fr","date_en","date_fr","datestamp_en","datestamp_fr","datetime_en","datetime_fr","image_en","image_fr","image_alt_en","image_alt_fr","image_title_en","image_title_fr","link_en","link_fr","number_decimal_en","number_decimal_fr","number_float_en","number_float_fr","number_integer_en","number_integer_fr","term_en","term_fr","text_en","text_fr" 1,,"Teste Feeds Multilingue 1",,"Ceci est la corps",,"05-11-1955",,-446731187,,"1955-11-05 12:00:13",,"public://images/la fayette.jpeg",,"La Fayette",,"la Fayette dans les bois",,"http://google.fr",,1.2,,5.6295,,2000,,"Nouvelles",,"Carottes" \ No newline at end of file diff --git a/tests/feeds_mapper_multilingual_fields.test b/tests/feeds_mapper_multilingual_fields.test index a37389a..28b6e29 100644 --- a/tests/feeds_mapper_multilingual_fields.test +++ b/tests/feeds_mapper_multilingual_fields.test @@ -5,19 +5,10 @@ * Contains FeedsMapperMultilingualFieldsTestCase. * * @todo - * - All tests + * - testAutocreatedTermLanguage() * - Language for created terms is not set. - * - Figure out why going to node/1/translate is required for translations to - * be available. - * - testChangedLanguageImport() - * - Dutch values are removed after importing French values. - * - testChangedLanguageImportForExistingNode() - * - Dutch values are removed after importing French values. - * - testDisabledLanguage() - * - Values are not imported in LANGUAGE_NONE after disabling French language. - * - Error messages on the mapping screen. - * - testRemovedLanguage() - * - Values are not imported in LANGUAGE_NONE after removing French language. + * - testClearOutValuesWithDisabledLanguage() + * - Values aren't cleared when configured language is no longer available. */ /** @@ -206,13 +197,9 @@ class FeedsMapperMultilingualFieldsTestCase extends FeedsMapperTestCase { $this->addMappings('node', $mappings); // Import file that has items with both English and French field values. - $this->importFile('node', $this->absolutePath() . '/tests/feeds/multilingual.csv'); + $this->importFile('node', $this->absolutePath() . '/tests/feeds/multilingual_en_fr.csv'); $this->assertText(t('Created 1 node')); - // @todo Figure out why this is required for the node to contain the French - // translation. - $this->drupalGet('node/1/translate'); - // Load node. $node = node_load(1, NULL, TRUE); @@ -257,7 +244,6 @@ class FeedsMapperMultilingualFieldsTestCase extends FeedsMapperTestCase { $this->assertText(t('Created 1 node')); // Assert that Dutch values were created. - $this->drupalGet('node/1/translate'); $node = node_load(1, NULL, TRUE); $dutch = $this->getDutchValues($node) + array( 'field_category' => array( @@ -287,7 +273,6 @@ class FeedsMapperMultilingualFieldsTestCase extends FeedsMapperTestCase { $this->assertText(t('Updated 1 node')); // Assert that French values were created. - $this->drupalGet('node/1/translate'); $node = node_load(1, NULL, TRUE); $french = $this->getFrenchValues($node) + array( 'field_category' => array( @@ -403,7 +388,6 @@ class FeedsMapperMultilingualFieldsTestCase extends FeedsMapperTestCase { $this->assertText(t('Updated 1 node')); // Assert that French values were created. - $this->drupalGet('node/1/translate'); $node = node_load(1, NULL, TRUE); $french = $this->getFrenchValues($node) + array( 'field_category' => array( @@ -452,7 +436,6 @@ class FeedsMapperMultilingualFieldsTestCase extends FeedsMapperTestCase { $this->assertText(t('Created 1 node')); // Assert that the fields were all created in French. - $this->drupalGet('node/1/translate'); $node = node_load(1, NULL, TRUE); $french = $this->getFrenchValues($node) + array( 'field_category' => array( @@ -489,7 +472,6 @@ class FeedsMapperMultilingualFieldsTestCase extends FeedsMapperTestCase { $this->assertText(t('Created 1 node')); // Assert that the fields were all created in French. - $this->drupalGet('node/1/translate'); $node = node_load(1, NULL, TRUE); $french = $this->getFrenchValues($node) + array( 'field_category' => array( @@ -528,7 +510,6 @@ class FeedsMapperMultilingualFieldsTestCase extends FeedsMapperTestCase { $this->assertText(t('Created 1 node')); // Assert that the fields were all created in LANGUAGE_NONE. - $this->drupalGet('node/1/translate'); $node = node_load(1, NULL, TRUE); $french = $this->getFrenchValues($node, LANGUAGE_NONE) + array( 'field_category' => array( @@ -561,7 +542,6 @@ class FeedsMapperMultilingualFieldsTestCase extends FeedsMapperTestCase { $this->assertText(t('Created 1 node')); // Assert that the fields were all created in LANGUAGE_NONE. - $this->drupalGet('node/1/translate'); $node = node_load(1, NULL, TRUE); $french = $this->getFrenchValues($node, LANGUAGE_NONE) + array( 'field_category' => array( @@ -611,6 +591,136 @@ class FeedsMapperMultilingualFieldsTestCase extends FeedsMapperTestCase { } /** + * Tests if values are cleared out when an empty value or no value is + * provided. + */ + public function testClearOutValues() { + // Set to update existing nodes. + $this->setSettings('node', 'FeedsNodeProcessor', array( + 'update_existing' => FEEDS_UPDATE_EXISTING, + )); + + // Add English mappers. + $index = 2; + $mappings = $this->getMappingsInLanguage('en', $index); + // Append "_en" to each source name. + foreach ($mappings as &$mapping) { + $mapping['source'] .= '_en'; + } + $this->addMappings('node', $mappings); + $index += count($mappings); + + // Add French mappers. + $mappings = $this->getMappingsInLanguage('fr', $index); + // Append "_fr" to each source name. + foreach ($mappings as &$mapping) { + $mapping['source'] .= '_fr'; + } + $this->addMappings('node', $mappings); + + // Import file that has items with both English and French field values. + $this->importFile('node', $this->absolutePath() . '/tests/feeds/multilingual_en_fr.csv'); + $this->assertText(t('Created 1 node')); + + // Now import a file where the French remained, but the English values were + // removed. + $this->importFile('node', $this->absolutePath() . '/tests/feeds/multilingual_en_fr_empty.csv'); + $this->assertText(t('Updated 1 node')); + + // Load node. + $node = node_load(1, NULL, TRUE); + + // Check that the English values are gone, but the French values are still + // there. + $fields = array( + 'body', + 'field_date', + 'field_datestamp', + 'field_datetime', + 'field_image', + 'field_link', + 'field_number_decimal', + 'field_number_float', + 'field_number_integer', + 'field_category', + 'field_text', + ); + foreach ($fields as $field_name) { + $this->assertTrue(empty($node->{$field_name}['en']), format_string('The field %field is empty.', array('%field' => $field_name))); + } + + // Inspect availability of French values. + // @todo field_image has "la fayette_0.jpeg." + $french = $this->getFrenchValues($node) + array( + 'field_category' => array( + 'expected' => 2, + 'actual' => $node->field_category['fr'][0]['tid'], + ), + ); + foreach ($french as $field_name => $value) { + $this->assertEqual($value['expected'], $value['actual'], format_string('The French field %field has the expected value (actual: @actual).', array('%field' => $field_name, '@actual' => $value['actual']))); + } + } + + /** + * Tests if values are cleared out when an empty value is provided for a + * language that got disabled. + */ + public function testClearOutValuesWithDisabledLanguage() { + // Set to update existing nodes. + $this->setSettings('node', 'FeedsNodeProcessor', array( + 'update_existing' => FEEDS_UPDATE_EXISTING, + )); + + // Configure importer to import in French language. + $this->setSettings('node', 'FeedsNodeProcessor', array( + 'language' => 'fr', + )); + $this->addMappings('node', $this->getMappingsInLanguage('fr')); + + // Now disable the French language. + $path = 'admin/config/regional/language'; + $edit = array( + 'enabled[fr]' => FALSE, + ); + $this->drupalPost($path, $edit, t('Save configuration')); + + // Ensure no error messages are shown on the mappings page. + $this->drupalGet('admin/structure/feeds/node/mapping'); + + // Import content. Since the French language was disabled, the content + // should be imported as LANGUAGE_NONE. + // @see ::testDisabledLanguage() + $this->importFile('node', $this->absolutePath() . '/tests/feeds/multilingual_fr.csv'); + $this->assertText(t('Created 1 node')); + + // Now import a file with empty values. + $this->importFile('node', $this->absolutePath() . '/tests/feeds/multilingual_empty.csv'); + $this->assertText(t('Updated 1 node')); + + // Load node. + $node = node_load(1, NULL, TRUE); + + // Check that the values in LANGUAGE_NONE are gone. + $fields = array( + 'body', + 'field_date', + 'field_datestamp', + 'field_datetime', + 'field_image', + 'field_link', + 'field_number_decimal', + 'field_number_float', + 'field_number_integer', + 'field_category', + 'field_text', + ); + foreach ($fields as $field_name) { + $this->assertTrue(empty($node->{$field_name}[LANGUAGE_NONE]), format_string('The field %field is empty.', array('%field' => $field_name))); + } + } + + /** * Adds a language to test with. * * @param string $langcode @@ -650,6 +760,10 @@ class FeedsMapperMultilingualFieldsTestCase extends FeedsMapperTestCase { foreach ($field_names as $field_name) { $this->drupalPost("admin/structure/types/manage/{$typename}/fields/{$field_name}", $edit, t('Save settings')); } + + // Reset static cache so that all languages are available when + // field_available_languages() is called during node_load(). + drupal_static_reset(); } /**