summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt4
-rw-r--r--plugins/FeedsParser.inc20
-rw-r--r--tests/feeds.test.inc12
-rw-r--r--tests/feeds/feeds-tests-files.tpl.php5
-rw-r--r--tests/feeds_fetcher_file.test8
-rw-r--r--tests/feeds_mapper_file.test104
-rw-r--r--tests/feeds_tests.module27
7 files changed, 154 insertions, 26 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index d063db5..733945f 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -3,8 +3,8 @@
Feeds 7.x 2.0 XXXXXXXXXXXXXXXXXXX
---------------------------------
-- alex_b: Fix file mapper, add file mapper tests, make flickr.xml point to
- local assets.
+- alex_b: Fix file mapper, add file mapper tests, generate flickr.xml and
+ files.csv dynamically.
- #953538 yhahn: Remove BOM from UTF-8 files.
Adds sanitizeFile() and sanitizeRaw() methods to FeedsFetcherResult.
Extending classes that override either the getRaw() or getFilePath() methods
diff --git a/plugins/FeedsParser.inc b/plugins/FeedsParser.inc
index 5048f4a..6b979e6 100644
--- a/plugins/FeedsParser.inc
+++ b/plugins/FeedsParser.inc
@@ -280,11 +280,10 @@ class FeedsEnclosure extends FeedsElement {
*
* @param $destination
* The path or uri specifying the target directory in which the file is
- * expected.
+ * expected. Don't use trailing slashes unless it's a streamwrapper scheme.
*
* @return
- * A Drupal file object of the enclosed resource. The file object is
- * permanent.
+ * A Drupal temporary file object of the enclosed resource.
*
* @throws Exception
* If file object could not be created.
@@ -294,16 +293,19 @@ class FeedsEnclosure extends FeedsElement {
if ($this->getValue()) {
// Prepare destination directory.
file_prepare_directory($destination, FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY);
-
// Copy or save file depending on whether it is remote or local.
if (drupal_realpath($this->getValue())) {
- $file = new stdClass();
- $file->uid = $user->uid;
- $file->status = FILE_STATUS_PERMANENT;
- $file->uri = $this->getValue();
- if (strpos($file->uri, $destination) !== 0) {
+ $file = new stdClass();
+ $file->uid = 0;
+ $file->uri = $this->getValue();
+ $file->filemime = $this->mime_type;
+ $file->filename = basename($file->uri);
+ if (dirname($file->uri) != $destination) {
$file = file_copy($file, $destination);
}
+ else {
+ file_save($file);
+ }
}
else {
$filename = basename($this->getValue());
diff --git a/tests/feeds.test.inc b/tests/feeds.test.inc
index 6f8d437..7ea79f2 100644
--- a/tests/feeds.test.inc
+++ b/tests/feeds.test.inc
@@ -409,4 +409,16 @@ class FeedsWebTestCase extends DrupalWebTestCase {
}
return $nid;
}
+
+ /**
+ * Copies a directory.
+ */
+ public function copyDir($source, $dest) {
+ $result = file_prepare_directory($dest, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+ foreach (scandir($source) as $file) {
+ if (is_file("$source/$file")) {
+ $file = file_unmanaged_copy("$source/$file", "$dest/$file");
+ }
+ }
+ }
}
diff --git a/tests/feeds/feeds-tests-files.tpl.php b/tests/feeds/feeds-tests-files.tpl.php
new file mode 100644
index 0000000..5c8aaa1
--- /dev/null
+++ b/tests/feeds/feeds-tests-files.tpl.php
@@ -0,0 +1,5 @@
+Title,published,file,GUID
+"Tubing is awesome",205200720,<?php print $files[0]; ?>,0
+"Jeff vs Tom",428112720,<?php print $files[1]; ?>,1
+"Attersee",1151766000,<?php print $files[2]; ?>,2
+"H Street NE",1256326995,<?php print $files[3]; ?>,3
diff --git a/tests/feeds_fetcher_file.test b/tests/feeds_fetcher_file.test
index 4bb41bd..c911412 100644
--- a/tests/feeds_fetcher_file.test
+++ b/tests/feeds_fetcher_file.test
@@ -60,14 +60,8 @@ class FeedsFileFetcherTestCase extends FeedsWebTestCase {
// Verify batching through directories.
// Copy directory of files.
- $source_dir = $this->absolutePath() . '/tests/feeds/batch';
$dir = 'public://batchtest';
- $result = file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
- foreach (scandir($source_dir) as $file) {
- if (is_file("$source_dir/$file")) {
- file_unmanaged_copy("$source_dir/$file", "$dir/$file");
- }
- }
+ $this->copyDir($this->absolutePath() . '/tests/feeds/batch', $dir);
// Ingest directory of files. Set limit to 5 to force processor to batch,
// too.
diff --git a/tests/feeds_mapper_file.test b/tests/feeds_mapper_file.test
index 89940b2..d91a2f6 100644
--- a/tests/feeds_mapper_file.test
+++ b/tests/feeds_mapper_file.test
@@ -37,6 +37,8 @@ class FeedsMapperFileTestCase extends FeedsMapperTestCase {
public function test() {
$typename = $this->createContentType(NULL, array('files' => 'file'));
+ // 1) Test mapping remote resources to file field.
+
// Create importer configuration.
$this->createImporterConfiguration();
$this->setPlugin('syndication', 'FeedsSimplePieParser');
@@ -51,23 +53,109 @@ class FeedsMapperFileTestCase extends FeedsMapperTestCase {
'target' => 'created'
),
array(
- 'source' => 'description',
- 'target' => 'body'
+ 'source' => 'enclosures',
+ 'target' => 'field_files'
),
+ ));
+ $nid = $this->createFeedNode('syndication', $GLOBALS['base_url'] . '/testing/feeds/flickr.xml');
+ $this->assertText('Created 4 nodes');
+
+ $files = $this->testFiles();
+ $entities = db_select('feeds_item')
+ ->fields('feeds_item', array('entity_id'))
+ ->condition('id', 'syndication')
+ ->execute();
+ foreach ($entities as $entity) {
+ $this->drupalGet('node/' . $entity->entity_id . '/edit');
+ $this->assertText(array_shift($files));
+ }
+
+ // 2) Test mapping local resources to file field.
+
+ // Copy directory of files, CSV file expects them in public://images, point
+ // file field to a 'resources' directory. Feeds should copy files from
+ // images/ to resources/ on import.
+ $this->copyDir($this->absolutePath() . '/tests/feeds/assets', 'public://images');
+ $edit = array(
+ 'instance[settings][file_directory]' => 'resources',
+ );
+ $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/field_files', $edit, t('Save settings'));
+
+ // Create a CSV importer configuration.
+ $this->createImporterConfiguration('Node import from CSV', 'node');
+ $this->setPlugin('node', 'FeedsCSVParser');
+ $this->setSettings('node', 'FeedsNodeProcessor', array('content_type' => $typename));
+ $this->addMappings('node', array(
array(
- 'source' => 'enclosures',
+ 'source' => 'title',
+ 'target' => 'title'
+ ),
+ array(
+ 'source' => 'file',
'target' => 'field_files'
),
));
+ $edit = array(
+ 'content_type' => '',
+ );
+ $this->drupalPost('admin/structure/feeds/edit/node/settings', $edit, 'Save');
- $nid = $this->createFeedNode('syndication', $GLOBALS['base_url'] . '/testing/feeds/flickr.xml');
+ // Import.
+ $edit = array(
+ 'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/testing/feeds/files.csv',
+ );
+ $this->drupalPost('import/node', $edit, 'Import');
$this->assertText('Created 4 nodes');
- $filename = array('tubing', 'foosball', 'attersee', 'hstreet');
- for($i = 0; $i < 4; $i++) {
- $this->drupalGet('node/'. ($i+2) .'/edit');
- $this->assertText($filename[$i]);
+ // Assert: files should be in resources/.
+ $files = $this->testFiles();
+ $entities = db_select('feeds_item')
+ ->fields('feeds_item', array('entity_id'))
+ ->condition('id', 'node')
+ ->execute();
+ foreach ($entities as $entity) {
+ $this->drupalGet('node/' . $entity->entity_id . '/edit');
+ $this->assertRaw('resources/' . array_shift($files));
}
+
+ // 3) Test mapping of local resources, this time leave files in place.
+ $this->drupalPost('import/node/delete-items', array(), 'Delete');
+ // Setting the fields file directory to images will make copying files
+ // obsolete.
+ $edit = array(
+ 'instance[settings][file_directory]' => 'images',
+ );
+ $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/field_files', $edit, t('Save settings'));
+ $edit = array(
+ 'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/testing/feeds/files.csv',
+ );
+ $this->drupalPost('import/node', $edit, 'Import');
+ $this->assertText('Created 4 nodes');
+
+ // Assert: files should be in images/ now.
+ $files = $this->testFiles();
+ $entities = db_select('feeds_item')
+ ->fields('feeds_item', array('entity_id'))
+ ->condition('id', 'node')
+ ->execute();
+ foreach ($entities as $entity) {
+ $this->drupalGet('node/' . $entity->entity_id . '/edit');
+ $this->assertRaw('images/' . array_shift($files));
+ }
+
+ // Deleting all imported items will delete the files from the images/ dir.
+ // @todo: for some reason the first file does not get deleted.
+// $this->drupalPost('import/node/delete-items', array(), 'Delete');
+// foreach ($this->testFiles() as $file) {
+// $this->assertFalse(is_file("public://images/$file"));
+// }
+ }
+
+ /**
+ * Lists test files.
+ */
+ public function testFiles() {
+ return array('tubing.jpeg', 'foosball.jpeg', 'attersee.jpeg', 'hstreet.jpeg');
}
/**
diff --git a/tests/feeds_tests.module b/tests/feeds_tests.module
index 40dd36e..c2a1b3e 100644
--- a/tests/feeds_tests.module
+++ b/tests/feeds_tests.module
@@ -10,6 +10,11 @@ function feeds_tests_menu() {
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
+ $items['testing/feeds/files.csv'] = array(
+ 'page callback' => 'feeds_tests_files',
+ 'access arguments' => array('access content'),
+ 'type' => MENU_CALLBACK,
+ );
return $items;
}
@@ -23,6 +28,11 @@ function feeds_tests_theme() {
'path' => drupal_get_path('module', 'feeds_tests') . '/feeds',
'template' => 'feeds-tests-flickr',
),
+ 'feeds_tests_files' => array(
+ 'variables' => array('files' => array()),
+ 'path' => drupal_get_path('module', 'feeds_tests') . '/feeds',
+ 'template' => 'feeds-tests-files',
+ ),
);
}
@@ -43,3 +53,20 @@ function feeds_tests_flickr() {
drupal_add_http_header('Content-Type', 'application/rss+xml; charset=utf-8');
print theme('feeds_tests_flickr', array('image_urls' => $images));
}
+
+/**
+ * Outputs a CSV file pointing to files.
+ */
+function feeds_tests_files() {
+ $images = array(
+ 0 => "tubing.jpeg",
+ 1 => "foosball.jpeg",
+ 2 => "attersee.jpeg",
+ 3 => "hstreet.jpeg",
+ );
+ foreach ($images as &$image) {
+ $image = "public://images/$image";
+ }
+ drupal_add_http_header('Content-Type', 'text/plain; charset=utf-8');
+ print theme('feeds_tests_files', array('files' => $images));
+}