From 079da32990ca3e5d828bbe94efd13dc43d32a9c0 Mon Sep 17 00:00:00 2001 From: Alex Barth <alex_b@53995.no-reply.drupal.org> Date: Fri, 15 Jan 2010 19:44:54 +0000 Subject: [PATCH] #623448: David Goode, alex_b, et al.: Date mapper. --- CHANGELOG.txt | 1 + libraries/common_syndication_parser.inc | 3 + mappers/date.inc | 64 ++++ plugins/FeedsParser.inc | 374 +++++++++++++++++++++--- tests/feeds/googlenewstz.rss2 | 8 + tests/feeds_mapper_date.test | 109 +++++++ 6 files changed, 526 insertions(+), 33 deletions(-) create mode 100644 mappers/date.inc create mode 100644 tests/feeds/googlenewstz.rss2 create mode 100644 tests/feeds_mapper_date.test diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 37d88faa..343d27ea 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -3,6 +3,7 @@ Feeds 6.x 1.0 XXXXXXX, 20XX-XX-XX --------------------------------- +- #623448: David Goode, alex_b, et al.: Date mapper. - #624088: mongolito404, David Goode, alex_b: Imagefield/filefield mapper, formalize feed elements. - #584034: aaroncouch, mongolito404: Views integration. diff --git a/libraries/common_syndication_parser.inc b/libraries/common_syndication_parser.inc index 2e5a7467..680d0589 100644 --- a/libraries/common_syndication_parser.inc +++ b/libraries/common_syndication_parser.inc @@ -439,6 +439,9 @@ function _parser_common_syndication_RSS20_parse($feed_XML) { * The timestamp of the string or the current time if can't be parsed */ function _parser_common_syndication_parse_date($date_str) { + // PHP < 5.3 doesn't like the GMT- notation for parsing timezones. + $date_str = str_replace("GMT-", "-", $date_str); + $date_str = str_replace("GMT+", "+", $date_str); $parsed_date = strtotime($date_str); if ($parsed_date === FALSE || $parsed_date == -1) { $parsed_date = _parser_common_syndication_parse_w3cdtf($date_str); diff --git a/mappers/date.inc b/mappers/date.inc new file mode 100644 index 00000000..9926a7c2 --- /dev/null +++ b/mappers/date.inc @@ -0,0 +1,64 @@ +<?php +// $Id$ + +/** + * @file + * On behalf implementation of Feeds mapping API for date + */ + +/** + * Implementation of hook_feeds_node_processor_targets_alter(). + * + * @see FeedsNodeProcessor::getMappingTargets(). + * + * @todo Only provides "end date" target if field allows it. + */ +function date_feeds_node_processor_targets_alter(&$targets, $content_type) { + $info = content_types($content_type); + if (isset($info['fields']) && count($info['fields'])) { + foreach ($info['fields'] as $field_name => $field) { + if (in_array($field['type'], array('date', 'datestamp', 'datetime'))) { + $name = isset($field['widget']['label']) ? $field['widget']['label'] : $field_name; + $targets[$field_name .':start'] = array( + 'name' => $name .': Start', + 'callback' => 'date_feeds_set_target', + 'description' => t('The start date for the !name field. Also use if mapping both start and end.', array('!name' => $name)), + ); + $targets[$field_name .':end'] = array( + 'name' => $name .': End', + 'callback' => 'date_feeds_set_target', + 'description' => t('The end date for the @name field.', array('@name' => $name)), + ); + } + } + } +} + +/** + * Implementation of hook_feeds_set_target(). + * + * @param $node + * The target node. + * @param $field_name + * The name of field on the target node to map to. + * @param $feed_element + * The value to be mapped. Should be either a (flexible) date string + * or a FeedsDateTimeElement object. + * + * @todo Support array of values for dates. + */ +function date_feeds_set_target($node, $target, $feed_element) { + list($field_name, $sub_field) = split(':', $target); + if (!($feed_element instanceof FeedsDateTimeElement)) { + if (is_array($feed_element)) { + $feed_element = $feed_element[0]; + } + if ($sub_field == 'end') { + $feed_element = new FeedsDateTimeElement(NULL, $feed_element); + } + else { + $feed_element = new FeedsDateTimeElement($feed_element, NULL); + } + } + $feed_element->buildDateField($node, $field_name); +} \ No newline at end of file diff --git a/plugins/FeedsParser.inc b/plugins/FeedsParser.inc index 117d14ed..3068c4ed 100644 --- a/plugins/FeedsParser.inc +++ b/plugins/FeedsParser.inc @@ -1,6 +1,61 @@ <?php // $Id$ +/** + * Abstract class, defines interface for parsers. + */ +abstract class FeedsParser extends FeedsPlugin { + + /** + * Parse content fetched by fetcher. + * + * Extending classes must implement this method. + * + * @param $batch + * FeedsImportBatch returned by fetcher. + * @param FeedsSource $source + * Source information. + */ + public abstract function parse(FeedsImportBatch $batch, FeedsSource $source); + + /** + * Clear all caches for results for given source. + * + * @param FeedsSource $source + * Source information for this expiry. Implementers can choose to only clear + * caches pertaining to this source. + */ + public function clear(FeedsSource $source) {} + + /** + * Declare the possible mapping sources that this parser produces. + * + * @return + * An array of mapping sources, or FALSE if the sources can be defined by + * typing a value in a text field. + * + * Example: + * array( + * 'title' => t('Title'), + * 'created' => t('Published date'), + * 'url' => t('Feed item URL'), + * 'guid' => t('Feed item GUID'), + * ) + */ + public function getMappingSources() { + return FALSE; + } + + /** + * Get an element identified by $element_key of the given item. + * The element key corresponds to the values in the array returned by + * FeedsParser::getMappingSources(). + */ + public function getSourceElement($item, $element_key) { + return isset($item[$element_key]) ? $item[$element_key] : ''; + } +} + /** * Defines an element of a parsed result. Such an element can be a simple type, * a complex type (derived from FeedsElement) or an array of either. @@ -43,56 +98,309 @@ class FeedsElement { } /** - * Abstract class, defines interface for parsers. + * Defines a date element of a parsed result (including ranges, repeat). */ -abstract class FeedsParser extends FeedsPlugin { +class FeedsDateTimeElement extends FeedsElement { + + // Start date and end date. + public $start; + public $end; /** - * Parse content fetched by fetcher. + * Constructor. * - * Extending classes must implement this method. + * @param $start + * A FeedsDateTime object or a date as accepted by FeedsDateTime. + * @param $end + * A FeedsDateTime object or a date as accepted by FeedsDateTime. + * @param $tz + * A PHP DateTimeZone object. + */ + public function __construct($start = NULL, $end = NULL, $tz = NULL) { + $this->start = (!isset($start) || ($start instanceof FeedsDateTime)) ? $start : new FeedsDateTime($start, $tz); + $this->end = (!isset($end) || ($end instanceof FeedsDateTime)) ? $end : new FeedsDateTime($end, $tz); + } + + /** + * Override FeedsElement::getValue(). + */ + public function getValue() { + return $this->start; + } + + /** + * Implementation of toString magic php method. + */ + public function __toString() { + $val = $this->getValue(); + if ($val) { + return $val->format('U'); + } + return ''; + } + + /** + * Merge this field with another. Most stuff goes down when merging the two + * sub-dates. * - * @param $batch - * FeedsImportBatch returned by fetcher. - * @param FeedsSource $source - * Source information. + * @see FeedsDateTime */ - public abstract function parse(FeedsImportBatch $batch, FeedsSource $source); + public function merge(FeedsDateTimeElement $other) { + $this2 = clone $this; + if ($this->start && $other->start) { + $this2->start = $this->start->merge($other->start); + } + elseif ($other->start) { + $this2->start = clone $other->start; + } + elseif ($this->start) { + $this2->start = clone $this->start; + } + + if ($this->end && $other->end) { + $this2->end = $this->end->merge($other->end); + } + elseif ($other->end) { + $this2->end = clone $other->end; + } + elseif ($this->end) { + $this2->end = clone $this->end; + } + return $this2; + } /** - * Clear all caches for results for given source. + * Helper method for buildDateField(). Build a FeedsDateTimeElement object + * from a standard formatted node. + */ + protected static function readDateField($node, $field_name) { + $field = content_fields($field_name); + $ret = new FeedsDateTimeElement(); + if ($node->{$field_name}[0]['date'] instanceof FeedsDateTime) { + $ret->start = $node->{$field_name}[0]['date']; + } + if ($node->{$field_name}[0]['date2'] instanceof FeedsDateTime) { + $ret->end = $node->{$field_name}[0]['date2']; + } + return $ret; + } + + /** + * Build a node's date CCK field from our object. * - * @param FeedsSource $source - * Source information for this expiry. Implementers can choose to only clear - * caches pertaining to this source. + * @param $node + * The node to build the date field on. + * @param $field_name + * The name of the field to build. */ - public function clear(FeedsSource $source) {} + public function buildDateField($node, $field_name) { + $field = content_fields($field_name); + $oldfield = FeedsDateTimeElement::readDateField($node, $field_name); + // Merge with any preexisting objects on the field; we take precedence. + $oldfield = $this->merge($oldfield); + $use_start = $oldfield->start; + $use_end = $oldfield->end; + + // Set timezone if not already in the FeedsDateTime object + $to_tz = date_get_timezone($field['tz_handling'], date_default_timezone_name()); + $temp = new FeedsDateTime($to_tz, NULL); + + $db_tz = ''; + if ($use_start) { + $use_start = $use_start->merge($temp); + if (!date_timezone_is_valid($use_start->getTimezone()->getName())) { + $use_start->setTimezone(new DateTimeZone("UTC")); + } + $db_tz = date_get_timezone_db($field['tz_handling'], $use_start->getTimezone()->getName()); + } + if ($use_end) { + $use_end = $use_end->merge($temp); + if (!date_timezone_is_valid($use_end->getTimezone()->getName())) { + $use_end->setTimezone(new DateTimeZone("UTC")); + } + if (!$db_tz) { + $db_tz = date_get_timezone_db($field['tz_handling'], $use_end->getTimezone()->getName()); + } + } + if (!$db_tz) { + return; + } + + $db_tz = new DateTimeZone($db_tz); + if (!isset($node->{$field_name})) { + $node->{$field_name} = array(); + } + if ($use_start) { + $node->{$field_name}[0]['timezone'] = $use_start->getTimezone()->getName(); + $node->{$field_name}[0]['offset'] = $use_start->getOffset(); + $use_start->setTimezone($db_tz); + $node->{$field_name}[0]['date'] = $use_start; + /** + * @todo the date_type_format line could be simplified based upon a patch + * DO issue #259308 could affect this, follow up on at some point. + * Without this, all granularity info is lost. + * $use_start->format(date_type_format($field['type'], $use_start->granularity)); + */ + $node->{$field_name}[0]['value'] = $use_start->format(date_type_format($field['type'])); + } + if ($use_end) { + // Don't ever use end to set timezone (for now) + $node->{$field_name}[0]['offset2'] = $use_end->getOffset(); + $use_end->setTimezone($db_tz); + $node->{$field_name}[0]['date2'] = $use_end; + $node->{$field_name}[0]['value2'] = $use_end->format(date_type_format($field['type'])); + } + } +} + +/** + * Extend PHP DateTime class with granularity handling, merge functionality and + * slightly more flexible initialization parameters. + * + * This class is a Drupal independent extension of the >= PHP 5.2 DateTime + * class. + * + * @see FeedsDateTimeElement class + */ +class FeedsDateTime extends DateTime { + public $granularity = array(); + protected static $allgranularity = array('year', 'month', 'day', 'hour', 'minute', 'second', 'zone'); /** - * Declare the possible mapping sources that this parser produces. + * Overridden constructor. * - * @return - * An array of mapping sources, or FALSE if the sources can be defined by - * typing a value in a text field. + * @param $time + * time string, flexible format including timestamp. + * @param $tz + * PHP DateTimeZone object, NULL allowed + */ + public function __construct($time = '', $tz = NULL) { + if (is_numeric($time)) { + // Assume timestamp. + $time = "@". $time; + } + // PHP < 5.3 doesn't like the GMT- notation for parsing timezones. + $time = str_replace("GMT-", "-", $time); + $time = str_replace("GMT+", "+", $time); + parent::__construct($time, $tz ? $tz : new DateTimeZone("UTC")); + $this->setGranularityFromTime($time, $tz); + if (!preg_match('/[a-zA-Z]/', $this->getTimezone()->getName())) { + // This tz was given as just an offset, which causes problems + $this->setTimezone(new DateTimeZone("UTC")); + } + } + + /** + * This function will keep this object's values by default. + */ + public function merge(FeedsDateTime $other) { + $other_tz = $other->getTimezone(); + $this_tz = $this->getTimezone(); + // Figure out which timezone to use for combination. + $use_tz = ($this->hasGranularity('zone') || !$other->hasGranularity('zone')) ? $this_tz : $other_tz; + + $this2 = clone $this; + $this2->setTimezone($use_tz); + $other->setTimezone($use_tz); + $val = $this2->toArray(); + $otherval = $other->toArray(); + foreach (self::$allgranularity as $g) { + if ($other->hasGranularity($g) && !$this2->hasGranularity($g)) { + // The other class has a property we don't; steal it. + $this2->addGranularity($g); + $val[$g] = $otherval[$g]; + } + } + $other->setTimezone($other_tz); + + $this2->setDate($val['year'], $val['month'], $val['day']); + $this2->setTime($val['hour'], $val['minute'], $val['second']); + return $this2; + } + + /** + * Overrides default DateTime function. Only changes output values if + * actually had time granularity. This should be used as a "converter" for + * output, to switch tzs. * - * Example: - * array( - * 'title' => t('Title'), - * 'created' => t('Published date'), - * 'url' => t('Feed item URL'), - * 'guid' => t('Feed item GUID'), - * ) + * In order to set a timezone for a datetime that doesn't have such + * granularity, merge() it with one that does. */ - public function getMappingSources() { - return FALSE; + public function setTimezone(DateTimeZone $tz, $force = FALSE) { + // PHP 5.2.6 has a fatal error when setting a date's timezone to itself. + // http://bugs.php.net/bug.php?id=45038 + if (version_compare(PHP_VERSION, '5.2.7', '<') && $tz == $this->getTimezone()) { + $tz = new DateTimeZone($tz->getName()); + } + + if (!$this->hasTime() || !$this->hasGranularity('zone') || $force) { + // this has no time or timezone granularity, so timezone doesn't mean much + // We set the timezone using the method, which will change the day/hour, but then we switch back + $arr = $this->toArray(); + parent::setTimezone($tz); + $this->setDate($arr['year'], $arr['month'], $arr['day']); + $this->setTime($arr['hour'], $arr['minute'], $arr['second']); + return; + } + parent::setTimezone($tz); } /** - * Get an element identified by $element_key of the given item. - * The element key corresponds to the values in the array returned by - * FeedsParser::getMappingSources(). + * Safely adds a granularity entry to the array. */ - public function getSourceElement($item, $element_key) { - return isset($item[$element_key]) ? $item[$element_key] : ''; + public function addGranularity($g) { + $this->granularity[] = $g; + $this->granularity = array_unique($this->granularity); } -} \ No newline at end of file + + /** + * Removes a granularity entry from the array. + */ + public function removeGranularity($g) { + if ($key = array_search($g, $this->granularity)) { + unset($this->granularity[$key]); + } + } + + /** + * Checks granularity array for a given entry. + */ + public function hasGranularity($g) { + return in_array($g, $this->granularity); + } + + /** + * Returns whether this object has time set. Used primarily for timezone + * conversion and fomratting. + * + * @todo currently very simplistic, but effective, see usage + */ + public function hasTime() { + return $this->hasGranularity('hour'); + } + + /** + * Protected function to find the granularity given by the arguments to the + * constructor. + */ + protected function setGranularityFromTime($time, $tz) { + $this->granularity = array(); + $temp = date_parse($time); + // This PHP method currently doesn't have resolution down to seconds, so if there is some time, all will be set. + foreach (self::$allgranularity AS $g) { + if (is_numeric($temp[$g]) || ($g == 'zone' && $temp['zone_type'] > 0)) { + $this->granularity[] = $g; + } + } + if ($tz) { + $this->addGranularity('zone'); + } + } + + /** + * Helper to return all standard date parts in an array. + */ + protected function toArray() { + return array('year' => $this->format('Y'), 'month' => $this->format('m'), 'day' => $this->format('d'), 'hour' => $this->format('H'), 'minute' => $this->format('i'), 'second' => $this->format('s'), 'zone' => $this->format('e')); + } +} diff --git a/tests/feeds/googlenewstz.rss2 b/tests/feeds/googlenewstz.rss2 new file mode 100644 index 00000000..66276d3d --- /dev/null +++ b/tests/feeds/googlenewstz.rss2 @@ -0,0 +1,8 @@ +<rss version="2.0"><channel><generator>NFE/1.0</generator><title>Top Stories - Google News</title><link>http://news.google.com?pz=1&ned=us&hl=en</link><language>en</language><webMaster>news-feedback@google.com</webMaster><copyright>&copy;2010 Google</copyright><pubDate>Wed, 06 Jan 2010 15:00:01 GMT+00:00</pubDate><lastBuildDate>Wed, 06 Jan 2010 15:00:01 GMT+00:00</lastBuildDate><image><title>Top Stories - Google News</title><url>http://www.gstatic.com/news/img/bluelogo/en_us/news.gif</url><link>http://news.google.com?pz=1&ned=us&hl=en</link></image> +<item><title>First thoughts: Dems' Black Tuesday - msnbc.com</title><link>http://news.google.com/news/url?fd=R&sa=T&url=http%3A%2F%2Ffirstread.msnbc.msn.com%2Farchive%2F2010%2F01%2F06%2F2166474.aspx&usg=AFQjCNFdbsCs9ORClyOyAOcv9NTwcsKzZQ</link><guid isPermaLink="false">tag:news.google.com,2005:cluster=17593687403189</guid><category>Top Stories</category><pubDate>Wed, 06 Jan 2010 14:26:27 GMT-05:00</pubDate><description><table border="0" cellpadding="2" cellspacing="7" style="vertical-align:top;"><tr><td width="80" align="center" valign="top"><font style="font-size:85%;font-family:arial,sans-serif"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.guardian.co.uk%2Fcommentisfree%2Fmichaeltomasky%2F2010%2Fjan%2F06%2Fchris-dodd-byron-dorgan&amp;usg=AFQjCNGqpLv5bhzKoO6HCYhiJ54B1AQiMw"><img src="http://nt0.ggpht.com/news/tbn/XPqi_u5kO1YrtM/6.jpg" alt="" border="1" width="80" height="80" /><br /><font size="-2">The Guardian</font></a></font></td><td valign="top" class="j"><font style="font-size:85%;font-family:arial,sans-serif"><br /><div style="padding-top:0.8em;"><img alt="" height="1" width="1" /></div><div class="lh"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Ffirstread.msnbc.msn.com%2Farchive%2F2010%2F01%2F06%2F2166474.aspx&amp;usg=AFQjCNFdbsCs9ORClyOyAOcv9NTwcsKzZQ"><b>First thoughts: Dems&#39; Black Tuesday</b></a><br /><font size="-1"><b><font color="#6f6f6f">msnbc.com</font></b></font><br /><font size="-1">Democrats experience a Black Tuesday with retirements from Dodd, Dorgan, and Ritter… While Dodd&#39;s exit is probably a political blessing, the same can&#39;t be said for Dorgan&#39;s or Ritter&#39;s decisions… Republicans are one step closer to putting 11 Senate <b>...</b></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.reuters.com%2Farticle%2FpoliticsNews%2FidUSTRE6052ET20100106&amp;usg=AFQjCNHBEpKDZvHhYMOcNY2De4EDLwhXxQ">Dodd&#39;s decision underscores Democrats&#39; vulnerability</a><font size="-1" color="#6f6f6f"><nobr>Reuters</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.chron.com%2Fdisp%2Fstory.mpl%2Fap%2Ftop%2Fall%2F6801127.html&amp;usg=AFQjCNFmZ6GwjUTYcIyZ7jP6IE17m0t8bw">Dodd, D-Conn., retiring from Senate; AG to run</a><font size="-1" color="#6f6f6f"><nobr>Houston Chronicle</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.miamiherald.com%2Fnews%2Fpolitics%2FAP%2Fstory%2F1411697.html&amp;usg=AFQjCNEtPzHHaLMIX4EMc68ieP7SHfHCfA">Sen. Dodd won&#39;t seek re-election</a><font size="-1" color="#6f6f6f"><nobr>MiamiHerald.com</nobr></font></font><br /><font size="-1" class="p"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.nytimes.com%2Faponline%2F2010%2F01%2F06%2Fus%2FAP-CT-DoddRetirement-Bl.html&amp;usg=AFQjCNHQssq-uyg6reJLjTsMtKjJj_83aQ"><nobr>New York Times</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.washingtonpost.com%2Fwp-dyn%2Fcontent%2Farticle%2F2010%2F01%2F06%2FAR2010010601258.html&amp;usg=AFQjCNGO_LBmoYqmETiD2Y2gdjU9IVxEww"><nobr>Washington Post</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.guardian.co.uk%2Fworld%2F2010%2Fjan%2F06%2Fdemocrat-senators-governors-election-obama&amp;usg=AFQjCNGU16BT2JSIHSYDl831UMHGtchvsQ"><nobr>The Guardian</nobr></a></font><br /><font class="p" size="-1"><a class="p" href="http://news.google.com/news/more?pz=1&amp;ned=us&amp;ncl=dBeDIZhDLhfRYOM2C0cJa6WmMPy3M&amp;topic=h"><nobr><b>all 1,751 news articles&nbsp;&raquo;</b></nobr></a></font></div></font></td></tr></table></description></item> +<item><title>Obama wants to fast track a final health care bill - USA Today</title><link>http://news.google.com/news/url?fd=R&sa=T&url=http%3A%2F%2Fcontent.usatoday.com%2Fcommunities%2Ftheoval%2Fpost%2F2010%2F01%2Fobama-wants-to-fast-track-a-final-health-care-bill%2F1&usg=AFQjCNF1sXxYAFz26OQqKIWh3rBJZxgksg</link><guid isPermaLink="false">tag:news.google.com,2005:cluster=17593688083752</guid><category>Top Stories</category><pubDate>Wed, 06 Jan 2010 13:21:20 GMT+03:00</pubDate><description><table border="0" cellpadding="2" cellspacing="7" style="vertical-align:top;"><tr><td width="80" align="center" valign="top"><font style="font-size:85%;font-family:arial,sans-serif"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.reuters.com%2Farticle%2FidUSTRE5B83ZG20100105&amp;usg=AFQjCNEVrKzaUBu2zEjPQPQ4hzCy6D09LA"><img src="http://nt1.ggpht.com/news/tbn/FWkTTQtlAJkNWM/6.jpg" alt="" border="1" width="80" height="80" /><br /><font size="-2">Reuters</font></a></font></td><td valign="top" class="j"><font style="font-size:85%;font-family:arial,sans-serif"><br /><div style="padding-top:0.8em;"><img alt="" height="1" width="1" /></div><div class="lh"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fcontent.usatoday.com%2Fcommunities%2Ftheoval%2Fpost%2F2010%2F01%2Fobama-wants-to-fast-track-a-final-health-care-bill%2F1&amp;usg=AFQjCNF1sXxYAFz26OQqKIWh3rBJZxgksg"><b>Obama wants to fast track a final health care bill</b></a><br /><font size="-1"><b><font color="#6f6f6f">USA Today</font></b></font><br /><font size="-1">The White House didn&#39;t say much about last night&#39;s health care talks between President Obama and congressional Democrats, but officials made it clear they&#39;re cool with fast-tracking the final phase of legislation, with no public hearings and no <b>...</b></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.medpagetoday.com%2FWashington-Watch%2FReform%2F17812&amp;usg=AFQjCNGFLIoORNDfDJFNXxiNWxuAdyMDNQ">Congress Likely to Combine Healthcare Bills Informally</a><font size="-1" color="#6f6f6f"><nobr>MedPage Today</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwashingtontimes.com%2Fnews%2F2010%2Fjan%2F06%2Freforms-bode-ill-for-tax-free-health-accounts%2F%3Ffeat%3Dhome_headlines&amp;usg=AFQjCNG9QTVx8kHcEaFWdxr3sKIItoB2Dw">Reforms bode ill for tax-free health accounts</a><font size="-1" color="#6f6f6f"><nobr>Washington Times</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fedition.cnn.com%2F2010%2FPOLITICS%2F01%2F06%2Fobama.dems.health.care%2F&amp;usg=AFQjCNHELvYyQ3TAaXqhQtOR5dNkg9qLIA">Sources: Obama, Dems to hold informal talks on health care</a><font size="-1" color="#6f6f6f"><nobr>CNN International</nobr></font></font><br /><font size="-1" class="p"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.nytimes.com%2F2010%2F01%2F06%2Fus%2Fpolitics%2F06cong.html&amp;usg=AFQjCNGcq7OwgK4J1pGeWDZmKrMH9W-Jxg"><nobr>New York Times</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.boston.com%2Fnews%2Fnation%2Fwashington%2Farticles%2F2010%2F01%2F06%2Fdemocrats_focus_on_health_consensus%2F&amp;usg=AFQjCNElF4ajwViPqbvpPD9R2OYeONCE1A"><nobr>Boston Globe</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.kaiserhealthnews.org%2FDaily-Reports%2F2010%2FJanuary%2F06%2FEyes-on-Pelosi-Health-Care.aspx&amp;usg=AFQjCNFS_LBgfNddk8KD2n091RFrqyu15w"><nobr>Kaiser Health News</nobr></a></font><br /><font class="p" size="-1"><a class="p" href="http://news.google.com/news/more?pz=1&amp;ned=us&amp;ncl=dZLcGGGFNPbQ-1My5ui0FO5ST5zTM&amp;topic=h"><nobr><b>all 1,917 news articles&nbsp;&raquo;</b></nobr></a></font></div></font></td></tr></table></description></item> +<item><title>Why the Nexus One Makes Other Android Phones Obsolete - PC World</title><link>http://news.google.com/news/url?fd=R&sa=T&url=http%3A%2F%2Fwww.pcworld.com%2Farticle%2F186006%2Fwhy_the_nexus_one_makes_other_android_phones_obsolete.html&usg=AFQjCNF4WnQcKVu-P5jICC0SNtPAH2IPVw</link><guid isPermaLink="false">tag:news.google.com,2005:cluster=17593685844960</guid><category>Top Stories</category><pubDate>Wed, 06 Jan 2010 13:42:47 GMT+00:00</pubDate><description><table border="0" cellpadding="2" cellspacing="7" style="vertical-align:top;"><tr><td width="80" align="center" valign="top"><font style="font-size:85%;font-family:arial,sans-serif"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.cbc.ca%2Ftechnology%2Fstory%2F2010%2F01%2F05%2Fgoogle-phone.html&amp;usg=AFQjCNGheVBsiY2XOoZ1MhvhbR_Lh6zGPA"><img src="http://nt3.ggpht.com/news/tbn/u_YKGJKq82TQoM/6.jpg" alt="" border="1" width="80" height="80" /><br /><font size="-2">CBC.ca</font></a></font></td><td valign="top" class="j"><font style="font-size:85%;font-family:arial,sans-serif"><br /><div style="padding-top:0.8em;"><img alt="" height="1" width="1" /></div><div class="lh"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.pcworld.com%2Farticle%2F186006%2Fwhy_the_nexus_one_makes_other_android_phones_obsolete.html&amp;usg=AFQjCNF4WnQcKVu-P5jICC0SNtPAH2IPVw"><b>Why the Nexus One Makes Other Android Phones Obsolete</b></a><br /><font size="-1"><b><font color="#6f6f6f">PC World</font></b></font><br /><font size="-1">Google&#39;s new &quot;superphone&quot; runs the latest and greatest version of Android, but don&#39;t expect to see it on older Android phones anytime soon. The Google Nexus One, unveiled on Tuesday, has all the bells and whistles to challenge Apple&#39;s ever-popular <b>...</b></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.crn.com%2Fmobile%2F222200427&amp;usg=AFQjCNEVYevIt9wqQZ8y4wspFqATjYQ_lA">What Google&#39;s Nexus One Really Means</a><font size="-1" color="#6f6f6f"><nobr>ChannelWeb</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Ffeeds.wired.com%2F~r%2Fwired%2Findex%2F~3%2FMO-ku8369hw%2F&amp;usg=AFQjCNFgvwgM3LIoGoTrMSNiqAvYPsZZAQ">Google Debuts Android-Powered Nexus One &#39;Superphone&#39;</a><font size="-1" color="#6f6f6f"><nobr>Wired News</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.reuters.com%2Farticle%2FidUS418924234220100106&amp;usg=AFQjCNHQ-U2aRSw0DP891RC59gRmkZIPjQ">Google Phone Makes a Small Splash</a><font size="-1" color="#6f6f6f"><nobr>Reuters</nobr></font></font><br /><font size="-1" class="p"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.mobileburn.com%2Fnews.jsp%3FId%3D8489&amp;usg=AFQjCNG5LCR6KvvWgtSFFGxctJ4VwoqGpQ"><nobr>Mobile Burn</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.theinquirer.net%2Finquirer%2Fnews%2F1567644%2Fgoogle-releases-nexus-smartphone&amp;usg=AFQjCNFTgpWj8iAnYZIsnC06jkJzkYbQEA"><nobr>Inquirer</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.computerworld.com%2Fs%2Farticle%2F9143115%2FNexus_One_another_tactic_in_Google_s_ad_revenue_strategy&amp;usg=AFQjCNEEev8nSakJJ9vfVc6DuW6jtkM4RQ"><nobr>Computerworld</nobr></a></font><br /><font class="p" size="-1"><a class="p" href="http://news.google.com/news/more?pz=1&amp;ned=us&amp;ncl=djgUAiDaCDB60kMkkiB30PWRy8X7M&amp;topic=h"><nobr><b>all 3,450 news articles&nbsp;&raquo;</b></nobr></a></font></div></font></td></tr></table></description></item> +<item><title>NEWSMAKER-New Japan finance minister a fiery battler - Reuters</title><link>http://news.google.com/news/url?fd=R&sa=T&url=http%3A%2F%2Fwww.reuters.com%2Farticle%2FidUSTOE60509W20100106&usg=AFQjCNGc_qEms8qqrYAmUdQTbFgBlsa51A</link><guid isPermaLink="false">tag:news.google.com,2005:cluster=17593685670703</guid><category>Top Stories</category><pubDate>Wed, 06 Jan 2010 14:05:40 GMT+08:00</pubDate><description><table border="0" cellpadding="2" cellspacing="7" style="vertical-align:top;"><tr><td width="80" align="center" valign="top"><font style="font-size:85%;font-family:arial,sans-serif"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.rte.ie%2Fbusiness%2F2010%2F0106%2Fjapan.html&amp;usg=AFQjCNGQWWOq_Q67WM9NLpuu12eNgAMhbA"><img src="http://nt1.ggpht.com/news/tbn/BVlP-eNLpkIPKM/6.jpg" alt="" border="1" width="80" height="80" /><br /><font size="-2">RTE.ie</font></a></font></td><td valign="top" class="j"><font style="font-size:85%;font-family:arial,sans-serif"><br /><div style="padding-top:0.8em;"><img alt="" height="1" width="1" /></div><div class="lh"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.reuters.com%2Farticle%2FidUSTOE60509W20100106&amp;usg=AFQjCNGc_qEms8qqrYAmUdQTbFgBlsa51A"><b>NEWSMAKER-New Japan finance minister a fiery battler</b></a><br /><font size="-1"><b><font color="#6f6f6f">Reuters</font></b></font><br /><font size="-1">TOKYO, Jan 6 (Reuters) - Japan&#39;s new finance minister, Naoto Kan, is a fiery ruling party heavyweight who faces the tough task of trying to stimulate the economy without upsetting investors by bloating an already huge public debt. <b>...</b></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fonline.wsj.com%2Farticle%2FBT-CO-20100106-706288.html%3Fmod%3DWSJ_World_MIDDLEHeadlinesAsia&amp;usg=AFQjCNG0SB2DSq-JypF3hTmbn6g8sD_gfw">Kan To Take Over As Japan&#39;s Finance Chief</a><font size="-1" color="#6f6f6f"><nobr>Wall Street Journal</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fedition.cnn.com%2F2010%2FWORLD%2Fasiapcf%2F01%2F06%2Fjapan.finance.minister.fujii%2F&amp;usg=AFQjCNG30pVGVZd1rJDOBbKu58fIDOe7Hg">Japanese finance minister Fujii quits</a><font size="-1" color="#6f6f6f"><nobr>CNN International</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fhome.kyodo.co.jp%2Fmodules%2FfstStory%2Findex.php%3Fstoryid%3D479144&amp;usg=AFQjCNGCKkHTxC2EiSqVwMXQOxpfwsEtEw">FOCUS: Figure of Ozawa looms again behind Fujii&#39;s resignation</a><font size="-1" color="#6f6f6f"><nobr>Kyodo News</nobr></font></font><br /><font size="-1" class="p"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.businessweek.com%2Fnews%2F2010-01-06%2Fyen-drops-versus-dollar-as-recovery-fujii-concern-curbs-demand.html&amp;usg=AFQjCNGDSOaJ1bpQh7PsMmjY991lvKkGWg"><nobr>BusinessWeek</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.marketwatch.com%2Fstory%2Fdeputy-pm-kan-named-as-japans-finance-minister-2010-01-06&amp;usg=AFQjCNEBsJZmpuzhn-K7v44k_IOatX2Nig"><nobr>MarketWatch</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.nytimes.com%2F2010%2F01%2F06%2Fworld%2Fasia%2F06japan.html&amp;usg=AFQjCNFs6L5M8MCCG7VuPDcTmE9ek121hw"><nobr>New York Times</nobr></a></font><br /><font class="p" size="-1"><a class="p" href="http://news.google.com/news/more?pz=1&amp;ned=us&amp;ncl=dNT65aGS3zkAmIM8rSpYdo38DRxVM&amp;topic=h"><nobr><b>all 1,156 news articles&nbsp;&raquo;</b></nobr></a></font></div></font></td></tr></table></description></item> +<item><title>Yemen Detains Al-Qaeda Suspects After Embassy Threats - Bloomberg</title><link>http://news.google.com/news/url?fd=R&sa=T&url=http%3A%2F%2Fwww.bloomberg.com%2Fapps%2Fnews%3Fpid%3D20601102%26sid%3DalTEErVe0CIs&usg=AFQjCNGKnUWVDulzUwkJgxAU6QNOPFiHeg</link><guid isPermaLink="false">tag:news.google.com,2005:cluster=17593688042489</guid><category>Top Stories</category><pubDate>Wed, 06 Jan 2010 14:26:39 GMT+03:00</pubDate><description><table border="0" cellpadding="2" cellspacing="7" style="vertical-align:top;"><tr><td width="80" align="center" valign="top"><font style="font-size:85%;font-family:arial,sans-serif"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.telegraph.co.uk%2Fnews%2Fworldnews%2Fmiddleeast%2Fyemen%2F6937316%2FYemen-orders-troops-into-al-Qaeda-strongholds.html&amp;usg=AFQjCNExyEywr12YTiceNZtzlq1NKX-EgQ"><img src="http://nt3.ggpht.com/news/tbn/awRvMhtywz3c-M/6.jpg" alt="" border="1" width="80" height="80" /><br /><font size="-2">Telegraph.co.uk</font></a></font></td><td valign="top" class="j"><font style="font-size:85%;font-family:arial,sans-serif"><br /><div style="padding-top:0.8em;"><img alt="" height="1" width="1" /></div><div class="lh"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.bloomberg.com%2Fapps%2Fnews%3Fpid%3D20601102%26sid%3DalTEErVe0CIs&amp;usg=AFQjCNGKnUWVDulzUwkJgxAU6QNOPFiHeg"><b>Yemen Detains Al-Qaeda Suspects After Embassy Threats</b></a><br /><font size="-1"><b><font color="#6f6f6f">Bloomberg</font></b></font><br /><font size="-1">Jan. 6 (Bloomberg) -- Yemeni security forces said they arrested three suspected al-Qaeda militants linked to a cell of the terrorist group blamed for threats against the US Embassy and other foreign missions. <b>...</b></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww1.voanews.com%2Fenglish%2Fnews%2Fmiddle-east%2FYemen-Claims-3-Al-Qaida-Militants-Captured-in-Connection-with-Embassy-Threat-80780967.html&amp;usg=AFQjCNH5X3tiJ8vsrZoEHFWnJDmw6k3sFw">Yemen Claims 3 Al-Qaida Militants Captured in Connection with Embassy Threat</a><font size="-1" color="#6f6f6f"><nobr>Voice of America</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fnews.bbc.co.uk%2F1%2Fhi%2Fworld%2Fmiddle_east%2F8443078.stm&amp;usg=AFQjCNGYwV-rqv5PegAz5SsldiRvr1dr_g">Yemen &#39;arrests al-Qaeda suspects&#39; wounded in raid</a><font size="-1" color="#6f6f6f"><nobr>BBC News</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fedition.cnn.com%2F2010%2FWORLD%2Fmeast%2F01%2F06%2Fyemen.al.qaeda%2F&amp;usg=AFQjCNFSfbY9qkFcgLRyGQLjfNex-5KNQw">Yemen arrests 3 al Qaeda suspects</a><font size="-1" color="#6f6f6f"><nobr>CNN International</nobr></font></font><br /><font size="-1" class="p"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.google.com%2Fhostednews%2Fafp%2Farticle%2FALeqM5h4NbgbHk88RSPSpOCG5Cg6f6FrvA&amp;usg=AFQjCNHN_z8Ds-OxNhIRl_MZxRtEeAp_dg"><nobr>AFP</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.chicagotribune.com%2Fnews%2Fchi-tc-nw-yemen-qaeda-0105-0106jan06%2C0%2C3246858.story&amp;usg=AFQjCNHto_VTKl2AdlO7yF7D9Uk3CkMlxw"><nobr>Chicago Tribune</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.ynetnews.com%2Farticles%2F0%2C7340%2CL-3830342%2C00.html&amp;usg=AFQjCNHK0DJcyGgEyjaz-fxTXgicYFGnLQ"><nobr>Ynetnews</nobr></a></font><br /><font class="p" size="-1"><a class="p" href="http://news.google.com/news/more?pz=1&amp;ned=us&amp;ncl=duEsXKdHWTVEzZMnfUiaVj_DuDpAM&amp;topic=h"><nobr><b>all 1,584 news articles&nbsp;&raquo;</b></nobr></a></font></div></font></td></tr></table></description></item> +<item><title>Egypt, Hamas exchange fire on Gaza frontier, 1 dead - Reuters</title><link>http://news.google.com/news/url?fd=R&sa=T&url=http%3A%2F%2Fwww.reuters.com%2Farticle%2FidUSTRE60526A20100106&usg=AFQjCNG4UuyUmz-Wd6YhmbdvupkbHbHYAA</link><guid isPermaLink="false">tag:news.google.com,2005:cluster=17593688298004</guid><category>Top Stories</category><pubDate>Wed, 06 Jan 2010 14:26:26 GMT-10:00</pubDate><description><table border="0" cellpadding="2" cellspacing="7" style="vertical-align:top;"><tr><td width="80" align="center" valign="top"><font style="font-size:85%;font-family:arial,sans-serif"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fenglish.aljazeera.net%2Fnews%2Fmiddleeast%2F2010%2F01%2F201016123715308843.html&amp;usg=AFQjCNF5jDZ_Ucs9aLP_5ohKQfuUwTh3Dg"><img src="http://nt3.ggpht.com/news/tbn/L9ZIsOJouvA_fM/6.jpg" alt="" border="1" width="80" height="80" /><br /><font size="-2">Aljazeera.net</font></a></font></td><td valign="top" class="j"><font style="font-size:85%;font-family:arial,sans-serif"><br /><div style="padding-top:0.8em;"><img alt="" height="1" width="1" /></div><div class="lh"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.reuters.com%2Farticle%2FidUSTRE60526A20100106&amp;usg=AFQjCNG4UuyUmz-Wd6YhmbdvupkbHbHYAA"><b>Egypt, Hamas exchange fire on Gaza frontier, 1 dead</b></a><br /><font size="-1"><b><font color="#6f6f6f">Reuters</font></b></font><br /><font size="-1">GAZA (Reuters) - An Egyptian soldier was killed and four Palestinians were wounded in a gunbattle on Wednesday during a protest against an anti-smuggling wall Cairo is building on the Gaza border. The violence was the most serious between Egyptian and <b>...</b></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fenglish.aljazeera.net%2Fnews%2Fmiddleeast%2F2010%2F01%2F201016123715308843.html&amp;usg=AFQjCNF5jDZ_Ucs9aLP_5ohKQfuUwTh3Dg">Lethal clashes at Gaza-Egypt border</a><font size="-1" color="#6f6f6f"><nobr>Aljazeera.net</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.google.com%2Fhostednews%2Fafp%2Farticle%2FALeqM5hlyBEcozp_DcZhUdakcB2mnTmUoQ&amp;usg=AFQjCNHFBHDUXezq_jQgJFOxw_6c7eghtg">Gaza gunfire kills Egypt policeman: Egypt state TV</a><font size="-1" color="#6f6f6f"><nobr>AFP</nobr></font></font><br /><font size="-1"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fnews.xinhuanet.com%2Fenglish%2F2010-01%2F06%2Fcontent_12766842.htm&amp;usg=AFQjCNGsyoHSwxXprG-AyOwX12dmdd9Q5g">Calm back to Egypt&#39;s borders with Gaza after clashes</a><font size="-1" color="#6f6f6f"><nobr>Xinhua</nobr></font></font><br /><font size="-1" class="p"><a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.ynetnews.com%2Farticles%2F0%2C7340%2CL-3830579%2C00.html&amp;usg=AFQjCNGsfWllg2QfhV4pX-MXEl8VRuIqsg"><nobr>Ynetnews</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.nytimes.com%2Faponline%2F2010%2F01%2F05%2Fworld%2FAP-ML-Palestinians-Sealing-Gaza.html&amp;usg=AFQjCNEf0LP7EnK0t3uIOBOtsPm9rDuVug"><nobr>New York Times</nobr></a>&nbsp;-<a href="http://news.google.com/news/url?fd=R&amp;sa=T&amp;url=http%3A%2F%2Fwww.guardian.co.uk%2Fworld%2F2010%2Fjan%2F06%2Fgeorge-galloway-gaza-aid-convoy&amp;usg=AFQjCNFQyAgvHovIr6y9DmwmjghS7WNRXQ"><nobr>The Guardian</nobr></a></font><br /><font class="p" size="-1"><a class="p" href="http://news.google.com/news/more?pz=1&amp;ned=us&amp;ncl=djNuENxfWRzRYjMzw1nruQqIJxslM&amp;topic=h"><nobr><b>all 635 news articles&nbsp;&raquo;</b></nobr></a></font></div></font></td></tr></table></description></item> +<description>Google News</description></channel></rss> \ No newline at end of file diff --git a/tests/feeds_mapper_date.test b/tests/feeds_mapper_date.test new file mode 100644 index 00000000..105eb936 --- /dev/null +++ b/tests/feeds_mapper_date.test @@ -0,0 +1,109 @@ +<?php +// $Id$ + +/** + * @file + * Test case for CCK date field mapper mappers/content.inc. + */ + +require_once(drupal_get_path('module', 'feeds') . '/tests/feeds_mapper_test.inc'); + +/** + * Class for testing Feeds <em>content</em> 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: 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 RSS', 'daterss'); + $this->setSettings('daterss', NULL, array('content_type' => '', 'import_period' => FEEDS_SCHEDULE_NEVER,)); + $this->setPlugin('daterss', 'FeedsFileFetcher'); + $this->setPlugin('daterss', 'FeedsSyndicationParser'); + $this->setSettings('daterss', 'FeedsNodeProcessor', array('content_type' => $typename)); + $this->addMappings('daterss', array( + array( + 'source' => 'title', + 'target' => 'title', + ), + array( + 'source' => 'description', + 'target' => 'body', + ), + array( + 'source' => 'timestamp', + 'target' => 'field_date:start', + ), + array( + 'source' => 'timestamp', + 'target' => 'field_datestamp:start', + ), + )); + + // Import CSV file. + $this->importFile('daterss', $this->absolutePath() .'/tests/feeds/googlenewstz.rss2'); + $this->assertText('Created 6 '. $typename .' nodes.'); + + // Check the imported nodes. + $values = array( + '01/06/2010 - 19:26', + '01/06/2010 - 10:21', + '01/06/2010 - 13:42', + '01/06/2010 - 06:05', + '01/06/2010 - 11:26', + '01/07/2010 - 00:26', + ); + for ($i = 1; $i <= 6; $i++) { + $this->drupalGet("node/$i/edit"); + $this->assertCCKFieldValue('date', $values[$i-1]); + $this->assertCCKFieldValue('datestamp', $values[$i-1]); + } + } + + 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); + } + } +} -- GitLab