diff --git a/feeds.api.php b/feeds.api.php
index c139da1..89188f2 100644
--- a/feeds.api.php
+++ b/feeds.api.php
@@ -283,8 +283,8 @@ function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle) {
// Specify both summary_callback and form_callback to add a per mapping
// configuration form.
- 'summary_callback' => 'my_module_summary_callback',
- 'form_callback' => 'my_module_form_callback',
+ 'summary_callback' => array('my_module_summary_callback'),
+ 'form_callback' => array('my_module_form_callback'),
);
$targets['my_node_field2'] = array(
'name' => t('My Second custom node field'),
diff --git a/feeds.info b/feeds.info
index 6e32601..eadb544 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_unique.test
diff --git a/feeds.module b/feeds.module
index 419e071..8becf38 100644
--- a/feeds.module
+++ b/feeds.module
@@ -35,6 +35,7 @@ function feeds_hook_info() {
'feeds_after_save',
'feeds_after_import',
'feeds_after_clear',
+ 'feeds_processor_targets',
'feeds_processor_targets_alter',
'feeds_parser_sources_alter',
);
@@ -904,6 +905,83 @@ function feeds_item_info_save($entity, $entity_id) {
}
/**
+ * Implements hook_feeds_processor_targets_alter().
+ */
+function locale_feeds_processor_targets_alter(array &$targets, $entity_type, $bundle_name) {
+ $language_options = feeds_mapper_options_language();
+
+ foreach ($targets as $target => $target_config) {
+ list($field_name) = explode(':', $target);
+ if (!$info = field_info_field($field_name)) {
+ continue;
+ }
+ if (!$info['translatable']) {
+ continue;
+ }
+
+ $targets[$target]['summary_callback'][] = 'feeds_mapper_locale_summary';
+ $targets[$target]['form_callback'][] = 'feeds_mapper_locale_form';
+ $targets[$target]['preprocess_callback'][] = 'feeds_mapper_locale_preprocess';
+ }
+}
+
+/**
+ * Summary callback for language configuration.
+ */
+function feeds_mapper_locale_summary(array $mapping, array $target, array $form, array &$form_state) {
+ list($field_name) = explode(':', $mapping['target']);
+ $info = field_info_field($field_name);
+
+ if ($info['translatable']) {
+ $language_options = feeds_mapper_options_language();
+ if (empty($mapping['language'])) {
+ return t('Language: @search', array('@search' => $language_options[LANGUAGE_NONE]));
+ }
+ return t('Language: @search', array('@search' => $language_options[$mapping['language']]));
+ }
+}
+
+/**
+ * Callback for language mapper configuration form.
+ */
+function feeds_mapper_locale_form(array $mapping, array $target, array $form, array &$form_state) {
+ list($field_name) = explode(':', $mapping['target']);
+ $info = field_info_field($field_name);
+ if ($info['translatable']) {
+ $form['language'] = array(
+ '#type' => 'select',
+ '#title' => t('Language'),
+ '#options' => feeds_mapper_options_language(),
+ '#default_value' => !empty($mapping['language']) ? $mapping['language'] : LANGUAGE_NONE,
+ '#description' => t('You can select a particular field language (or language nautral) or use language code saved in entity\'s language property (e.g. $node->language) you set by some mapper above.'),
+ );
+ }
+ return $form;
+}
+
+/**
+ * Callback for processing the mapping configuration.
+ */
+function feeds_mapper_locale_preprocess(FeedsSource $source, $entity, $target, array $terms, array &$mapping) {
+ // Set the language of the field depending on the mapping configuration.
+ $mapping['language'] = !empty($mapping['language']) ? $mapping['language'] : LANGUAGE_NONE;
+ $mapping['language'] = $mapping['language'] === 'from_property' ? $entity->language : $mapping['language'];
+}
+
+/**
+ * Return the options list of language options for target configuration.
+ *
+ * @return array
+ * A list of available language options.
+ */
+function feeds_mapper_options_language() {
+ return array(
+ 'from_property' => t('Inherit language'),
+ LANGUAGE_NONE => t('Language neutral'),
+ ) + locale_language_list('name');
+}
+
+/**
* @}
*/
diff --git a/feeds_ui/feeds_ui.admin.inc b/feeds_ui/feeds_ui.admin.inc
index 45b423c..01a7493 100644
--- a/feeds_ui/feeds_ui.admin.inc
+++ b/feeds_ui/feeds_ui.admin.inc
@@ -633,12 +633,10 @@ function feeds_ui_mapping_settings_form($form, $form_state, $i, $mapping, $targe
}
if ($form_state['mapping_settings_edit'] === $i) {
+ $settings_form = array();
// Build the form.
- if (isset($target['form_callback'])) {
- $settings_form = call_user_func($target['form_callback'], $mapping, $target, $form, $form_state);
- }
- else {
- $settings_form = array();
+ foreach ((array) $target['form_callback'] as $callback) {
+ $settings_form += $callback($mapping, $target, array(), $form_state);
}
// Merge in the optional unique form.
@@ -663,12 +661,11 @@ function feeds_ui_mapping_settings_form($form, $form_state, $i, $mapping, $targe
}
else {
// Build the summary.
- if (isset($target['summary_callback'])) {
- $summary = call_user_func($target['summary_callback'], $mapping, $target, $form, $form_state);
- }
- else {
- $summary = '';
+ $summary = array();
+ foreach ((array) $target['summary_callback'] as $callback) {
+ $summary[] = $callback($mapping, $target, $form, $form_state);
}
+ $summary = implode('
', $summary);
// Append the optional unique summary.
if ($optional_unique_summary = feeds_ui_mapping_settings_optional_unique_summary($mapping, $target, $form, $form_state)) {
diff --git a/mappers/date.inc b/mappers/date.inc
index 061962d..165db5a 100644
--- a/mappers/date.inc
+++ b/mappers/date.inc
@@ -6,13 +6,12 @@
*/
/**
- * Implements hook_feeds_processor_targets_alter().
- *
- * @see FeedsNodeProcessor::getMappingTargets().
+ * Implements hook_feeds_processor_targets().
*
* @todo Only provides "end date" target if field allows it.
*/
-function date_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+function date_feeds_processor_targets($entity_type, $bundle_name) {
+ $targets = array();
foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name);
if (in_array($info['type'], array('date', 'datestamp', 'datetime'))) {
@@ -30,12 +29,13 @@ function date_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
);
}
}
+ return $targets;
}
/**
* Callback for setting target values.
*/
-function date_feeds_set_target($source, $entity, $target, array $values) {
+function date_feeds_set_target(FeedsSource $source, $entity, $target, array $values, array $mapping) {
list($field_name, $sub_field) = explode(':', $target, 2);
$delta = 0;
diff --git a/mappers/file.inc b/mappers/file.inc
index e9cbc26..3c73d38 100644
--- a/mappers/file.inc
+++ b/mappers/file.inc
@@ -7,11 +7,10 @@
*/
/**
- * Implements hook_feeds_processor_targets_alter().
- *
- * @see FeedsNodeProcessor::getMappingTargets()
+ * Implements hook_feeds_processor_targets().
*/
-function file_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+function file_feeds_processor_targets($entity_type, $bundle_name) {
+ $targets = array();
foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name);
@@ -39,16 +38,13 @@ function file_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
}
}
}
+ return $targets;
}
/**
- * Callback for mapping. Here is where the actual mapping happens.
- *
- * When the callback is invoked, $target contains the name of the field the
- * user has decided to map to and $value contains the value of the feed item
- * element the user has picked as a source.
+ * Callback for mapping files.
*/
-function file_feeds_set_target($source, $entity, $target, array $values) {
+function file_feeds_set_target(FeedsSource $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);
@@ -84,30 +80,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($mapping['language'] => 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[$mapping['language']][$delta])) {
+ $field[$mapping['language']][$delta] = array();
}
switch ($sub_field) {
case 'alt':
case 'title':
- $field[LANGUAGE_NONE][$delta][$sub_field] = $v;
+ $field[$mapping['language']][$delta][$sub_field] = $v;
break;
case 'uri':
if ($v) {
try {
$file = $v->getFile($destination);
- $field[LANGUAGE_NONE][$delta] += (array) $file;
+ $field[$mapping['language']][$delta] += (array) $file;
// @todo: Figure out how to properly populate this field.
- $field[LANGUAGE_NONE][$delta]['display'] = 1;
+ $field[$mapping['language']][$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..7a64e10 100644
--- a/mappers/link.inc
+++ b/mappers/link.inc
@@ -6,11 +6,10 @@
*/
/**
- * Implements hook_feeds_processor_targets_alter().
- *
- * @see FeedsProcessor::getMappingTargets()
+ * Implements hook_feeds_processor_targets().
*/
-function link_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+function link_feeds_processor_targets($entity_type, $bundle_name) {
+ $targets = array();
foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name);
if ($info['type'] == 'link_field') {
@@ -32,6 +31,7 @@ function link_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
}
}
}
+ return $targets;
}
/**
@@ -41,10 +41,10 @@ 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(FeedsSource $source, $entity, $target, array $values, array $mapping) {
list($field_name, $column) = explode(':', $target);
- $field = isset($entity->$field_name) ? $entity->$field_name : array('und' => array());
+ $field = isset($entity->$field_name) ? $entity->$field_name : array($mapping['language'] => array());
$delta = 0;
foreach ($values as $value) {
@@ -53,7 +53,7 @@ function link_feeds_set_target($source, $entity, $target, array $values) {
}
if (is_scalar($value)) {
- $field['und'][$delta][$column] = (string) $value;
+ $field[$mapping['language']][$delta][$column] = (string) $value;
}
$delta++;
}
diff --git a/mappers/number.inc b/mappers/number.inc
index 338d569..6541aa1 100644
--- a/mappers/number.inc
+++ b/mappers/number.inc
@@ -6,11 +6,10 @@
*/
/**
- * Implements hook_feeds_processor_targets_alter().
- *
- * @see FeedsProcessor::getMappingTargets()
+ * Implements hook_feeds_processor_targets().
*/
-function number_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+function number_feeds_processor_targets($entity_type, $bundle_name) {
+ $targets = array();
$numeric_types = array(
'list_integer',
'list_float',
@@ -30,6 +29,7 @@ function number_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_n
);
}
}
+ return $targets;
}
/**
@@ -37,9 +37,9 @@ 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(FeedsSource $source, $entity, $target, array $values, array $mapping) {
// Iterate over all values.
- $field = isset($entity->$target) ? $entity->$target : array('und' => array());
+ $field = isset($entity->$target) ? $entity->$target : array($mapping['language'] => array());
foreach ($values as $value) {
@@ -48,7 +48,7 @@ function number_feeds_set_target($source, $entity, $target, array $values) {
}
if (is_numeric($value)) {
- $field['und'][] = array('value' => $value);
+ $field[$mapping['language']][] = array('value' => $value);
}
}
diff --git a/mappers/path.inc b/mappers/path.inc
index cd39fb1..8d86391 100644
--- a/mappers/path.inc
+++ b/mappers/path.inc
@@ -6,11 +6,11 @@
*/
/**
- * Implements hook_feeds_processor_targets_alter().
- *
- * @see FeedsNodeProcessor::getMappingTargets().
+ * Implements hook_feeds_processor_targets().
*/
-function path_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+function path_feeds_processor_targets($entity_type, $bundle_name) {
+ $targets = array();
+
switch ($entity_type) {
case 'node':
case 'taxonomy_term':
@@ -19,11 +19,12 @@ function path_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
'name' => t('Path alias'),
'description' => t('URL path alias of the node.'),
'callback' => 'path_feeds_set_target',
- 'summary_callback' => 'path_feeds_summary_callback',
- 'form_callback' => 'path_feeds_form_callback',
+ 'summary_callback' => array('path_feeds_summary_callback'),
+ 'form_callback' => array('path_feeds_form_callback'),
);
break;
}
+ return $targets;
}
/**
@@ -73,7 +74,7 @@ function path_feeds_set_target($source, $entity, $target, array $values, $mappin
* Associative array of the mapping settings.
* @param $target
* Array of target settings, as defined by the processor or
- * hook_feeds_processor_targets_alter().
+ * hook_feeds_processor_targets().
* @param $form
* The whole mapping form.
* @param $form_state
diff --git a/mappers/profile.inc b/mappers/profile.inc
index 00fdf3a..20f4843 100644
--- a/mappers/profile.inc
+++ b/mappers/profile.inc
@@ -6,10 +6,10 @@
*/
/**
- * Implements hook_feeds_processor_target_alter().
+ * Implements hook_feeds_processor_targets().
*/
-function profile_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
-
+function profile_feeds_processor_targets($entity_type, $bundle_name) {
+ $targets = array();
if ($entity_type != 'user') {
return;
}
@@ -25,6 +25,7 @@ function profile_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_
);
}
}
+ return $targets;
}
/**
diff --git a/mappers/taxonomy.inc b/mappers/taxonomy.inc
index 088a558..5b6e5ef 100644
--- a/mappers/taxonomy.inc
+++ b/mappers/taxonomy.inc
@@ -55,9 +55,10 @@ function taxonomy_feeds_get_source(FeedsSource $source, FeedsParserResult $resul
}
/**
- * Implements hook_feeds_processor_targets_alter().
+ * Implements hook_feeds_processor_targets().
*/
-function taxonomy_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+function taxonomy_feeds_processor_targets($entity_type, $bundle_name) {
+ $targets = array();
foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name);
if ($info['type'] == 'taxonomy_term_reference') {
@@ -65,8 +66,9 @@ function taxonomy_feeds_processor_targets_alter(&$targets, $entity_type, $bundle
'name' => check_plain($instance['label']),
'callback' => 'taxonomy_feeds_set_target',
'description' => t('The @label field of the entity.', array('@label' => $instance['label'])),
- 'summary_callback' => 'taxonomy_feeds_summary_callback',
- 'form_callback' => 'taxonomy_feeds_form_callback',
+ 'summary_callback' => array('taxonomy_feeds_summary_callback'),
+ 'form_callback' => array('taxonomy_feeds_form_callback'),
+ 'preprocess_callback' => array('taxonomy_feeds_preprocess_callback'),
);
}
}
@@ -75,20 +77,26 @@ function taxonomy_feeds_processor_targets_alter(&$targets, $entity_type, $bundle
$targets['tid']['description'] = t('The tid of the taxonomy term. NOTE: use this feature with care, node ids are usually assigned by Drupal.');
unset($targets['vocabulary']);
}
+ return $targets;
}
/**
- * Callback for mapping. Here is where the actual mapping happens.
- *
- * @todo Do not create new terms for non-autotag fields.
+ * Callback for processing the mapping array.
*/
-function taxonomy_feeds_set_target($source, $entity, $target, array $terms, $mapping = array()) {
+function taxonomy_feeds_preprocess_callback(FeedsSource $source, $entity, $target, array $terms, array &$mapping) {
// Add in default values.
$mapping += array(
'term_search' => FEEDS_TAXONOMY_SEARCH_TERM_NAME,
'autocreate' => FALSE,
);
+}
+/**
+ * Callback for mapping. Here is where the actual mapping happens.
+ *
+ * @todo Do not create new terms for non-autotag fields.
+ */
+function taxonomy_feeds_set_target(FeedsSource $source, $entity, $target, array $terms, array $mapping) {
$info = field_info_field($target);
$cache = &drupal_static(__FUNCTION__);
@@ -110,10 +118,10 @@ 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($mapping['language'] => array());
// Allow for multiple mappings to the same target.
- $delta = count($field['und']);
+ $delta = count($field[$mapping['language']]);
// 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[$mapping['language']][] = array('tid' => $tid);
$delta++;
}
}
@@ -244,7 +252,7 @@ function taxonomy_feeds_term_lookup_term_by_guid($guid) {
* Associative array of the mapping settings.
* @param array $target
* Array of target settings, as defined by the processor or
- * hook_feeds_processor_targets_alter().
+ * hook_feeds_processor_targets().
* @param array $form
* The whole mapping form.
* @param array $form_state
diff --git a/mappers/text.inc b/mappers/text.inc
index 235aea3..7d4c60d 100644
--- a/mappers/text.inc
+++ b/mappers/text.inc
@@ -6,11 +6,10 @@
*/
/**
- * Implements hook_feeds_processor_targets_alter().
- *
- * @see FeedsProcessor::getMappingTargets()
+ * Implements hook_feeds_processor_targets().
*/
-function text_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+function text_feeds_processor_targets($entity_type, $bundle_name) {
+ $targets = array();
$text_types = array(
'list_text',
'text',
@@ -38,16 +37,17 @@ function text_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
}
if (!empty($instance['settings']['text_processing'])) {
- $targets[$name]['summary_callback'] = 'text_feeds_summary_callback';
- $targets[$name]['form_callback'] = 'text_feeds_form_callback';
+ $targets[$name]['summary_callback'] = array('text_feeds_summary_callback');
+ $targets[$name]['form_callback'] = array('text_feeds_form_callback');
}
}
+ return $targets;
}
/**
* Callback for mapping text fields.
*/
-function text_feeds_set_target(FeedsSource $source, $entity, $target, array $values, array $mapping = array()) {
+function text_feeds_set_target(FeedsSource $source, $entity, $target, array $values, array $mapping) {
list($field_name, $column) = explode(':', $target . ':value');
if ($column === 'value' && isset($source->importer->processor->config['input_format'])) {
@@ -58,7 +58,7 @@ function text_feeds_set_target(FeedsSource $source, $entity, $target, array $val
);
}
- $field = isset($entity->$field_name) ? $entity->$field_name : array('und' => array());
+ $field = isset($entity->$field_name) ? $entity->$field_name : array($mapping['language'] => array());
// Iterate over all values.
$delta = 0;
@@ -70,10 +70,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[$mapping['language']][$delta][$column] = (string) $value;
if (isset($mapping['format'])) {
- $field['und'][$delta]['format'] = $mapping['format'];
+ $field[$mapping['language']][$delta]['format'] = $mapping['format'];
}
}
@@ -88,7 +88,7 @@ function text_feeds_set_target(FeedsSource $source, $entity, $target, array $val
*
* Displays which text format will be used for the text field target.
*
- * @see text_feeds_processor_targets_alter()
+ * @see text_feeds_processor_targets()
* @see text_feeds_form_callback()
*/
function text_feeds_summary_callback(array $mapping, $target, array $form, array $form_state) {
@@ -110,7 +110,7 @@ function text_feeds_summary_callback(array $mapping, $target, array $form, array
*
* Allows to select a text format for the text field target.
*
- * @see text_feeds_processor_targets_alter()
+ * @see text_feeds_processor_targets()
* @see text_feeds_summary_callback()
*/
function text_feeds_form_callback(array $mapping, $target, array $form, array $form_state) {
diff --git a/plugins/FeedsEntityProcessor.inc b/plugins/FeedsEntityProcessor.inc
index 5125c94..4e48fe9 100644
--- a/plugins/FeedsEntityProcessor.inc
+++ b/plugins/FeedsEntityProcessor.inc
@@ -260,10 +260,7 @@ class FeedsEntityProcessor extends FeedsProcessor {
unset($targets[$entity_info['bundle keys']['bundle']]);
}
- // Let other modules expose mapping targets.
- self::loadMappers();
- $type = $this->entityType();
- drupal_alter('feeds_processor_targets', $targets, $type, $info['bundle']);
+ $this->getHookTargets($targets);
return $targets;
}
diff --git a/plugins/FeedsNodeProcessor.inc b/plugins/FeedsNodeProcessor.inc
index d3d3bb4..1f8e584 100644
--- a/plugins/FeedsNodeProcessor.inc
+++ b/plugins/FeedsNodeProcessor.inc
@@ -339,11 +339,7 @@ class FeedsNodeProcessor extends FeedsProcessor {
);
}
- // Let other modules expose mapping targets.
- self::loadMappers();
- $entity_type = $this->entityType();
- $bundle = $this->bundle();
- drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle);
+ $this->getHookTargets($targets);
return $targets;
}
diff --git a/plugins/FeedsProcessor.inc b/plugins/FeedsProcessor.inc
index 1c56f62..baa59fd 100755
--- a/plugins/FeedsProcessor.inc
+++ b/plugins/FeedsProcessor.inc
@@ -80,6 +80,21 @@ 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() {
+ if (!module_exists('locale')) {
+ return array();
+ }
+ return array(
+ LANGUAGE_NONE => t('Language neutral'),
+ ) + locale_language_list('name') ;
+ }
+
+ /**
* Create a new entity.
*
* @param $source
@@ -669,6 +684,11 @@ abstract class FeedsProcessor extends FeedsPlugin {
$value = array($value);
}
+ foreach ($mapping['preprocess_callback'] as $preprocess) {
+ $preprocess($source, $target_item, $mapping['target'], $value, $mapping);
+ }
+ $mapping += array('language' => $this->config['language']);
+
$callback($source, $target_item, $mapping['target'], $value, $mapping);
}
else {
@@ -703,6 +723,7 @@ abstract class FeedsProcessor extends FeedsPlugin {
'input_format' => NULL,
'skip_hash_check' => FALSE,
'bundle' => $bundle,
+ 'language' => LANGUAGE_NONE,
);
}
@@ -729,6 +750,16 @@ abstract class FeedsProcessor extends FeedsPlugin {
);
}
+ if (module_exists('locale')) {
+ $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(
@@ -820,6 +851,27 @@ abstract class FeedsProcessor extends FeedsPlugin {
}
/**
+ * Allows other modules to expose targets.
+ *
+ * @param array &$targets
+ * The existing target array.
+ */
+ protected function getHookTargets(array &$targets) {
+ self::loadMappers();
+ $type = $this->entityType();
+ $bundle = $this->bundle();
+ $targets += module_invoke_all('feeds_processor_targets', $type, $bundle);
+ foreach ($targets as $target => $info) {
+ $targets[$target] += array(
+ 'summary_callback' => array(),
+ 'form_callback' => array(),
+ 'preprocess_callback' => array(),
+ );
+ }
+ drupal_alter('feeds_processor_targets', $targets, $type, $bundle);
+ }
+
+ /**
* Set a concrete target element. Invoked from FeedsProcessor::map().
*
* @ingroup mappingapi
diff --git a/plugins/FeedsTermProcessor.inc b/plugins/FeedsTermProcessor.inc
index 9b0024e..d4670d4 100644
--- a/plugins/FeedsTermProcessor.inc
+++ b/plugins/FeedsTermProcessor.inc
@@ -177,21 +177,13 @@ class FeedsTermProcessor extends FeedsProcessor {
'description' => array(
'name' => t('Term description'),
'description' => t('Description of the taxonomy term.'),
- 'summary_callback' => 'text_feeds_summary_callback',
- 'form_callback' => 'text_feeds_form_callback',
+ 'summary_callback' => array('text_feeds_summary_callback'),
+ 'form_callback' => array('text_feeds_form_callback'),
),
);
- // Let implementers of hook_feeds_term_processor_targets() add their targets.
- try {
- self::loadMappers();
- $entity_type = $this->entityType();
- $bundle = $this->bundle();
- drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle);
- }
- catch (Exception $e) {
- // Do nothing.
- }
+ $this->getHookTargets($targets);
+
return $targets;
}
diff --git a/plugins/FeedsUserProcessor.inc b/plugins/FeedsUserProcessor.inc
index d01db43..02607f2 100644
--- a/plugins/FeedsUserProcessor.inc
+++ b/plugins/FeedsUserProcessor.inc
@@ -193,11 +193,7 @@ class FeedsUserProcessor extends FeedsProcessor {
);
}
- // Let other modules expose mapping targets.
- self::loadMappers();
- $entity_type = $this->entityType();
- $bundle = $this->bundle();
- drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle);
+ $this->getHookTargets($targets);
return $targets;
}
diff --git a/tests/feeds_tests.module b/tests/feeds_tests.module
index fe25704..1b22539 100644
--- a/tests/feeds_tests.module
+++ b/tests/feeds_tests.module
@@ -102,17 +102,17 @@ function feeds_tests_files_remote() {
}
/**
- * Implements hook_feeds_processor_targets_alter().
+ * Implements hook_feeds_processor_targets().
*/
-function feeds_tests_feeds_processor_targets_alter(&$targets, $entity_type, $bundle) {
+function feeds_tests_feeds_processor_targets($entity_type, $bundle) {
+ $targets = array();
$targets['test_target'] = array(
'name' => t('Test Target'),
'description' => t('This is a test target.'),
'callback' => 'feeds_tests_mapper_set_target',
- 'summary_callback' => 'feeds_tests_mapper_summary',
- 'form_callback' => 'feeds_tests_mapper_form',
+ 'summary_callback' => array('feeds_tests_mapper_summary'),
+ 'form_callback' => array('feeds_tests_mapper_form'),
);
-
$targets['test_unique_target'] = array(
'name' => t('Test unique target'),
'description' => t('This is a unique test target.'),
@@ -120,6 +120,7 @@ function feeds_tests_feeds_processor_targets_alter(&$targets, $entity_type, $bun
'optional_unique' => TRUE,
'unique_callbacks' => array('feeds_tests_mapper_unique'),
);
+ return $targets;
}
/**
@@ -127,8 +128,8 @@ function feeds_tests_feeds_processor_targets_alter(&$targets, $entity_type, $bun
*
* @see my_module_set_target()
*/
-function feeds_tests_mapper_set_target($source, $entity, $target, $value, $mapping) {
- $entity->body['und'][0]['value'] = serialize($mapping);
+function feeds_tests_mapper_set_target(FeedsSource $source, $entity, $target, array $values, array $mapping) {
+ $entity->body[$mapping['language']][0]['value'] = serialize($mapping);
}
/**
@@ -217,7 +218,7 @@ function feeds_tests_mapper_form($mapping, $target, $form, $form_state) {
/**
* Callback for unique_callbacks for test_target mapper.
*
- * @see feeds_tests_feeds_processor_targets_alter()
+ * @see feeds_tests_feeds_processor_targets()
*/
function feeds_tests_mapper_unique(FeedsSource $source, $entity_type, $bundle, $target, array $values) {
$query = new EntityFieldQuery();