Projet

Général

Profil

Paste
Télécharger (34,1 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / feeds / tests / feeds_mapper_file.test @ 651307cd

1
<?php
2

    
3
/**
4
 * @file
5
 * Contains FeedsMapperFileTestCase.
6
 */
7

    
8
/**
9
 * Test case for Filefield mapper mappers/filefield.inc.
10
 */
11
class FeedsMapperFileTestCase extends FeedsMapperTestCase {
12

    
13
  public static function getInfo() {
14
    return array(
15
      'name' => 'Mapper: File field',
16
      'description' => 'Test Feeds Mapper support for file fields. <strong>Requires SimplePie library</strong>.',
17
      'group' => 'Feeds',
18
    );
19
  }
20

    
21
  public function setUp() {
22
    parent::setUp(array('dblog'));
23

    
24
    // If this is unset (or FALSE) http_request.inc will use curl, and will
25
    // generate a 404 for the feed url provided by feeds_tests. However, if
26
    // feeds_tests was enabled in your site before running the test, it will
27
    // work fine. Since it is truly screwy, lets just force it to use
28
    // drupal_http_request() for this test case.
29
    variable_set('feeds_never_use_curl', TRUE);
30

    
31
    // Get our defined constants and any helper functions.
32
    module_load_include('inc', 'feeds', 'mappers/file');
33
  }
34

    
35
  /**
36
   * Basic test loading a single entry CSV file.
37
   */
38
  public function test() {
39
    // Only download simplepie if the plugin doesn't already exist somewhere.
40
    // People running tests locally might have it.
41
    $this->requireSimplePie();
42

    
43
    $typename = $this->createContentType(array(), array(
44
      'files' => array(
45
        'type' => 'file',
46
        'instance_settings' => array(
47
          'instance[settings][file_extensions]' => 'png, gif, jpg, jpeg',
48
        ),
49
      ),
50
    ));
51

    
52
    // 1) Test mapping remote resources to file field.
53

    
54
    // Create importer configuration.
55
    $this->createImporterConfiguration();
56
    $this->setPlugin('syndication', 'FeedsSimplePieParser');
57
    $this->setSettings('syndication', 'FeedsNodeProcessor', array('bundle' => $typename));
58
    $this->addMappings('syndication', array(
59
      0 => array(
60
        'source' => 'title',
61
        'target' => 'title',
62
      ),
63
      1 => array(
64
        'source' => 'timestamp',
65
        'target' => 'created',
66
      ),
67
      2 => array(
68
        'source' => 'enclosures',
69
        'target' => 'field_files:uri',
70
      ),
71
    ));
72
    $nid = $this->createFeedNode('syndication', $GLOBALS['base_url'] . '/testing/feeds/flickr.xml', 'Test Title');
73
    $this->assertText('Created 5 nodes');
74

    
75
    $files = $this->listTestFiles();
76
    $entities = db_select('feeds_item')
77
      ->fields('feeds_item', array('entity_id'))
78
      ->condition('id', 'syndication')
79
      ->execute();
80
    foreach ($entities as $entity) {
81
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
82
      $this->assertText(str_replace(' ', '_', array_shift($files)));
83
    }
84

    
85
    // 2) Test mapping local resources to file field.
86

    
87
    // Copy directory of files, CSV file expects them in public://images, point
88
    // file field to a 'resources' directory. Feeds should copy files from
89
    // images/ to resources/ on import.
90
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', 'public://images');
91
    $edit = array(
92
      'instance[settings][file_directory]' => 'resources',
93
    );
94
    $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/field_files', $edit, t('Save settings'));
95

    
96
    // Create a CSV importer configuration.
97
    $this->createImporterConfiguration('Node import from CSV', 'node');
98
    $this->setPlugin('node', 'FeedsCSVParser');
99
    $this->setSettings('node', 'FeedsNodeProcessor', array('bundle' => $typename));
100
    $this->setSettings('node', NULL, array('content_type' => ''));
101
    $this->addMappings('node', array(
102
      0 => array(
103
        'source' => 'title',
104
        'target' => 'title',
105
      ),
106
      1 => array(
107
        'source' => 'file',
108
        'target' => 'field_files:uri',
109
      ),
110
    ));
111

    
112
    // Import.
113
    $edit = array(
114
      'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files.csv', array('absolute' => TRUE)),
115
    );
116
    $this->drupalPost('import/node', $edit, 'Import');
117
    $this->assertText('Created 5 nodes');
118

    
119
    // Assert: files should be in resources/.
120
    $files = $this->listTestFiles();
121
    $entities = db_select('feeds_item')
122
      ->fields('feeds_item', array('entity_id'))
123
      ->condition('id', 'node')
124
      ->execute();
125

    
126
    foreach ($entities as $entity) {
127
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
128
      $this->assertRaw('resources/' . rawurlencode(array_shift($files)));
129
    }
130

    
131
    // 3) Test mapping of local resources, this time leave files in place.
132
    $this->drupalPost('import/node/delete-items', array(), 'Delete');
133
    // Setting the fields file directory to images will make copying files
134
    // obsolete.
135
    $edit = array(
136
      'instance[settings][file_directory]' => 'images',
137
    );
138
    $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/field_files', $edit, t('Save settings'));
139
    $edit = array(
140
      'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/testing/feeds/files.csv',
141
    );
142
    $this->drupalPost('import/node', $edit, 'Import');
143
    $this->assertText('Created 5 nodes');
144

    
145
    // Assert: files should be in images/ now.
146
    $files = $this->listTestFiles();
147
    $entities = db_select('feeds_item')
148
      ->fields('feeds_item', array('entity_id'))
149
      ->condition('id', 'node')
150
      ->execute();
151

    
152
    foreach ($entities as $entity) {
153
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
154
      $this->assertRaw('images/' . rawurlencode(array_shift($files)));
155
    }
156

    
157
    // Deleting all imported items will delete the files from the images/ dir.
158
    $this->drupalPost('import/node/delete-items', array(), 'Delete');
159
    foreach ($this->listTestFiles() as $file) {
160
      $this->assertFalse(is_file("public://images/$file"));
161
    }
162
  }
163

    
164
  /**
165
   * Test mapping of local resources with the file exists "Rename" setting.
166
   *
167
   * In this test, files to import should be renamed if files with the same name
168
   * already exist in the destination folder.
169
   * Example: on the destination folder there exist a file named 'foo.jpg'. When
170
   * importing a file with the same name, that file should be renamed to
171
   * 'foo_0.jpg'.
172
   */
173
  public function testFileExistsRename() {
174
    // Copy the files to import to the folder 'images'.
175
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', 'public://images');
176

    
177
    // Create a content type. Save imported files into the directory
178
    // 'destination_rename'.
179
    $typename = $this->createContentTypeWithFileField('destination_rename');
180

    
181
    // Copy files with the same names to the destination folder. These files
182
    // should remain intact, while the files to import should get renamed.
183
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', 'public://destination_rename');
184

    
185
    // Create a CSV importer configuration.
186
    $this->createImporterConfiguration('Node import from CSV -- File Exists Rename', 'node_rename');
187
    $this->setSettings('node_rename', NULL, array('content_type' => ''));
188
    $this->setPlugin('node_rename', 'FeedsCSVParser');
189
    $this->setSettings('node_rename', 'FeedsNodeProcessor', array('bundle' => $typename));
190
    $this->addMappings('node_rename', array(
191
      0 => array(
192
        'source' => 'title',
193
        'target' => 'title',
194
      ),
195
      1 => array(
196
        'source' => 'file',
197
        'target' => 'field_files:uri',
198
        'file_exists' => FILE_EXISTS_RENAME,
199
      ),
200
    ));
201

    
202
    // Perform the import.
203
    $edit = array(
204
      'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/testing/feeds/files.csv',
205
    );
206
    $this->drupalPost('import/node_rename', $edit, 'Import');
207
    $this->assertText('Created 5 nodes');
208

    
209
    // Assert: all imported files should be renamed.
210
    $files = $this->listTestFiles();
211
    $entities = db_select('feeds_item')
212
      ->fields('feeds_item', array('entity_id'))
213
      ->condition('id', 'node_rename')
214
      ->execute();
215
    foreach ($entities as $entity) {
216
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
217
      $f = new FeedsEnclosure(array_shift($files), NULL);
218
      $renamed_file = str_replace('.jpeg', '_0.jpeg', $f->getUrlEncodedValue());
219
      $this->assertRaw('destination_rename/' . $renamed_file);
220
    }
221

    
222
    // Clean up the last import.
223
    $this->drupalPost('import/node_rename/delete-items', array(), 'Delete');
224
  }
225

    
226
  /**
227
   * Test mapping of local resources with the file exists "Replace" setting.
228
   *
229
   * In this test, files to import should be replaced if files with the same
230
   * name already exist in the destination folder.
231
   * Example: on the destination folder there exist a file named 'foo.jpg'.
232
   * When importing a file with the same name, that file should replace the
233
   * existing 'foo.jpg'.
234
   */
235
  public function testFileExistsReplace() {
236
    $source = 'public://images';
237
    $dest = 'public://destination_replace';
238

    
239
    // Copy the files to import to the folder 'images'.
240
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', $source);
241

    
242
    // Create a content type. Save imported files into the directory
243
    // 'destination_replace'.
244
    $typename = $this->createContentTypeWithFileField('destination_replace');
245

    
246
    // Copy files with the same name to the destination folder, but make sure
247
    // that the files are different by shuffling the file names. These files
248
    // should get overwritten upon import.
249
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', $dest, $this->listTestFilesNameMap());
250

    
251
    // Confirm the files from the source folder are all different from the
252
    // destination folder.
253
    foreach (@scandir($source) as $file) {
254
      if (is_file("$source/$file")) {
255
        $message = "$source/$file is not the same as $dest/$file";
256
        $this->assertFalse(file_feeds_file_compare("$source/$file", "$dest/$file"), $message);
257
      }
258
    }
259

    
260
    // Create a CSV importer configuration.
261
    $this->createImporterConfiguration('Node import from CSV -- File Exists Replace', 'node_replace');
262
    $this->setSettings('node_replace', NULL, array('content_type' => ''));
263
    $this->setPlugin('node_replace', 'FeedsCSVParser');
264
    $this->setSettings('node_replace', 'FeedsNodeProcessor', array('bundle' => $typename));
265
    $this->addMappings('node_replace', array(
266
      0 => array(
267
        'source' => 'title',
268
        'target' => 'title',
269
      ),
270
      1 => array(
271
        'source' => 'file',
272
        'target' => 'field_files:uri',
273
        'file_exists' => FILE_EXISTS_REPLACE,
274
      ),
275
    ));
276

    
277
    // Perform the import.
278
    $edit = array(
279
      'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/testing/feeds/files.csv',
280
    );
281
    $this->drupalPost('import/node_replace', $edit, 'Import');
282
    $this->assertText('Created 5 nodes');
283

    
284
    // Assert: all files in the destination folder should be exactly the same as
285
    // the files in the source folder.
286
    foreach (@scandir($source) as $file) {
287
      if (is_file("$source/$file")) {
288
        $message = "$source/$file is the same as $dest/$file";
289
        $this->assertTrue(file_feeds_file_compare("$source/$file", "$dest/$file"), $message);
290
      }
291
    }
292

    
293
    // Clean up the last import.
294
    $this->drupalPost('import/node_replace/delete-items', array(), 'Delete');
295
  }
296

    
297
  /**
298
   * Test mapping of local resources with the file exists "Rename if different"
299
   * setting.
300
   *
301
   * In this test, files to import should only be renamed under the following
302
   * circumstances:
303
   * - A file the same name already exist in the destination folder;
304
   * - AND this file is different.
305
   *
306
   * Example: on the destination folder there exist two files: one called
307
   * 'foo.jpg' and an other called 'bar.jpg'. On an import two files with the
308
   * same name are imported. The 'foo.jpg' is exactly the same as the one that
309
   * already exist on the destination, but 'bar.jpg' is different. In this case,
310
   * only 'bar.jpg' should get imported and it should be renamed to 'bar_0.jpg'.
311
   * Importing 'foo.jpg' should be skipped as it is already there. The file's
312
   * timestamp will remain the same.
313
   */
314
  public function testFileExistsRenameIfDifferent() {
315
    $source = 'public://images';
316
    $dest = 'public://destination_rename_diff';
317

    
318
    // Copy the files to import to the folder 'images'.
319
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', $source);
320

    
321
    // Create a content type. Save imported files into the directory
322
    // 'destination_rename_diff'.
323
    $typename = $this->createContentTypeWithFileField('destination_rename_diff');
324

    
325
    // Shuffle a couple of the file names so the files appear to be different.
326
    // Leave a few others the same.
327
    $same = array(
328
      'foosball.jpeg' => 'foosball.jpeg',
329
      'attersee.jpeg' => 'attersee.jpeg',
330
      'hstreet.jpeg' => 'hstreet.jpeg',
331
    );
332
    $different = array(
333
      'la fayette.jpeg' => 'tubing.jpeg',
334
      'tubing.jpeg' => 'la fayette.jpeg',
335
    );
336

    
337
    // Copy files with the same name to the destination folder. A few of them
338
    // however, will be different. Only these files should get renamed upon
339
    // import.
340
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', $dest, $same + $different);
341

    
342
    // Note the timestamps that the files got in the destination folder.
343
    $file_timestamps = array();
344
    foreach (@scandir($dest) as $file) {
345
      $file_timestamps[$file] = filemtime("$dest/$file");
346
    }
347

    
348
    // Confirm that some of the files are the same.
349
    foreach ($same as $file) {
350
      if (is_file("$source/$file")) {
351
        $message = "$source/$file IS the same as $dest/$file";
352
        $this->assertTrue(file_feeds_file_compare("$source/$file", "$dest/$file"), $message);
353
      }
354
    }
355

    
356
    // Confirm that some of the files are different.
357
    foreach ($different as $file) {
358
      if (is_file("$source/$file")) {
359
        $message = "$source/$file is NOT the same as $dest/$file";
360
        $this->assertFalse(file_feeds_file_compare("$source/$file", "$dest/$file"), $message);
361
      }
362
    }
363

    
364
    // Create a CSV importer configuration.
365
    $this->createImporterConfiguration('Node import from CSV -- File Exists Rename if Different', 'node_rename_diff');
366
    $this->setSettings('node_rename_diff', NULL, array('content_type' => ''));
367
    $this->setPlugin('node_rename_diff', 'FeedsCSVParser');
368
    $this->setSettings('node_rename_diff', 'FeedsNodeProcessor', array('bundle' => $typename));
369
    $this->addMappings('node_rename_diff', array(
370
      0 => array(
371
        'source' => 'title',
372
        'target' => 'title',
373
      ),
374
      1 => array(
375
        'source' => 'file',
376
        'target' => 'field_files:uri',
377
        'file_exists' => FEEDS_FILE_EXISTS_RENAME_DIFFERENT,
378
      ),
379
    ));
380

    
381
    // Perform the import.
382
    $edit = array(
383
      'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/testing/feeds/files.csv',
384
    );
385
    $this->drupalPost('import/node_rename_diff', $edit, 'Import');
386
    $this->assertText('Created 5 nodes');
387

    
388
    // Assert that only files that were different should have been renamed.
389
    $files = $this->listTestFiles();
390
    $entities = db_select('feeds_item')
391
      ->fields('feeds_item', array('entity_id'))
392
      ->condition('id', 'node_rename_diff')
393
      ->execute();
394
    foreach ($entities as $entity) {
395
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
396
      $f = new FeedsEnclosure(array_shift($files), NULL);
397
      $original_file = $f->getUrlEncodedValue();
398
      $renamed_file = str_replace('.jpeg', '_0.jpeg', $f->getUrlEncodedValue());
399

    
400
      if (isset($same[$original_file])) {
401
        // Assert that the file still has the same name.
402
        $this->assertRaw('destination_rename_diff/' . $original_file);
403
      }
404
      else {
405
        // Assert that the file still has been renamed.
406
        $this->assertRaw('destination_rename_diff/' . $renamed_file);
407
      }
408
    }
409

    
410
    // Assert that some files have been kept the same.
411
    foreach ($same as $file) {
412
      if (is_file("$source/$file")) {
413
        $message = "$source/$file is STILL the same as $dest/$file";
414
        $this->assertTrue(file_feeds_file_compare("$source/$file", "$dest/$file"), $message);
415
        $message = "$dest/$file was not replaced (modification time is the same as before import)";
416
        $this->assertEqual(filemtime("$dest/$file"), $file_timestamps[$file], $message);
417
      }
418
    }
419

    
420
    // Clean up the last import.
421
    $this->drupalPost('import/node_rename_diff/delete-items', array(), 'Delete');
422
  }
423

    
424
  /**
425
   * Test mapping of local resources with the file exists "Replace if different"
426
   * setting.
427
   *
428
   * In this test, files to import should only be replaced under the following
429
   * circumstances:
430
   * - A file the same name already exist in the destination folder;
431
   * - AND this file is different.
432
   *
433
   * Example: on the destination folder there exist two files: one called
434
   * 'foo.jpg' and an other called 'bar.jpg'. On an import two files with the
435
   * same name are imported. The 'foo.jpg' is exactly the same as the one that
436
   * already exist on the destination, but 'bar.jpg' is different. In this case,
437
   * only 'bar.jpg' should get imported and it should overwrite the existing
438
   * 'bar.jpg'. Importing 'foo.jpg' should be skipped as it is already there.
439
   * The file's timestamp will remain the same.
440
   */
441
  public function testFileExistsReplaceIfDifferent() {
442
    $source = 'public://images';
443
    $dest = 'public://destination_replace_diff';
444

    
445
    // Copy the files to import to the folder 'images'.
446
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', $source);
447

    
448
    // Create a content type. Save imported files into the directory
449
    // 'destination_replace_diff'.
450
    $typename = $this->createContentTypeWithFileField('destination_replace_diff');
451

    
452
    // Shuffle a couple of the file names so the files appear to be different.
453
    // Leave a few others the same.
454
    $same = array(
455
      'foosball.jpeg' => 'foosball.jpeg',
456
      'attersee.jpeg' => 'attersee.jpeg',
457
      'hstreet.jpeg' => 'hstreet.jpeg',
458
    );
459
    $different = array(
460
      'la fayette.jpeg' => 'tubing.jpeg',
461
      'tubing.jpeg' => 'la fayette.jpeg',
462
    );
463

    
464
    // Copy files with the same name to the destination folder. A few of them
465
    // however, will be different. Only these files should get replaced upon
466
    // import.
467
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', $dest, $same + $different);
468

    
469
    // Note the timestamps that the files got in the destination folder.
470
    $file_timestamps = array();
471
    foreach (@scandir($dest) as $file) {
472
      $file_timestamps[$file] = filemtime("$dest/$file");
473
    }
474

    
475
    // Confirm that some of the files are the same.
476
    foreach ($same as $file) {
477
      if (is_file("$source/$file")) {
478
        $message = "$source/$file IS the same as $dest/$file";
479
        $this->assertTrue(file_feeds_file_compare("$source/$file", "$dest/$file"), $message);
480
      }
481
    }
482

    
483
    // Confirm that some of the files are different.
484
    foreach ($different as $file) {
485
      if (is_file("$source/$file")) {
486
        $message = "$source/$file is NOT the same as $dest/$file";
487
        $this->assertFalse(file_feeds_file_compare("$source/$file", "$dest/$file"), $message);
488
      }
489
    }
490

    
491
    // Create a CSV importer configuration.
492
    $this->createImporterConfiguration('Node import from CSV -- File Exists Replace if Different', 'node_replace_diff');
493
    $this->setSettings('node_replace_diff', NULL, array('content_type' => ''));
494
    $this->setPlugin('node_replace_diff', 'FeedsCSVParser');
495
    $this->setSettings('node_replace_diff', 'FeedsNodeProcessor', array('bundle' => $typename));
496
    $this->addMappings('node_replace_diff', array(
497
      0 => array(
498
        'source' => 'title',
499
        'target' => 'title',
500
      ),
501
      1 => array(
502
        'source' => 'file',
503
        'target' => 'field_files:uri',
504
        'file_exists' => FEEDS_FILE_EXISTS_REPLACE_DIFFERENT,
505
      ),
506
    ));
507

    
508
    // Perform the import.
509
    $edit = array(
510
      'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/testing/feeds/files.csv',
511
    );
512
    $this->drupalPost('import/node_replace_diff', $edit, 'Import');
513
    $this->assertText('Created 5 nodes');
514

    
515
    // Assert that some files have been kept the same.
516
    foreach ($same as $file) {
517
      if (is_file("$source/$file")) {
518
        $message = "$source/$file is STILL the same as $dest/$file";
519
        $this->assertTrue(file_feeds_file_compare("$source/$file", "$dest/$file"), $message);
520
        $message = "$dest/$file was not replaced (modification time is the same as before import)";
521
        $this->assertEqual(filemtime("$dest/$file"), $file_timestamps[$file], $message);
522
      }
523
    }
524

    
525
    // Assert that some files were replaced.
526
    foreach ($different as $file) {
527
      if (is_file("$source/$file")) {
528
        $message = "$source/$file successfully replaced $dest/$file";
529
        $this->assertTrue(file_feeds_file_compare("$source/$file", "$dest/$file"), $message);
530
        $this->assertNotEqual(filemtime("$dest/$file"), $file_timestamps[$file], $message);
531
      }
532
    }
533

    
534
    // Clean up the last import.
535
    $this->drupalPost('import/node_replace_diff/delete-items', array(), 'Delete');
536
  }
537

    
538
  /**
539
   * Test mapping of local resources with the file exists "Skip existig"
540
   * setting.
541
   *
542
   * In this test, files should only be imported if no file exist yet with the
543
   * given name.
544
   * Example: on the destination folder there exist a file named 'foo.jpg'. When
545
   * importing a file with the same name, that file should not be imported
546
   * as there already is a file with that name.
547
   */
548
  public function testFileExistsSkip() {
549
    $source = 'public://images';
550
    $dest = 'public://destination_skip';
551

    
552
    // Copy the files to import to the folder 'images'.
553
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', $source);
554

    
555
    // Create a content type. Save imported files into the directory
556
    // 'destination_skip'.
557
    $typename = $this->createContentTypeWithFileField('destination_skip');
558

    
559
    // Copy a few images also to the destination directory.
560
    $same = array(
561
      'foosball.jpeg' => 'foosball.jpeg',
562
      'attersee.jpeg' => 'attersee.jpeg',
563
      'hstreet.jpeg' => 'hstreet.jpeg',
564
    );
565
    $different = array(
566
      'la fayette.jpeg' => FALSE,
567
      'tubing.jpeg' => FALSE,
568
    );
569
    $this->copyDir($this->absolutePath() . '/tests/feeds/assets', $dest, $same + $different);
570

    
571
    // Note the timestamps that the files got in the destination folder.
572
    $file_timestamps = array();
573
    foreach (@scandir($dest) as $file) {
574
      $file_timestamps[$file] = filemtime("$dest/$file");
575
    }
576

    
577
    // Confirm that some of the files are the same.
578
    foreach ($same as $file) {
579
      if (is_file("$source/$file")) {
580
        $message = "$source/$file IS the same as $dest/$file";
581
        $this->assertTrue(file_feeds_file_compare("$source/$file", "$dest/$file"), $message);
582
      }
583
    }
584

    
585
    // Confirm that some of the files do not exist.
586
    foreach ($different as $file => $value) {
587
      $message = "$dest/$file does not exist.";
588
      $this->assertFalse(file_exists("$dest/$file"), $message);
589
    }
590

    
591
    // Create a CSV importer configuration.
592
    $this->createImporterConfiguration('Node import from CSV -- File Exists Replace if Different', 'node_skip');
593
    $this->setSettings('node_skip', NULL, array('content_type' => ''));
594
    $this->setPlugin('node_skip', 'FeedsCSVParser');
595
    $this->setSettings('node_skip', 'FeedsNodeProcessor', array('bundle' => $typename));
596
    $this->addMappings('node_skip', array(
597
      0 => array(
598
        'source' => 'title',
599
        'target' => 'title',
600
      ),
601
      1 => array(
602
        'source' => 'file',
603
        'target' => 'field_files:uri',
604
        'file_exists' => FEEDS_FILE_EXISTS_SKIP,
605
      ),
606
    ));
607

    
608
    // Perform the import.
609
    $edit = array(
610
      'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/testing/feeds/files.csv',
611
    );
612
    $this->drupalPost('import/node_skip', $edit, 'Import');
613
    $this->assertText('Created 5 nodes');
614

    
615
    // Assert that files that were already in the destination folder were not
616
    // overwritten.
617
    foreach ($same as $file) {
618
      if (is_file("$source/$file")) {
619
        $message = "$dest/$file was skipped (modification time is the same as before import)";
620
        $this->assertEqual(filemtime("$dest/$file"), $file_timestamps[$file], $message);
621
      }
622
    }
623

    
624
    // Assert that the other files were added with the expected names.
625
    $files = $this->listTestFiles();
626
    $entities = db_select('feeds_item')
627
      ->fields('feeds_item', array('entity_id'))
628
      ->condition('id', 'node_skip')
629
      ->execute();
630
    foreach ($entities as $entity) {
631
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
632
      $f = new FeedsEnclosure(array_shift($files), NULL);
633
      $this->assertRaw('destination_skip/' . $f->getUrlEncodedValue());
634
    }
635
  }
636

    
637
  /**
638
   * Tests mapping to an image field.
639
   */
640
  public function testImages() {
641
    variable_set('feeds_never_use_curl', TRUE);
642

    
643
    $typename = $this->createContentType(array(), array('images' => 'image'));
644

    
645
    // Enable title and alt mapping.
646
    $edit = array(
647
      'instance[settings][alt_field]' => 1,
648
      'instance[settings][title_field]' => 1,
649
    );
650
    $this->drupalPost("admin/structure/types/manage/$typename/fields/field_images", $edit, t('Save settings'));
651

    
652
    // Create a CSV importer configuration.
653
    $this->createImporterConfiguration('Node import from CSV', 'image_test');
654
    $this->setPlugin('image_test', 'FeedsCSVParser');
655
    $this->setSettings('image_test', 'FeedsNodeProcessor', array('bundle' => $typename));
656
    $this->setSettings('image_test', NULL, array('content_type' => ''));
657
    $this->addMappings('image_test', array(
658
      0 => array(
659
        'source' => 'title',
660
        'target' => 'title',
661
      ),
662
      1 => array(
663
        'source' => 'file',
664
        'target' => 'field_images:uri',
665
      ),
666
      2 => array(
667
        'source' => 'title2',
668
        'target' => 'field_images:title',
669
      ),
670
      3 => array(
671
        'source' => 'alt',
672
        'target' => 'field_images:alt',
673
      ),
674
    ));
675

    
676
    // Import.
677
    $edit = array(
678
      'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-remote.csv', array('absolute' => TRUE)),
679
    );
680
    $this->drupalPost('import/image_test', $edit, 'Import');
681
    $this->assertText('Created 5 nodes');
682

    
683
    // Assert files exist.
684
    $files = $this->listTestFiles();
685
    $entities = db_select('feeds_item')
686
      ->fields('feeds_item', array('entity_id'))
687
      ->condition('id', 'image_test')
688
      ->execute();
689

    
690
    foreach ($entities as $i => $entity) {
691
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
692
      $this->assertRaw(str_replace(' ', '_', array_shift($files)));
693
      $this->assertRaw("Alt text $i");
694
      $this->assertRaw("Title text $i");
695
    }
696
  }
