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/...

Comments

reikiman’s picture

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'),
  );
}
zany’s picture

Status: Active » Closed (won't fix)

Good idea but D6 (and FeedApi) isn't that useful anymore. Closing.