From 7ef4e4558cf5f3c3830d4b1a91ef84918fc74645 Mon Sep 17 00:00:00 2001
From: eiriksm <eiriksm@1014468.no-reply.drupal.org>
Date: Tue, 16 Apr 2013 01:55:30 -0700
Subject: [PATCH] Issue #697842 by eiriksm, franz, Webmaster Perpignan: Added
 Support array of values for dates.

---
 feeds.info                            |   1 +
 mappers/date.inc                      |  27 +++---
 plugins/FeedsParser.inc               |  34 ++++----
 tests/feeds/multi-date.xml            |  29 +++++++
 tests/feeds_mapper_date.test          |  26 +++++-
 tests/feeds_mapper_date_multiple.test | 118 ++++++++++++++++++++++++++
 6 files changed, 205 insertions(+), 30 deletions(-)
 create mode 100644 tests/feeds/multi-date.xml
 create mode 100644 tests/feeds_mapper_date_multiple.test

diff --git a/feeds.info b/feeds.info
index 052010e2..8041cbff 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 a96143a3..9344d279 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 8772e32e..13fcaa0d 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 00000000..13a705df
--- /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 429bca1c..c3cb067f 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 00000000..3886c5a1
--- /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);
+      }
+    }
+  }
+}
-- 
GitLab