697

    
698
  public function testInvalidFileExtension() {
699
    variable_set('feeds_never_use_curl', TRUE);
700

    
701
    $typename = $this->createContentType(array(), array(
702
      'files' => array(
703
        'type' => 'file',
704
        'instance_settings' => array(
705
          'instance[settings][file_extensions]' => 'txt',
706
        ),
707
      ),
708
    ));
709

    
710
    // Create a CSV importer configuration.
711
    $this->createImporterConfiguration('Node import from CSV', 'invalid_extension');
712
    $this->setPlugin('invalid_extension', 'FeedsCSVParser');
713
    $this->setSettings('invalid_extension', 'FeedsNodeProcessor', array('bundle' => $typename));
714
    $this->setSettings('invalid_extension', NULL, array('content_type' => ''));
715
    $this->addMappings('invalid_extension', array(
716
      0 => array(
717
        'source' => 'title',
718
        'target' => 'title',
719
      ),
720
      1 => array(
721
        'source' => 'file',
722
        'target' => 'field_files:uri',
723
      ),
724
    ));
725

    
726
    // Import.
727
    $edit = array(
728
      'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-remote.csv', array('absolute' => TRUE)),
729
    );
730
    $this->drupalPost('import/invalid_extension', $edit, 'Import');
731
    $this->assertText('Created 5 nodes');
