Projet

Général

Profil

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

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

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
  /**
14
   * {@inheritdoc}
15
   */
16
  public static function getInfo() {
17
    return array(
18
      'name' => 'Mapper: File field',
19
      'description' => 'Test Feeds Mapper support for file fields. <strong>Requires SimplePie library</strong>.',
20
      'group' => 'Feeds',
21
    );
22
  }
23

    
24
  /**
25
   * {@inheritdoc}
26
   */
27
  public function setUp() {
28
    parent::setUp(array('dblog'));
29

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

    
37
    // Get our defined constants and any helper functions.
38
    module_load_include('inc', 'feeds', 'mappers/file');
39
  }
40

    
41
  /**
42
   * Basic test loading a single entry CSV file.
43
   */
44
  public function test() {
45
    // Only download simplepie if the plugin doesn't already exist somewhere.
46
    // People running tests locally might have it.
47
    $this->requireSimplePie();
48

    
49
    $typename = $this->createContentType(array(), array(
50
      'files' => array(
51
        'type' => 'file',
52
        'instance_settings' => array(
53
          'instance[settings][file_extensions]' => 'png, gif, jpg, jpeg',
54
        ),
55
      ),
56
    ));
57

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

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

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

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

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

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

    
130
    foreach ($entities as $entity) {
131
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
132
      $this->assertRaw('resources/' . rawurlencode(array_shift($files)));
133
    }
134

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

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

    
156
    foreach ($entities as $entity) {
157
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
158
      $this->assertRaw('images/' . rawurlencode(array_shift($files)));
159
    }
160

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

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

    
181
    // Create a content type. Save imported files into the directory
182
    // 'destination_rename'.
183
    $typename = $this->createContentTypeWithFileField('destination_rename');
184

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

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

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

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

    
226
    // Clean up the last import.
227
    $this->drupalPost('import/node_rename/delete-items', array(), 'Delete');
228
  }
229

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

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

    
246
    // Create a content type. Save imported files into the directory
247
    // 'destination_replace'.
248
    $typename = $this->createContentTypeWithFileField('destination_replace');
249

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

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

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

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

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

    
297
    // Clean up the last import.
298
    $this->drupalPost('import/node_replace/delete-items', array(), 'Delete');
299
  }
300

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

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

    
325
    // Create a content type. Save imported files into the directory
326
    // 'destination_rename_diff'.
327
    $typename = $this->createContentTypeWithFileField('destination_rename_diff');
328

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

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

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

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

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

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

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

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

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

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

    
424
    // Clean up the last import.
425
    $this->drupalPost('import/node_rename_diff/delete-items', array(), 'Delete');
426
  }
427

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

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

    
452
    // Create a content type. Save imported files into the directory
453
    // 'destination_replace_diff'.
454
    $typename = $this->createContentTypeWithFileField('destination_replace_diff');
455

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

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

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

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

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

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

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

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

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

    
538
    // Clean up the last import.
539
    $this->drupalPost('import/node_replace_diff/delete-items', array(), 'Delete');
540
  }
541

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

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

    
559
    // Create a content type. Save imported files into the directory
560
    // 'destination_skip'.
561
    $typename = $this->createContentTypeWithFileField('destination_skip');
562

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

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

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

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

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

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

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

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

    
641
  /**
642
   * Tests mapping to an image field.
643
   */
644
  public function testImages() {
645
    variable_set('feeds_never_use_curl', TRUE);
646

    
647
    $typename = $this->createContentType(array(), array('images' => 'image'));
648

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

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

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

    
687
    // Assert files exist.
688
    $files = $this->listTestFiles();
689
    $entities = db_select('feeds_item')
690
      ->fields('feeds_item', array('entity_id'))
691
      ->condition('id', 'image_test')
692
      ->execute();
693

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

    
702
  /**
703
   * {@inheritdoc}
704
   */
705
  public function testInvalidFileExtension() {
706
    variable_set('feeds_never_use_curl', TRUE);
707

    
708
    $typename = $this->createContentType(array(), array(
709
      'files' => array(
710
        'type' => 'file',
711
        'instance_settings' => array(
712
          'instance[settings][file_extensions]' => 'txt',
713
        ),
714
      ),
715
    ));
716

    
717
    // Create a CSV importer configuration.
718
    $this->createImporterConfiguration('Node import from CSV', 'invalid_extension');
719
    $this->setPlugin('invalid_extension', 'FeedsCSVParser');
720
    $this->setSettings('invalid_extension', 'FeedsNodeProcessor', array('bundle' => $typename));
721
    $this->setSettings('invalid_extension', NULL, array('content_type' => ''));
722
    $this->addMappings('invalid_extension', array(
723
      0 => array(
724
        'source' => 'title',
725
        'target' => 'title',
726
      ),
727
      1 => array(
728
        'source' => 'file',
729
        'target' => 'field_files:uri',
730
      ),
731
    ));
732

    
733
    // Import.
734
    $edit = array(
735
      'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-remote.csv', array('absolute' => TRUE)),
736
    );
737
    $this->drupalPost('import/invalid_extension', $edit, 'Import');
738
    $this->assertText('Created 5 nodes');
739

    
740
    foreach (range(1, 5) as $nid) {
741
      $node = node_load($nid);
742
      $this->assertTrue(empty($node->field_files));
743
    }
744

    
745
    foreach ($this->listTestFiles() as $filename) {
746
      $message = t('The file @file has an invalid extension.', array('@file' => $filename));
747
      $this->assertTrue(db_query("SELECT 1 FROM {watchdog} WHERE message = :message", array(':message' => $message))->fetchField());
748
    }
749

    
750
    // Test that query string and fragments are removed.
751
    $enclosure = new FeedsEnclosure('http://example.com/image.jpg?thing=stuff', 'text/plain');
752
    $this->assertEqual($enclosure->getLocalValue(), 'image.jpg');
753
    $enclosure = new FeedsEnclosure('http://example.com/image.jpg#stuff', 'text/plain');
754
    $this->assertEqual($enclosure->getLocalValue(), 'image.jpg');
755
    $enclosure = new FeedsEnclosure('http://example.com/image.JPG?thing=stuff#stuff', 'text/plain');
756
    $this->assertEqual($enclosure->getLocalValue(), 'image.JPG');
757
  }
