From b1b072ef8dec726455a603f0eb3de956b32c474d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bobi=CC=81k?= Date: Thu, 7 Aug 2014 20:44:39 +0200 Subject: [PATCH] Issue #1183440: Multilingual Feeds - Make field import language-aware --- feeds.info | 1 + feeds.module | 71 ++++++++++++++++++++ mappers/file.inc | 23 +++++-- mappers/link.inc | 11 +++- mappers/number.inc | 16 ++++- mappers/taxonomy.inc | 33 ++++++++-- mappers/text.inc | 16 ++++- mappers/text.inc.orig | 139 +++++++++++++++++++++++++++++++++++++++ mappers/text.inc.rej | 62 +++++++++++++++++ plugins/FeedsEntityProcessor.inc | 1 + plugins/FeedsNodeProcessor.inc | 1 - plugins/FeedsProcessor.inc | 130 ++++++++++++++++++++++++++++++++++++ tests/feeds_tests.info | 1 + 13 files changed, 483 insertions(+), 22 deletions(-) create mode 100644 mappers/text.inc.orig create mode 100644 mappers/text.inc.rej diff --git a/feeds.info b/feeds.info index eb7387b..c1dbdc3 100644 --- a/feeds.info +++ b/feeds.info @@ -36,6 +36,7 @@ files[] = tests/feeds_mapper_date.test files[] = tests/feeds_mapper_date_multiple.test files[] = tests/feeds_mapper_field.test files[] = tests/feeds_mapper_file.test +files[] = tests/feeds_mapper_multilingual_fields.test files[] = tests/feeds_mapper_path.test files[] = tests/feeds_mapper_profile.test files[] = tests/feeds_mapper.test diff --git a/feeds.module b/feeds.module index cba702d..b9cd6cf 100644 --- a/feeds.module +++ b/feeds.module @@ -896,6 +896,77 @@ function feeds_item_info_save($entity, $entity_id) { } /** + * Returns the language summary text for use in a mapper target summary_callback + * + * @param array $mapping + * Associative array of the mapping settings. + * @param array $target + * Array of target settings, as defined by the processor or + * hook_feeds_processor_targets_alter(). + * @param array $form + * The whole mapping form. + * @param array $form_state + * The form state of the mapping form. + * + * @return string + * Returns, as a string that may contain HTML, the summary to display while + * the full form isn't visible. + * If the return value is empty, no summary and no option to view the form + * will be displayed. + */ +function feeds_mapper_summary_language($mapping, $target, $form, $form_state) { + if (module_exists('locale')) { + list($field_name) = explode(':', $mapping['target']); + $info = field_info_field($field_name); + if ($info['translatable']) { + $language_options = array(LANGUAGE_NONE => t('All languages')) + locale_language_list('name'); + if (empty($mapping['language'])) { + return t('Language: @search', array('@search' => $language_options[LANGUAGE_NONE])); + } + return t('Language: @search', array('@search' => $language_options[$mapping['language']])); + } + } + return FALSE; +} + +/** + * Returns tha language form for use in a mapper target form_callback + * + * @param array $mapping + * Associative array of the mapping settings. + * @param array $target + * Array of target settings, as defined by the processor or + * hook_feeds_processor_targets_alter(). + * @param array $form + * The whole mapping form. + * @param array $form_state + * The form state of the mapping form. + * + * @return string + * Returns, as a string that may contain HTML, the summary to display while + * the full form isn't visible. + * If the return value is empty, no summary and no option to view the form + * will be displayed. + */ +function feeds_mapper_form_language($mapping, $target, $form, $form_state) { + $form = array(); + if (module_exists('locale')) { + list($field_name) = explode(':', $mapping['target']); + $info = field_info_field($field_name); + if ($info['translatable']) { + $language_options = array(LANGUAGE_NONE => t('All languages')) + locale_language_list('name'); + $form['language'] = array( + '#type' => 'select', + '#title' => t('Language'), + '#options' => $language_options, + '#default_value' => !empty($mapping['language']) ? $mapping['language'] : LANGUAGE_NONE, + ); + } + } + return $form; +} + +/** * @} */ diff --git a/mappers/file.inc b/mappers/file.inc index e9cbc26..3e015c9 100644 --- a/mappers/file.inc +++ b/mappers/file.inc @@ -21,6 +21,8 @@ function file_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam 'callback' => 'file_feeds_set_target', 'description' => t('The URI of the @label field.', array('@label' => $instance['label'])), 'real_target' => $name, + 'summary_callback' => 'feeds_mapper_summary_language', + 'form_callback' => 'feeds_mapper_form_language', ); if ($info['type'] == 'image') { @@ -29,12 +31,16 @@ function file_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam 'callback' => 'file_feeds_set_target', 'description' => t('The alt tag of the @label field.', array('@label' => $instance['label'])), 'real_target' => $name, + 'summary_callback' => 'feeds_mapper_summary_language', + 'form_callback' => 'feeds_mapper_form_language', ); $targets[$name . ':title'] = array( 'name' => t('@label: Title', array('@label' => $instance['label'])), 'callback' => 'file_feeds_set_target', 'description' => t('The title of the @label field.', array('@label' => $instance['label'])), 'real_target' => $name, + 'summary_callback' => 'feeds_mapper_summary_language', + 'form_callback' => 'feeds_mapper_form_language', ); } } @@ -48,11 +54,14 @@ function file_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam * user has decided to map to and $value contains the value of the feed item * element the user has picked as a source. */ -function file_feeds_set_target($source, $entity, $target, array $values) { +function file_feeds_set_target($source, $entity, $target, array $values, $mapping = array()) { // Add default of uri for backwards compatibility. list($field_name, $sub_field) = explode(':', $target . ':uri'); $info = field_info_field($field_name); + // Set the language of the field depending on the mapping configuration. + $langcode = isset($mapping['language']) ? $mapping['language'] : LANGUAGE_NONE; + if ($sub_field == 'uri') { foreach ($values as $k => $v) { @@ -84,30 +93,30 @@ function file_feeds_set_target($source, $entity, $target, array $values) { } // Populate entity. - $field = isset($entity->$field_name) ? $entity->$field_name : array(LANGUAGE_NONE => array()); + $field = isset($entity->$field_name) ? $entity->$field_name : array($langcode => array()); $delta = 0; foreach ($values as $v) { if ($info['cardinality'] == $delta) { break; } - if (!isset($field[LANGUAGE_NONE][$delta])) { - $field[LANGUAGE_NONE][$delta] = array(); + if (!isset($field[$langcode][$delta])) { + $field[$langcode][$delta] = array(); } switch ($sub_field) { case 'alt': case 'title': - $field[LANGUAGE_NONE][$delta][$sub_field] = $v; + $field[$langcode][$delta][$sub_field] = $v; break; case 'uri': if ($v) { try { $file = $v->getFile($destination); - $field[LANGUAGE_NONE][$delta] += (array) $file; + $field[$langcode][$delta] += (array) $file; // @todo: Figure out how to properly populate this field. - $field[LANGUAGE_NONE][$delta]['display'] = 1; + $field[$langcode][$delta]['display'] = 1; } catch (Exception $e) { watchdog_exception('Feeds', $e, nl2br(check_plain($e))); diff --git a/mappers/link.inc b/mappers/link.inc index 90b5268..54254a1 100644 --- a/mappers/link.inc +++ b/mappers/link.inc @@ -20,6 +20,8 @@ function link_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam 'callback' => 'link_feeds_set_target', 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])), 'real_target' => $name, + 'summary_callback' => 'feeds_mapper_summary_language', + 'form_callback' => 'feeds_mapper_form_language', ); } if (array_key_exists('title', $info['columns'])) { @@ -28,6 +30,8 @@ function link_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam 'callback' => 'link_feeds_set_target', 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])), 'real_target' => $name, + 'summary_callback' => 'feeds_mapper_summary_language', + 'form_callback' => 'feeds_mapper_form_language', ); } } @@ -41,19 +45,22 @@ function link_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam * user has decided to map to and $value contains the value of the feed item * element the user has picked as a source. */ -function link_feeds_set_target($source, $entity, $target, array $values) { +function link_feeds_set_target($source, $entity, $target, array $values, $mapping = array()) { list($field_name, $column) = explode(':', $target); $field = isset($entity->$field_name) ? $entity->$field_name : array('und' => array()); $delta = 0; + // Set the language of the field depending on the mapping configuration. + $langcode = isset($mapping['language']) ? $mapping['language'] : LANGUAGE_NONE; + foreach ($values as $value) { if (is_object($value) && ($value instanceof FeedsElement)) { $value = $value->getValue(); } if (is_scalar($value)) { - $field['und'][$delta][$column] = (string) $value; + $field[$langcode][$delta][$column] = (string) $value; } $delta++; } diff --git a/mappers/number.inc b/mappers/number.inc index 338d569..7ed7e72 100644 --- a/mappers/number.inc +++ b/mappers/number.inc @@ -27,6 +27,8 @@ function number_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_n 'name' => check_plain($instance['label']), 'callback' => 'number_feeds_set_target', 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])), + 'summary_callback' => 'feeds_mapper_summary_language', + 'form_callback' => 'feeds_mapper_form_language', ); } } @@ -37,9 +39,17 @@ function number_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_n * * Ensure that $value is a numeric to avoid database errors. */ -function number_feeds_set_target($source, $entity, $target, array $values) { +function number_feeds_set_target($source, $entity, $target, array $values, $mapping = array()) { + // Set the language of the field depending on the mapping configuration. + $langcode = isset($mapping['language']) ? $mapping['language'] : LANGUAGE_NONE; + // Iterate over all values. - $field = isset($entity->$target) ? $entity->$target : array('und' => array()); + $field = isset($entity->$target) ? $entity->$target : array($langcode => array()); + + // If it's a new language we need to add it to the field + if (!isset($field[$langcode])) { + $field[$langcode] = array(); + } foreach ($values as $value) { @@ -48,7 +58,7 @@ function number_feeds_set_target($source, $entity, $target, array $values) { } if (is_numeric($value)) { - $field['und'][] = array('value' => $value); + $field[$langcode][] = array('value' => $value); } } diff --git a/mappers/taxonomy.inc b/mappers/taxonomy.inc index 088a558..d513381 100644 --- a/mappers/taxonomy.inc +++ b/mappers/taxonomy.inc @@ -87,7 +87,10 @@ function taxonomy_feeds_set_target($source, $entity, $target, array $terms, $map $mapping += array( 'term_search' => FEEDS_TAXONOMY_SEARCH_TERM_NAME, 'autocreate' => FALSE, + 'language' => LANGUAGE_NONE, ); + // Grab the language for convenience + $langcode = $mapping['language']; $info = field_info_field($target); @@ -110,10 +113,15 @@ function taxonomy_feeds_set_target($source, $entity, $target, array $terms, $map ->range(0, 1); - $field = isset($entity->$target) ? $entity->$target : array('und' => array()); + $field = isset($entity->$target) ? $entity->$target : array($langcode => array()); + + // If it's a new language we need to add it to the field + if (!isset($field[$langcode])) { + $field[$langcode] = array(); + } // Allow for multiple mappings to the same target. - $delta = count($field['und']); + $delta = count($field[$langcode]); // Iterate over all values. foreach ($terms as $term) { @@ -166,7 +174,7 @@ function taxonomy_feeds_set_target($source, $entity, $target, array $terms, $map } if ($tid && isset($cache['allowed_values'][$target][$tid])) { - $field['und'][] = array('tid' => $tid); + $field[$langcode][] = array('tid' => $tid); $delta++; } } @@ -257,11 +265,21 @@ function taxonomy_feeds_term_lookup_term_by_guid($guid) { * will be displayed. */ function taxonomy_feeds_summary_callback($mapping, $target, $form, $form_state) { + $output = ''; $options = _taxonomy_feeds_form_callback_options(); if (empty($mapping['term_search'])) { - return t('Search taxonomy terms by: @search', array('@search' => $options[FEEDS_TAXONOMY_SEARCH_TERM_NAME])); + $output = t('Search taxonomy terms by: @search', array('@search' => $options[FEEDS_TAXONOMY_SEARCH_TERM_NAME])); + } + else { + $output = t('Search taxonomy terms by: @search', array('@search' => $options[$mapping['term_search']])); + } + if ($language_summary = feeds_mapper_summary_language($mapping, $target, $form, $form_state)) { + $output .= '
' . $language_summary; } - return t('Search taxonomy terms by: @search', array('@search' => $options[$mapping['term_search']])); + if (!empty($mapping['autocreate'])) { + $output .= '
' . t('Autocreate Terms: Yes'); + } + return $output; } /** @@ -272,7 +290,8 @@ function taxonomy_feeds_summary_callback($mapping, $target, $form, $form_state) * be populated with the form values. */ function taxonomy_feeds_form_callback($mapping, $target, $form, $form_state) { - return array( + $return = feeds_mapper_form_language($mapping, $target, $form, $form_state); + $return += array( 'term_search' => array( '#type' => 'select', '#title' => t('Search taxonomy terms by'), @@ -291,6 +310,8 @@ function taxonomy_feeds_form_callback($mapping, $target, $form, $form_state) { ), ), ); + + return $return; } /** diff --git a/mappers/text.inc b/mappers/text.inc index 235aea3..f9a6633 100644 --- a/mappers/text.inc +++ b/mappers/text.inc @@ -25,6 +25,8 @@ function text_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam 'name' => check_plain($instance['label']), 'callback' => 'text_feeds_set_target', 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])), + 'summary_callback' => 'feeds_mapper_summary_language', + 'form_callback' => 'feeds_mapper_form_language', ); if ($info['type'] == 'text_with_summary') { // Allow mapping to summary. @@ -58,7 +60,15 @@ function text_feeds_set_target(FeedsSource $source, $entity, $target, array $val ); } - $field = isset($entity->$field_name) ? $entity->$field_name : array('und' => array()); + // Set the language of the field depending on the mapping configuration. + $langcode = isset($mapping['language']) ? $mapping['language'] : LANGUAGE_NONE; + + $field = isset($entity->$target) ? $entity->$target : array($langcode => array()); + + // If it's a new language we need to add it to the field + if (!isset($field[$langcode])) { + $field[$langcode] = array(); + } // Iterate over all values. $delta = 0; @@ -70,10 +80,10 @@ function text_feeds_set_target(FeedsSource $source, $entity, $target, array $val if (is_scalar($value) && strlen($value)) { - $field['und'][$delta][$column] = (string) $value; + $field[$langcode][$delta][$column] = (string) $value; if (isset($mapping['format'])) { - $field['und'][$delta]['format'] = $mapping['format']; + $field[$langcode][$delta]['format'] = $format; } } diff --git a/mappers/text.inc.orig b/mappers/text.inc.orig new file mode 100644 index 0000000..235aea3 --- /dev/null +++ b/mappers/text.inc.orig @@ -0,0 +1,139 @@ + $instance) { + $info = field_info_field($name); + + if (in_array($info['type'], $text_types)) { + $targets[$name] = array( + 'name' => check_plain($instance['label']), + 'callback' => 'text_feeds_set_target', + 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])), + ); + if ($info['type'] == 'text_with_summary') { + // Allow mapping to summary. + $targets[$name . ':summary'] = array( + 'name' => t('@name: Summary', array('@name' => $instance['label'])), + 'callback' => 'text_feeds_set_target', + 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])), + 'real_target' => $name, + ); + } + } + + if (!empty($instance['settings']['text_processing'])) { + $targets[$name]['summary_callback'] = 'text_feeds_summary_callback'; + $targets[$name]['form_callback'] = 'text_feeds_form_callback'; + } + } +} + +/** + * Callback for mapping text fields. + */ +function text_feeds_set_target(FeedsSource $source, $entity, $target, array $values, array $mapping = array()) { + list($field_name, $column) = explode(':', $target . ':value'); + + if ($column === 'value' && isset($source->importer->processor->config['input_format'])) { + $format = $source->importer->processor->config['input_format']; + // Add in default values. + $mapping += array( + 'format' => $format, + ); + } + + $field = isset($entity->$field_name) ? $entity->$field_name : array('und' => array()); + + // Iterate over all values. + $delta = 0; + foreach ($values as $value) { + + if (is_object($value) && $value instanceof FeedsElement) { + $value = $value->getValue(); + } + + if (is_scalar($value) && strlen($value)) { + + $field['und'][$delta][$column] = (string) $value; + + if (isset($mapping['format'])) { + $field['und'][$delta]['format'] = $mapping['format']; + } + } + + $delta++; + } + + $entity->$field_name = $field; +} + +/** + * Summary callback for text field targets. + * + * Displays which text format will be used for the text field target. + * + * @see text_feeds_processor_targets_alter() + * @see text_feeds_form_callback() + */ +function text_feeds_summary_callback(array $mapping, $target, array $form, array $form_state) { + global $user; + $formats = filter_formats($user); + + // Processor-wide input format setting. + $importer = feeds_importer($form['#importer']); + $default_format = !empty($importer->processor->config['input_format']) ? $importer->processor->config['input_format'] : filter_fallback_format(); + $mapping += array( + 'format' => $default_format, + ); + + return t('Text format: %format', array('%format' => $formats[$mapping['format']]->name)); +} + +/** + * Form callback for text field targets. + * + * Allows to select a text format for the text field target. + * + * @see text_feeds_processor_targets_alter() + * @see text_feeds_summary_callback() + */ +function text_feeds_form_callback(array $mapping, $target, array $form, array $form_state) { + global $user; + $formats_options = array(); + $formats = filter_formats($user); + foreach ($formats as $id => $format) { + $formats_options[$id] = $format->name; + } + + // Processor-wide text format setting. + $importer = feeds_importer($form['#importer']); + $default_format = !empty($importer->processor->config['input_format']) ? $importer->processor->config['input_format'] : filter_fallback_format(); + $mapping += array( + 'format' => $default_format, + ); + + return array( + 'format' => array( + '#type' => 'select', + '#title' => t('Text format'), + '#options' => $formats_options, + '#default_value' => $mapping['format'], + ), + ); +} diff --git a/mappers/text.inc.rej b/mappers/text.inc.rej new file mode 100644 index 0000000..88e8d29 --- /dev/null +++ b/mappers/text.inc.rej @@ -0,0 +1,62 @@ +*************** +*** 42,55 **** + /** + * Callback for mapping text fields. + */ +- function text_feeds_set_target($source, $entity, $target, array $values) { + list($field_name, $column) = explode(':', $target . ':value'); + + if ($column === 'value' && isset($source->importer->processor->config['input_format'])) { + $format = $source->importer->processor->config['input_format']; + } + +- $field = isset($entity->$field_name) ? $entity->$field_name : array('und' => array()); + + // Iterate over all values. + $delta = 0; +--- 44,65 ---- + /** + * Callback for mapping text fields. + */ ++ function text_feeds_set_target($source, $entity, $target, array $values, $mapping = array()) { + list($field_name, $column) = explode(':', $target . ':value'); + + if ($column === 'value' && isset($source->importer->processor->config['input_format'])) { + $format = $source->importer->processor->config['input_format']; + } + ++ // Set the language of the field depending on the mapping configuration. ++ $langcode = isset($mapping['language']) ? $mapping['language'] : LANGUAGE_NONE; ++ ++ $field = isset($entity->$target) ? $entity->$target : array($langcode => array()); ++ ++ // If it's a new language we need to add it to the field ++ if (!isset($field[$langcode])) { ++ $field[$langcode] = array(); ++ } + + // Iterate over all values. + $delta = 0; +*************** +*** 61,70 **** + + if (is_scalar($value) && strlen($value)) { + +- $field['und'][$delta][$column] = (string) $value; + + if (isset($format)) { +- $field['und'][$delta]['format'] = $format; + } + } + +--- 71,80 ---- + + if (is_scalar($value) && strlen($value)) { + ++ $field[$langcode][$delta][$column] = (string) $value; + + if (isset($format)) { ++ $field[$langcode][$delta]['format'] = $format; + } + } + diff --git a/plugins/FeedsEntityProcessor.inc b/plugins/FeedsEntityProcessor.inc index 833800f..725753a 100644 --- a/plugins/FeedsEntityProcessor.inc +++ b/plugins/FeedsEntityProcessor.inc @@ -135,6 +135,7 @@ class FeedsEntityProcessor extends FeedsProcessor { 'skip_hash_check' => FALSE, 'bundle' => NULL, 'values' => array(), + 'language' => LANGUAGE_NONE, ); } diff --git a/plugins/FeedsNodeProcessor.inc b/plugins/FeedsNodeProcessor.inc index 8b63c53..d490c3c 100644 --- a/plugins/FeedsNodeProcessor.inc +++ b/plugins/FeedsNodeProcessor.inc @@ -34,7 +34,6 @@ class FeedsNodeProcessor extends FeedsProcessor { $node->type = $this->bundle(); $node->changed = REQUEST_TIME; $node->created = REQUEST_TIME; - $node->language = LANGUAGE_NONE; $node->is_new = TRUE; node_object_prepare($node); // Populate properties that are set by node_object_prepare(). diff --git a/plugins/FeedsProcessor.inc b/plugins/FeedsProcessor.inc index 833cd2c..969b015 100755 --- a/plugins/FeedsProcessor.inc +++ b/plugins/FeedsProcessor.inc @@ -14,6 +14,9 @@ define('FEEDS_UPDATE_EXISTING', 2); // processors. define('FEEDS_PROCESS_LIMIT', 50); +// Default Language trigger +define('FEEDS_LANGUAGE_DEFAULT', 'xx_'); + /** * Thrown if a validation fails. */ @@ -77,6 +80,23 @@ abstract class FeedsProcessor extends FeedsPlugin { } /** + * Provides a list of language options for use in select lists. + * + * @return array + * A keyed array of langcode => language. + */ + public function languageOptions() { + $options = array( + FEEDS_LANGUAGE_DEFAULT => t('Default Language'), + LANGUAGE_NONE => t('Language neutral'), + ); + foreach (language_list() as $langcode => $language) { + $options[$langcode] = $language->name; + } + return $options; + } + + /** * Create a new entity. * * @param $source @@ -216,11 +236,16 @@ abstract class FeedsProcessor extends FeedsPlugin { // Build a new entity. else { $entity = $this->newEntity($source); + // Set the language if it wasn't set specifically by a processor + if (!isset($entity->language)) { + $entity->language = $this->getConfigLanguage(); + } $this->newItemInfo($entity, $source->feed_nid, $hash); } // Set property and field values. $this->map($source, $parser_result, $entity); + $this->processEntityTitleReplacements($entity); $this->entityValidate($entity); // Allow modules to alter the entity before saving. @@ -236,6 +261,7 @@ abstract class FeedsProcessor extends FeedsPlugin { // This will throw an exception on failure. $this->entitySaveAccess($entity); + $this->processTranslations($entity); $this->entitySave($entity); // Allow modules to perform operations using the saved entity data. @@ -609,6 +635,7 @@ abstract class FeedsProcessor extends FeedsPlugin { 'input_format' => NULL, 'skip_hash_check' => FALSE, 'bundle' => $bundle, + 'language' => LANGUAGE_NONE, ); } @@ -635,6 +662,14 @@ abstract class FeedsProcessor extends FeedsPlugin { ); } + $form['language'] = array( + '#type' => 'select', + '#options' => $this->languageOptions(), + '#title' => t('Language'), + '#required' => TRUE, + '#default_value' => $this->config['language'], + ); + $tokens = array('@entities' => strtolower($info['label plural'])); $form['update_existing'] = array( @@ -732,6 +767,101 @@ abstract class FeedsProcessor extends FeedsPlugin { } /** + * Returns the configured language for the processor + * + * @return + * The language code configured for the processor + */ + public function getConfigLanguage() { + return ($this->config['language'] == FEEDS_LANGUAGE_DEFAULT) ? language_default('language') : $this->config['language']; + } + + /** + * Returns the language for the entity. + * + * @param string $entity + * The entity for which to get the language. + * + * @return + * The language code for the entity, or the language code that's configured + * for the processor if the entity doesn't have any language support. + */ + public function getEntityLanguage($entity) { + $language = entity_language($this->entityType(), $entity); + return $language ? $language : $this->getConfigLanguage(); + } + + /** + * Process entity properties that have been replaced with the title module + * + * @param object $entity + * The entity to check for replaced properties + */ + public function processEntityTitleReplacements(&$entity) { + if (module_exists('title')) { + // Get the possible replacements for this entity type + if ($replacements = title_field_replacement_info($this->entityType())) { + // Loop through replacements + foreach ($replacements as $legacy_field => $field_info) { + // Populate legacy field with value from the field of the language + // for the entity. + $language = $this->getEntityLanguage($entity); + if (!empty($entity->{$field_info['field']['field_name']}[$language]) && empty($entity->{$legacy_field})) { + $entity->{$legacy_field} = $entity->{$field_info['field']['field_name']}[$language][0]['value']; + } + } + } + } + } + + /** + * Add translations to an entity for each mapped language + * + * @param object $entity + * The entity to add translations to + */ + public function processTranslations(&$entity) { + // Add translations (if the entity_translation module exists) provided at + // least one field has a translation + if (module_exists('entity_translation')) { + $handler = entity_translation_get_handler($this->entityType(), $entity); + $languages = array(); + $default_langcode = $this->getEntityLanguage($entity); + + // Init the translations if there's not translation data yet + if (empty($entity->translations->data)) { + $handler->initTranslations(); + } + + // Loop through the mappings + foreach ($this->getMappings() as $mapping) { + if (!empty($mapping['language']) && $mapping['language'] != LANGUAGE_NONE && $mapping['language'] != $default_langcode && empty($entity->translations->data[$mapping['language']])) { + list($field_name) = explode(':', $mapping['target']); + + // If this field's language has items we create a translation for it + if (!empty($entity->{$field_name}[$mapping['language']])) { + $translation = array( + 'translate' => 0, + 'status' => 1, + 'language' => $mapping['language'], + 'source' => $default_langcode, + ); + $handler->setTranslation($translation, $entity); + } + } + } + + // Loop through every language for the site, and remove translations for + // the one that hasn't got any values. + foreach (language_list() as $language) { + if (!isset($entity->translations->data[$language->language])) { + $handler->removeTranslation($language->language); + } + } + } + } + + /** * Retrieve the target entity's existing id if available. Otherwise return 0. * * @ingroup mappingapi diff --git a/tests/feeds_tests.info b/tests/feeds_tests.info index 0e1d123..f135070 100644 --- a/tests/feeds_tests.info +++ b/tests/feeds_tests.info @@ -4,4 +4,5 @@ package = Testing version = VERSION core = 7.x test_dependencies[] = entity +test_dependencies[] = entity_translation hidden = TRUE -- 1.8.3.4