Second round of improvements on file field mapper: better tests, files.csv.
authorAlex Barth
Wed, 27 Oct 2010 22:33:32 +0000 (22:33 +0000)
committerAlex Barth
Wed, 27 Oct 2010 22:33:32 +0000 (22:33 +0000)
CHANGELOG.txt
plugins/FeedsParser.inc
tests/feeds.test.inc
tests/feeds/feeds-tests-files.tpl.php [new file with mode: 0644]
tests/feeds_fetcher_file.test
tests/feeds_mapper_file.test
tests/feeds_tests.module

index d063db5..733945f 100644 (file)
@@ -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
index 5048f4a..6b979e6 100644 (file)
@@ -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());
index 6f8d437..7ea79f2 100644 (file)
@@ -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 (file)
index 0000000..5c8aaa1
--- /dev/null
@@ -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
index 4bb41bd..c911412 100644 (file)
@@ -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.
index 89940b2..d91a2f6 100644 (file)
@@ -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');
   }
 
   /**
index 40dd36e..c2a1b3e 100644 (file)
@@ -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));
+}