=== added file 'mappers/link.inc'
--- mappers/link.inc	1970-01-01 00:00:00 +0000
+++ mappers/link.inc	2009-11-25 07:33:27 +0000
@@ -0,0 +1,77 @@
+<?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' => $name . ' (' . t('url').')',
+          'callback' => 'link_feeds_set_target',
+          'description' => t('The URL for the CCK !name field of the node.', array('!name' => $name)),
+        );
+        if(in_array($field['title'], array('optional', 'required'))) {
+          //Provides a mapping target for the field title if used
+          $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 $vid
+ *   The selected link CCK field.
+ *
+ * @param $value 
+ *
+ */
+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(!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;
+}

=== added file 'tests/feeds_mapper_link.test'
--- tests/feeds_mapper_link.test	1970-01-01 00:00:00 +0000
+++ tests/feeds_mapper_link.test	2009-11-25 07:33:21 +0000
@@ -0,0 +1,167 @@
+<?php
+// $Id:$
+
+require_once(drupal_get_path('module', 'feeds') . '/tests/feeds_mapper_test.inc');
+
+/**
+ * Class for testing Feeds <em>content</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 
+   */
+  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);
+    }
+  }
+}

