feeds_mapper_file.test 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. <?php
  2. /**
  3. * @file
  4. * Contains FeedsMapperFileTestCase.
  5. */
  6. /**
  7. * Test case for Filefield mapper mappers/filefield.inc.
  8. */
  9. class FeedsMapperFileTestCase extends FeedsMapperTestCase {
  10. public static function getInfo() {
  11. return array(
  12. 'name' => 'Mapper: File field',
  13. 'description' => 'Test Feeds Mapper support for file fields. <strong>Requires SimplePie library</strong>.',
  14. 'group' => 'Feeds',
  15. );
  16. }
  17. public function setUp() {
  18. parent::setUp(array('dblog'));
  19. }
  20. /**
  21. * Basic test loading a single entry CSV file.
  22. */
  23. public function test() {
  24. // If this is unset (or FALSE) http_request.inc will use curl, and will
  25. // generate a 404 for this feel 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. // Only download simplepie if the plugin doesn't already exist somewhere.
  31. // People running tests locally might have it.
  32. if (!feeds_simplepie_exists()) {
  33. $this->downloadExtractSimplePie('1.3');
  34. $this->assertTrue(feeds_simplepie_exists());
  35. // Reset all the caches!
  36. $this->resetAll();
  37. }
  38. $typename = $this->createContentType(array(), array(
  39. 'files' => array(
  40. 'type' => 'file',
  41. 'instance_settings' => array(
  42. 'instance[settings][file_extensions]' => 'png, gif, jpg, jpeg',
  43. ),
  44. ),
  45. ));
  46. // 1) Test mapping remote resources to file field.
  47. // Create importer configuration.
  48. $this->createImporterConfiguration();
  49. $this->setPlugin('syndication', 'FeedsSimplePieParser');
  50. $this->setSettings('syndication', 'FeedsNodeProcessor', array('bundle' => $typename));
  51. $this->addMappings('syndication', array(
  52. 0 => array(
  53. 'source' => 'title',
  54. 'target' => 'title',
  55. ),
  56. 1 => array(
  57. 'source' => 'timestamp',
  58. 'target' => 'created',
  59. ),
  60. 2 => array(
  61. 'source' => 'enclosures',
  62. 'target' => 'field_files:uri',
  63. ),
  64. ));
  65. $nid = $this->createFeedNode('syndication', $GLOBALS['base_url'] . '/testing/feeds/flickr.xml');
  66. $this->assertText('Created 5 nodes');
  67. $files = $this->listTestFiles();
  68. $entities = db_select('feeds_item')
  69. ->fields('feeds_item', array('entity_id'))
  70. ->condition('id', 'syndication')
  71. ->execute();
  72. foreach ($entities as $entity) {
  73. $this->drupalGet('node/' . $entity->entity_id . '/edit');
  74. $this->assertText(str_replace(' ', '_', array_shift($files)));
  75. }
  76. // 2) Test mapping local resources to file field.
  77. // Copy directory of files, CSV file expects them in public://images, point
  78. // file field to a 'resources' directory. Feeds should copy files from
  79. // images/ to resources/ on import.
  80. $this->copyDir($this->absolutePath() . '/tests/feeds/assets', 'public://images');
  81. $edit = array(
  82. 'instance[settings][file_directory]' => 'resources',
  83. );
  84. $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/field_files', $edit, t('Save settings'));
  85. // Create a CSV importer configuration.
  86. $this->createImporterConfiguration('Node import from CSV', 'node');
  87. $this->setPlugin('node', 'FeedsCSVParser');
  88. $this->setSettings('node', 'FeedsNodeProcessor', array('bundle' => $typename));
  89. $this->setSettings('node', NULL, array('content_type' => ''));
  90. $this->addMappings('node', array(
  91. 0 => array(
  92. 'source' => 'title',
  93. 'target' => 'title',
  94. ),
  95. 1 => array(
  96. 'source' => 'file',
  97. 'target' => 'field_files:uri',
  98. ),
  99. ));
  100. // Import.
  101. $edit = array(
  102. 'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files.csv', array('absolute' => TRUE)),
  103. );
  104. $this->drupalPost('import/node', $edit, 'Import');
  105. $this->assertText('Created 5 nodes');
  106. // Assert: files should be in resources/.
  107. $files = $this->listTestFiles();
  108. $entities = db_select('feeds_item')
  109. ->fields('feeds_item', array('entity_id'))
  110. ->condition('id', 'node')
  111. ->execute();
  112. foreach ($entities as $entity) {
  113. $this->drupalGet('node/' . $entity->entity_id . '/edit');
  114. $this->assertRaw('resources/' . rawurlencode(array_shift($files)));
  115. }
  116. // 3) Test mapping of local resources, this time leave files in place.
  117. $this->drupalPost('import/node/delete-items', array(), 'Delete');
  118. // Setting the fields file directory to images will make copying files
  119. // obsolete.
  120. $edit = array(
  121. 'instance[settings][file_directory]' => 'images',
  122. );
  123. $this->drupalPost('admin/structure/types/manage/' . $typename . '/fields/field_files', $edit, t('Save settings'));
  124. $edit = array(
  125. 'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/testing/feeds/files.csv',
  126. );
  127. $this->drupalPost('import/node', $edit, 'Import');
  128. $this->assertText('Created 5 nodes');
  129. // Assert: files should be in images/ now.
  130. $files = $this->listTestFiles();
  131. $entities = db_select('feeds_item')
  132. ->fields('feeds_item', array('entity_id'))
  133. ->condition('id', 'node')
  134. ->execute();
  135. foreach ($entities as $entity) {
  136. $this->drupalGet('node/' . $entity->entity_id . '/edit');
  137. $this->assertRaw('images/' . rawurlencode(array_shift($files)));
  138. }
  139. // Deleting all imported items will delete the files from the images/ dir.
  140. $this->drupalPost('import/node/delete-items', array(), 'Delete');
  141. foreach ($this->listTestFiles() as $file) {
  142. $this->assertFalse(is_file("public://images/$file"));
  143. }
  144. }
  145. /**
  146. * Tests mapping to an image field.
  147. */
  148. public function testImages() {
  149. variable_set('feeds_never_use_curl', TRUE);
  150. $typename = $this->createContentType(array(), array('images' => 'image'));
  151. // Enable title and alt mapping.
  152. $edit = array(
  153. 'instance[settings][alt_field]' => 1,
  154. 'instance[settings][title_field]' => 1,
  155. );
  156. $this->drupalPost("admin/structure/types/manage/$typename/fields/field_images", $edit, t('Save settings'));
  157. // Create a CSV importer configuration.
  158. $this->createImporterConfiguration('Node import from CSV', 'image_test');
  159. $this->setPlugin('image_test', 'FeedsCSVParser');
  160. $this->setSettings('image_test', 'FeedsNodeProcessor', array('bundle' => $typename));
  161. $this->setSettings('image_test', NULL, array('content_type' => ''));
  162. $this->addMappings('image_test', array(
  163. 0 => array(
  164. 'source' => 'title',
  165. 'target' => 'title',
  166. ),
  167. 1 => array(
  168. 'source' => 'file',
  169. 'target' => 'field_images:uri',
  170. ),
  171. 2 => array(
  172. 'source' => 'title2',
  173. 'target' => 'field_images:title',
  174. ),
  175. 3 => array(
  176. 'source' => 'alt',
  177. 'target' => 'field_images:alt',
  178. ),
  179. ));
  180. // Import.
  181. $edit = array(
  182. 'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-remote.csv', array('absolute' => TRUE)),
  183. );
  184. $this->drupalPost('import/image_test', $edit, 'Import');
  185. $this->assertText('Created 5 nodes');
  186. // Assert files exist.
  187. $files = $this->listTestFiles();
  188. $entities = db_select('feeds_item')
  189. ->fields('feeds_item', array('entity_id'))
  190. ->condition('id', 'image_test')
  191. ->execute();
  192. foreach ($entities as $i => $entity) {
  193. $this->drupalGet('node/' . $entity->entity_id . '/edit');
  194. $this->assertRaw(str_replace(' ', '_', array_shift($files)));
  195. $this->assertRaw("Alt text $i");
  196. $this->assertRaw("Title text $i");
  197. }
  198. }
  199. public function testInvalidFileExtension() {
  200. variable_set('feeds_never_use_curl', TRUE);
  201. $typename = $this->createContentType(array(), array(
  202. 'files' => array(
  203. 'type' => 'file',
  204. 'instance_settings' => array(
  205. 'instance[settings][file_extensions]' => 'txt',
  206. ),
  207. ),
  208. ));
  209. // Create a CSV importer configuration.
  210. $this->createImporterConfiguration('Node import from CSV', 'invalid_extension');
  211. $this->setPlugin('invalid_extension', 'FeedsCSVParser');
  212. $this->setSettings('invalid_extension', 'FeedsNodeProcessor', array('bundle' => $typename));
  213. $this->setSettings('invalid_extension', NULL, array('content_type' => ''));
  214. $this->addMappings('invalid_extension', array(
  215. 0 => array(
  216. 'source' => 'title',
  217. 'target' => 'title',
  218. ),
  219. 1 => array(
  220. 'source' => 'file',
  221. 'target' => 'field_files:uri',
  222. ),
  223. ));
  224. // Import.
  225. $edit = array(
  226. 'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-remote.csv', array('absolute' => TRUE)),
  227. );
  228. $this->drupalPost('import/invalid_extension', $edit, 'Import');
  229. $this->assertText('Created 5 nodes');
  230. foreach (range(1, 5) as $nid) {
  231. $node = node_load($nid);
  232. $this->assertTrue(empty($node->field_files));
  233. }
  234. foreach ($this->listTestFiles() as $filename) {
  235. $message = t('The file @file has an invalid extension.', array('@file' => $filename));
  236. $this->assertTrue(db_query("SELECT 1 FROM {watchdog} WHERE message = :message", array(':message' => $message))->fetchField());
  237. }
  238. // Test that query string and fragments are removed.
  239. $enclosure = new FeedsEnclosure('http://example.com/image.jpg?thing=stuff', 'text/plain');
  240. $this->assertEqual($enclosure->getLocalValue(), 'image.jpg');
  241. $enclosure = new FeedsEnclosure('http://example.com/image.jpg#stuff', 'text/plain');
  242. $this->assertEqual($enclosure->getLocalValue(), 'image.jpg');
  243. $enclosure = new FeedsEnclosure('http://example.com/image.JPG?thing=stuff#stuff', 'text/plain');
  244. $this->assertEqual($enclosure->getLocalValue(), 'image.JPG');
  245. }
  246. /**
  247. * Tests if values are cleared out when an empty value or no value
  248. * is provided.
  249. */
  250. public function testClearOutValues() {
  251. variable_set('feeds_never_use_curl', TRUE);
  252. $this->createContentType(array(), array('files' => 'file'));
  253. $typename = $this->createContentType(array(), array(
  254. 'images' => 'image',
  255. ));
  256. // Enable title and alt mapping.
  257. $edit = array(
  258. 'instance[settings][alt_field]' => 1,
  259. 'instance[settings][title_field]' => 1,
  260. );
  261. $this->drupalPost("admin/structure/types/manage/$typename/fields/field_images", $edit, t('Save settings'));
  262. // Create and configure importer.
  263. $this->createImporterConfiguration('Content CSV', 'csv');
  264. $this->setSettings('csv', NULL, array(
  265. 'content_type' => '',
  266. 'import_period' => FEEDS_SCHEDULE_NEVER,
  267. ));
  268. $this->setPlugin('csv', 'FeedsCSVParser');
  269. $this->setSettings('csv', 'FeedsNodeProcessor', array(
  270. 'bundle' => $typename,
  271. 'update_existing' => 1,
  272. ));
  273. $this->addMappings('csv', array(
  274. 0 => array(
  275. 'source' => 'guid',
  276. 'target' => 'guid',
  277. 'unique' => TRUE,
  278. ),
  279. 1 => array(
  280. 'source' => 'title',
  281. 'target' => 'title',
  282. ),
  283. 2 => array(
  284. 'source' => 'file',
  285. 'target' => 'field_images:uri',
  286. ),
  287. 3 => array(
  288. 'source' => 'title2',
  289. 'target' => 'field_images:title',
  290. ),
  291. 4 => array(
  292. 'source' => 'alt',
  293. 'target' => 'field_images:alt',
  294. ),
  295. ));
  296. // Import.
  297. $edit = array(
  298. 'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-remote.csv', array('absolute' => TRUE)),
  299. );
  300. $this->drupalPost('import/csv', $edit, 'Import');
  301. $this->assertText('Created 5 nodes');
  302. // Assert files exist.
  303. $files = $this->listTestFiles();
  304. foreach ($files as $file) {
  305. $file_path = drupal_realpath('public://') . '/' . str_replace(' ', '_', $file);
  306. $this->assertTrue(file_exists($file_path), format_string('The file %file exists.', array(
  307. '%file' => $file_path,
  308. )));
  309. }
  310. // Assert files exists with the expected alt/title on node edit form.
  311. $entities = db_select('feeds_item')
  312. ->fields('feeds_item', array('entity_id'))
  313. ->condition('id', 'csv')
  314. ->execute()
  315. ->fetchAll();
  316. foreach ($entities as $i => $entity) {
  317. $this->drupalGet('node/' . $entity->entity_id . '/edit');
  318. $this->assertRaw(str_replace(' ', '_', array_shift($files)));
  319. $this->assertRaw("Alt text $i");
  320. $this->assertRaw("Title text $i");
  321. }
  322. // Import CSV with empty alt/title fields and check if these are removed.
  323. $edit = array(
  324. 'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-empty-alt-title.csv', array('absolute' => TRUE)),
  325. );
  326. $this->drupalPost('import/csv', $edit, 'Import');
  327. $this->assertText('Updated 5 nodes');
  328. $files = $this->listTestFiles();
  329. foreach ($entities as $i => $entity) {
  330. $this->drupalGet('node/' . $entity->entity_id . '/edit');
  331. $this->assertRaw(str_replace(' ', '_', array_shift($files)));
  332. $this->assertNoRaw("Alt text $i");
  333. $this->assertNoRaw("Title text $i");
  334. }
  335. // Import CSV with empty file fields and check if all files are removed.
  336. $edit = array(
  337. 'feeds[FeedsHTTPFetcher][source]' => url('testing/feeds/files-empty.csv', array('absolute' => TRUE)),
  338. );
  339. $this->drupalPost('import/csv', $edit, 'Import');
  340. $this->assertText('Updated 5 nodes');
  341. // Assert files are removed.
  342. $files = $this->listTestFiles();
  343. foreach ($files as $file) {
  344. $file_path = drupal_realpath('public://') . '/' . str_replace(' ', '_', $file);
  345. $this->assertFalse(file_exists($file_path), format_string('The file %file no longer exists.', array(
  346. '%file' => $file_path,
  347. )));
  348. }
  349. // Check if the files are removed from the node edit form as well.
  350. foreach ($entities as $i => $entity) {
  351. $this->drupalGet('node/' . $entity->entity_id . '/edit');
  352. $this->assertNoRaw(str_replace(' ', '_', array_shift($files)));
  353. }
  354. }
  355. /**
  356. * Lists test files.
  357. */
  358. protected function listTestFiles() {
  359. return array(
  360. 'tubing.jpeg',
  361. 'foosball.jpeg',
  362. 'attersee.jpeg',
  363. 'hstreet.jpeg',
  364. 'la fayette.jpeg',
  365. );
  366. }
  367. }