732

    
733
    foreach (range(1, 5) as $nid) {
734
      $node = node_load($nid);
735
      $this->assertTrue(empty($node->field_files));
736
    }
737

    
738
    foreach ($this->listTestFiles() as $filename) {
739
      $message = t('The file @file has an invalid extension.', array('@file' => $filename));
740
      $this->assertTrue(db_query("SELECT 1 FROM {watchdog} WHERE message = :message", array(':message' => $message))->fetchField());
741
    }
742

    
743
    // Test that query string and fragments are removed.
744
    $enclosure = new FeedsEnclosure('http://example.com/image.jpg?thing=stuff', 'text/plain');
745
    $this->assertEqual($enclosure->getLocalValue(), 'image.jpg');
746
    $enclosure = new FeedsEnclosure('http://example.com/image.jpg#stuff', 'text/plain');
747
    $this->assertEqual($enclosure->getLocalValue(), 'image.jpg');
748
    $enclosure = new FeedsEnclosure('http://example.com/image.JPG?thing=stuff#stuff', 'text/plain');
749
    $this->assertEqual($enclosure->getLocalValue(), 'image.JPG');
750
  }
751

    
752
  /**
753
   * Tests if values are cleared out when an empty value or no value
754
   * is provided.
755
   */
756
  public function testClearOutValues() {
757
    variable_set('feeds_never_use_curl', TRUE);
758

    
759
    $this->createContentType(array(), array('files' => 'file'));
760
    $typename = $this->createContentType(array(), array(
761
      'images' => 'image',
762
    ));
763

    
764
    // Enable title and alt mapping.
765
    $edit = array(
766
      'instance[settings][alt_field]' => 1,
767
      'instance[settings][title_field]' => 1,
768
    );
769
    $this->drupalPost("admin/structure/types/manage/$typename/fields/field_images", $edit, t('Save settings'));
770

    
771
    // Create and configure importer.
772
    $this->createImporterConfiguration('Content CSV', 'csv');
773
    $this->setSettings('csv', NULL, array(
774
      'content_type' => '',
775
      'import_period' => FEEDS_SCHEDULE_NEVER,
776
    ));
777
    $this->setPlugin('csv', 'FeedsCSVParser');
778
    $this->setSettings('csv', 'FeedsNodeProcessor', array(
779
      'bundle' => $typename,
780
      'update_existing' => 1,
781
    ));
782
    $this->addMappings('csv', array(
783
      0 => array(
784
        'source' => 'guid',
785
        'target' => 'guid',
786
        'unique' => TRUE,
787
      ),
788
      1 => array(
789
        'source' => 'title',
790
        'target' => 'title',
791
      ),
792
      2 => array(
793
        'source' => 'file',
794
        'target' => 'field_images:uri',
795
      ),
796
      3 => array(
797
        'source' => 'title2',
798
        'target' => 'field_images:title',
799
      ),
800
      4 => array(
801
        'source' => 'alt',
802
        'target' => 'field_images:alt',
803
      ),
804
    ));
805

    
806
    // Import.
807
    $edit = array(
808
      'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-remote.csv', array('absolute' => TRUE)),
809
    );
