| Commit | Line | Data |
|---|---|---|
| 060d70b8 | 1 | <?php |
| 060d70b8 NH |
2 | |
| 3 | class 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 | */ | |
| 192 | class 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 | */ | |
| 288 | class 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 | */ | |
| 333 | class 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 | */ | |
| 559 | class 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 | } |