Issue #1027184 by Aron Novak: Expose file download URL as a token.
[project/filefield.git] / tests / filefield.test
CommitLineData
060d70b8 1<?php
060d70b8
NH
2
3class FileFieldTestCase extends DrupalWebTestCase {
ef620a1a
NH
4 protected $admin_user;
5
060d70b8
NH
6 /**
7 * Implementation of setUp().
8 */
9 function setUp() {
93c5556a
NH
10 // Views is included here just so that it doesn't whine when CCK tries to
11 // clear the caches.
12 $modules = array_merge(func_get_args(), array('content', 'filefield', 'filefield_meta', 'getid3', 'mimedetect', 'token', 'views'));
ef620a1a 13 call_user_func_array(array($this, 'parent::setUp'), $modules);
060d70b8
NH
14
15 // Create and login user
ef620a1a
NH
16 $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'administer files'));
17 $this->drupalLogin($this->admin_user);
060d70b8
NH
18 }
19
20 /**
21 * Get a sample file of the specified type.
22 */
ef620a1a 23 function getTestFile($type, $size = NULL) {
060d70b8 24 // Get a file to upload.
ef620a1a 25 $file = current($this->drupalGetTestFiles($type, $size));
060d70b8
NH
26
27 // SimpleTest files incorrectly use "filename" instead of "filepath".
28 $file->filepath = $file->filename;
ef620a1a
NH
29 $file->filename = basename($file->filepath);
30 $file->filesize = filesize($file->filepath);
060d70b8
NH
31
32 return $file;
33 }
34
35 /**
36 * Create a new file field.
37 *
38 * @param $name
39 * The name of the new field (all lowercase), exclude the "field_" prefix.
40 * @param $type
41 * The node type that this field will be added to.
42 * @param $field_options
43 * A list of field options that will be added to the defaults.
44 * @param $widget_options
45 * A list of widget options that will be added to the widget defaults.
46 */
47 function createFileField($name, $type, $field_options = array(), $widget_options = array()) {
48 module_load_include('inc', 'content', 'includes/content.crud');
49 $field = array(
50 'label' => $name,
ef620a1a 51 'field_name' => $name,
060d70b8
NH
52 'type' => 'filefield',
53 'widget_type' => 'filefield_widget',
54 'weight' => 0,
55 'parent' => 0,
56 'type_name' => $type,
57 'list_field' => 0,
58 'list_default' => 1,
59 'description_field' => 0,
60 );
61
62 $field = array_merge($field, $field_options);
63 $field = content_field_instance_create($field);
64
65 $widget = array(
66 'type' => 'filefield_widget',
ef620a1a 67 'file_extensions' => '',
060d70b8
NH
68 );
69
70 $field['widget'] = array_merge($field['widget'], $widget, $widget_options);
71 $field = content_field_instance_update($field);
72
73 return $field;
74 }
75
76 /**
77 * Update an existing FileField with new settings.
78 */
ef620a1a
NH
79 function updateFileField($name, $type, $field_options = array(), $widget_options = array()) {
80 $field = content_fields($name, $type);
060d70b8
NH
81 $field = array_merge($field, $field_options);
82 $field['widget'] = array_merge($field['widget'], $widget_options);
83
84 return content_field_instance_update($field);
85 }
86
87 /**
88 * Upload a file to a node.
89 */
93c5556a
NH
90 function uploadNodeFile($file, $field, $nid_or_type, $new_revision = TRUE) {
91 $field_name = $field['field_name'];
060d70b8
NH
92 $edit = array(
93 'title' => $this->randomName(),
060d70b8
NH
94 'revision' => (string) (int) $new_revision,
95 );
96
97 if (is_numeric($nid_or_type)) {
ef620a1a
NH
98 $node = node_load($nid_or_type);
99 $delta = isset($node->$field_name) ? count($node->$field_name) : 0;
100 $edit['files[' . $field_name . '_' . $delta . ']'] = realpath($file->filepath);
060d70b8
NH
101 $this->drupalPost('node/' . $nid_or_type . '/edit', $edit, t('Save'));
102 }
103 else {
93c5556a
NH
104 $delta = '0';
105 $edit['files[' . $field_name . '_' . $delta . ']'] = realpath($file->filepath);
060d70b8
NH
106 $type = str_replace('_', '-', $nid_or_type);
107 $this->drupalPost('node/add/' . $type, $edit, t('Save'));
108 }
109
110 $matches = array();
111 preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
93c5556a
NH
112 $nid = isset($matches[1]) ? $matches[1] : FALSE;
113
114 // Edit the node and add a description if possible.
115 if ($nid && $field['description_field']) {
116 $edit = array(
117 'revision' => 0,
118 $field_name . '[' . $delta . '][data][description]' => $this->randomString(),
119 );
120 $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save'));
121 }
122
123 return $nid;
060d70b8
NH
124 }
125
126 /**
127 * Remove a file from a node.
128 *
129 * Note that if replacing a file, it must first be removed then added again.
130 */
131 function removeNodeFile($nid, $new_revision = TRUE) {
132 $edit = array(
133 'revision' => (string) (int) $new_revision,
134 );
135
136 $this->drupalPost('node/' . $nid . '/edit', array(), t('Remove'));
137 $this->drupalPost(NULL, $edit, t('Save'));
138 }
139
140 /**
141 * Replace a file within a node.
142 */
143 function replaceNodeFile($file, $field_name, $nid, $new_revision = TRUE) {
144 $edit = array(
ef620a1a 145 'files[' . $field_name . '_0]' => realpath($file->filepath),
060d70b8
NH
146 'revision' => (string) (int) $new_revision,
147 );
148
149 $this->drupalPost('node/' . $nid . '/edit', array(), t('Remove'));
150 $this->drupalPost(NULL, $edit, t('Save'));
151 }
152
153 /**
154 * Assert that a file exists physically on disk.
155 */
156 function assertFileExists($file, $message = NULL) {
157 $message = isset($message) ? $message : t('File %file exists on the disk.', array('%file' => $file['filepath']));
158 $this->assertTrue(is_file($file['filepath']), $message);
159 }
160
161 /**
162 * Assert that a file exists in the database.
163 */
164 function assertFileEntryExists($file, $message = NULL) {
165 module_load_include('inc', 'filefield', 'field_file');
166 $db_file = field_file_load($file['fid'], TRUE);
167 $message = isset($message) ? $message : t('File %file exists in database at the correct path.', array('%file' => $file['filepath']));
168 $this->assertEqual($db_file['filepath'], $file['filepath'], $message);
169 }
170
171 /**
172 * Assert that a file does not exist on disk.
173 */
174 function assertFileNotExists($file, $message = NULL) {
175 $message = isset($message) ? $message : t('File %file exists on the disk.', array('%file' => $file['filepath']));
176 $this->assertFalse(is_file($file['filepath']), $message);
177 }
178
179 /**
180 * Assert that a file does not exist in the database.
181 */
182 function assertFileEntryNotExists($file, $message) {
183 module_load_include('inc', 'filefield', 'field_file');
184 $message = isset($message) ? $message : t('File %file exists in database at the correct path.', array('%file' => $file['filepath']));
185 $this->assertFalse(field_file_load($file['fid'], TRUE), $message);
186 }
187}
188
189/**
190 * Test class to test file handling with node revisions.
191 */
192class FileFieldRevisionTestCase extends FileFieldTestCase {
193 function getInfo() {
194 return array(
195 'name' => t('FileField revision test'),
196 'description' => t('Test creating and deleting revisions with files attached.'),
197 'group' => t('FileField'),
198 );
199 }
200
201 /**
202 * Test creating multiple revisions of a node and managing the attached files.
203 *
204 * Expected behaviors:
205 * - Adding a new revision will make another entry in the field table, but
206 * the original file will not be duplicated.
207 * - Deleting a revision should not delete the original file if the file
208 * is in use by another revision.
209 * - When the last revision that uses a file is deleted, the original file
210 * should be deleted also.
211 */
212 function testRevisions() {
ef620a1a 213 $field_name = 'field_' . strtolower($this->randomName());
060d70b8 214 $type = $this->drupalCreateContentType();
93c5556a
NH
215 $field_options = array(
216 'description_field' => '1',
217 );
218 $field = $this->createFileField($field_name, $type->name, $field_options);
060d70b8
NH
219
220 $test_file = $this->getTestFile('text');
221
222 // Create a new node with the uploaded file.
93c5556a 223 $nid = $this->uploadNodeFile($test_file, $field, $type->name);
060d70b8
NH
224
225 // Check that the file exists on disk and in the database.
226 $node = node_load($nid, NULL, TRUE);
227 $node_file_r1 = $node->{$field['field_name']}[0];
228 $node_vid_r1 = $node->vid;
229 $this->assertFileExists($node_file_r1, t('New file saved to disk on node creation.'));
230 $this->assertFileEntryExists($node_file_r1, t('File entry exists in database on node creation.'));
231
232 // Upload another file to the same node in a new revision.
233 $this->replaceNodeFile($test_file, $field_name, $nid);
234 $node = node_load($nid, NULL, TRUE);
235 $node_file_r2 = $node->{$field['field_name']}[0];
236 $node_vid_r2 = $node->vid;
237 $this->assertFileExists($node_file_r2, t('Replacement file exists on disk after creating new revision.'));
238 $this->assertFileEntryExists($node_file_r2, t('Replacement file entry exists in database after creating new revision.'));
239
240 // Check that the original file is still in place on the first revision.
241 $node = node_load($nid, $node_vid_r1, TRUE);
242 $this->assertEqual($node_file_r1, $node->{$field['field_name']}[0], t('Original file still in place after replacing file in new revision.'));
243 $this->assertFileExists($node_file_r1, t('Original file still in place after replacing file in new revision.'));
244 $this->assertFileEntryExists($node_file_r1, t('Original file entry still in place after replacing file in new revision'));
245
246 // Save a new version of the node without any changes.
247 // Check that the file is still the same as the previous revision.
248 $this->drupalPost('node/' . $nid . '/edit', array('revision' => '1'), t('Save'));
249 $node = node_load($nid, NULL, TRUE);
250 $node_file_r3 = $node->{$field['field_name']}[0];
251 $node_vid_r3 = $node->vid;
93c5556a
NH
252
253 // FileField Meta's extensive meta data can be difficult to match up exactly
254 // (mostly differences between strings and integers). Just compare the
255 // descriptions.
256 $node_file_r2['data'] = array('description' => $node_file_r2['data']['description']);
257 $node_file_r3['data'] = array('description' => $node_file_r3['data']['description']);
060d70b8
NH
258 $this->assertEqual($node_file_r2, $node_file_r3, t('Previous revision file still in place after creating a new revision without a new file.'));
259
260 // Revert to the first revision and check that the original file is active.
261 $this->drupalPost('node/' . $nid . '/revisions/' . $node_vid_r1 . '/revert', array(), t('Revert'));
262 $node = node_load($nid, NULL, TRUE);
263 $node_file_r4 = $node->{$field['field_name']}[0];
264 $node_vid_r4 = $node->vid;
265 $this->assertEqual($node_file_r1, $node_file_r4, t('Original revision file still in place after reverting to the original revision.'));
266
267 // Delete the second revision and check that the file is kept (since it is
268 // still being used by the third revision).
269 $this->drupalPost('node/' . $nid . '/revisions/' . $node_vid_r2 . '/delete', array(), t('Delete'));
270 $this->assertFileExists($node_file_r3, t('Second file is still available after deleting second revision, since it is being used by the third revision.'));
271 $this->assertFileEntryExists($node_file_r3, t('Second file entry is still available after deleting second revision, since it is being used by the third revision.'));
272
273 // Delete the third revision and check that the file is deleted also.
274 $this->drupalPost('node/' . $nid . '/revisions/' . $node_vid_r3 . '/delete', array(), t('Delete'));
275 $this->assertFileNotExists($node_file_r3, t('Second file is now deleted after deleting third revision, since it is no longer being used by any other nodes.'));
276 $this->assertFileEntryNotExists($node_file_r3, t('Second file entry is now deleted after deleting third revision, since it is no longer being used by any other nodes.'));
277
278 // Delete the entire node and check that the original file is deleted.
279 $this->drupalPost('node/' . $nid . '/delete', array(), t('Delete'));
280 $this->assertFileNotExists($node_file_r1, t('Original file is deleted after deleting the entire node with two revisions remaining.'));
281 $this->assertFileEntryNotExists($node_file_r1, t('Original file entry is deleted after deleting the entire node with two revisions remaining.'));
282 }
283}
284
285/**
286 * Test class to check that formatters are working properly.
287 */
288class FileFieldDisplayTestCase extends FileFieldTestCase {
289 function getInfo() {
290 return array(
291 'name' => t('FileField display tests'),
292 'description' => t('Test the display of file fields in node and views.'),
293 'group' => t('FileField'),
294 );
295 }
296
297 /**
298 * Test normal formatter display on node display.
299 */
300 function testNodeDisplay() {
ef620a1a 301 $field_name = 'field_' . strtolower($this->randomName());
060d70b8
NH
302 $type = $this->drupalCreateContentType();
303 $field_options = array(
304 'description_field' => '1',
305 'list_field' => '1',
306 'list_default' => '1',
307 );
308 $field = $this->createFileField($field_name, $type->name, $field_options);
309 $test_file = $this->getTestFile('text');
310
311 // Create a new node with the uploaded file.
93c5556a
NH
312 $nid = $this->uploadNodeFile($test_file, $field, $type->name);
313 $this->drupalGet('node/' . $nid);
060d70b8
NH
314
315 // Check that the default formatter is displaying with the file name.
316 $node = node_load($nid, NULL, TRUE);
317 $node_file = $node->{$field['field_name']}[0];
318 $default_output = theme('filefield_file', $node_file);
319 $this->assertRaw($default_output, t('Default formatter displaying correctly on full node view.'));
320
321 // Turn the "list" option off and check that the file is no longer listed.
322 $edit = array($field['field_name'] . '[0][list]' => FALSE);
323 $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save'));
324
325 $this->assertNoRaw($default_output, t('Field is hidden when "list" option is unchecked.'));
326
327 }
328}
ef620a1a
NH
329
330/**
331 * Test class to check for various validations.
332 */
333class FileFieldValidateTestCase extends FileFieldTestCase {
bad951d7
NH
334 protected $field;
335 protected $node_type;
ef620a1a
NH
336
337 function getInfo() {
338 return array(
339 'name' => t('FileField validation tests'),
340 'description' => t('Tests validation functions such as file type, max file size, max size per node, and required.'),
341 'group' => t('FileField'),
342 );
343 }
344
345 /**
346 * Implementation of setUp().
347 */
348 function setUp() {
93c5556a 349 $modules = array_merge(func_get_args(), array('content', 'filefield', 'filefield_meta', 'getid3', 'mimedetect', 'token', 'views'));
bad951d7 350 call_user_func_array(array($this, 'parent::setUp'), $modules);
ef620a1a
NH
351
352 $this->node_type = $this->drupalCreateContentType();
353 $this->node_type->url_name = str_replace('_', '-', $this->node_type->name);
354 $field_name = 'field_' . strtolower($this->randomName());
355 $this->field = $this->createFileField($field_name, $this->node_type->name);
356 }
357
358 /**
359 * Test required property on file fields.
360 */
361 function testRequired() {
362 $type = $this->node_type;
363 $field = $this->field;
364
365 // Make our field required.
366 $this->updateFileField($field['field_name'], $type->name, array('required' => '1'));
367
bad951d7 368 $test_file = $this->getTestFile('image');
ef620a1a
NH
369
370 // Try to post a new node without uploading a file.
371 $edit = array('title' => $this->randomName());
372 $this->drupalPost('node/add/' . $type->url_name, $edit, t('Save'));
373
374 $this->assertRaw(t('%title field is required.', array('%title' => $field['widget']['label'])), t('Node save failed when required file field was empty.'));
375
376 // Create a new node with the uploaded file.
93c5556a 377 $nid = $this->uploadNodeFile($test_file, $field, $type->name);
ef620a1a
NH
378 $node = node_load($nid, NULL, TRUE);
379 $node_file = $node->{$field['field_name']}[0];
380 $this->assertFileExists($node_file, t('File exists after uploading to the required field.'));
381 $this->assertFileEntryExists($node_file, t('File entry exists after uploading to the required field.'));
382
383 // Try again with a multiple value field.
384 $this->updateFileField($field['field_name'], $type->name, array('multiple' => '0', 'required' => '1'));
385
386 // Try to post a new node without uploading a file in the multivalue field.
387 $edit = array('title' => $this->randomName());
388 $this->drupalPost('node/add/' . $type->url_name, $edit, t('Save'));
389
390 $this->assertRaw(t('%title field is required.', array('%title' => $field['widget']['label'])), t('Node save failed when required multiple value file field was empty.'));
391
392 // Create a new node with the uploaded file into the multivalue field.
93c5556a 393 $nid = $this->uploadNodeFile($test_file, $field, $type->name);
ef620a1a
NH
394 $node = node_load($nid, NULL, TRUE);
395 $node_file = $node->{$field['field_name']}[0];
396 $this->assertFileExists($node_file, t('File exists after uploading to the required multiple value field.'));
397 $this->assertFileEntryExists($node_file, t('File entry exists after uploading to the required multipel value field.'));
398
399 // Set the field back to not required.
400 $this->updateFileField($field['field_name'], $type->name, array('multiple' => '0', 'required' => '1'));
401 }
402
403 /**
404 * Test the max file size validator.
405 */
406 function testFileMaxSize() {
407 $type = $this->node_type;
408 $field = $this->field;
409
410 $small_file = $this->getTestFile('text', 131072); // 128KB.
411 $large_file = $this->getTestFile('text', 1310720); // 1.2MB
412
413 // Test uploading both a large and small file with different increments.
414 $sizes = array(
415 '1M' => 1048576,
416 '1024K' => 1048576,
417 '1048576' => 1048576,
418 );
419
420 foreach ($sizes as $max_filesize_per_file => $file_limit) {
421 // Set the max file upload size.
422 $this->updateFileField($field['field_name'], $type->name, array(), array('max_filesize_per_file' => $max_filesize_per_file));
423
424 // Create a new node with the small file, which should pass.
93c5556a 425 $nid = $this->uploadNodeFile($small_file, $field, $type->name);
ef620a1a
NH
426 $node = node_load($nid, NULL, TRUE);
427 $node_file = $node->{$field['field_name']}[0];
428 $this->assertFileExists($node_file, t('File exists after uploading a file (%filesize) under the max limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_filesize_per_file)));
429 $this->assertFileEntryExists($node_file, t('File entry exists after uploading a file (%filesize) under the max limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_filesize_per_file)));
430
431 // Check that uploading the large file fails (1M limit).
93c5556a 432 $nid = $this->uploadNodeFile($large_file, $field, $type->name);
ef620a1a
NH
433 $error_message = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size($large_file->filesize), '%maxsize' => format_size($file_limit)));
434 $this->assertRaw($error_message, t('Node save failed when file (%filesize) exceeded the max upload size (%maxsize).', array('%filesize' => format_size($large_file->filesize), '%maxsize' => $max_filesize_per_file)));
435 }
436
437 // Turn off the max filesize.
438 $this->updateFileField($field['field_name'], $type->name, array(), array('max_filesize_per_file' => ''));
439
440 // Upload the big file successfully.
93c5556a 441 $nid = $this->uploadNodeFile($large_file, $field, $type->name);
ef620a1a
NH
442 $node = node_load($nid, NULL, TRUE);
443 $node_file = $node->{$field['field_name']}[0];
444 $this->assertFileExists($node_file, t('File exists after uploading a file (%filesize) with no max limit.', array('%filesize' => format_size($large_file->filesize))));
445 $this->assertFileEntryExists($node_file, t('File entry exists after uploading a file (%filesize) with no max limit.', array('%filesize' => format_size($large_file->filesize))));
446 }
447
448 /**
449 * Test the max file size per node validator.
450 */
451 function testNodeMaxSize() {
452 $type = $this->node_type;
453 $field = $this->field;
454
455 $small_file = $this->getTestFile('text', 131072); // 128KB.
456 $large_file = $this->getTestFile('text', 1310720); // 1.2MB
457
458 // Set the max file upload size.
459 $max_node_limit = '256K';
460 $file_limit = 262144;
461 $this->updateFileField($field['field_name'], $type->name, array('multiple' => '1'), array('max_filesize_per_node' => $max_node_limit));
462
463 // Create a new node with the small file, which should pass.
93c5556a 464 $nid = $this->uploadNodeFile($small_file, $field, $type->name);
ef620a1a
NH
465 $node = node_load($nid, NULL, TRUE);
466 $node_file = $node->{$field['field_name']}[0];
467 $this->assertFileExists($node_file, t('File exists after uploading a file (%filesize) under the max node limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_node_limit)));
468 $this->assertFileEntryExists($node_file, t('File entry exists after uploading a file (%filesize) under the max node limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_node_limit)));
469
470 // Add a second file to the same node which should pass.
93c5556a 471 $nid = $this->uploadNodeFile($small_file, $field, $nid);
ef620a1a
NH
472 $node = node_load($nid, NULL, TRUE);
473 $node_file = $node->{$field['field_name']}[0];
474 $this->assertFileExists($node_file, t('File exists after uploading a file (%filesize) under the max node limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_node_limit)));
475 $this->assertFileEntryExists($node_file, t('File entry exists after uploading a file (%filesize) under the max node limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_node_limit)));
476
477 // Add a third file to the same node which should fail.
93c5556a 478 $nid = $this->uploadNodeFile($small_file, $field, $nid);
ef620a1a
NH
479 $error_message = t('exceeds field settings of %msize.', array('%msize' => format_size($file_limit)));
480 $this->assertRaw($error_message, t('File not uploaded as the file (%filesize) exceeds the max node limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_node_limit)));
481
482 // Check that uploading the large file fails (1M limit).
93c5556a 483 $nid = $this->uploadNodeFile($large_file, $field, $type->name);
ef620a1a
NH
484 $error_message = t('exceeds field settings of %msize.', array('%msize' => format_size($file_limit)));
485 $this->assertRaw($error_message, t('File not uploaded as the file (%filesize) exceeds the max node limit (%maxsize).', array('%filesize' => format_size($large_file->filesize), '%maxsize' => $max_node_limit)));
486
487 // Turn off the max filesize per node.
488 $this->updateFileField($field['field_name'], $type->name, array('multiple' => '0'), array('max_filesize_per_node' => ''));
489 }
490
491 /**
492 * Test the file extension, do additional checks if mimedetect is installed.
493 */
494 function testFileExtension() {
495 $type = $this->node_type;
496 $field = $this->field;
497
498 // Setup files for extension checking.
bad951d7 499 $test_file = $this->getTestFile('image');
894255af
NH
500 preg_match('/(?<=\.)[^\.]*$/', $test_file->filename, $matches);
501 $extention = current($matches);
bad951d7 502 $wrong_extension_file = drupal_clone($test_file);
894255af 503 $wrong_extension_file->filename = str_replace(".$extention", '.jpg', $test_file->filename);
ef620a1a 504 $wrong_extension_file->filepath = file_directory_path() .'/'. $wrong_extension_file->filename;
bad951d7 505 $original_path = $test_file->filepath;
ef620a1a
NH
506 file_copy($original_path, $wrong_extension_file->filepath);
507
508 $this->updateFileField($field['field_name'], $type->name, array(), array('file_extensions' => ''));
509
510 // Check that the file can be uploaded with no extension checking.
93c5556a 511 $nid = $this->uploadNodeFile($test_file, $field, $type->name);
ef620a1a
NH
512 $node = node_load($nid, NULL, TRUE);
513 $node_file = $node->{$field['field_name']}[0];
514 $this->assertFileExists($node_file, t('File exists after uploading a file with no extension checking.'));
515 $this->assertFileEntryExists($node_file, t('File entry exists after uploading a file with no extension checking.'));
516
517 // Enable extension checking.
894255af 518 $this->updateFileField($field['field_name'], $type->name, array(), array('file_extensions' => "txt png jpg $extention"));
ef620a1a
NH
519
520 // Check that the file can be uploaded with extension checking.
93c5556a 521 $nid = $this->uploadNodeFile($test_file, $field, $type->name);
ef620a1a
NH
522 $node = node_load($nid, NULL, TRUE);
523 $node_file = $node->{$field['field_name']}[0];
524 $this->assertFileExists($node_file, t('File exists after uploading a file with extension checking.'));
525 $this->assertFileEntryExists($node_file, t('File entry exists after uploading a file with extension checking.'));
526
527 // Check that a mismatched extension cannot be uploaded.
80094f1c 528 $mimedetect = FALSE;
ef620a1a 529 if (module_exists('mimedetect')) {
80094f1c
NH
530 $mimedetect = TRUE;
531 module_load_include('install', 'mimedetect');
532 if (!extension_loaded('fileinfo')) {
533 variable_set('mimedetect_enable_file_binary', 1);
534 }
535 $requirements = mimedetect_requirements('runtime');
536 foreach ($requirements as $requirement) {
537 if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) {
538 $mimedetect = FALSE;
539 }
540 }
541 }
542 if ($mimedetect) {
93c5556a 543 $this->uploadNodeFile($wrong_extension_file, $field, $type->name);
f4dd3d44 544 $error_pattern = "/The file contents \([a-z\-\/]+\) do not match its extension \([a-z]+\)\./";
ef620a1a
NH
545 $this->assertPattern($error_pattern, t('File prevented from uploading because its extension does not match its content.'));
546 }
547 else {
548 $this->assertTrue(TRUE, t('Mime type checking and extension spoofing skipped because the mimedetect module is not available.'));
549 }
550
551 // Disable the extension checking.
552 $this->updateFileField($field['field_name'], $type->name, array(), array('file_extensions' => ''));
553 }
554}
555
556/**
557 * Test class to check that files are uploaded to proper locations.
558 */
559class FileFieldPathTestCase extends FileFieldTestCase {
560 function getInfo() {
561 return array(
562 'name' => t('FileField file path tests'),
563 'description' => t('Test that files are uploaded to the proper location, extra testing if Token module is available.'),
564 'group' => t('FileField'),
565 );
566 }
567
568 /**
569 * Test normal formatter display on node display.
570 */
571 function testUploadPath() {
572 $field_name = 'field_' . strtolower($this->randomName());
573 $type = $this->drupalCreateContentType();
574 $field = $this->createFileField($field_name, $type->name);
575 $test_file = $this->getTestFile('text');
576
577 // Create a new node.
93c5556a 578 $nid = $this->uploadNodeFile($test_file, $field, $type->name);
ef620a1a
NH
579
580 // Check that the file was uploaded to the file root.
581 $node = node_load($nid, NULL, TRUE);
582 $node_file = $node->{$field['field_name']}[0];
583 $this->assertPathMatch(file_directory_path() . '/' . $test_file->filename, $node_file['filepath'], t('The file %file was uploaded to the correct path.', array('%file' => $node_file['filepath'])));
584
585 // Change the path to contain multiple subdirectories.
586 $field = $this->updateFileField($field['field_name'], $type->name, array(), array('file_path' => 'foo/bar/baz'));
587
588 // Upload a new file into the subdirectories.
93c5556a 589 $nid = $this->uploadNodeFile($test_file, $field, $type->name);
ef620a1a
NH
590
591 // Check that the file was uploaded into the subdirectory.
592 $node = node_load($nid, NULL, TRUE);
593 $node_file = $node->{$field['field_name']}[0];
594 $this->assertPathMatch(file_directory_path() . '/foo/bar/baz/' . $test_file->filename, $node_file['filepath'], t('The file %file was uploaded to the correct path.', array('%file' => $node_file['filepath'])));
595
596 // Check the path when used with tokens.
6040fe25 597 if (module_exists('token')) {
ef620a1a
NH
598 // Change the path to contain multiple token directories.
599 $field = $this->updateFileField($field['field_name'], $type->name, array(), array('file_path' => '[uid]/[user-raw]'));
600
601 // Upload a new file into the token subdirectories.
93c5556a 602 $nid = $this->uploadNodeFile($test_file, $field, $type->name);
ef620a1a
NH
603
604 // Check that the file was uploaded into the subdirectory.
605 $node = node_load($nid, NULL, TRUE);
606 $node_file = $node->{$field['field_name']}[0];
607 $subdirectory = token_replace('[uid]/[user-raw]', 'user', $this->admin_user);
608 $this->assertPathMatch(file_directory_path() . '/' . $subdirectory . '/' . $test_file->filename, $node_file['filepath'], t('The file %file was uploaded to the correct path with token replacements.', array('%file' => $node_file['filepath'])));
609 }
610 else {
611 $this->assertTrue(TRUE, t('File path token test skipped because the Token module is not available.'));
612 }
613
614 }
615
616 /**
617 * A loose assertion to check that a file is uploaded to the right location.
618 *
619 * @param $expected_path
620 * The location where the file is expected to be uploaded. Duplicate file
621 * names to not need to be taken into account.
622 * @param $actual_path
623 * Where the file was actually uploaded.
624 * @param $message
625 * The message to display with this assertion.
626 */
627 function assertPathMatch($expected_path, $actual_path, $message) {
628 // Strip off the extension of the expected path to allow for _0, _1, etc.
629 // suffixes when the file hits a duplicate name.
630 $pos = strrpos($expected_path, '.');
631 $base_path = substr($expected_path, 0, $pos);
632 $extension = substr($expected_path, $pos + 1);
633
634 $result = preg_match('/' . preg_quote($base_path, '/') . '(_[0-9]+)?\.' . preg_quote($extension, '/') . '/', $actual_path);
635 $this->assertTrue($result, $message);
636 }
637}