810
    $this->drupalPost('import/csv', $edit, 'Import');
811
    $this->assertText('Created 5 nodes');
812

    
813
    // Assert files exist.
814
    $files = $this->listTestFiles();
815
    foreach ($files as $file) {
816
      $file_path = drupal_realpath('public://') . '/' . str_replace(' ', '_', $file);
817
      $this->assertTrue(file_exists($file_path), format_string('The file %file exists.', array(
818
        '%file' => $file_path,
819
      )));
820
    }
821

    
822
    // Assert files exists with the expected alt/title on node edit form.
823
    $entities = db_select('feeds_item')
824
      ->fields('feeds_item', array('entity_id'))
825
      ->condition('id', 'csv')
826
      ->execute()
827
      ->fetchAll();
828

    
829
    foreach ($entities as $i => $entity) {
830
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
831
      $this->assertRaw(str_replace(' ', '_', array_shift($files)));
832
      $this->assertRaw("Alt text $i");
833
      $this->assertRaw("Title text $i");
834
    }
835

    
836
    // Import CSV with empty alt/title fields and check if these are removed.
837
    $edit = array(
838
      'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-empty-alt-title.csv', array('absolute' => TRUE)),
839
    );
840
    $this->drupalPost('import/csv', $edit, 'Import');
841
    $this->assertText('Updated 5 nodes');
