Index: mappers/link.inc
===================================================================
RCS file: mappers/link.inc
diff -N mappers/link.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ mappers/link.inc	11 Mar 2010 10:53:09 -0000
@@ -0,0 +1,82 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * On behalf implementation of Feeds mapping API for link.module (CCK).
+ */
+
+/**
+ * Implementation of hook_feeds_node_processor_targets_alter().
+ */
+function link_feeds_node_processor_targets_alter($targets, $content_type) {
+  $info = content_types($content_type);
+
+  $fields = array();
+  if (isset($info['fields']) && count($info['fields'])) {
+    foreach ($info['fields'] as $field_name => $field) {
+
+      if (in_array($field['type'], array('link'))) {
+        $name = isset($field['widget']['label']) ? $field['widget']['label'] : $field_name;
+        $targets[$field_name .':url'] = array(
+          'name' => t('!field_name (URL)', array('!field_name' => $name)),
+          'callback' => 'link_feeds_set_target',
+          'description' => t('The URL for the CCK !name field of the node.', array('!name' => $name)),
+        );
+
+        //Provides a mapping target for the field title if used.
+        if (in_array($field['title'], array('optional', 'required'))) {
+          $targets[$field_name .':title'] = array(
+            'name' => $name .' (' . t('title').')',
+            'callback' => 'link_feeds_set_target',
+            'description' => t('The title for the CCK !name field of the node.', array('!name' => $name)),
+          );
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Callback for mapping to link field.
+ *
+ * @param $node
+ *   Reference to the node object we are working on.
+ * @param $target
+ *   The selected link CCK field.
+ * @param $value
+ *   The value to assign to the CCK field.
+ */
+function link_feeds_set_target($node, $target, $value) {
+  static $defaults = array();
+  list($field_name, $sub_field) = split(':', $target);
+
+  if (!isset($defaults[$node->type][$field_name])) {
+    $field = content_fields($field_name, $node->type);
+    $defaults[$node->type][$field_name]['attributes'] = $field['attributes'];
+    if (!in_array($field['title'], array('optional', 'required', 'none'))) {
+      $defaults[$node->type][$field_name]['title'] = $field['title_value'];
+    }
+  }
+  $field_data = isset($node->$field_name) ? $node->$field_name : array();
+
+  if (!is_array($value)) {
+  	$value = array($value);
+  }
+
+  $i = 0;
+  foreach ($value as $v) {
+    if ($v instanceof FeedsEnclosure) {
+      $v = $v->getValue(); 
+    }
+    if (!isset($field_data[$i])) {
+      $field_data[$i] = $defaults[$node->type][$field_name];
+    }
+    if ($sub_field != 'url' || (($v = link_cleanup_url($v)) && valid_url($v, true))) {
+      $field_data[$i][$sub_field] = $v;
+    }
+    $i++;
+  }
+
+  $node->$field_name = $field_data;
+}
Index: tests/feeds_mapper_link.test
===================================================================
RCS file: tests/feeds_mapper_link.test
diff -N tests/feeds_mapper_link.test
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/feeds_mapper_link.test	11 Mar 2010 10:53:10 -0000
@@ -0,0 +1,169 @@
+<?php
+// $Id$
+
+require_once(drupal_get_path('module', 'feeds') . '/tests/feeds_mapper_test.inc');
+
+/**
+ * Class for testing Feeds <em>link</em> mapper.
+ */
+class FeedsMapperLinkTestCase extends FeedsMapperTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => t('Mapper: Link'),
+      'description' => t('Test Feeds Mapper support for Link CCK fields'),
+      'group' => t('Feeds'),
+    );
+  }
+
+  /**
+   * Set up the test.
+   */
+  public function setUp() {
+    // Call parent setup with the required module
+    parent::setUp(
+    	'devel', 'feeds', 'feeds_ui', 'ctools', 'content', 'link'
+    );
+
+    // Create user and login
+    $this->drupalLogin($this->drupalCreateUser(
+        array(
+          'administer content types',
+          'administer feeds',
+          'administer nodes',
+          'administer site configuration',
+        	'access devel information'
+        )
+    ));
+  }
+
+  /**
+   * Basic test loading a single entry CSV file.
+   */
+  public function test() {
+    $static_title = $this->randomName();
+
+    // Create content type.
+    $typename = $this->createContentType(NULL, array(
+      'alpha' => array(
+        'type' => 'link',
+        'settings' => array(
+          'title' => 'required',
+          'multiple' =>  '0',
+        ),
+      ),
+      'beta' => array(
+        'type' => 'link',
+        'settings' => array(
+          'title' => 'none',
+          'multiple' => '0',
+        ),
+      ),
+      'gamma' => array(
+        'type' => 'link',
+        'settings' => array(
+          'title' => 'optional',
+          'multiple' =>  '0',
+        ),
+      ),
+      'omega' => array(
+      'type' => 'link',
+        'settings' => array(
+          'title' => 'value',
+          'title_value' => $static_title,
+          'multiple' =>  '0',
+        ),
+      ),
+    ));
+
+    //Create importer configuration
+    $this->createFeedConfiguration(); //Create a default importer configuration
+    $this->setSettings('syndication', 'FeedsNodeProcessor', array('content_type' => $typename)); //Processor settings
+    $this->addMappings('syndication', array(
+      array(
+        'source' => 'title',
+        'target' => 'title'
+      ),
+      array(
+        'source' => 'timestamp',
+        'target' => 'created'
+      ),
+      array(
+        'source' => 'description',
+        'target' => 'body'
+      ),
+      array(
+        'source' => 'url',
+        'target' => 'field_alpha:url'
+      ),
+      array(
+        'source' => 'title',
+        'target' => 'field_alpha:title'
+      ),
+      array(
+        'source' => 'url',
+        'target' => 'field_beta:url'
+      ),
+      array(
+        'source' => 'url',
+        'target' => 'field_gamma:url'
+      ),
+      array(
+        'source' => 'title',
+        'target' => 'field_gamma:title'
+      ),
+      array(
+        'source' => 'url',
+        'target' => 'field_omega:url'
+      ),
+    ));
+
+    // Import RSS file.
+    $nid = $this->createFeedNode();
+    // Assert 10 items aggregated after creation of the node.
+    $this->assertText('Created 10 '. $typename .' nodes.');
+
+    // Edit the imported node.
+    $this->drupalGet('node/2/edit');
+
+    $url = 'http://developmentseed.org/blog/2009/oct/06/open-atrium-translation-workflow-two-way-updating';
+    $title = 'Open Atrium Translation Workflow: Two Way Translation Updates';
+    $this->assertCCKFieldValue('alpha', array('url' => $url, 'static' => $title));
+    $this->assertCCKFieldValue('beta', array('url' =>  $url));
+    $this->assertCCKFieldValue('gamma', array('url' => $url, 'static' => $title));
+    $this->assertCCKFieldValue('omega', array('url' => $url, 'static' => $static_title));
+
+    // Test the static title.
+    $this->drupalGet('node/2');
+    $this->assertText($static_title, 'Static title link found.');
+
+  }
+
+  protected function getFormFieldsNames($field_name, $index) {
+    if(in_array($field_name, array('alpha', 'beta', 'gamma', 'omega'))) {
+      $fields = array("field_{$field_name}[{$index}][url]");
+      if(in_array($field_name, array('alpha', 'gamma'))) {
+        $fields[] = "field_{$field_name}[{$index}][title]";
+      }
+      return $fields;
+    }
+    else {
+      return parent::getFormFieldsNames($field_name, $index);
+    }
+  }
+
+  protected function getFormFieldsValues($field_name, $value) {
+    $field = content_fields($field_name);
+    if(in_array($field_name, array('alpha', 'beta', 'gamma', 'omega'))) {
+      if(!is_array($value)) $value = array('url' => $value);
+      $values = array($value['url']);
+      if(in_array($field_name, array('alpha', 'gamma'))) {
+        $values[] = $value['title'];
+      }
+      return $values;
+    }
+    else {
+      return parent::getFormFieldsValues($field_name, $index);
+    }
+  }
+}
