in Drupal, Feeds

Combine images from few feeds and fill multiple value image field

Task:

Fill multiple images field in entity from feeds xml use Xpath parser.

Solution:

1) At first we need install module Feeds entity processor(feeds_entity_processor) to use our feeds with entity

2) We need to create our mapping with hook hook_feeds_node_processor_targets_alter().

and create our virtual field and create callback for this field

3)Within hook

if($name == 'field_name'){
$targets[$info['field_name'] . ':values'] = array (
'name' => t($instance['label'] . ' Values'),
'callback' => 'module_name_set_target_simple_images',
'real_target' => $info['field_name'],
);
}

4)Create callback and alter mapping for our new field

/**
* Example callback specified in hook_feeds_processor_targets_alter().
*
* @param $source
* Field mapper source settings.
* @param $entity
* An entity object, for instance a node object.
* @param $target
* A string identifying the target on the node.
* @param $values
* The values to populate the target with.
*
*/

function module_name_set_target_simple_images($source, $entity, $target, $values) {

// Add default of uri for backwards compatibility.
list($field_name, $sub_field) = explode(':', $target . ':values');
$info = field_info_field($field_name);

if ($sub_field == 'values') {

foreach ($values as $k => $v) {
if (!($v instanceof FeedsEnclosure)) {
if (is_string($v)) {
$values[$k] = new FeedsEnclosure($v, file_get_mimetype($v));
}
else {
// Set the value for FALSE rather than remove it to keep our deltas
// correct.
$values[$k] = FALSE;
}
}
}

$entity_type = $source->importer->processor->entityType();
$bundle = $source->importer->processor->bundle();

$instance_info = field_info_instance($entity_type, $field_name, $bundle);

// Determine file destination.
// @todo This needs review and debugging.
$data = array();
if (!empty($entity->uid)) {
$data[$entity_type] = $entity;
}

$destination = file_field_widget_uri($info, $instance_info, $data);
}

// Populate entity.
$field = isset($entity->$field_name) ? $entity->$field_name : array(LANGUAGE_NONE => array());
$delta = 0;
//dsm($entity);
foreach ($values as $v) {
if ($info['cardinality'] == $delta) {
break;
}

if (!isset($field[LANGUAGE_NONE][$delta])) {
$field[LANGUAGE_NONE][$delta] = array();
}

switch ($sub_field) {
case 'alt':
case 'title':
case 'description':
$field[LANGUAGE_NONE][$delta][$sub_field] = $v;
break;

case 'values':
if ($v) {
try {
$v->setAllowedExtensions($instance_info['settings']['file_extensions']);
$field[LANGUAGE_NONE][$delta] += (array) $v->getFile($destination);
// @todo: Figure out how to properly populate this field.
$field[LANGUAGE_NONE][$delta]['display'] = 1;
}
catch (Exception $e) {
watchdog('feeds', check_plain($e->getMessage()));
}
}
break;
}

$delta++;
}

$entity->$field_name = $field;
}

5)Final step we need to create Hook_feeds_after_parse to combine images from two feeds into one array

/**
* @param \FeedsSource $source
* @param \FeedsParserResult $result
* Implement hook_after_parse
*/
function module_name_feeds_after_parse(FeedsSource $source, FeedsParserResult $result) {
$count = count($result->items);
for($i=0;$i<$count;$i++) { $items[] = $result->items[$i]['xpathparseritem'];
$last = end($result->items);
$last['xpathparseritem'] = $items;
$result->items[$i] = $last;
}
}