842

    
843
    $files = $this->listTestFiles();
844
    foreach ($entities as $i => $entity) {
845
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
846
      $this->assertRaw(str_replace(' ', '_', array_shift($files)));
847
      $this->assertNoRaw("Alt text $i");
848
      $this->assertNoRaw("Title text $i");
849
    }
850

    
851
    // Import CSV with empty file fields and check if all files are removed.
852
    $edit = array(
853
      'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-empty.csv', array('absolute' => TRUE)),
854
    );
855
    $this->drupalPost('import/csv', $edit, 'Import');
856
    $this->assertText('Updated 5 nodes');
857

    
858
    // Assert files are removed.
859
    $files = $this->listTestFiles();
860
    foreach ($files as $file) {
861
      $file_path = drupal_realpath('public://') . '/' . str_replace(' ', '_', $file);
862
      $this->assertFalse(file_exists($file_path), format_string('The file %file no longer exists.', array(
863
        '%file' => $file_path,
864
      )));
865
    }
866
    // Check if the files are removed from the node edit form as well.
867
    foreach ($entities as $i => $entity) {
868
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
869
      $this->assertNoRaw(str_replace(' ', '_', array_shift($files)));
870
    }
871
  }
872

    
873
  /**
874
   * Creates a content type with a file field.
875
   *
876
   * @param string $dest
877
   *   The folder to save files to. Leave empty to not set that.
878
   *
879
   * @return string
880
   *   The name of the content type that was created.
881
   */
