diff --git a/feeds.info b/feeds.info index 0ce45e0..ec2ffda 100644 --- a/feeds.info +++ b/feeds.info @@ -48,6 +48,7 @@ files[] = tests/feeds_processor_term.test files[] = tests/feeds_processor_user.test files[] = tests/feeds_scheduler.test files[] = tests/feeds_mapper_link.test +files[] = tests/feeds_mapper_summary.test files[] = tests/feeds_mapper_taxonomy.test files[] = tests/http_request.test files[] = tests/parser_csv.test diff --git a/mappers/text.inc b/mappers/text.inc index 5646753..cfc13a4 100644 --- a/mappers/text.inc +++ b/mappers/text.inc @@ -26,6 +26,14 @@ function text_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam 'callback' => 'text_feeds_set_target', 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])), ); + if ($info['type'] == 'text_with_summary') { + // Allow mapping to summary. + $targets[$name . ':summary'] = array( + 'name' => t('@name: Summary', array('@name' => $instance['label'])), + 'callback' => 'text_feeds_set_target', + 'description' => t('The @label field of the entity.', array('@label' => $instance['label'])), + ); + } } } } @@ -34,28 +42,39 @@ function text_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam * Callback for mapping text fields. */ function text_feeds_set_target($source, $entity, $target, array $values) { + list($field_name, $column) = explode(':', $target . ':value'); + $info = field_info_field($field_name); + if (isset($source->importer->processor->config['input_format'])) { $format = $source->importer->processor->config['input_format']; } - $field = isset($entity->$target) ? $entity->$target : array('und' => array()); + $field = isset($entity->$field_name) ? $entity->$field_name : array('und' => array()); // Iterate over all values. + $delta = 0; foreach ($values as $value) { + if ($info['cardinality'] == $delta) { + break; + } + + if (!isset($field['und'][$delta])) { + $field['und'][$delta] = array(); + } if (is_object($value) && ($value instanceof FeedsElement)) { $value = $value->getValue(); } if (is_scalar($value) && strlen($value)) { - $value = array('value' => (string) $value); + $field['und'][$delta][$column] = (string) $value; if (isset($format)) { - $value['format'] = $format; + $field['und'][$delta]['format'] = $format; } - - $field['und'][] = $value; } + + $delta++; } - $entity->$target = $field; + $entity->$field_name = $field; } diff --git a/tests/feeds/node_summary.csv b/tests/feeds/node_summary.csv new file mode 100644 index 0000000..5d59184 --- /dev/null +++ b/tests/feeds/node_summary.csv @@ -0,0 +1,4 @@ +"guid","title","summary","body" +1,"Lorem ipsum","Lorem ipsum summary","Lorem ipsum body" +2,"Ut wisi enim ad minim veniam","","Ut wisi enim ad minim veniam body" +3,"Duis autem vel eum iriure dolor","","" \ No newline at end of file diff --git a/tests/feeds_mapper_summary.test b/tests/feeds_mapper_summary.test new file mode 100644 index 0000000..b913225 --- /dev/null +++ b/tests/feeds_mapper_summary.test @@ -0,0 +1,160 @@ + 'Mapper: Text with summary', + 'description' => 'Test Feeds Mapper support for text with summary fields.', + 'group' => 'Feeds', + ); + } + + /** + * Tests importing CSV files for text fields with summary. + */ + public function test() { + // Create and configure importer. + $this->createImporterWithSummaryMapper(); + + // Import CSV file. + $this->importFile('syndication', $this->absolutePath() . '/tests/feeds/node_summary.csv'); + $this->assertText('Created 3 nodes'); + + // Check the three imported nodes. + $this->drupalGet('node/1/edit'); + $this->assertNodeFieldValue('summary', 'Lorem ipsum summary'); + $this->assertNodeFieldValue('body', 'Lorem ipsum body'); + $this->drupalGet('node/2/edit'); + $this->assertNodeFieldValue('summary', ''); + $this->assertNodeFieldValue('body', 'Ut wisi enim ad minim veniam body'); + $this->drupalGet('node/3/edit'); + $this->assertNodeFieldValue('summary', ''); + $this->assertNodeFieldValue('body', ''); + + // Check the teasers of the three imported nodes, assumed to be all present on the front page. + $this->drupalGet(''); + $this->assertText('Lorem ipsum summary'); + $this->assertNoText('Lorem ipsum body'); + $this->assertText('Ut wisi enim ad minim veniam body'); + } + + /** + * Tests if summary/body gets emptied. + */ + public function testEmptyValues() { + // Create and configure importer. + $this->createImporterWithSummaryMapper(); + // The "update existing" and "skip hash check" are turned on so we can test + // later if the summaries of the nodes get overwritten with the values from + // the source. + $this->setSettings('syndication', 'FeedsNodeProcessor', array('update_existing' => 2, 'skip_hash_check' => TRUE)); + + // Import CSV file. + $this->importFile('syndication', $this->absolutePath() . '/tests/feeds/node_summary.csv'); + $this->assertText('Created 3 nodes'); + + // Set a summary and a text for each imported node. + $edit = array( + 'body[und][0][summary]' => 'Nam liber tempor summary', + 'body[und][0][value]' => 'Nam liber tempor body', + ); + $this->drupalPost('node/1/edit', $edit, t('Save')); + $this->drupalPost('node/2/edit', $edit, t('Save')); + $this->drupalPost('node/3/edit', $edit, t('Save')); + + // Import the same CSV file again. + $this->importFile('syndication', $this->absolutePath() . '/tests/feeds/node_summary.csv'); + $this->assertText('Updated 3 nodes'); + + // Check the three nodes. + $this->drupalGet('node/1/edit'); + $this->assertNodeFieldValue('summary', 'Lorem ipsum summary'); + $this->assertNodeFieldValue('body', 'Lorem ipsum body'); + $this->drupalGet('node/2/edit'); + $this->assertNodeFieldValue('summary', ''); + $this->assertNodeFieldValue('body', 'Ut wisi enim ad minim veniam body'); + $this->drupalGet('node/3/edit'); + $this->assertNodeFieldValue('summary', ''); + $this->assertNodeFieldValue('body', ''); + + // Check the teasers of the three nodes. + $this->drupalGet(''); + $this->assertText('Lorem ipsum summary'); + $this->assertNoText('Lorem ipsum body'); + $this->assertText('Ut wisi enim ad minim veniam body'); + // The previous texts of the nodes should no longer be visible. + $this->assertNoText('Nam liber tempor summary'); + $this->assertNoText('Nam liber tempor body'); + } + + /** + * Creates an importer with a summary mapper. + * + * @param $name + * The natural name of the feed. + * @param $id + * The persistent id of the feed. + * + * @return void + */ + protected function createImporterWithSummaryMapper($name = 'Syndication', $id = 'syndication') { + // Create content type. A field named "body" which is of type "Long text and summary" + // will be created by default, so we don't need to create a field of that type here. + $typename = $this->createContentType(array()); + + // Create and configure importer. + $this->createImporterConfiguration($name, $id); + $this->setSettings('syndication', NULL, array('content_type' => '', 'import_period' => FEEDS_SCHEDULE_NEVER)); + $this->setPlugin('syndication', 'FeedsFileFetcher'); + $this->setPlugin('syndication', 'FeedsCSVParser'); + $this->setSettings('syndication', 'FeedsNodeProcessor', array('bundle' => $typename)); + $this->addMappings('syndication', + array( + 0 => array( + 'source' => 'title', + 'target' => 'title', + ), + 1 => array( + 'source' => 'summary', + 'target' => 'body:summary', + ), + 2 => array( + 'source' => 'body', + 'target' => 'body', + ), + 3 => array( + 'source' => 'guid', + 'target' => 'guid', + 'unique' => TRUE, + ), + ) + ); + } + + /** + * Overrides FeedsMapperTestCase::getFormFieldsNames(). + * + * Returns different form field names for: + * - body + * This field doesn't have the "field_" prefix. + * - summary + * Which is part of the body field. + */ + protected function getFormFieldsNames($field_name, $index) { + switch ($field_name) { + case 'body': + return array("body[und][{$index}][value]"); + case 'summary': + return array("body[und][{$index}][summary]"); + } + return parent::getFormFieldsNames($field_name, $index); + } +}