758

    
759
  /**
760
   * Tests if values are cleared out when an empty value or no value
761
   * is provided.
762
   */
763
  public function testClearOutValues() {
764
    variable_set('feeds_never_use_curl', TRUE);
765

    
766
    $this->createContentType(array(), array('files' => 'file'));
767
    $typename = $this->createContentType(array(), array(
768
      'images' => 'image',
769
    ));
770

    
771
    // Enable title and alt mapping.
772
    $edit = array(
773
      'instance[settings][alt_field]' => 1,
774
      'instance[settings][title_field]' => 1,
775
    );
776
    $this->drupalPost("admin/structure/types/manage/$typename/fields/field_images", $edit, t('Save settings'));
777

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

    
813
    // Import.
814
    $edit = array(
815
      'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-remote.csv', array('absolute' => TRUE)),
816
    );
817
    $this->drupalPost('import/csv', $edit, 'Import');
818
    $this->assertText('Created 5 nodes');
819

    
820
    // Assert files exist.
821
    $files = $this->listTestFiles();
822
    foreach ($files as $file) {
823
      $file_path = drupal_realpath('public://') . '/' . str_replace(' ', '_', $file);
824
      $this->assertTrue(file_exists($file_path), format_string('The file %file exists.', array(
825
        '%file' => $file_path,
826
      )));
827
    }
828

    
829
    // Assert files exists with the expected alt/title on node edit form.
830
    $entities = db_select('feeds_item')
831
      ->fields('feeds_item', array('entity_id'))
832
      ->condition('id', 'csv')
833
      ->execute()
834
      ->fetchAll();
835

    
836
    foreach ($entities as $i => $entity) {
837
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
838
      $this->assertRaw(str_replace(' ', '_', array_shift($files)));
839
      $this->assertRaw("Alt text $i");
840
      $this->assertRaw("Title text $i");
841
    }
842

    
843
    // Import CSV with empty alt/title fields and check if these are removed.
844
    $edit = array(
845
      'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-empty-alt-title.csv', array('absolute' => TRUE)),
846
    );
847
    $this->drupalPost('import/csv', $edit, 'Import');
848
    $this->assertText('Updated 5 nodes');
849

    
850
    $files = $this->listTestFiles();
851
    foreach ($entities as $i => $entity) {
852
      $this->drupalGet('node/' . $entity->entity_id . '/edit');
853
      $this->assertRaw(str_replace(' ', '_', array_shift($files)));
854
      $this->assertNoRaw("Alt text $i");
855
      $this->assertNoRaw("Title text $i");
856
    }
857

    
858
    // Import CSV with empty file fields and check if all files are removed.
859
    $edit = array(
860
      'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-empty.csv', array('absolute' => TRUE)),
861
    );
862
    $this->drupalPost('import/csv', $edit, 'Import');
863
    $this->assertText('Updated 5 nodes');
864

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

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

    
899
    // Set a destination folder, if given.
900
    if ($dest) {
901
      $edit = array(
902
        'instance[settings][file_directory]' => $dest,
903
      );
904
      $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/field_files', $edit, t('Save settings'));
905
    }
906

    
907
    return $typename;
908
  }
909

    
910
  /**
911
   * Checks if SimplePie is available and eventually downloads it.
912
   */
913
  protected function requireSimplePie() {
914
    if (!feeds_simplepie_exists()) {
915
      $this->downloadExtractSimplePie('1.3');
916
      $this->assertTrue(feeds_simplepie_exists());
917
      // Reset all the caches!
918
      $this->resetAll();
919
    }
920
  }
921

    
922
  /**
923
   * Lists test files.
924
   */
925
  protected function listTestFiles() {
926
    return array(
927
      'tubing.jpeg',
928
      'foosball.jpeg',
929
      'attersee.jpeg',
930
      'hstreet.jpeg',
931
      'la fayette.jpeg',
932
    );
933
  }
934

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

    
953
}