882
  protected function createContentTypeWithFileField($dest = '') {
883
    $typename = $this->createContentType(array(), array(
884
      'files' => array(
885
        'type' => 'file',
886
        'instance_settings' => array(
887
          'instance[settings][file_extensions]' => 'png, gif, jpg, jpeg',
888
        ),
889
      ),
890
    ));
891

    
892
    // Set a destination folder, if given.
893
    if ($dest) {
894
      $edit = array(
895
        'instance[settings][file_directory]' => $dest,
896
      );
897
      $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/field_files', $edit, t('Save settings'));
898
    }
899

    
900
    return $typename;
901
  }
902

    
903
  /**
904
   * Checks if SimplePie is available and eventually downloads it.
905
   */
906
  protected function requireSimplePie() {
907
    if (!feeds_simplepie_exists()) {
908
      $this->downloadExtractSimplePie('1.3');
909
      $this->assertTrue(feeds_simplepie_exists());
910
      // Reset all the caches!
911
      $this->resetAll();
912
    }
913
  }
914

    
915
  /**
916
   * Lists test files.
917
   */
918
  protected function listTestFiles() {
919
    return array(
920
      'tubing.jpeg',
921
      'foosball.jpeg',
922
      'attersee.jpeg',
923
      'hstreet.jpeg',
924
      'la fayette.jpeg',
925
    );
926
  }
927

    
928
  /**
929
   * Lists test files mapping.
930
   *
931
   * Used to rename images so the ::testFileExistsReplace() test can check if
932
   * they are replaced on import.
933
   *
934
   * @see testFileExistsReplace()
935
   */
936
  protected function listTestFilesNameMap() {
937
    return array(
938
      'la fayette.jpeg' => 'tubing.jpeg',
939
      'tubing.jpeg' => 'foosball.jpeg',
940
      'foosball.jpeg' => 'attersee.jpeg',
941
      'attersee.jpeg' => 'hstreet.jpeg',
942
      'hstreet.jpeg' => 'la fayette.jpeg',
943
    );
944
  }
945

    
946
}