=== added file 'mappers/date.inc' --- mappers/date.inc 1970-01-01 00:00:00 +0000 +++ mappers/date.inc 2009-12-01 13:39:53 +0000 @@ -0,0 +1,184 @@ + $field) { + // Check to see if the field type is a date (CCK). + if (in_array($field['type'], array('date', 'datestamp', 'datetime'))) { + // Set the name for the source label to be the label of the field or the field name if no label exists + $name = isset($field['widget']['label']) ? $field['widget']['label'] : $field_name; + + $targets[$field_name.'#'] = array( + 'name' => $name . ' (' . $sub_field .')', + 'callback' => 'date_feeds_set_target', + 'description' => t('The start date for the !name field when set from a UNIX timestamp source.', array('!date_time' => $description, '!name' => $name)), + ); + $targets[$field_name.'#2'] = array( + 'name' => $name . ' (' . $sub_field .')', + 'callback' => 'date_feeds_set_target', + 'description' => t('The end date for the !name field when set from a UNIX timestamp source.', array('!date_time' => $description, '!name' => $name)), + ); + + //Special target for iCal VEVENT + $targets[$field_name.'#ical'] = array( + 'name' => $name .' (iCal)', + 'description' => t('The !name field when set from an iCal VEVENT source.', array('!name' => $name)), + 'callback' => 'date_feeds_set_target_from_ical', + ); + } + } + } +} + +/** + * Callback for mapping from an iCal VEVENT source to CCK date fields. + */ +function date_feeds_set_target_from_ical(&$node, $target, $values) { + + list($field_name, $sub_filed) = split('#', $target); + $field = isset($node->$field_name) ? $node->$field_name : array(); + + //We handle multiple values, be sure that $values is an array of values + if(!is_array($values)) { + $values = array($values); + } else { + //Ok we have an array, but is it used as structured data ? + foreach(arrays_keys($values) as $key) { + if(!is_numeric($key)) { + $values = array($values); + continue; + } + } + } + + foreach(array_values($values) as $delta => $value) { + if(array_key_exists('DATE', $value)) { + $value = $value['DATE']; + } + //Set the field value from + if(isset($value['DTSTART']['datetime'])) date_feeds_set_target($node, $field_name.'#', array($delta => $value['DTSTART']['datetime'])); + if(isset($value['DTSTART']['datetime'])) date_feeds_set_target($node, $field_name.'#', array($delta => $value['DTSTART']['datetime'])); + } +} + +/** + * Callback for mapping to a CCK date field. + * + * @todo: Add support for the field format when parsing values (as 1st fallback) + * @todo: Add support for common formats when parsing values on PHP < 5.3 (see _create_date_from_known_formats) + */ +function date_feeds_set_target(&$node, $target, $values) { + //Seperate out component parts. $field_name should be set to field_date, $sub_field to date. + list($field_name, $suffix) = split('#', $target); + + $field = content_fields($field_name, $node->type); + + //Timezone objects + $timezone_utc = timezone_open('UTC'); + $field_timezone = timezone_open(date_get_timezone($field['tz_handling'], date_default_timezone_name())); + if(!$field_timezone) { + $field_timezone = $timezone_utc; + } + + //Initial values from the field + $field_data = isset($node->$field_name) ? $node->$field_name : array(); + + //We handle multiple values, be sure that $values is an array of values + if(!is_array($values)) { + $values = array($values); + } else { + //Ok we have an array, but is it used as structured data ? + foreach(arrays_keys($values) as $key) { + if(!is_numeric($key)) { + $values = array($values); + continue; + } + } + } + + foreach(array_values($values) as $delta => $value) { + //Read the $value as a DateTime object + //Parse it as a timestamp + $date = date_create("@$value", $timezone_utc); + //TODO: 1st fallback, parse it using the field format + //if(!$date) $date = ... + //2nd fallback, parse it using known date formats (W3C, etc.) + if(!$date) $date = _create_date_from_known_formats($value, $timezone_utc); + //Everything else failed, let date_create parse the string + if(!$date) $date = date_create($value, $timezone_utc); + + if($date) { + //Are these value needed ? + //$field_data[$delta][$sub_field]['date'.$suffix] = $date; + //$field_data[$delta][$sub_field]['offset'.$suffix] = $date->getOffset(); + //$field_data[$delta][$sub_field]['timezone'.$suffix] = $field_timezone->getName(); + $date->setTimezone($field_timezone); + $field_data[$delta]['value'.$suffix] = $date->format(date_type_format($field['type'])); + } else { + drupal_set_message(t('Could not parse %value as a date.', array('%value' => $value)), 'error'); + } + } + $node->$field_name = $field_data; +} + +if (version_compare(PHP_VERSION, '5.3', '>=')) { + /** + * Tries to parse a string to a DateTime object using known date formats. + * + * @param $time String representing the time. + * @param $timezone Time zone + * + * @return A DateTime object. Or FALSE if $value cannot be parsed using a + * known format. + */ + function _create_date_from_known_formats($time, $timezone) { + //See http://php.net/manual/class.datetime.php#datetime.constants.types + static $formats = array( + DateTime::ATOM, + DateTime::RSS, + DateTime::W3C, + DateTime::RFC3339, + DateTime::RFC2822, + DateTime::RFC1123, + DateTime::RFC1036, + DateTime::RFC850, + DateTime::RFC822, + DateTime::ISO8601, + DateTime::COOKIE, + ); + + foreach($formats as $format) { + if($date = DateTime::createFromFormat($format, $value, $timezone)) { + return $date; + } + } + return FALSE; + } +} else { + /** + * @todo + * + * @param $time String representing the time. + * @param $timezone Time zone + * + * @return A DateTime object. Or FALSE if $value cannot be parsed using a + * known format. + */ + function _create_date_from_known_formats($time, $timezone) { + return FALSE; + } +} \ No newline at end of file === added file 'tests/feeds_mapper_date.test' --- tests/feeds_mapper_date.test 1970-01-01 00:00:00 +0000 +++ tests/feeds_mapper_date.test 2009-12-01 13:30:23 +0000 @@ -0,0 +1,107 @@ +content mapper. + * + * @todo: Add test method iCal + * @todo: Add test method for end date + */ +class FeedsMapperDateTestCase extends FeedsMapperTestCase { + + public static function getInfo() { + return array( + 'name' => t('Mapper: CCK Date'), + 'description' => t('Test Feeds Mapper support for CCK date fields'), + 'group' => t('Feeds'), + ); + } + + /** + * Set up the test. + */ + public function setUp() { + // Call parent setup with the required module. + parent::setUp('feeds', 'feeds_ui', 'ctools', 'content', 'date_api', 'date'); + + // Create user and login. + $this->drupalLogin($this->drupalCreateUser( + array( + 'administer content types', + 'administer feeds', + 'administer nodes', + 'administer site configuration', + ) + )); + } + + /** + * Basic test loading a single entry CSV file. + */ + public function test() { + + // Create content type. + $typename = $this->createContentType(NULL, array( + 'date' => 'date', + 'datestamp' => 'datestamp', + 'datetime' => 'datetime', + )); + + // Create and configure importer. + $this->createFeedConfiguration('Date CSV', 'csv'); + $this->setSettings('csv', NULL, array('content_type' => '','import_period' => FEEDS_SCHEDULE_NEVER,)); + $this->setPlugin('csv', 'FeedsFileFetcher'); + $this->setPlugin('csv', 'FeedsCSVParser'); + $this->setSettings('csv', 'FeedsNodeProcessor', array('content_type' => $typename)); + $this->addMappings('csv', array( + array( + 'source' => 'format', + 'target' => 'title', + ), + array( + 'source' => 'value', + 'target' => 'body', + ), + array( + 'source' => 'value', + 'target' => 'field_date#', + ), + array( + 'source' => 'value', + 'target' => 'field_datetime#', + ), + array( + 'source' => 'value', + 'target' => 'field_datestamp#', + ), + )); + + // Import CSV file. + $this->importFile('csv', $this->absolutePath() .'/tests/feeds/date.csv'); + $this->assertText('Created 13 '. $typename .' nodes.'); + + // Check the imported nodes. + $date = '12/01/2009 - 12:41'; + for($i = 1; $i <= 13; $i++) { + $this->drupalGet("node/$i/edit"); + $this->assertCCKFieldValue('date', $date); + $this->assertCCKFieldValue('datetime', $date); + $this->assertCCKFieldValue('datestamp', $date); + } + } + +protected function getFormFieldsNames($field_name, $index) { + if(in_array($field_name, array('date', 'datetime', 'datestamp'))) { + return array("field_{$field_name}[{$index}][value][date]"); + } else { + return parent::getFormFieldsNames($field_name, $index); + } + } +}