diff --git a/feeds.info b/feeds.info index 052010e256a269c8c1123abd2feaaa78d4dcd8cd..8041cbff26fc8cad0b3c9f0602666928b262945f 100644 --- a/feeds.info +++ b/feeds.info @@ -32,6 +32,7 @@ files[] = plugins/FeedsUserProcessor.inc files[] = tests/feeds.test files[] = tests/feeds_date_time.test files[] = tests/feeds_mapper_date.test +files[] = tests/feeds_mapper_date_multiple.test files[] = tests/feeds_mapper_field.test files[] = tests/feeds_mapper_file.test files[] = tests/feeds_mapper_path.test diff --git a/mappers/date.inc b/mappers/date.inc index a96143a340e132c2c568481244ef599c1ab92fe5..9344d279bdaec67be1c71d4c7b6ecb1a7a281eef 100644 --- a/mappers/date.inc +++ b/mappers/date.inc @@ -43,23 +43,26 @@ function date_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam * 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($source, $entity, $target, $feed_element) { list($field_name, $sub_field) = explode(':', $target, 2); if (!($feed_element instanceof FeedsDateTimeElement)) { - if (is_array($feed_element)) { - $feed_element = $feed_element[0]; + if (!is_array($feed_element)) { + $feed_element = array($feed_element); } - if (empty($feed_element) || !is_numeric($feed_element) && !date_create($feed_element)) { - $feed_element = new FeedsDateTimeElement(NULL, NULL); - } - elseif ($sub_field == 'end') { - $feed_element = new FeedsDateTimeElement(NULL, $feed_element); - } - else { - $feed_element = new FeedsDateTimeElement($feed_element, NULL); + $delta = 0; + foreach ($feed_element as $f) { + if (empty($f) || !is_numeric($f) && !date_create($f)) { + $array_element = new FeedsDateTimeElement(NULL, NULL); + } + elseif ($sub_field == 'end') { + $array_element = new FeedsDateTimeElement(NULL, $f); + } + else { + $array_element = new FeedsDateTimeElement($f, NULL); + } + $array_element->buildDateField($entity, $field_name, $delta); + $delta++; } } - $feed_element->buildDateField($entity, $field_name); } diff --git a/plugins/FeedsParser.inc b/plugins/FeedsParser.inc index 8772e32efb00e54d3dcbbaa7c75f2091d19131c6..13fcaa0de93db7294914dceeba1845f04617e728 100644 --- a/plugins/FeedsParser.inc +++ b/plugins/FeedsParser.inc @@ -465,13 +465,13 @@ class FeedsDateTimeElement extends FeedsElement { * Helper method for buildDateField(). Build a FeedsDateTimeElement object * from a standard formatted node. */ - protected static function readDateField($entity, $field_name) { + protected static function readDateField($entity, $field_name, $delta = 0) { $ret = new FeedsDateTimeElement(); - if (isset($entity->{$field_name}['und'][0]['date']) && $entity->{$field_name}['und'][0]['date'] instanceof FeedsDateTime) { - $ret->start = $entity->{$field_name}['und'][0]['date']; + if (isset($entity->{$field_name}['und'][$delta]['date']) && $entity->{$field_name}['und'][$delta]['date'] instanceof FeedsDateTime) { + $ret->start = $entity->{$field_name}['und'][$delta]['date']; } - if (isset($entity->{$field_name}['und'][0]['date2']) && $entity->{$field_name}['und'][0]['date2'] instanceof FeedsDateTime) { - $ret->end = $entity->{$field_name}['und'][0]['date2']; + if (isset($entity->{$field_name}['und'][$delta]['date2']) && $entity->{$field_name}['und'][$delta]['date2'] instanceof FeedsDateTime) { + $ret->end = $entity->{$field_name}['und'][$delta]['date2']; } return $ret; } @@ -479,15 +479,17 @@ class FeedsDateTimeElement extends FeedsElement { /** * Build a entity's date field from our object. * - * @param $entity + * @param object $entity * The entity to build the date field on. - * @param $field_name + * @param str $field_name * The name of the field to build. + * @param int $delta + * The delta in the field. */ - public function buildDateField($entity, $field_name) { + public function buildDateField($entity, $field_name, $delta = 0) { $info = field_info_field($field_name); - $oldfield = FeedsDateTimeElement::readDateField($entity, $field_name); + $oldfield = FeedsDateTimeElement::readDateField($entity, $field_name, $delta); // Merge with any preexisting objects on the field; we take precedence. $oldfield = $this->merge($oldfield); $use_start = $oldfield->start; @@ -523,24 +525,24 @@ class FeedsDateTimeElement extends FeedsElement { $entity->{$field_name} = array('und' => array()); } if ($use_start) { - $entity->{$field_name}['und'][0]['timezone'] = $use_start->getTimezone()->getName(); - $entity->{$field_name}['und'][0]['offset'] = $use_start->getOffset(); + $entity->{$field_name}['und'][$delta]['timezone'] = $use_start->getTimezone()->getName(); + $entity->{$field_name}['und'][$delta]['offset'] = $use_start->getOffset(); $use_start->setTimezone($db_tz); - $entity->{$field_name}['und'][0]['date'] = $use_start; + $entity->{$field_name}['und'][$delta]['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)); */ - $entity->{$field_name}['und'][0]['value'] = $use_start->format(date_type_format($info['type'])); + $entity->{$field_name}['und'][$delta]['value'] = $use_start->format(date_type_format($info['type'])); } if ($use_end) { // Don't ever use end to set timezone (for now) - $entity->{$field_name}['und'][0]['offset2'] = $use_end->getOffset(); + $entity->{$field_name}['und'][$delta]['offset2'] = $use_end->getOffset(); $use_end->setTimezone($db_tz); - $entity->{$field_name}['und'][0]['date2'] = $use_end; - $entity->{$field_name}['und'][0]['value2'] = $use_end->format(date_type_format($info['type'])); + $entity->{$field_name}['und'][$delta]['date2'] = $use_end; + $entity->{$field_name}['und'][$delta]['value2'] = $use_end->format(date_type_format($info['type'])); } } } diff --git a/tests/feeds/multi-date.xml b/tests/feeds/multi-date.xml new file mode 100644 index 0000000000000000000000000000000000000000..13a705df5179c2830def2062e2f7e0618dea75b6 --- /dev/null +++ b/tests/feeds/multi-date.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<items> + <item> + <title>2 date values</title> + <guid>123456789</guid> + <date>Wed, 06 Jan 2010 15:05:00 GMT+00:00</date> + <date>Thu, 07 Jan 2010 15:08:00 GMT+00:00</date> + </item> + <item> + <title>4 date values</title> + <guid>1234567890</guid> + <date>Wed, 06 Jan 2010 15:00:00 GMT+00:00</date> + <date>Thu, 07 Jan 2010 15:00:00 GMT+00:00</date> + <date>Fri, 08 Jan 2010 15:00:00 GMT+00:00</date> + <date>Sat, 09 Jan 2010 15:00:00 GMT+00:00</date> + </item> + <item> + <title>Bogus date values</title> + <guid>1234567892</guid> + <date>Wed, 36 Jan 2010 15:00:00 GMT+00:00</date> + <date>Foo, 07 Bar 2010 95:00:00 GMT+00:00</date> + <date>This is just pure bogus. No date here!</date> + </item> + <item> + <title>Single date value</title> + <guid>1234567894</guid> + <date>Wed, 06 Jan 2010 14:00:00 GMT+00:00</date> + </item> +</items> diff --git a/tests/feeds_mapper_date.test b/tests/feeds_mapper_date.test index 429bca1c1c51cdc5820d057d75766eba903ef686..c3cb067fbb20336efa9ced8bb7b006a695678f41 100644 --- a/tests/feeds_mapper_date.test +++ b/tests/feeds_mapper_date.test @@ -39,11 +39,33 @@ class FeedsMapperDateTestCase extends FeedsMapperTestCase { //'datetime' => 'datetime', // REMOVED because the field is broken ATM. )); + // Hack to get date fields to not round to every 15 minutes. + foreach (array('date', 'datestamp') as $field) { + $field = 'field_' . $field; + $edit = array( + 'widget_type' => 'date_select', + ); + $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/' . $field . '/widget-type', $edit, 'Continue'); + $edit = array( + 'instance[widget][settings][increment]' => 1, + ); + $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/' . $field, $edit, 'Save settings'); + $edit = array( + 'widget_type' => 'date_text', + ); + $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/' . $field . '/widget-type', $edit, 'Continue'); + } + // Create and configure importer. $this->createImporterConfiguration('Date RSS', 'daterss'); - $this->setSettings('daterss', NULL, array('content_type' => '', 'import_period' => FEEDS_SCHEDULE_NEVER)); + $this->setSettings('daterss', NULL, array( + 'content_type' => '', + 'import_period' => FEEDS_SCHEDULE_NEVER, + )); $this->setPlugin('daterss', 'FeedsFileFetcher'); - $this->setSettings('daterss', 'FeedsNodeProcessor', array('bundle' => $typename)); + $this->setSettings('daterss', 'FeedsNodeProcessor', array( + 'bundle' => $typename, + )); $this->addMappings('daterss', array( 0 => array( 'source' => 'title', diff --git a/tests/feeds_mapper_date_multiple.test b/tests/feeds_mapper_date_multiple.test new file mode 100644 index 0000000000000000000000000000000000000000..3886c5a163b2ca3e9d6b52313db54353214edb45 --- /dev/null +++ b/tests/feeds_mapper_date_multiple.test @@ -0,0 +1,118 @@ +<?php + +/** + * @file + * Test case for CCK date multi-field mapper mappers/date.inc. + */ + +/** + * Class for testing Feeds <em>content</em> mapper. + * + * @todo: Add test method iCal + * @todo: Add test method for end date + */ +class FeedsMapperDateMultipleTestCase extends FeedsMapperTestCase { + public static function getInfo() { + return array( + 'name' => 'Mapper: Date, multi value fields', + 'description' => 'Test Feeds Mapper support for CCK multi valiue Date fields.', + 'group' => 'Feeds', + 'dependencies' => array('date', 'feeds_xpathparser'), + ); + } + + public function setUp() { + parent::setUp(array('date_api', 'date', 'feeds_xpathparser')); + variable_set('date_default_timezone', 'UTC'); + } + + /** + * Testing import by loading a 4 item XML file. + */ + public function test() { + $this->drupalGet('admin/config/regional/settings'); + + // Create content type. + $typename = $this->createContentType(array(), array( + 'date' => 'date', + )); + // Make the field hold unlimited values + $edit = array( + 'field[cardinality]' => -1, + ); + $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/field_date', $edit, 'Save settings'); + $this->assertText('Saved date_date_label configuration'); + + // Create and configure importer. + $this->createImporterConfiguration('Multi dates', 'multidates'); + $this->setSettings('multidates', NULL, array( + 'content_type' => '', + 'import_period' => FEEDS_SCHEDULE_NEVER, + )); + $this->setPlugin('multidates', 'FeedsFileFetcher'); + $this->setPlugin('multidates', 'FeedsXPathParserXML'); + + $this->setSettings('multidates', 'FeedsNodeProcessor', array( + 'bundle' => $typename, + )); + $this->addMappings('multidates', array( + 0 => array( + 'source' => 'xpathparser:0', + 'target' => 'title', + ), + 1 => array( + 'source' => 'xpathparser:1', + 'target' => 'guid', + ), + 2 => array( + 'source' => 'xpathparser:2', + 'target' => 'field_date:start', + ), + )); + + $edit = array( + 'xpath[context]' => '//item', + 'xpath[sources][xpathparser:0]' => 'title', + 'xpath[sources][xpathparser:1]' => 'guid', + 'xpath[sources][xpathparser:2]' => 'date', + 'xpath[allow_override]' => FALSE, + ); + $this->setSettings('multidates', 'FeedsXPathParserXML', $edit); + + $edit = array( + 'allowed_extensions' => 'xml', + 'directory' => 'public://feeds', + ); + $this->setSettings('multidates', 'FeedsFileFetcher', $edit); + + // Import XML file. + $this->importFile('multidates', $this->absolutePath() . '/tests/feeds/multi-date.xml'); + $this->assertText('Created 4 nodes'); + + // Check the imported nodes. + $values = array( + 1 => array( + '01/06/2010 - 15:00', + '01/07/2010 - 15:15', + ), + 2 => array( + '01/06/2010 - 15:00', + '01/07/2010 - 15:00', + '01/08/2010 - 15:00', + '01/09/2010 - 15:00', + ), + 3 => array( + '', // Bogus date was filtered out. + ), + 4 => array( + '01/06/2010 - 14:00', + ) + ); + foreach ($values as $v => $key) { + $this->drupalGet("node/$v/edit"); + foreach ($key as $delta => $value) { + $this->assertFieldById('edit-field-date-und-' . $delta . '-value-date', $value); + } + } + } +}