Skip to content
Snippets Groups Projects
Commit 11c68ef7 authored by twistor's avatar twistor Committed by Chris Leppanen
Browse files

Issue #2333029 by twistor, MegaChriz: Extend mapping API to allow for defaults...

Issue #2333029 by twistor, MegaChriz: Extend mapping API to allow for defaults and multiple callbacks
parent 79918b8f
No related branches found
No related tags found
No related merge requests found
Showing
with 508 additions and 244 deletions
...@@ -257,7 +257,7 @@ function my_source_get_source(FeedsSource $source, FeedsParserResult $result, $k ...@@ -257,7 +257,7 @@ function my_source_get_source(FeedsSource $source, FeedsParserResult $result, $k
} }
/** /**
* Alters mapping targets for processors. * Adds mapping targets for processors.
* *
* This hook allows additional target options to be added to the processors * This hook allows additional target options to be added to the processors
* mapping form. * mapping form.
...@@ -265,18 +265,20 @@ function my_source_get_source(FeedsSource $source, FeedsParserResult $result, $k ...@@ -265,18 +265,20 @@ function my_source_get_source(FeedsSource $source, FeedsParserResult $result, $k
* If the key in $targets[] does not correspond to the actual key on the node * If the key in $targets[] does not correspond to the actual key on the node
* object ($node->key), real_target MUST be specified. See mappers/link.inc * object ($node->key), real_target MUST be specified. See mappers/link.inc
* *
* For an example implementation, see mappers/content.inc * For an example implementation, see mappers/text.inc
* *
* @param &$targets * @param string $entity_type
* Array containing the targets to be offered to the user. Add to this array
* to expose additional options. Remove from this array to suppress options.
* Remove with caution.
* @param $entity_type
* The entity type of the target, for instance a 'node' entity. * The entity type of the target, for instance a 'node' entity.
* @param $bundle * @param string $bundle
* The bundle name for which to alter targets. * The entity bundle to return targets for.
*
* @return array
* Array containing the targets to be offered to the user. This function must
* return an array, even an empty one.
*/ */
function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle) { function hook_feeds_processor_targets($entity_type, $bundle) {
$targets = array();
if ($entity_type == 'node') { if ($entity_type == 'node') {
$targets['my_node_field'] = array( $targets['my_node_field'] = array(
'name' => t('My custom node field'), 'name' => t('My custom node field'),
...@@ -285,8 +287,8 @@ function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle) { ...@@ -285,8 +287,8 @@ function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle) {
// Specify both summary_callback and form_callback to add a per mapping // Specify both summary_callback and form_callback to add a per mapping
// configuration form. // configuration form.
'summary_callback' => 'my_module_summary_callback', 'summary_callbacks' => array('my_module_summary_callback'),
'form_callback' => 'my_module_form_callback', 'form_callbacks' => array('my_module_form_callback'),
); );
$targets['my_node_field2'] = array( $targets['my_node_field2'] = array(
'name' => t('My Second custom node field'), 'name' => t('My Second custom node field'),
...@@ -304,26 +306,56 @@ function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle) { ...@@ -304,26 +306,56 @@ function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle) {
// targets. // targets.
'optional_unique' => TRUE, 'optional_unique' => TRUE,
'unique_callbacks' => array('my_module_mapper_unique'), 'unique_callbacks' => array('my_module_mapper_unique'),
// Preprocess callbacks are called before the actual callback allowing you
// to prepare values on the entity or mapping array.
'preprocess_callbacks' => array('my_module_preprocess_callback'),
); );
} }
return $targets;
} }
/** /**
* Example callback specified in hook_feeds_processor_targets_alter(). * Alters the target array.
* *
* @param $source * This hook allows modifying the target array.
*
* @param array &$targets
* Array containing the targets to be offered to the user. Add to this array
* to expose additional options.
* @param string $entity_type
* The entity type of the target, for instance a 'node' entity.
* @param string $bundle
* The entity bundle to return targets for.
*
* @see hook_feeds_processor_targets()
*/
function hook_feeds_processor_targets_alter(array &$targets, $entity_type, $bundle) {
if ($entity_type == 'node' && $bundle == 'article') {
if (isset($targets['nid'])) {
$targets['nid']['unique_callbacks'][] = 'my_module_mapper_unique';
$targets['nid']['optional_unique'] = TRUE;
}
}
}
/**
* Example callback specified in hook_feeds_processor_targets().
*
* @param FeedsSource $source
* Field mapper source settings. * Field mapper source settings.
* @param $entity * @param object $entity
* An entity object, for instance a node object. * An entity object, for instance a node object.
* @param $target * @param string $target
* A string identifying the target on the node. * A string identifying the target on the node.
* @param $values * @param array $values
* The value to populate the target with. * The value to populate the target with.
* @param $mapping * @param array $mapping
* Associative array of the mapping settings from the per mapping * Associative array of the mapping settings from the per mapping
* configuration form. * configuration form.
*/ */
function my_module_set_target($source, $entity, $target, array $values, $mapping) { function my_module_set_target(FeedsSource $source, $entity, $target, array $values, array $mapping) {
$entity->{$target}[$entity->language][0]['value'] = reset($values); $entity->{$target}[$entity->language][0]['value'] = reset($values);
if (isset($source->importer->processor->config['input_format'])) { if (isset($source->importer->processor->config['input_format'])) {
$entity->{$target}[$entity->language][0]['format'] = $source->importer->processor->config['input_format']; $entity->{$target}[$entity->language][0]['format'] = $source->importer->processor->config['input_format'];
...@@ -331,26 +363,25 @@ function my_module_set_target($source, $entity, $target, array $values, $mapping ...@@ -331,26 +363,25 @@ function my_module_set_target($source, $entity, $target, array $values, $mapping
} }
/** /**
* Example of the summary_callback specified in * Example of the summary_callback specified in hook_feeds_processor_targets().
* hook_feeds_processor_targets_alter().
* *
* @param $mapping * @param array $mapping
* Associative array of the mapping settings. * Associative array of the mapping settings.
* @param $target * @param string $target
* Array of target settings, as defined by the processor or * Array of target settings, as defined by the processor or
* hook_feeds_processor_targets_alter(). * hook_feeds_processor_targets_alter().
* @param $form * @param array $form
* The whole mapping form. * The whole mapping form.
* @param $form_state * @param array $form_state
* The form state of the mapping form. * The form state of the mapping form.
* *
* @return * @return string
* Returns, as a string that may contain HTML, the summary to display while * Returns, as a string that may contain HTML, the summary to display while
* the full form isn't visible. * the full form isn't visible.
* If the return value is empty, no summary and no option to view the form * If the return value is empty, no summary and no option to view the form
* will be displayed. * will be displayed.
*/ */
function my_module_summary_callback($mapping, $target, $form, $form_state) { function my_module_summary_callback(array $mapping, $target, array $form, array $form_state) {
if (empty($mapping['my_setting'])) { if (empty($mapping['my_setting'])) {
return t('My setting <strong>not</strong> active'); return t('My setting <strong>not</strong> active');
} }
...@@ -360,18 +391,17 @@ function my_module_summary_callback($mapping, $target, $form, $form_state) { ...@@ -360,18 +391,17 @@ function my_module_summary_callback($mapping, $target, $form, $form_state) {
} }
/** /**
* Example of the form_callback specified in * Example of the form_callback specified in hook_feeds_processor_targets().
* hook_feeds_processor_targets_alter().
* *
* The arguments are the same that my_module_summary_callback() gets. * The arguments are the same that my_module_summary_callback() gets.
* *
* @return * @return array
* The per mapping configuration form. Once the form is saved, $mapping will * The per mapping configuration form. Once the form is saved, $mapping will
* be populated with the form values. * be populated with the form values.
* *
* @see my_module_summary_callback() * @see my_module_summary_callback()
*/ */
function my_module_form_callback($mapping, $target, $form, $form_state) { function my_module_form_callback(array $mapping, $target, array $form, array $form_state) {
return array( return array(
'my_setting' => array( 'my_setting' => array(
'#type' => 'checkbox', '#type' => 'checkbox',
...@@ -382,8 +412,7 @@ function my_module_form_callback($mapping, $target, $form, $form_state) { ...@@ -382,8 +412,7 @@ function my_module_form_callback($mapping, $target, $form, $form_state) {
} }
/** /**
* Example of the unique_callbacks specified in * Example of the unique_callbacks specified in hook_feeds_processor_targets().
* hook_feeds_processor_targets_alter().
* *
* @param FeedsSource $source * @param FeedsSource $source
* The Feed source. * The Feed source.
...@@ -396,10 +425,10 @@ function my_module_form_callback($mapping, $target, $form, $form_state) { ...@@ -396,10 +425,10 @@ function my_module_form_callback($mapping, $target, $form, $form_state) {
* @param array $values * @param array $values
* The unique values to be checked. * The unique values to be checked.
* *
* @return int * @return int|null
* The existing entity id, or NULL if no existing entity is found. * The existing entity id, or NULL if no existing entity is found.
* *
* @see hook_feeds_processor_targets_alter() * @see hook_feeds_processor_targets()
* @see FeedsProcessor::existingEntityId() * @see FeedsProcessor::existingEntityId()
*/ */
function my_module_mapper_unique(FeedsSource $source, $entity_type, $bundle, $target, array $values) { function my_module_mapper_unique(FeedsSource $source, $entity_type, $bundle, $target, array $values) {
...@@ -417,6 +446,25 @@ function my_module_mapper_unique(FeedsSource $source, $entity_type, $bundle, $ta ...@@ -417,6 +446,25 @@ function my_module_mapper_unique(FeedsSource $source, $entity_type, $bundle, $ta
} }
} }
/**
* Example of the preprocess_callbacks specified in hook_feeds_processor_targets().
*
* @param FeedsSource $source
* The Feed source.
* @param object $entity
* The entity being processed.
* @param array $target
* The full target definition.
* @param array &$mapping
* The mapping configuration.
*
* @see hook_feeds_processor_targets()
*/
function my_module_preprocess_callback(FeedsSource $source, $entity, array $target, array &$mapping) {
// Add in default values.
$mapping += array('setting_value' => TRUE);
}
/** /**
* @} * @}
*/ */
<?php
/**
* @file
* Feeds hooks.
*/
/**
* Implements hook_feeds_processor_targets().
*/
function feeds_feeds_processor_targets($entity_type, $bundle) {
// Record that we've been called.
// @see _feeds_feeds_processor_targets_alter()
$called = &drupal_static('feeds_feeds_processor_targets', FALSE);
$called = TRUE;
return array();
}
/**
* Implements hook_feeds_processor_targets_alter().
*/
function feeds_feeds_processor_targets_alter(array &$targets, $entity_type, $bundle) {
// This hook gets called last, so that we normalize the whole array.
feeds_normalize_targets($targets);
}
/**
* Normalizes the target array.
*
* @param array &$targets
* The Feeds target array.
*/
function feeds_normalize_targets(array &$targets) {
static $defaults = array(
'description' => '',
'summary_callbacks' => array(),
'form_callbacks' => array(),
'preprocess_callbacks' => array(),
'unique_callbacks' => array(),
);
foreach (array_keys($targets) as $target) {
$targets[$target] += $defaults;
// Filter out any uncallable keys.
_feeds_filter_callback_arrays($targets[$target]);
}
}
/**
* Filters the callbacks of a single target array.
*
* @param array &$target
* The target arary.
*/
function _feeds_filter_callback_arrays(array &$target) {
// Migrate keys summary_callback and form_callback to the new keys.
if (isset($target['summary_callback'])) {
$target['summary_callbacks'][] = $target['summary_callback'];
}
if (isset($target['form_callback'])) {
$target['form_callbacks'][] = $target['form_callback'];
}
unset($target['summary_callback'], $target['form_callback']);
static $callback_keys = array(
'summary_callbacks',
'form_callbacks',
'preprocess_callbacks',
'unique_callbacks',
);
// Filter out any incorrect callbacks. Do it here so it only has to be done
// once.
foreach ($callback_keys as $callback_key) {
$target[$callback_key] = array_filter($target[$callback_key], 'is_callable');
}
// This makes checking in FeedsProcessor::mapToTarget() simpler.
if (empty($target['callback']) || !is_callable($target['callback'])) {
unset($target['callback']);
}
}
...@@ -36,6 +36,7 @@ files[] = tests/feeds_mapper_date.test ...@@ -36,6 +36,7 @@ files[] = tests/feeds_mapper_date.test
files[] = tests/feeds_mapper_date_multiple.test files[] = tests/feeds_mapper_date_multiple.test
files[] = tests/feeds_mapper_field.test files[] = tests/feeds_mapper_field.test
files[] = tests/feeds_mapper_file.test files[] = tests/feeds_mapper_file.test
files[] = tests/feeds_mapper_hooks.test
files[] = tests/feeds_mapper_link.test files[] = tests/feeds_mapper_link.test
files[] = tests/feeds_mapper_path.test files[] = tests/feeds_mapper_path.test
files[] = tests/feeds_mapper_profile.test files[] = tests/feeds_mapper_profile.test
......
...@@ -35,6 +35,7 @@ function feeds_hook_info() { ...@@ -35,6 +35,7 @@ function feeds_hook_info() {
'feeds_after_save', 'feeds_after_save',
'feeds_after_import', 'feeds_after_import',
'feeds_after_clear', 'feeds_after_clear',
'feeds_processor_targets',
'feeds_processor_targets_alter', 'feeds_processor_targets_alter',
'feeds_parser_sources_alter', 'feeds_parser_sources_alter',
); );
...@@ -784,6 +785,36 @@ function feeds_system_info_alter(array &$info, $file, $type) { ...@@ -784,6 +785,36 @@ function feeds_system_info_alter(array &$info, $file, $type) {
} }
} }
/**
* Implements hook_module_implements_alter().
*/
function feeds_module_implements_alter(array &$implementations, $hook) {
if ($hook === 'feeds_processor_targets_alter') {
// We need two implementations of this hook, so we add one that gets
// called first, and move the normal one to last.
$implementations = array('_feeds' => FALSE) + $implementations;
// Move normal implementation to last.
$group = $implementations['feeds'];
unset($implementations['feeds']);
$implementations['feeds'] = $group;
}
}
/**
* Implements hook_feeds_processor_targets_alter().
*
* @see feeds_feeds_processor_targets()
* @see feeds_feeds_processor_targets_alter()
*/
function _feeds_feeds_processor_targets_alter(array &$targets, $entity_type, $bundle) {
// If hook_feeds_processor_targets() hasn't been called, for instance, by
// older processors, invoke it ourself.
if (!drupal_static('feeds_feeds_processor_targets', FALSE)) {
$targets += module_invoke_all('feeds_processor_targets', $entity_type, $bundle);
}
}
/** /**
* @} * @}
*/ */
......
...@@ -634,12 +634,10 @@ function feeds_ui_mapping_settings_form($form, $form_state, $i, $mapping, $targe ...@@ -634,12 +634,10 @@ function feeds_ui_mapping_settings_form($form, $form_state, $i, $mapping, $targe
} }
if ($form_state['mapping_settings_edit'] === $i) { if ($form_state['mapping_settings_edit'] === $i) {
// Build the form. $settings_form = array();
if (isset($target['form_callback'])) {
$settings_form = call_user_func($target['form_callback'], $mapping, $target, $form, $form_state); foreach ($target['form_callbacks'] as $callback) {
} $settings_form += call_user_func($callback, $mapping, $target, $form, $form_state);
else {
$settings_form = array();
} }
// Merge in the optional unique form. // Merge in the optional unique form.
...@@ -664,13 +662,15 @@ function feeds_ui_mapping_settings_form($form, $form_state, $i, $mapping, $targe ...@@ -664,13 +662,15 @@ function feeds_ui_mapping_settings_form($form, $form_state, $i, $mapping, $targe
} }
else { else {
// Build the summary. // Build the summary.
if (isset($target['summary_callback'])) { $summary = array();
$summary = call_user_func($target['summary_callback'], $mapping, $target, $form, $form_state);
} foreach ($target['summary_callbacks'] as $callback) {
else { $summary[] = call_user_func($callback, $mapping, $target, $form, $form_state);
$summary = '';
} }
// Filter out empty summary values.
$summary = implode('<br />', array_filter($summary));
// Append the optional unique summary. // Append the optional unique summary.
if ($optional_unique_summary = feeds_ui_mapping_settings_optional_unique_summary($mapping, $target, $form, $form_state)) { if ($optional_unique_summary = feeds_ui_mapping_settings_optional_unique_summary($mapping, $target, $form, $form_state)) {
$summary .= ' ' . $optional_unique_summary; $summary .= ' ' . $optional_unique_summary;
......
...@@ -6,13 +6,13 @@ ...@@ -6,13 +6,13 @@
*/ */
/** /**
* Implements hook_feeds_processor_targets_alter(). * Implements hook_feeds_processor_targets().
*
* @see FeedsNodeProcessor::getMappingTargets().
* *
* @todo Only provides "end date" target if field allows it. * @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) { foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name); $info = field_info_field($name);
if (in_array($info['type'], array('date', 'datestamp', 'datetime'))) { if (in_array($info['type'], array('date', 'datestamp', 'datetime'))) {
...@@ -30,12 +30,14 @@ function date_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam ...@@ -30,12 +30,14 @@ function date_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
); );
} }
} }
return $targets;
} }
/** /**
* Callback for setting target values. * Callback for setting date values.
*/ */
function date_feeds_set_target($source, $entity, $target, array $values) { function date_feeds_set_target(FeedsSource $source, $entity, $target, array $values) {
list($field_name, $sub_field) = explode(':', $target, 2); list($field_name, $sub_field) = explode(':', $target, 2);
$delta = 0; $delta = 0;
......
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
*/ */
/** /**
* Implements hook_feeds_processor_targets_alter(). * Implements hook_feeds_processor_targets().
*
* @see FeedsNodeProcessor::getMappingTargets()
*/ */
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) { foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name); $info = field_info_field($name);
...@@ -47,16 +47,14 @@ function file_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam ...@@ -47,16 +47,14 @@ function file_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
} }
} }
} }
return $targets;
} }
/** /**
* Callback for mapping. Here is where the actual mapping happens. * Callback for mapping file fields.
*
* 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.
*/ */
function file_feeds_set_target($source, $entity, $target, array $values) { function file_feeds_set_target(FeedsSource $source, $entity, $target, array $values) {
// Add default of uri for backwards compatibility. // Add default of uri for backwards compatibility.
list($field_name, $sub_field) = explode(':', $target . ':uri'); list($field_name, $sub_field) = explode(':', $target . ':uri');
$info = field_info_field($field_name); $info = field_info_field($field_name);
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
*/ */
/** /**
* Implements hook_feeds_processor_targets_alter(). * Implements hook_feeds_processor_targets().
*
* @see FeedsProcessor::getMappingTargets()
*/ */
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) { foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name); $info = field_info_field($name);
if ($info['type'] == 'link_field') { if ($info['type'] == 'link_field') {
...@@ -32,16 +32,14 @@ function link_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam ...@@ -32,16 +32,14 @@ function link_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
} }
} }
} }
return $targets;
} }
/** /**
* Callback for mapping. Here is where the actual mapping happens. * Callback for mapping link fields.
*
* 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.
*/ */
function link_feeds_set_target($source, $entity, $target, array $values) { function link_feeds_set_target(FeedsSource $source, $entity, $target, array $values) {
list($field_name, $column) = explode(':', $target); 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('und' => array());
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
*/ */
/** /**
* Implements hook_feeds_processor_targets_alter(). * Implements hook_feeds_processor_targets().
*
* @see FeedsProcessor::getMappingTargets()
*/ */
function list_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) { function list_feeds_processor_targets($entity_type, $bundle_name) {
$targets = array();
foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) { foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name); $info = field_info_field($name);
...@@ -42,12 +42,14 @@ function list_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam ...@@ -42,12 +42,14 @@ function list_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
break; break;
} }
} }
return $targets;
} }
/** /**
* Callback for setting list_boolean fields. * Callback for setting list_boolean fields.
*/ */
function list_feeds_set_boolean_target(FeedsSource $source, $entity, $target, array $values, array $mapping = array()) { function list_feeds_set_boolean_target(FeedsSource $source, $entity, $target, array $values) {
$field = isset($entity->$target) ? $entity->$target : array(LANGUAGE_NONE => array()); $field = isset($entity->$target) ? $entity->$target : array(LANGUAGE_NONE => array());
foreach ($values as $value) { foreach ($values as $value) {
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
*/ */
/** /**
* Implements hook_feeds_processor_targets_alter(). * Implements hook_feeds_processor_targets().
*
* @see FeedsProcessor::getMappingTargets()
*/ */
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( $numeric_types = array(
'number_integer', 'number_integer',
'number_decimal', 'number_decimal',
...@@ -27,14 +27,14 @@ function number_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_n ...@@ -27,14 +27,14 @@ function number_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_n
); );
} }
} }
return $targets;
} }
/** /**
* Callback for mapping numerics. * Callback for mapping number fields.
*
* 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) {
// Iterate over all values. // Iterate over all values.
$field = isset($entity->$target) ? $entity->$target : array('und' => array()); $field = isset($entity->$target) ? $entity->$target : array('und' => array());
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
*/ */
/** /**
* Implements hook_feeds_processor_targets_alter(). * Implements hook_feeds_processor_targets().
*
* @see FeedsNodeProcessor::getMappingTargets().
*/ */
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) { switch ($entity_type) {
case 'node': case 'node':
case 'taxonomy_term': case 'taxonomy_term':
...@@ -19,21 +19,19 @@ function path_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam ...@@ -19,21 +19,19 @@ function path_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
'name' => t('Path alias'), 'name' => t('Path alias'),
'description' => t('URL path alias of the node.'), 'description' => t('URL path alias of the node.'),
'callback' => 'path_feeds_set_target', 'callback' => 'path_feeds_set_target',
'summary_callback' => 'path_feeds_summary_callback', 'summary_callbacks' => array('path_feeds_summary_callback'),
'form_callback' => 'path_feeds_form_callback', 'form_callbacks' => array('path_feeds_form_callback'),
); );
break; break;
} }
return $targets;
} }
/** /**
* Callback for mapping. Here is where the actual mapping happens. * Callback for mapping path aliases.
*
* 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.
*/ */
function path_feeds_set_target($source, $entity, $target, array $values, $mapping) { function path_feeds_set_target(FeedsSource $source, $entity, $target, array $values, array $mapping) {
$alias = FALSE; $alias = FALSE;
// Path alias cannot be multi-valued, so use the first non-empty value. // Path alias cannot be multi-valued, so use the first non-empty value.
foreach ($values as $value) { foreach ($values as $value) {
...@@ -68,24 +66,8 @@ function path_feeds_set_target($source, $entity, $target, array $values, $mappin ...@@ -68,24 +66,8 @@ function path_feeds_set_target($source, $entity, $target, array $values, $mappin
/** /**
* Mapping configuration summary for path.module. * Mapping configuration summary for path.module.
*
* @param $mapping
* Associative array of the mapping settings.
* @param $target
* Array of target settings, as defined by the processor or
* hook_feeds_processor_targets_alter().
* @param $form
* The whole mapping form.
* @param $form_state
* The form state of the mapping form.
*
* @return
* 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 path_feeds_summary_callback($mapping, $target, $form, $form_state) { function path_feeds_summary_callback(array $mapping, $target, array $form, array $form_state) {
if (!module_exists('pathauto')) { if (!module_exists('pathauto')) {
return; return;
} }
...@@ -101,12 +83,8 @@ function path_feeds_summary_callback($mapping, $target, $form, $form_state) { ...@@ -101,12 +83,8 @@ function path_feeds_summary_callback($mapping, $target, $form, $form_state) {
/** /**
* Settings form callback. * Settings form callback.
*
* @return
* The per mapping configuration form. Once the form is saved, $mapping will
* be populated with the form values.
*/ */
function path_feeds_form_callback($mapping, $target, $form, $form_state) { function path_feeds_form_callback(array $mapping, $target, array $form, array $form_state) {
return array( return array(
'pathauto_override' => array( 'pathauto_override' => array(
'#type' => 'checkbox', '#type' => 'checkbox',
......
...@@ -2,16 +2,17 @@ ...@@ -2,16 +2,17 @@
/** /**
* @file * @file
* On behalf implementation of Feeds mapping API for user profiles. * On behalf implementation of Feeds mapping API for profile.module.
*/ */
/** /**
* 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') { if ($entity_type != 'user') {
return; return $targets;
} }
$categories = profile_user_categories(); $categories = profile_user_categories();
...@@ -25,11 +26,13 @@ function profile_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_ ...@@ -25,11 +26,13 @@ function profile_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_
); );
} }
} }
return $targets;
} }
/** /**
* Set the user profile target after import. * Set the user profile target after import.
*/ */
function profile_feeds_set_target($source, $entity, $target, array $values, $mapping) { function profile_feeds_set_target(FeedsSource $source, $entity, $target, array $values) {
$entity->$target = reset($values); $entity->$target = reset($values);
} }
...@@ -23,7 +23,7 @@ define('FEEDS_TAXONOMY_SEARCH_TERM_GUID', 2); ...@@ -23,7 +23,7 @@ define('FEEDS_TAXONOMY_SEARCH_TERM_GUID', 2);
/** /**
* Implements hook_feeds_parser_sources_alter(). * Implements hook_feeds_parser_sources_alter().
*/ */
function taxonomy_feeds_parser_sources_alter(&$sources, $content_type) { function taxonomy_feeds_parser_sources_alter(array &$sources, $content_type) {
if (!empty($content_type)) { if (!empty($content_type)) {
foreach (taxonomy_get_vocabularies($content_type) as $vocabulary) { foreach (taxonomy_get_vocabularies($content_type) as $vocabulary) {
$sources['parent:taxonomy:' . $vocabulary->machine_name] = array( $sources['parent:taxonomy:' . $vocabulary->machine_name] = array(
...@@ -55,9 +55,11 @@ function taxonomy_feeds_get_source(FeedsSource $source, FeedsParserResult $resul ...@@ -55,9 +55,11 @@ 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) { foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name); $info = field_info_field($name);
if ($info['type'] == 'taxonomy_term_reference') { if ($info['type'] == 'taxonomy_term_reference') {
...@@ -65,8 +67,8 @@ function taxonomy_feeds_processor_targets_alter(&$targets, $entity_type, $bundle ...@@ -65,8 +67,8 @@ function taxonomy_feeds_processor_targets_alter(&$targets, $entity_type, $bundle
'name' => check_plain($instance['label']), 'name' => check_plain($instance['label']),
'callback' => 'taxonomy_feeds_set_target', 'callback' => 'taxonomy_feeds_set_target',
'description' => t('The @label field of the entity.', array('@label' => $instance['label'])), 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])),
'summary_callback' => 'taxonomy_feeds_summary_callback', 'summary_callbacks' => array('taxonomy_feeds_summary_callback'),
'form_callback' => 'taxonomy_feeds_form_callback', 'form_callbacks' => array('taxonomy_feeds_form_callback'),
); );
} }
} }
...@@ -75,14 +77,14 @@ function taxonomy_feeds_processor_targets_alter(&$targets, $entity_type, $bundle ...@@ -75,14 +77,14 @@ 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.'); $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']); unset($targets['vocabulary']);
} }
return $targets;
} }
/** /**
* Callback for mapping. Here is where the actual mapping happens. * Callback for mapping taxonomy terms.
*
* @todo Do not create new terms for non-autotag fields.
*/ */
function taxonomy_feeds_set_target($source, $entity, $target, array $terms, $mapping = array()) { function taxonomy_feeds_set_target(FeedsSource $source, $entity, $target, array $terms, array $mapping) {
// Add in default values. // Add in default values.
$mapping += array( $mapping += array(
'term_search' => FEEDS_TAXONOMY_SEARCH_TERM_NAME, 'term_search' => FEEDS_TAXONOMY_SEARCH_TERM_NAME,
...@@ -252,24 +254,8 @@ function taxonomy_feeds_term_lookup_term_by_guid($guid) { ...@@ -252,24 +254,8 @@ function taxonomy_feeds_term_lookup_term_by_guid($guid) {
/** /**
* Mapping configuration summary for taxonomy.module. * Mapping configuration summary for taxonomy.module.
*
* @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 taxonomy_feeds_summary_callback($mapping, $target, $form, $form_state) { function taxonomy_feeds_summary_callback(array $mapping, $target, array $form, array $form_state) {
$options = _taxonomy_feeds_form_callback_options(); $options = _taxonomy_feeds_form_callback_options();
if (empty($mapping['term_search'])) { if (empty($mapping['term_search'])) {
return t('Search taxonomy terms by: <strong>@search</strong>', array('@search' => $options[FEEDS_TAXONOMY_SEARCH_TERM_NAME])); return t('Search taxonomy terms by: <strong>@search</strong>', array('@search' => $options[FEEDS_TAXONOMY_SEARCH_TERM_NAME]));
...@@ -279,12 +265,8 @@ function taxonomy_feeds_summary_callback($mapping, $target, $form, $form_state) ...@@ -279,12 +265,8 @@ function taxonomy_feeds_summary_callback($mapping, $target, $form, $form_state)
/** /**
* Settings form callback. * Settings form callback.
*
* @return array
* The per mapping configuration form. Once the form is saved, $mapping will
* be populated with the form values.
*/ */
function taxonomy_feeds_form_callback($mapping, $target, $form, $form_state) { function taxonomy_feeds_form_callback(array $mapping, $target, array $form, array $form_state) {
return array( return array(
'term_search' => array( 'term_search' => array(
'#type' => 'select', '#type' => 'select',
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
*/ */
/** /**
* Implements hook_feeds_processor_targets_alter(). * Implements hook_feeds_processor_targets().
*
* @see FeedsProcessor::getMappingTargets()
*/ */
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( $text_types = array(
'text', 'text',
'text_long', 'text_long',
...@@ -37,16 +37,18 @@ function text_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam ...@@ -37,16 +37,18 @@ function text_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
} }
if (!empty($instance['settings']['text_processing'])) { if (!empty($instance['settings']['text_processing'])) {
$targets[$name]['summary_callback'] = 'text_feeds_summary_callback'; $targets[$name]['summary_callbacks'] = array('text_feeds_summary_callback');
$targets[$name]['form_callback'] = 'text_feeds_form_callback'; $targets[$name]['form_callbacks'] = array('text_feeds_form_callback');
} }
} }
return $targets;
} }
/** /**
* Callback for mapping text fields. * 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'); list($field_name, $column) = explode(':', $target . ':value');
if ($column === 'value' && isset($source->importer->processor->config['input_format'])) { if ($column === 'value' && isset($source->importer->processor->config['input_format'])) {
...@@ -87,7 +89,7 @@ function text_feeds_set_target(FeedsSource $source, $entity, $target, array $val ...@@ -87,7 +89,7 @@ function text_feeds_set_target(FeedsSource $source, $entity, $target, array $val
* *
* Displays which text format will be used for the text field target. * 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() * @see text_feeds_form_callback()
*/ */
function text_feeds_summary_callback(array $mapping, $target, array $form, array $form_state) { function text_feeds_summary_callback(array $mapping, $target, array $form, array $form_state) {
...@@ -109,7 +111,7 @@ function text_feeds_summary_callback(array $mapping, $target, array $form, array ...@@ -109,7 +111,7 @@ function text_feeds_summary_callback(array $mapping, $target, array $form, array
* *
* Allows to select a text format for the text field target. * 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() * @see text_feeds_summary_callback()
*/ */
function text_feeds_form_callback(array $mapping, $target, array $form, array $form_state) { function text_feeds_form_callback(array $mapping, $target, array $form, array $form_state) {
......
...@@ -339,11 +339,7 @@ class FeedsNodeProcessor extends FeedsProcessor { ...@@ -339,11 +339,7 @@ class FeedsNodeProcessor extends FeedsProcessor {
); );
} }
// Let other modules expose mapping targets. $this->getHookTargets($targets);
self::loadMappers();
$entity_type = $this->entityType();
$bundle = $this->bundle();
drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle);
return $targets; return $targets;
} }
......
...@@ -585,6 +585,47 @@ abstract class FeedsProcessor extends FeedsPlugin { ...@@ -585,6 +585,47 @@ abstract class FeedsProcessor extends FeedsPlugin {
return db_query("SELECT count(*) FROM {feeds_item} WHERE id = :id AND entity_type = :entity_type AND feed_nid = :feed_nid", array(':id' => $this->id, ':entity_type' => $this->entityType(), ':feed_nid' => $source->feed_nid))->fetchField(); return db_query("SELECT count(*) FROM {feeds_item} WHERE id = :id AND entity_type = :entity_type AND feed_nid = :feed_nid", array(':id' => $this->id, ':entity_type' => $this->entityType(), ':feed_nid' => $source->feed_nid))->fetchField();
} }
/**
* Returns a statically cached version of the target mappings.
*
* @return array
* The targets for this importer.
*/
protected function getCachedTargets() {
$targets = &drupal_static('FeedsProcessor::getCachedTargets', array());
if (!isset($targets[$this->id])) {
$targets[$this->id] = $this->getMappingTargets();
}
return $targets[$this->id];
}
/**
* Returns a statically cached version of the source mappings.
*
* @return array
* The sources for this importer.
*/
protected function getCachedSources() {
$sources = &drupal_static('FeedsProcessor::getCachedSources', array());
if (!isset($sources[$this->id])) {
$sources[$this->id] = feeds_importer($this->id)->parser->getMappingSources();
if (is_array($sources[$this->id])) {
foreach ($sources[$this->id] as $source_key => $source) {
if (empty($source['callback']) || !is_callable($source['callback'])) {
unset($sources[$this->id][$source_key]['callback']);
}
}
}
}
return $sources[$this->id];
}
/** /**
* Execute mapping on an item. * Execute mapping on an item.
* *
...@@ -603,23 +644,12 @@ abstract class FeedsProcessor extends FeedsPlugin { ...@@ -603,23 +644,12 @@ abstract class FeedsProcessor extends FeedsPlugin {
* @ingroup mappingapi * @ingroup mappingapi
* *
* @see hook_feeds_parser_sources_alter() * @see hook_feeds_parser_sources_alter()
* @see hook_feeds_data_processor_targets_alter() * @see hook_feeds_processor_targets()
* @see hook_feeds_node_processor_targets_alter() * @see hook_feeds_processor_targets_alter()
* @see hook_feeds_term_processor_targets_alter()
* @see hook_feeds_user_processor_targets_alter()
*/ */
protected function map(FeedsSource $source, FeedsParserResult $result, $target_item = NULL) { protected function map(FeedsSource $source, FeedsParserResult $result, $target_item = NULL) {
$targets = $this->getCachedTargets();
// Static cache $targets as getMappingTargets() may be an expensive method.
static $sources;
if (!isset($sources[$this->id])) {
$sources[$this->id] = feeds_importer($this->id)->parser->getMappingSources();
}
static $targets;
if (!isset($targets[$this->id])) {
$targets[$this->id] = $this->getMappingTargets();
}
$parser = feeds_importer($this->id)->parser;
if (empty($target_item)) { if (empty($target_item)) {
$target_item = array(); $target_item = array();
} }
...@@ -628,57 +658,87 @@ abstract class FeedsProcessor extends FeedsPlugin { ...@@ -628,57 +658,87 @@ abstract class FeedsProcessor extends FeedsPlugin {
// need to clear target elements of each item before mapping in case we are // need to clear target elements of each item before mapping in case we are
// mapping on a prepopulated item such as an existing node. // mapping on a prepopulated item such as an existing node.
foreach ($this->config['mappings'] as $mapping) { foreach ($this->config['mappings'] as $mapping) {
if (isset($targets[$this->id][$mapping['target']]['real_target'])) { if (isset($targets[$mapping['target']]['real_target'])) {
$target_item->{$targets[$this->id][$mapping['target']]['real_target']} = NULL; $target_item->{$targets[$mapping['target']]['real_target']} = NULL;
} }
else { else {
$target_item->{$mapping['target']} = NULL; $target_item->{$mapping['target']} = NULL;
} }
} }
/* // This is where the actual mapping happens: For every mapping we invoke
This is where the actual mapping happens: For every mapping we envoke // the parser's getSourceElement() method to retrieve the value of the
the parser's getSourceElement() method to retrieve the value of the source // source element and pass it to the processor's setTargetElement() to stick
element and pass it to the processor's setTargetElement() to stick it // it on the right place of the target item.
on the right place of the target item.
If the mapping specifies a callback method, use the callback instead of
setTargetElement().
*/
self::loadMappers();
foreach ($this->config['mappings'] as $mapping) { foreach ($this->config['mappings'] as $mapping) {
// Retrieve source element's value from parser. $value = $this->getSourceValue($source, $result, $mapping['source']);
if (isset($sources[$this->id][$mapping['source']]) &&
is_array($sources[$this->id][$mapping['source']]) &&
isset($sources[$this->id][$mapping['source']]['callback']) &&
function_exists($sources[$this->id][$mapping['source']]['callback'])) {
$callback = $sources[$this->id][$mapping['source']]['callback'];
$value = $callback($source, $result, $mapping['source']);
}
else {
$value = $parser->getSourceElement($source, $result, $mapping['source']);
}
// Map the source element's value to the target. $this->mapToTarget($source, $mapping['target'], $target_item, $value, $mapping);
if (isset($targets[$this->id][$mapping['target']]) && }
is_array($targets[$this->id][$mapping['target']]) &&
isset($targets[$this->id][$mapping['target']]['callback']) &&
function_exists($targets[$this->id][$mapping['target']]['callback'])) {
$callback = $targets[$this->id][$mapping['target']]['callback'];
// All target callbacks expect an array. return $target_item;
if (!is_array($value)) { }
$value = array($value);
} /**
* Returns the values from the parser, or callback.
*
* @param FeedsSource $source
* The feed source.
* @param FeedsParserResult $result
* The parser result.
* @param string $source_key
* The current key being processed.
*
* @return mixed
* A value, or a list of values.
*/
protected function getSourceValue(FeedsSource $source, FeedsParserResult $result, $source_key) {
$sources = $this->getCachedSources();
if (isset($sources[$source_key]['callback'])) {
return call_user_func($sources[$source_key]['callback'], $source, $result, $source_key);
}
return feeds_importer($this->id)->parser->getSourceElement($source, $result, $source_key);
}
/**
* Maps values onto the target item.
*
* @param FeedsSource $source
* The feed source.
* @param mixed &$target_item
* The target item to apply values into.
* @param mixed $value
* A value, or a list of values.
* @param array $mapping
* The mapping configuration.
*/
protected function mapToTarget(FeedsSource $source, $target, &$target_item, $value, array $mapping) {
$targets = $this->getCachedTargets();
$callback($source, $target_item, $mapping['target'], $value, $mapping); if (isset($targets[$target]['preprocess_callbacks'])) {
foreach ($targets[$target]['preprocess_callbacks'] as $callback) {
call_user_func_array($callback, array($source, $target_item, $target, &$mapping));
} }
else { }
$this->setTargetElement($source, $target_item, $mapping['target'], $value, $mapping);
// Map the source element's value to the target.
// If the mapping specifies a callback method, use the callback instead of
// setTargetElement().
if (isset($targets[$target]['callback'])) {
// All target callbacks expect an array.
if (!is_array($value)) {
$value = array($value);
} }
call_user_func($targets[$target]['callback'], $source, $target_item, $target, $value, $mapping);
} }
return $target_item; else {
$this->setTargetElement($source, $target_item, $target, $value, $mapping);
}
} }
/** /**
...@@ -821,6 +881,22 @@ abstract class FeedsProcessor extends FeedsPlugin { ...@@ -821,6 +881,22 @@ 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();
$entity_type = $this->entityType();
$bundle = $this->bundle();
$targets += module_invoke_all('feeds_processor_targets', $entity_type, $bundle);
drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle);
}
/** /**
* Set a concrete target element. Invoked from FeedsProcessor::map(). * Set a concrete target element. Invoked from FeedsProcessor::map().
* *
...@@ -832,6 +908,7 @@ abstract class FeedsProcessor extends FeedsPlugin { ...@@ -832,6 +908,7 @@ abstract class FeedsProcessor extends FeedsPlugin {
case 'guid': case 'guid':
$target_item->feeds_item->$target_element = $value; $target_item->feeds_item->$target_element = $value;
break; break;
default: default:
$target_item->$target_element = $value; $target_item->$target_element = $value;
break; break;
...@@ -852,10 +929,7 @@ abstract class FeedsProcessor extends FeedsPlugin { ...@@ -852,10 +929,7 @@ abstract class FeedsProcessor extends FeedsPlugin {
* The serial id of an entity if found, 0 otherwise. * The serial id of an entity if found, 0 otherwise.
*/ */
protected function existingEntityId(FeedsSource $source, FeedsParserResult $result) { protected function existingEntityId(FeedsSource $source, FeedsParserResult $result) {
$targets = &drupal_static('FeedsProcessor::existingEntityId', array()); $targets = $this->getCachedTargets();
if (!isset($targets[$this->id])) {
$targets[$this->id] = $this->getMappingTargets();
}
$entity_id = 0; $entity_id = 0;
...@@ -873,13 +947,13 @@ abstract class FeedsProcessor extends FeedsPlugin { ...@@ -873,13 +947,13 @@ abstract class FeedsProcessor extends FeedsPlugin {
->fetchField(); ->fetchField();
} }
if (!$entity_id && !empty($targets[$this->id][$target]['unique_callbacks'])) { if (!$entity_id && !empty($targets[$target]['unique_callbacks'])) {
if (!is_array($value)) { if (!is_array($value)) {
$value = array($value); $value = array($value);
} }
foreach ($targets[$this->id][$target]['unique_callbacks'] as $callback) { foreach ($targets[$target]['unique_callbacks'] as $callback) {
if (is_callable($callback) && $entity_id = call_user_func_array($callback, array($source, $this->entityType(), $this->bundle(), $target, $value))) { if ($entity_id = call_user_func($callback, $source, $this->entityType(), $this->bundle(), $target, $value)) {
// Stop at the first unique ID returned by a callback. // Stop at the first unique ID returned by a callback.
break; break;
} }
......
...@@ -177,21 +177,13 @@ class FeedsTermProcessor extends FeedsProcessor { ...@@ -177,21 +177,13 @@ class FeedsTermProcessor extends FeedsProcessor {
'description' => array( 'description' => array(
'name' => t('Term description'), 'name' => t('Term description'),
'description' => t('Description of the taxonomy term.'), 'description' => t('Description of the taxonomy term.'),
'summary_callback' => 'text_feeds_summary_callback', 'summary_callbacks' => array('text_feeds_summary_callback'),
'form_callback' => 'text_feeds_form_callback', 'form_callbacks' => array('text_feeds_form_callback'),
), ),
); );
// Let implementers of hook_feeds_term_processor_targets() add their targets. $this->getHookTargets($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.
}
return $targets; return $targets;
} }
......
...@@ -193,11 +193,7 @@ class FeedsUserProcessor extends FeedsProcessor { ...@@ -193,11 +193,7 @@ class FeedsUserProcessor extends FeedsProcessor {
); );
} }
// Let other modules expose mapping targets. $this->getHookTargets($targets);
self::loadMappers();
$entity_type = $this->entityType();
$bundle = $this->bundle();
drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle);
return $targets; return $targets;
} }
......
...@@ -37,6 +37,8 @@ class FeedsMapperConfigTestCase extends FeedsMapperTestCase { ...@@ -37,6 +37,8 @@ class FeedsMapperConfigTestCase extends FeedsMapperTestCase {
// Click gear to get form. // Click gear to get form.
$this->drupalPostAJAX(NULL, array(), 'mapping_settings_edit_0'); $this->drupalPostAJAX(NULL, array(), 'mapping_settings_edit_0');
$second_callback_value = $this->randomString();
// Set some settings. // Set some settings.
$edit = array( $edit = array(
'config[0][settings][checkbox]' => 1, 'config[0][settings][checkbox]' => 1,
...@@ -44,6 +46,7 @@ class FeedsMapperConfigTestCase extends FeedsMapperTestCase { ...@@ -44,6 +46,7 @@ class FeedsMapperConfigTestCase extends FeedsMapperTestCase {
'config[0][settings][textarea]' => 'Textarea value: Didery dofffffffffffffffffffffffffffffffffffff', 'config[0][settings][textarea]' => 'Textarea value: Didery dofffffffffffffffffffffffffffffffffffff',
'config[0][settings][radios]' => 'option1', 'config[0][settings][radios]' => 'option1',
'config[0][settings][select]' => 'option4', 'config[0][settings][select]' => 'option4',
'config[0][settings][second_value]' => $second_callback_value,
); );
$this->drupalPostAJAX(NULL, $edit, 'mapping_settings_update_0'); $this->drupalPostAJAX(NULL, $edit, 'mapping_settings_update_0');
$this->assertText(t('* Changes made to target configuration are stored temporarily. Click Save to make your changes permanent.')); $this->assertText(t('* Changes made to target configuration are stored temporarily. Click Save to make your changes permanent.'));
...@@ -60,6 +63,7 @@ class FeedsMapperConfigTestCase extends FeedsMapperTestCase { ...@@ -60,6 +63,7 @@ class FeedsMapperConfigTestCase extends FeedsMapperTestCase {
$this->assertText('Textarea value: Didery dofffffffffffffffffffffffffffffffffffff'); $this->assertText('Textarea value: Didery dofffffffffffffffffffffffffffffffffffff');
$this->assertText('Radios value: Option 1'); $this->assertText('Radios value: Option 1');
$this->assertText('Select value: Another One'); $this->assertText('Select value: Another One');
$this->assertText(t('Second summary: @value', array('@value' => $second_callback_value)));
// Check that settings are in db. // Check that settings are in db.
$config = unserialize(db_query("SELECT config FROM {feeds_importer} WHERE id='syndication'")->fetchField()); $config = unserialize(db_query("SELECT config FROM {feeds_importer} WHERE id='syndication'")->fetchField());
...@@ -70,6 +74,7 @@ class FeedsMapperConfigTestCase extends FeedsMapperTestCase { ...@@ -70,6 +74,7 @@ class FeedsMapperConfigTestCase extends FeedsMapperTestCase {
$this->assertEqual($settings['textarea'], 'Textarea value: Didery dofffffffffffffffffffffffffffffffffffff'); $this->assertEqual($settings['textarea'], 'Textarea value: Didery dofffffffffffffffffffffffffffffffffffff');
$this->assertEqual($settings['radios'], 'option1'); $this->assertEqual($settings['radios'], 'option1');
$this->assertEqual($settings['select'], 'option4'); $this->assertEqual($settings['select'], 'option4');
$this->assertEqual($settings['second_value'], $second_callback_value);
// Check that form validation works. // Check that form validation works.
......
<?php
/**
* @file
* Test case for the various callbacks implemented for mappers.
*/
/**
* Class for testing Feeds field mapper.
*/
class FeedsMapperHookTestCase extends FeedsMapperTestCase {
public static function getInfo() {
return array(
'name' => 'Mapper: Hooks and callbacks',
'description' => 'Test case for the various callbacks implemented for mappers.',
'group' => 'Feeds',
);
}
/**
* Basic test loading a double entry CSV file.
*/
public function test() {
// Create and configure importer.
$this->createImporterConfiguration();
$this->addMappings('syndication', array(
0 => array(
'source' => 'title',
'target' => 'title',
),
1 => array(
'source' => 'description',
'target' => 'test_target',
),
));
// Checks that alter hooks are invoked.
$this->assertText(t('The target description was altered.'));
// Inherently tests preprocess callbacks.
// @see feeds_tests_mapper_set_target()
$nid = $this->createFeedNode();
$this->drupalGet('node/2/edit');
$body_value = $this->xpath('//*[@name = "body[und][0][value]"]');
$value = unserialize((string) $body_value[0]);
$this->assertTrue(!empty($value));
// Tests old-style target keys.
$this->addMappings('syndication', array(
2 => array(
'source' => 'url',
'target' => 'test_target_compat',
),
));
// Click gear to get form.
$this->drupalPostAJAX(NULL, array(), 'mapping_settings_edit_2');
// Set some settings.
$edit = array(
'config[2][settings][checkbox]' => 1,
'config[2][settings][textfield]' => 'Some text',
'config[2][settings][textarea]' => 'Textarea value: Didery dofffffffffffffffffffffffffffffffffffff',
'config[2][settings][radios]' => 'option1',
'config[2][settings][select]' => 'option4',
);
$this->drupalPostAJAX(NULL, $edit, 'mapping_settings_update_2');
$this->assertText(t('* Changes made to target configuration are stored temporarily. Click Save to make your changes permanent.'));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment