FeedAPI mapper support

reikiman - September 2, 2009 - 05:00
Project:RSS Remote Enclosure
Version:6.x-1.0
Component:Code
Category:feature request
Priority:normal
Assigned:reikiman
Status:active
Description

To be done after: #565904: Add CCK support

Implement a FeedAPI mapper function to convert enclosure tags on incoming feeds into encl_remote fields.

I have code here: http://hg.davidherron.com/index.cgi/drupalv6/file/tip/sites/all/modules/...

#1

reikiman - September 7, 2009 - 20:43

As noted in the other issue (to convert encl_remote into a CCK type) I just wrote a FieldAPI mapper that converts RSS elements into encl_remote fields. It involves adding two small functions to encl_remote.

With the functions encl_remote shows up in the list of targets.

I'm using FeedAPI with the simplepie parser. Am able to define a mapping from options->all->enclosure to the encl_remote target and it works perfectly.

I need to do this as a proper patch, yes, but this is the code.

//////////////////////////
// FEEDAPI MAPPER SUPPORT
//////////////////////////

/**
* Implement hook_feedapi_mapper() to map an element of a feed to a field on a
* node.
*
* Mapping flow
*
* 1) hook_feedapi_mapper('list')
*
* This operation is invoked when the mapper is about to present mapping
* options to the user. When $op is 'list' the $node parameter contains the
* type of the node at $node->type, all other parameters are not present.
* Examine $node->type and determine which mapping targets are available.
*
* If no mapping target is available return FALSE.
*
* If a single mapping target is available return:
* array(
*   'single_target' => t('Single target'), // 'single_target' will be the value of $field_name on 'map'
* )
*
* If multiple mapping targets are available return:
* array(
*   'target1' => t('Target 1'), // 'target1' will be the field name on 'map'
*   'target2' => t('Target 2'), // 'target2' will be the field name on 'map'
* )
*
* Feed Element Mapper also supports sub fields:
* array(
*   'multiple_targets' => array( // 'multiple_targets' will be the value of $field_name on 'map'
*     'target1' => t('Target 1'), // 'target1' will be the value of $sub_field on 'map'
*     'target2' => t('Target 2'), // 'target2' will be the value of $sub_field on 'map'
*   )
* )
*
*
* 2) hook_feedapi_mapper('map')
*
* This operation is invoked when the actual mapping happens. If a user
* selected the mapping functionality exposed on 'list' hook_feedapi_mapper
* will be called on node prepare with $op == 'map', $node = feed item node the
* mapping is performed on, $feed_element = the element of the feed that a user
* chose as a mapping source, $field_name = the name of the field that a user
* chose as a mapping target, $sub_field = the name of the sub field that a user
* chose as a mapping target.
*
*
* hook_feedapi_mapper('describe') is used to generate help text on the
* mapping form.
*
* Which feed elements are available for mapping is up to the parser.
*
* @param $op
*   Operation to perform.
*   Value of $op is one of 'describe', 'list' or 'map'.
* @param $node
*   Drupal node object.
* @param $feed_element
*   Parameter only present on $op = 'map'
*   Element of the feed to map from. A simple data type (number, string) or a
*   one dimensional array of simple types.
* @param $field_name
*   Parameter only present on $op = 'map'
*   Name of the field to map to.
* @param $sub_field
*   Parameter only present on $op = 'map'
*   If given, a subfield on the node to map to.
*   This parameter will depend on if the hook implementation returns a subfield on
*   $op = 'list'.
*  
*/
function encl_remote_feedapi_mapper($op, $node, $feed_element = array(), $field_name = '', $sub_field = '') {
  // Test for the node field that we would like to map to.
  if ($op == 'describe') {
    return t('Maps an enclosure tag to encl_remote.');
  }
  else if ($op == 'list') {
    if (_encl_remote_is_nodetype_allowed($node->type)) {
      $fields = array();
      $field_name = 'encl_remote';
      $fields[$field_name] = $field_name;
      return $fields; 
    }
    return FALSE;
  }
  else if ($op == 'map') {
    if (is_array($feed_element)) {
      // These are the attributes of an <enclosure>
      $node->url   = $feed_element['@url'];
      $node->link_text  = $feed_element['#text'];
      $node->size  = $feed_element['@length'];
      $node->mime_type = $feed_element['@type'];
      // The rest is handled in nodeapi hook presave && update/insert
    }
    return $node;
  }
}

/**
* Implement hook_feedapi_mapper_elements to define standard elements that your
* configuration should be able to map to.
*
* When FeedAPI Mapper exposes the mapping form on a feed node (node/%/map), it
* parses the feed and uses the result to make elements of it available as
* mapping sources.
*
* However, when FeedAPI mapper exposes the mapping form on a content type
* form (admin/content/node-type/%/map), there is no feed to parse for
* discovering feed elements. In this case FeedAPI Mapper exposes some standard
* elements. You may find yourself in the need for more specific standard
* elements on the content type level, in this case implement
* hook_feedapi_mapper_elements() in your module.
*
* @see _feedapi_mapper_get_standard_elements().
*
* @return
*   An array of arrays that describe the path to a feed element on a feed.
*/
function encl_remote_feedapi_mapper_elements() {
  return array(
    array('options', 'enclosures'),
  );
}

 
 

Drupal is a registered trademark of Dries Buytaert.