See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Unit tests for /lib/filestorage/file_storage.php 19 * 20 * @package core 21 * @category test 22 * @copyright 2012 David Mudrak <david@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 namespace core; 27 28 use file_exception; 29 use file_reference_exception; 30 use repository; 31 use stored_file; 32 use stored_file_creation_exception; 33 34 defined('MOODLE_INTERNAL') || die(); 35 36 global $CFG; 37 require_once($CFG->libdir . '/filelib.php'); 38 require_once($CFG->dirroot . '/repository/lib.php'); 39 require_once($CFG->libdir . '/filestorage/stored_file.php'); 40 41 /** 42 * Unit tests for /lib/filestorage/file_storage.php 43 * 44 * @package core 45 * @category test 46 * @copyright 2012 David Mudrak <david@moodle.com> 47 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 48 * @coversDefaultClass \file_storage 49 */ 50 class file_storage_test extends \advanced_testcase { 51 52 /** 53 * Files can be created from strings. 54 * 55 * @covers ::create_file_from_string 56 */ 57 public function test_create_file_from_string() { 58 global $DB; 59 60 $this->resetAfterTest(true); 61 62 // Number of files installed in the database on a fresh Moodle site. 63 $installedfiles = $DB->count_records('files', array()); 64 65 $content = 'abcd'; 66 $syscontext = \context_system::instance(); 67 $filerecord = array( 68 'contextid' => $syscontext->id, 69 'component' => 'core', 70 'filearea' => 'unittest', 71 'itemid' => 0, 72 'filepath' => '/images/', 73 'filename' => 'testfile.txt', 74 ); 75 $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']); 76 77 $fs = get_file_storage(); 78 $file = $fs->create_file_from_string($filerecord, $content); 79 80 $this->assertInstanceOf('stored_file', $file); 81 $this->assertTrue($file->compare_to_string($content)); 82 $this->assertSame($pathhash, $file->get_pathnamehash()); 83 84 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>$pathhash))); 85 86 $filesystem = $fs->get_file_system(); 87 $location = $filesystem->get_local_path_from_storedfile($file, true); 88 89 $this->assertFileExists($location); 90 91 // Verify the dir placeholder files are created. 92 $this->assertEquals($installedfiles + 3, $DB->count_records('files', array())); 93 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].'/.')))); 94 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].'.')))); 95 96 // Tests that missing content file is recreated. 97 98 unlink($location); 99 $this->assertFileDoesNotExist($location); 100 101 $filerecord['filename'] = 'testfile2.txt'; 102 $file2 = $fs->create_file_from_string($filerecord, $content); 103 $this->assertInstanceOf('stored_file', $file2); 104 $this->assertSame($file->get_contenthash(), $file2->get_contenthash()); 105 $this->assertFileExists($location); 106 107 $this->assertEquals($installedfiles + 4, $DB->count_records('files', array())); 108 109 // Test that borked content file is recreated. 110 111 $this->assertSame(2, file_put_contents($location, 'xx')); 112 113 $filerecord['filename'] = 'testfile3.txt'; 114 $file3 = $fs->create_file_from_string($filerecord, $content); 115 $this->assertInstanceOf('stored_file', $file3); 116 $this->assertSame($file->get_contenthash(), $file3->get_contenthash()); 117 $this->assertFileExists($location); 118 119 $this->assertSame($content, file_get_contents($location)); 120 $this->assertDebuggingCalled(); 121 122 $this->assertEquals($installedfiles + 5, $DB->count_records('files', array())); 123 } 124 125 /** 126 * Local files can be added to the filepool 127 * 128 * @covers ::create_file_from_pathname 129 */ 130 public function test_create_file_from_pathname() { 131 global $CFG, $DB; 132 133 $this->resetAfterTest(true); 134 135 // Number of files installed in the database on a fresh Moodle site. 136 $installedfiles = $DB->count_records('files', array()); 137 138 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 139 $syscontext = \context_system::instance(); 140 $filerecord = array( 141 'contextid' => $syscontext->id, 142 'component' => 'core', 143 'filearea' => 'unittest', 144 'itemid' => 0, 145 'filepath' => '/images/', 146 'filename' => 'testimage.jpg', 147 ); 148 $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']); 149 150 $fs = get_file_storage(); 151 $file = $fs->create_file_from_pathname($filerecord, $filepath); 152 153 $this->assertInstanceOf('stored_file', $file); 154 $this->assertTrue($file->compare_to_path($filepath)); 155 156 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>$pathhash))); 157 158 $filesystem = $fs->get_file_system(); 159 $location = $filesystem->get_local_path_from_storedfile($file, true); 160 161 $this->assertFileExists($location); 162 163 // Verify the dir placeholder files are created. 164 $this->assertEquals($installedfiles + 3, $DB->count_records('files', array())); 165 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].'/.')))); 166 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].'.')))); 167 168 // Tests that missing content file is recreated. 169 170 unlink($location); 171 $this->assertFileDoesNotExist($location); 172 173 $filerecord['filename'] = 'testfile2.jpg'; 174 $file2 = $fs->create_file_from_pathname($filerecord, $filepath); 175 $this->assertInstanceOf('stored_file', $file2); 176 $this->assertSame($file->get_contenthash(), $file2->get_contenthash()); 177 $this->assertFileExists($location); 178 179 $this->assertEquals($installedfiles + 4, $DB->count_records('files', array())); 180 181 // Test that borked content file is recreated. 182 183 $this->assertSame(2, file_put_contents($location, 'xx')); 184 185 $filerecord['filename'] = 'testfile3.jpg'; 186 $file3 = $fs->create_file_from_pathname($filerecord, $filepath); 187 $this->assertInstanceOf('stored_file', $file3); 188 $this->assertSame($file->get_contenthash(), $file3->get_contenthash()); 189 $this->assertFileExists($location); 190 191 $this->assertSame(file_get_contents($filepath), file_get_contents($location)); 192 $this->assertDebuggingCalled(); 193 194 $this->assertEquals($installedfiles + 5, $DB->count_records('files', array())); 195 196 // Test invalid file creation. 197 198 $filerecord['filename'] = 'testfile4.jpg'; 199 try { 200 $fs->create_file_from_pathname($filerecord, $filepath.'nonexistent'); 201 $this->fail('Exception expected when trying to add non-existent stored file.'); 202 } catch (\Exception $e) { 203 $this->assertInstanceOf('file_exception', $e); 204 } 205 } 206 207 /** 208 * Tests get get file. 209 * 210 * @covers ::get_file 211 */ 212 public function test_get_file() { 213 global $CFG; 214 215 $this->resetAfterTest(false); 216 217 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 218 $syscontext = \context_system::instance(); 219 $filerecord = array( 220 'contextid' => $syscontext->id, 221 'component' => 'core', 222 'filearea' => 'unittest', 223 'itemid' => 0, 224 'filepath' => '/images/', 225 'filename' => 'testimage.jpg', 226 ); 227 $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']); 228 229 $fs = get_file_storage(); 230 $file = $fs->create_file_from_pathname($filerecord, $filepath); 231 232 $this->assertInstanceOf('stored_file', $file); 233 $this->assertEquals($syscontext->id, $file->get_contextid()); 234 $this->assertEquals('core', $file->get_component()); 235 $this->assertEquals('unittest', $file->get_filearea()); 236 $this->assertEquals(0, $file->get_itemid()); 237 $this->assertEquals('/images/', $file->get_filepath()); 238 $this->assertEquals('testimage.jpg', $file->get_filename()); 239 $this->assertEquals(filesize($filepath), $file->get_filesize()); 240 $this->assertEquals($pathhash, $file->get_pathnamehash()); 241 242 return $file; 243 } 244 245 /** 246 * Local images can be added to the filepool and their preview can be obtained 247 * 248 * @param stored_file $file 249 * @depends test_get_file 250 * @covers ::get_file_preview 251 */ 252 public function test_get_file_preview(stored_file $file) { 253 global $CFG; 254 255 $this->resetAfterTest(); 256 $fs = get_file_storage(); 257 258 $previewtinyicon = $fs->get_file_preview($file, 'tinyicon'); 259 $this->assertInstanceOf('stored_file', $previewtinyicon); 260 $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename()); 261 262 $previewtinyicon = $fs->get_file_preview($file, 'thumb'); 263 $this->assertInstanceOf('stored_file', $previewtinyicon); 264 $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename()); 265 266 $this->expectException('file_exception'); 267 $fs->get_file_preview($file, 'amodewhichdoesntexist'); 268 } 269 270 /** 271 * Tests for get_file_preview without an image. 272 * 273 * @covers ::get_file_preview 274 */ 275 public function test_get_file_preview_nonimage() { 276 $this->resetAfterTest(true); 277 $syscontext = \context_system::instance(); 278 $filerecord = array( 279 'contextid' => $syscontext->id, 280 'component' => 'core', 281 'filearea' => 'unittest', 282 'itemid' => 0, 283 'filepath' => '/textfiles/', 284 'filename' => 'testtext.txt', 285 ); 286 287 $fs = get_file_storage(); 288 $fs->create_file_from_string($filerecord, 'text contents'); 289 $textfile = $fs->get_file($syscontext->id, $filerecord['component'], $filerecord['filearea'], 290 $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename']); 291 292 $preview = $fs->get_file_preview($textfile, 'thumb'); 293 $this->assertFalse($preview); 294 } 295 296 /** 297 * Make sure renaming is working 298 * 299 * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} 300 * @covers \stored_file::rename 301 */ 302 public function test_file_renaming() { 303 global $CFG; 304 305 $this->resetAfterTest(); 306 $fs = get_file_storage(); 307 $syscontext = \context_system::instance(); 308 $component = 'core'; 309 $filearea = 'unittest'; 310 $itemid = 0; 311 $filepath = '/'; 312 $filename = 'test.txt'; 313 314 $filerecord = array( 315 'contextid' => $syscontext->id, 316 'component' => $component, 317 'filearea' => $filearea, 318 'itemid' => $itemid, 319 'filepath' => $filepath, 320 'filename' => $filename, 321 ); 322 323 $originalfile = $fs->create_file_from_string($filerecord, 'Test content'); 324 $this->assertInstanceOf('stored_file', $originalfile); 325 $contenthash = $originalfile->get_contenthash(); 326 $newpath = '/test/'; 327 $newname = 'newtest.txt'; 328 329 // This should work. 330 $originalfile->rename($newpath, $newname); 331 $file = $fs->get_file($syscontext->id, $component, $filearea, $itemid, $newpath, $newname); 332 $this->assertInstanceOf('stored_file', $file); 333 $this->assertEquals($contenthash, $file->get_contenthash()); 334 335 // Try break it. 336 $this->expectException('file_exception'); 337 $this->expectExceptionMessage('Cannot create file 1/core/unittest/0/test/newtest.txt (file exists, cannot rename)'); 338 // This shall throw exception. 339 $originalfile->rename($newpath, $newname); 340 } 341 342 /** 343 * Create file from reference tests 344 * 345 * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} 346 * @covers ::create_file_from_reference 347 */ 348 public function test_create_file_from_reference() { 349 global $CFG, $DB; 350 351 $this->resetAfterTest(); 352 // Create user. 353 $generator = $this->getDataGenerator(); 354 $user = $generator->create_user(); 355 $this->setUser($user); 356 $usercontext = \context_user::instance($user->id); 357 $syscontext = \context_system::instance(); 358 359 $fs = get_file_storage(); 360 361 $repositorypluginname = 'user'; 362 // Override repository permission. 363 $capability = 'repository/' . $repositorypluginname . ':view'; 364 $guestroleid = $DB->get_field('role', 'id', array('shortname' => 'guest')); 365 assign_capability($capability, CAP_ALLOW, $guestroleid, $syscontext->id, true); 366 367 $args = array(); 368 $args['type'] = $repositorypluginname; 369 $repos = repository::get_instances($args); 370 $userrepository = reset($repos); 371 $this->assertInstanceOf('repository', $userrepository); 372 373 $component = 'user'; 374 $filearea = 'private'; 375 $itemid = 0; 376 $filepath = '/'; 377 $filename = 'userfile.txt'; 378 379 $filerecord = array( 380 'contextid' => $usercontext->id, 381 'component' => $component, 382 'filearea' => $filearea, 383 'itemid' => $itemid, 384 'filepath' => $filepath, 385 'filename' => $filename, 386 ); 387 388 $content = 'Test content'; 389 $originalfile = $fs->create_file_from_string($filerecord, $content); 390 $this->assertInstanceOf('stored_file', $originalfile); 391 392 $newfilerecord = array( 393 'contextid' => $syscontext->id, 394 'component' => 'core', 395 'filearea' => 'phpunit', 396 'itemid' => 0, 397 'filepath' => $filepath, 398 'filename' => $filename, 399 ); 400 $ref = $fs->pack_reference($filerecord); 401 $newstoredfile = $fs->create_file_from_reference($newfilerecord, $userrepository->id, $ref); 402 $this->assertInstanceOf('stored_file', $newstoredfile); 403 $this->assertEquals($userrepository->id, $newstoredfile->get_repository_id()); 404 $this->assertEquals($originalfile->get_contenthash(), $newstoredfile->get_contenthash()); 405 $this->assertEquals($originalfile->get_filesize(), $newstoredfile->get_filesize()); 406 $this->assertMatchesRegularExpression('#' . $filename. '$#', $newstoredfile->get_reference_details()); 407 408 // Test looking for references. 409 $count = $fs->get_references_count_by_storedfile($originalfile); 410 $this->assertEquals(1, $count); 411 $files = $fs->get_references_by_storedfile($originalfile); 412 $file = reset($files); 413 $this->assertEquals($file, $newstoredfile); 414 415 // Look for references by repository ID. 416 $files = $fs->get_external_files($userrepository->id); 417 $file = reset($files); 418 $this->assertEquals($file, $newstoredfile); 419 420 // Try convert reference to local file. 421 $importedfile = $fs->import_external_file($newstoredfile); 422 $this->assertFalse($importedfile->is_external_file()); 423 $this->assertInstanceOf('stored_file', $importedfile); 424 // Still readable? 425 $this->assertEquals($content, $importedfile->get_content()); 426 } 427 428 /** 429 * Create file from reference tests 430 * 431 * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} 432 * @covers ::create_file_from_reference 433 */ 434 public function test_create_file_from_reference_with_content_hash() { 435 global $CFG, $DB; 436 437 $this->resetAfterTest(); 438 // Create user. 439 $generator = $this->getDataGenerator(); 440 $user = $generator->create_user(); 441 $this->setUser($user); 442 $usercontext = \context_user::instance($user->id); 443 $syscontext = \context_system::instance(); 444 445 $fs = get_file_storage(); 446 447 $repositorypluginname = 'user'; 448 // Override repository permission. 449 $capability = 'repository/' . $repositorypluginname . ':view'; 450 $guestroleid = $DB->get_field('role', 'id', array('shortname' => 'guest')); 451 assign_capability($capability, CAP_ALLOW, $guestroleid, $syscontext->id, true); 452 453 $args = array(); 454 $args['type'] = $repositorypluginname; 455 $repos = repository::get_instances($args); 456 $userrepository = reset($repos); 457 $this->assertInstanceOf('repository', $userrepository); 458 459 $component = 'user'; 460 $filearea = 'private'; 461 $itemid = 0; 462 $filepath = '/'; 463 $filename = 'userfile.txt'; 464 465 $filerecord = array( 466 'contextid' => $usercontext->id, 467 'component' => $component, 468 'filearea' => $filearea, 469 'itemid' => $itemid, 470 'filepath' => $filepath, 471 'filename' => $filename, 472 ); 473 474 $content = 'Test content'; 475 $originalfile = $fs->create_file_from_string($filerecord, $content); 476 $this->assertInstanceOf('stored_file', $originalfile); 477 478 $otherfilerecord = $filerecord; 479 $otherfilerecord['filename'] = 'other-filename.txt'; 480 $otherfilewithsamecontents = $fs->create_file_from_string($otherfilerecord, $content); 481 $this->assertInstanceOf('stored_file', $otherfilewithsamecontents); 482 483 $newfilerecord = array( 484 'contextid' => $syscontext->id, 485 'component' => 'core', 486 'filearea' => 'phpunit', 487 'itemid' => 0, 488 'filepath' => $filepath, 489 'filename' => $filename, 490 'contenthash' => $originalfile->get_contenthash(), 491 ); 492 $ref = $fs->pack_reference($filerecord); 493 $newstoredfile = $fs->create_file_from_reference($newfilerecord, $userrepository->id, $ref); 494 $this->assertInstanceOf('stored_file', $newstoredfile); 495 $this->assertEquals($userrepository->id, $newstoredfile->get_repository_id()); 496 $this->assertEquals($originalfile->get_contenthash(), $newstoredfile->get_contenthash()); 497 $this->assertEquals($originalfile->get_filesize(), $newstoredfile->get_filesize()); 498 $this->assertMatchesRegularExpression('#' . $filename . '$#', $newstoredfile->get_reference_details()); 499 } 500 501 private function setup_three_private_files() { 502 503 $this->resetAfterTest(); 504 505 $generator = $this->getDataGenerator(); 506 $user = $generator->create_user(); 507 $this->setUser($user->id); 508 $usercontext = \context_user::instance($user->id); 509 // Create a user private file. 510 $file1 = new \stdClass; 511 $file1->contextid = $usercontext->id; 512 $file1->component = 'user'; 513 $file1->filearea = 'private'; 514 $file1->itemid = 0; 515 $file1->filepath = '/'; 516 $file1->filename = '1.txt'; 517 $file1->source = 'test'; 518 519 $fs = get_file_storage(); 520 $userfile1 = $fs->create_file_from_string($file1, 'file1 content'); 521 $this->assertInstanceOf('stored_file', $userfile1); 522 523 $file2 = clone($file1); 524 $file2->filename = '2.txt'; 525 $userfile2 = $fs->create_file_from_string($file2, 'file2 content longer'); 526 $this->assertInstanceOf('stored_file', $userfile2); 527 528 $file3 = clone($file1); 529 $file3->filename = '3.txt'; 530 $userfile3 = $fs->create_file_from_storedfile($file3, $userfile2); 531 $this->assertInstanceOf('stored_file', $userfile3); 532 533 $user->ctxid = $usercontext->id; 534 535 return $user; 536 } 537 538 /** 539 * Tests for get_area_files 540 * 541 * @covers ::get_area_files 542 */ 543 public function test_get_area_files() { 544 $user = $this->setup_three_private_files(); 545 $fs = get_file_storage(); 546 547 // Get area files with default options. 548 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 549 550 // Should be the two files we added plus the folder. 551 $this->assertEquals(4, count($areafiles)); 552 553 // Verify structure. 554 foreach ($areafiles as $key => $file) { 555 $this->assertInstanceOf('stored_file', $file); 556 $this->assertEquals($key, $file->get_pathnamehash()); 557 } 558 559 // Get area files without a folder. 560 $folderlessfiles = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'sortorder', false); 561 // Should be the two files without folder. 562 $this->assertEquals(3, count($folderlessfiles)); 563 564 // Verify structure. 565 foreach ($folderlessfiles as $key => $file) { 566 $this->assertInstanceOf('stored_file', $file); 567 $this->assertEquals($key, $file->get_pathnamehash()); 568 } 569 570 // Get area files ordered by id. 571 $filesbyid = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'id', false); 572 // Should be the two files without folder. 573 $this->assertEquals(3, count($filesbyid)); 574 575 // Verify structure. 576 foreach ($filesbyid as $key => $file) { 577 $this->assertInstanceOf('stored_file', $file); 578 $this->assertEquals($key, $file->get_pathnamehash()); 579 } 580 581 // Test the limit feature to retrieve each individual file. 582 $limited = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'filename', false, 583 0, 0, 1); 584 $mapfunc = function($f) { 585 return $f->get_filename(); 586 }; 587 $this->assertEquals(array('1.txt'), array_values(array_map($mapfunc, $limited))); 588 $limited = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'filename', false, 589 0, 1, 50); 590 $this->assertEquals(array('2.txt', '3.txt'), array_values(array_map($mapfunc, $limited))); 591 592 // Test with an itemid with no files. 593 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', 666, 'sortorder', false); 594 // Should be none. 595 $this->assertEmpty($areafiles); 596 } 597 598 /** 599 * Tests for get_area_tree 600 * 601 * @covers ::get_area_tree 602 */ 603 public function test_get_area_tree() { 604 $user = $this->setup_three_private_files(); 605 $fs = get_file_storage(); 606 607 // Get area files with default options. 608 $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0); 609 $this->assertEmpty($areatree['subdirs']); 610 $this->assertNotEmpty($areatree['files']); 611 $this->assertCount(3, $areatree['files']); 612 613 // Ensure an empty try with a fake itemid. 614 $emptytree = $fs->get_area_tree($user->ctxid, 'user', 'private', 666); 615 $this->assertEmpty($emptytree['subdirs']); 616 $this->assertEmpty($emptytree['files']); 617 618 // Create a subdir. 619 $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/'); 620 $this->assertInstanceOf('stored_file', $dir); 621 622 // Add a file to the subdir. 623 $filerecord = array( 624 'contextid' => $user->ctxid, 625 'component' => 'user', 626 'filearea' => 'private', 627 'itemid' => 0, 628 'filepath' => '/testsubdir/', 629 'filename' => 'test-get-area-tree.txt', 630 ); 631 632 $directoryfile = $fs->create_file_from_string($filerecord, 'Test content'); 633 $this->assertInstanceOf('stored_file', $directoryfile); 634 635 $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0); 636 637 // At the top level there should still be 3 files. 638 $this->assertCount(3, $areatree['files']); 639 640 // There should now be a subdirectory. 641 $this->assertCount(1, $areatree['subdirs']); 642 643 // The test subdir is named testsubdir. 644 $subdir = $areatree['subdirs']['testsubdir']; 645 $this->assertNotEmpty($subdir); 646 // It should have one file we added. 647 $this->assertCount(1, $subdir['files']); 648 // And no subdirs itself. 649 $this->assertCount(0, $subdir['subdirs']); 650 651 // Verify the file is the one we added. 652 $subdirfile = reset($subdir['files']); 653 $this->assertInstanceOf('stored_file', $subdirfile); 654 $this->assertEquals($filerecord['filename'], $subdirfile->get_filename()); 655 } 656 657 /** 658 * Tests for get_file_by_id 659 * 660 * @covers ::get_file_by_id 661 */ 662 public function test_get_file_by_id() { 663 $user = $this->setup_three_private_files(); 664 $fs = get_file_storage(); 665 666 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 667 668 // Test get_file_by_id. 669 $filebyid = reset($areafiles); 670 $shouldbesame = $fs->get_file_by_id($filebyid->get_id()); 671 $this->assertEquals($filebyid->get_contenthash(), $shouldbesame->get_contenthash()); 672 673 // Test an id which doens't exist. 674 $doesntexist = $fs->get_file_by_id(99999); 675 $this->assertFalse($doesntexist); 676 } 677 678 /** 679 * Tests for get_file_by_hash 680 * 681 * @covers ::get_file_by_hash 682 */ 683 public function test_get_file_by_hash() { 684 $user = $this->setup_three_private_files(); 685 $fs = get_file_storage(); 686 687 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 688 // Test get_file_by_hash. 689 $filebyhash = reset($areafiles); 690 $shouldbesame = $fs->get_file_by_hash($filebyhash->get_pathnamehash()); 691 $this->assertEquals($filebyhash->get_id(), $shouldbesame->get_id()); 692 693 // Test an hash which doens't exist. 694 $doesntexist = $fs->get_file_by_hash('DOESNTEXIST'); 695 $this->assertFalse($doesntexist); 696 } 697 698 /** 699 * Tests for get_external_files 700 * 701 * @covers ::get_external_files 702 */ 703 public function test_get_external_files() { 704 $user = $this->setup_three_private_files(); 705 $fs = get_file_storage(); 706 707 $repos = repository::get_instances(array('type'=>'user')); 708 $userrepository = reset($repos); 709 $this->assertInstanceOf('repository', $userrepository); 710 711 // No aliases yet. 712 $exfiles = $fs->get_external_files($userrepository->id, 'id'); 713 $this->assertEquals(array(), $exfiles); 714 715 // Create three aliases linking the same original: $aliasfile1 and $aliasfile2 are 716 // created via create_file_from_reference(), $aliasfile3 created from $aliasfile2. 717 $originalfile = null; 718 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) { 719 if (!$areafile->is_directory()) { 720 $originalfile = $areafile; 721 break; 722 } 723 } 724 $this->assertInstanceOf('stored_file', $originalfile); 725 $originalrecord = array( 726 'contextid' => $originalfile->get_contextid(), 727 'component' => $originalfile->get_component(), 728 'filearea' => $originalfile->get_filearea(), 729 'itemid' => $originalfile->get_itemid(), 730 'filepath' => $originalfile->get_filepath(), 731 'filename' => $originalfile->get_filename(), 732 ); 733 734 $aliasrecord = $this->generate_file_record(); 735 $aliasrecord->filepath = '/foo/'; 736 $aliasrecord->filename = 'one.txt'; 737 738 $ref = $fs->pack_reference($originalrecord); 739 $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref); 740 741 $aliasrecord->filepath = '/bar/'; 742 $aliasrecord->filename = 'uno.txt'; 743 // Change the order of the items in the array to make sure that it does not matter. 744 ksort($originalrecord); 745 $ref = $fs->pack_reference($originalrecord); 746 $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref); 747 748 $aliasrecord->filepath = '/bar/'; 749 $aliasrecord->filename = 'jedna.txt'; 750 $aliasfile3 = $fs->create_file_from_storedfile($aliasrecord, $aliasfile2); 751 752 // Make sure we get three aliases now. 753 $exfiles = $fs->get_external_files($userrepository->id, 'id'); 754 $this->assertEquals(3, count($exfiles)); 755 foreach ($exfiles as $exfile) { 756 $this->assertTrue($exfile->is_external_file()); 757 } 758 // Make sure they all link the same original (thence that all are linked with the same 759 // record in {files_reference}). 760 $this->assertEquals($aliasfile1->get_referencefileid(), $aliasfile2->get_referencefileid()); 761 $this->assertEquals($aliasfile3->get_referencefileid(), $aliasfile2->get_referencefileid()); 762 } 763 764 /** 765 * Tests for create_directory with a negative contextid. 766 * 767 * @covers ::create_directory 768 */ 769 public function test_create_directory_contextid_negative() { 770 $fs = get_file_storage(); 771 772 $this->expectException('file_exception'); 773 $fs->create_directory(-1, 'core', 'unittest', 0, '/'); 774 } 775 776 /** 777 * Tests for create_directory with an invalid contextid. 778 * 779 * @covers ::create_directory 780 */ 781 public function test_create_directory_contextid_invalid() { 782 $fs = get_file_storage(); 783 784 $this->expectException('file_exception'); 785 $fs->create_directory('not an int', 'core', 'unittest', 0, '/'); 786 } 787 788 /** 789 * Tests for create_directory with an invalid component. 790 * 791 * @covers ::create_directory 792 */ 793 public function test_create_directory_component_invalid() { 794 $fs = get_file_storage(); 795 $syscontext = \context_system::instance(); 796 797 $this->expectException('file_exception'); 798 $fs->create_directory($syscontext->id, 'bad/component', 'unittest', 0, '/'); 799 } 800 801 /** 802 * Tests for create_directory with an invalid filearea. 803 * 804 * @covers ::create_directory 805 */ 806 public function test_create_directory_filearea_invalid() { 807 $fs = get_file_storage(); 808 $syscontext = \context_system::instance(); 809 810 $this->expectException('file_exception'); 811 $fs->create_directory($syscontext->id, 'core', 'bad-filearea', 0, '/'); 812 } 813 814 /** 815 * Tests for create_directory with a negative itemid 816 * 817 * @covers ::create_directory 818 */ 819 public function test_create_directory_itemid_negative() { 820 $fs = get_file_storage(); 821 $syscontext = \context_system::instance(); 822 823 $this->expectException('file_exception'); 824 $fs->create_directory($syscontext->id, 'core', 'unittest', -1, '/'); 825 } 826 827 /** 828 * Tests for create_directory with an invalid itemid 829 * 830 * @covers ::create_directory 831 */ 832 public function test_create_directory_itemid_invalid() { 833 $fs = get_file_storage(); 834 $syscontext = \context_system::instance(); 835 836 $this->expectException('file_exception'); 837 $fs->create_directory($syscontext->id, 'core', 'unittest', 'notanint', '/'); 838 } 839 840 /** 841 * Tests for create_directory with an invalid filepath 842 * 843 * @covers ::create_directory 844 */ 845 public function test_create_directory_filepath_invalid() { 846 $fs = get_file_storage(); 847 $syscontext = \context_system::instance(); 848 849 $this->expectException('file_exception'); 850 $fs->create_directory($syscontext->id, 'core', 'unittest', 0, '/not-with-trailing/or-leading-slash'); 851 } 852 853 /** 854 * Tests for get_directory_files. 855 * 856 * @covers ::get_directory_files 857 */ 858 public function test_get_directory_files() { 859 $user = $this->setup_three_private_files(); 860 $fs = get_file_storage(); 861 862 $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/'); 863 $this->assertInstanceOf('stored_file', $dir); 864 865 // Add a file to the subdir. 866 $filerecord = array( 867 'contextid' => $user->ctxid, 868 'component' => 'user', 869 'filearea' => 'private', 870 'itemid' => 0, 871 'filepath' => '/testsubdir/', 872 'filename' => 'test-get-area-tree.txt', 873 ); 874 875 $directoryfile = $fs->create_file_from_string($filerecord, 'Test content'); 876 $this->assertInstanceOf('stored_file', $directoryfile); 877 878 // Don't recurse without dirs. 879 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, false, 'id'); 880 // 3 files only. 881 $this->assertCount(3, $files); 882 foreach ($files as $key => $file) { 883 $this->assertInstanceOf('stored_file', $file); 884 $this->assertEquals($key, $file->get_pathnamehash()); 885 } 886 887 // Don't recurse with dirs. 888 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, true, 'id'); 889 // 3 files + 1 directory. 890 $this->assertCount(4, $files); 891 foreach ($files as $key => $file) { 892 $this->assertInstanceOf('stored_file', $file); 893 $this->assertEquals($key, $file->get_pathnamehash()); 894 } 895 896 // Recurse with dirs. 897 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, true, 'id'); 898 // 3 files + 1 directory + 1 subdir file. 899 $this->assertCount(5, $files); 900 foreach ($files as $key => $file) { 901 $this->assertInstanceOf('stored_file', $file); 902 $this->assertEquals($key, $file->get_pathnamehash()); 903 } 904 905 // Recurse without dirs. 906 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, false, 'id'); 907 // 3 files + 1 subdir file. 908 $this->assertCount(4, $files); 909 foreach ($files as $key => $file) { 910 $this->assertInstanceOf('stored_file', $file); 911 $this->assertEquals($key, $file->get_pathnamehash()); 912 } 913 } 914 915 /** 916 * Tests for search_references. 917 * 918 * @covers ::search_references 919 */ 920 public function test_search_references() { 921 $user = $this->setup_three_private_files(); 922 $fs = get_file_storage(); 923 $repos = repository::get_instances(array('type'=>'user')); 924 $repo = reset($repos); 925 926 $alias1 = array( 927 'contextid' => $user->ctxid, 928 'component' => 'user', 929 'filearea' => 'private', 930 'itemid' => 0, 931 'filepath' => '/aliases/', 932 'filename' => 'alias-to-1.txt' 933 ); 934 935 $alias2 = array( 936 'contextid' => $user->ctxid, 937 'component' => 'user', 938 'filearea' => 'private', 939 'itemid' => 0, 940 'filepath' => '/aliases/', 941 'filename' => 'another-alias-to-1.txt' 942 ); 943 944 $reference = \file_storage::pack_reference(array( 945 'contextid' => $user->ctxid, 946 'component' => 'user', 947 'filearea' => 'private', 948 'itemid' => 0, 949 'filepath' => '/', 950 'filename' => '1.txt' 951 )); 952 953 // There are no aliases now. 954 $result = $fs->search_references($reference); 955 $this->assertEquals(array(), $result); 956 957 $result = $fs->search_references_count($reference); 958 $this->assertSame($result, 0); 959 960 // Create two aliases and make sure they are returned. 961 $fs->create_file_from_reference($alias1, $repo->id, $reference); 962 $fs->create_file_from_reference($alias2, $repo->id, $reference); 963 964 $result = $fs->search_references($reference); 965 $this->assertTrue(is_array($result)); 966 $this->assertEquals(count($result), 2); 967 foreach ($result as $alias) { 968 $this->assertTrue($alias instanceof stored_file); 969 } 970 971 $result = $fs->search_references_count($reference); 972 $this->assertSame($result, 2); 973 974 // The method can't be used for references to files outside the filepool. 975 $exceptionthrown = false; 976 try { 977 $fs->search_references('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg'); 978 } catch (file_reference_exception $e) { 979 $exceptionthrown = true; 980 } 981 $this->assertTrue($exceptionthrown); 982 983 $exceptionthrown = false; 984 try { 985 $fs->search_references_count('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg'); 986 } catch (file_reference_exception $e) { 987 $exceptionthrown = true; 988 } 989 $this->assertTrue($exceptionthrown); 990 } 991 992 /** 993 * Tests for delete_area_files. 994 * 995 * @covers ::delete_area_files 996 */ 997 public function test_delete_area_files() { 998 $user = $this->setup_three_private_files(); 999 $fs = get_file_storage(); 1000 1001 // Get area files with default options. 1002 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1003 // Should be the two files we added plus the folder. 1004 $this->assertEquals(4, count($areafiles)); 1005 $fs->delete_area_files($user->ctxid, 'user', 'private'); 1006 1007 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1008 // Should be the two files we added plus the folder. 1009 $this->assertEquals(0, count($areafiles)); 1010 } 1011 1012 /** 1013 * Tests for delete_area_files using an itemid. 1014 * 1015 * @covers ::delete_area_files 1016 */ 1017 public function test_delete_area_files_itemid() { 1018 $user = $this->setup_three_private_files(); 1019 $fs = get_file_storage(); 1020 1021 // Get area files with default options. 1022 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1023 // Should be the two files we added plus the folder. 1024 $this->assertEquals(4, count($areafiles)); 1025 $fs->delete_area_files($user->ctxid, 'user', 'private', 9999); 1026 1027 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1028 $this->assertEquals(4, count($areafiles)); 1029 } 1030 1031 /** 1032 * Tests for delete_area_files_select. 1033 * 1034 * @covers ::delete_area_files_select 1035 */ 1036 public function test_delete_area_files_select() { 1037 $user = $this->setup_three_private_files(); 1038 $fs = get_file_storage(); 1039 1040 // Get area files with default options. 1041 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1042 // Should be the two files we added plus the folder. 1043 $this->assertEquals(4, count($areafiles)); 1044 $fs->delete_area_files_select($user->ctxid, 'user', 'private', '!= :notitemid', array('notitemid'=>9999)); 1045 1046 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1047 // Should be the two files we added plus the folder. 1048 $this->assertEquals(0, count($areafiles)); 1049 } 1050 1051 /** 1052 * Tests for delete_component_files. 1053 * 1054 * @covers ::delete_component_files 1055 */ 1056 public function test_delete_component_files() { 1057 $user = $this->setup_three_private_files(); 1058 $fs = get_file_storage(); 1059 1060 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1061 $this->assertEquals(4, count($areafiles)); 1062 $fs->delete_component_files('user'); 1063 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1064 $this->assertEquals(0, count($areafiles)); 1065 } 1066 1067 /** 1068 * Tests for create_file_from_url. 1069 * 1070 * @covers ::create_file_from_url 1071 */ 1072 public function test_create_file_from_url() { 1073 $this->resetAfterTest(true); 1074 1075 $syscontext = \context_system::instance(); 1076 $filerecord = array( 1077 'contextid' => $syscontext->id, 1078 'component' => 'core', 1079 'filearea' => 'unittest', 1080 'itemid' => 0, 1081 'filepath' => '/downloadtest/', 1082 ); 1083 $url = $this->getExternalTestFileUrl('/test.html'); 1084 1085 $fs = get_file_storage(); 1086 1087 // Test creating file without filename. 1088 $file1 = $fs->create_file_from_url($filerecord, $url); 1089 $this->assertInstanceOf('stored_file', $file1); 1090 1091 // Set filename. 1092 $filerecord['filename'] = 'unit-test-filename.html'; 1093 $file2 = $fs->create_file_from_url($filerecord, $url); 1094 $this->assertInstanceOf('stored_file', $file2); 1095 1096 // Use temporary file. 1097 $filerecord['filename'] = 'unit-test-with-temp-file.html'; 1098 $file3 = $fs->create_file_from_url($filerecord, $url, null, true); 1099 $file3 = $this->assertInstanceOf('stored_file', $file3); 1100 } 1101 1102 /** 1103 * Tests for cron. 1104 * 1105 * @covers ::cron 1106 */ 1107 public function test_cron() { 1108 $this->resetAfterTest(true); 1109 1110 // Note: this is only testing DB compatibility atm, rather than 1111 // that work is done. 1112 $fs = get_file_storage(); 1113 1114 $this->expectOutputRegex('/Cleaning up/'); 1115 $fs->cron(); 1116 } 1117 1118 /** 1119 * Tests for is_area_empty. 1120 * 1121 * @covers ::is_area_empty 1122 */ 1123 public function test_is_area_empty() { 1124 $user = $this->setup_three_private_files(); 1125 $fs = get_file_storage(); 1126 1127 $this->assertFalse($fs->is_area_empty($user->ctxid, 'user', 'private')); 1128 1129 // File area with madeup itemid should be empty. 1130 $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999)); 1131 // Still empty with dirs included. 1132 $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999, false)); 1133 } 1134 1135 /** 1136 * Tests for move_area_files_to_new_context. 1137 * 1138 * @covers ::move_area_files_to_new_context 1139 */ 1140 public function test_move_area_files_to_new_context() { 1141 $this->resetAfterTest(true); 1142 1143 // Create a course with a page resource. 1144 $course = $this->getDataGenerator()->create_course(); 1145 $page1 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id)); 1146 $page1context = \context_module::instance($page1->cmid); 1147 1148 // Add a file to the page. 1149 $fs = get_file_storage(); 1150 $filerecord = array( 1151 'contextid' => $page1context->id, 1152 'component' => 'mod_page', 1153 'filearea' => 'content', 1154 'itemid' => 0, 1155 'filepath' => '/', 1156 'filename' => 'unit-test-file.txt', 1157 ); 1158 1159 $originalfile = $fs->create_file_from_string($filerecord, 'Test content'); 1160 $this->assertInstanceOf('stored_file', $originalfile); 1161 1162 $pagefiles = $fs->get_area_files($page1context->id, 'mod_page', 'content', 0, 'sortorder', false); 1163 // Should be one file in filearea. 1164 $this->assertFalse($fs->is_area_empty($page1context->id, 'mod_page', 'content')); 1165 1166 // Create a new page. 1167 $page2 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id)); 1168 $page2context = \context_module::instance($page2->cmid); 1169 1170 // Newly created page area is empty. 1171 $this->assertTrue($fs->is_area_empty($page2context->id, 'mod_page', 'content')); 1172 1173 // Move the files. 1174 $fs->move_area_files_to_new_context($page1context->id, $page2context->id, 'mod_page', 'content'); 1175 1176 // Page2 filearea should no longer be empty. 1177 $this->assertFalse($fs->is_area_empty($page2context->id, 'mod_page', 'content')); 1178 1179 // Page1 filearea should now be empty. 1180 $this->assertTrue($fs->is_area_empty($page1context->id, 'mod_page', 'content')); 1181 1182 $page2files = $fs->get_area_files($page2context->id, 'mod_page', 'content', 0, 'sortorder', false); 1183 $movedfile = reset($page2files); 1184 1185 // The two files should have the same content hash. 1186 $this->assertEquals($movedfile->get_contenthash(), $originalfile->get_contenthash()); 1187 } 1188 1189 /** 1190 * Tests for convert_image. 1191 * 1192 * @covers ::convert_image 1193 */ 1194 public function test_convert_image() { 1195 global $CFG; 1196 1197 $this->resetAfterTest(false); 1198 1199 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1200 $syscontext = \context_system::instance(); 1201 $filerecord = array( 1202 'contextid' => $syscontext->id, 1203 'component' => 'core', 1204 'filearea' => 'unittest', 1205 'itemid' => 0, 1206 'filepath' => '/images/', 1207 'filename' => 'testimage.jpg', 1208 ); 1209 1210 $fs = get_file_storage(); 1211 $original = $fs->create_file_from_pathname($filerecord, $filepath); 1212 1213 $filerecord['filename'] = 'testimage-converted-10x10.jpg'; 1214 $converted = $fs->convert_image($filerecord, $original, 10, 10, true, 100); 1215 $this->assertInstanceOf('stored_file', $converted); 1216 1217 $filerecord['filename'] = 'testimage-convereted-nosize.jpg'; 1218 $converted = $fs->convert_image($filerecord, $original); 1219 $this->assertInstanceOf('stored_file', $converted); 1220 } 1221 1222 /** 1223 * Tests for convert_image with a PNG. 1224 * 1225 * @covers ::convert_image 1226 */ 1227 public function test_convert_image_png() { 1228 global $CFG; 1229 1230 $this->resetAfterTest(false); 1231 1232 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.png'; 1233 $syscontext = \context_system::instance(); 1234 $filerecord = array( 1235 'contextid' => $syscontext->id, 1236 'component' => 'core', 1237 'filearea' => 'unittest', 1238 'itemid' => 0, 1239 'filepath' => '/images/', 1240 'filename' => 'testimage.png', 1241 ); 1242 1243 $fs = get_file_storage(); 1244 $original = $fs->create_file_from_pathname($filerecord, $filepath); 1245 1246 // Vanilla test. 1247 $filerecord['filename'] = 'testimage-converted-nosize.png'; 1248 $vanilla = $fs->convert_image($filerecord, $original); 1249 $this->assertInstanceOf('stored_file', $vanilla); 1250 // Assert that byte 25 has the ascii value 6 for PNG-24. 1251 $this->assertTrue(ord(substr($vanilla->get_content(), 25, 1)) == 6); 1252 1253 // 10x10 resize test; also testing for a ridiculous quality setting, which 1254 // we should if necessary scale to the 0 - 9 range. 1255 $filerecord['filename'] = 'testimage-converted-10x10.png'; 1256 $converted = $fs->convert_image($filerecord, $original, 10, 10, true, 100); 1257 $this->assertInstanceOf('stored_file', $converted); 1258 // Assert that byte 25 has the ascii value 6 for PNG-24. 1259 $this->assertTrue(ord(substr($converted->get_content(), 25, 1)) == 6); 1260 1261 // Transparency test. 1262 $filerecord['filename'] = 'testimage-converted-102x31.png'; 1263 $converted = $fs->convert_image($filerecord, $original, 102, 31, true, 9); 1264 $this->assertInstanceOf('stored_file', $converted); 1265 // Assert that byte 25 has the ascii value 6 for PNG-24. 1266 $this->assertTrue(ord(substr($converted->get_content(), 25, 1)) == 6); 1267 1268 $originalfile = imagecreatefromstring($original->get_content()); 1269 $convertedfile = imagecreatefromstring($converted->get_content()); 1270 $vanillafile = imagecreatefromstring($vanilla->get_content()); 1271 1272 $originalcolors = imagecolorsforindex($originalfile, imagecolorat($originalfile, 0, 0)); 1273 $convertedcolors = imagecolorsforindex($convertedfile, imagecolorat($convertedfile, 0, 0)); 1274 $vanillacolors = imagecolorsforindex($vanillafile, imagecolorat($vanillafile, 0, 0)); 1275 $this->assertEquals(count($originalcolors), 4); 1276 $this->assertEquals(count($convertedcolors), 4); 1277 $this->assertEquals(count($vanillacolors), 4); 1278 $this->assertEquals($originalcolors['red'], $convertedcolors['red']); 1279 $this->assertEquals($originalcolors['green'], $convertedcolors['green']); 1280 $this->assertEquals($originalcolors['blue'], $convertedcolors['blue']); 1281 $this->assertEquals($originalcolors['alpha'], $convertedcolors['alpha']); 1282 $this->assertEquals($originalcolors['red'], $vanillacolors['red']); 1283 $this->assertEquals($originalcolors['green'], $vanillacolors['green']); 1284 $this->assertEquals($originalcolors['blue'], $vanillacolors['blue']); 1285 $this->assertEquals($originalcolors['alpha'], $vanillacolors['alpha']); 1286 $this->assertEquals($originalcolors['alpha'], 127); 1287 1288 } 1289 1290 private function generate_file_record() { 1291 $syscontext = \context_system::instance(); 1292 $filerecord = new \stdClass(); 1293 $filerecord->contextid = $syscontext->id; 1294 $filerecord->component = 'core'; 1295 $filerecord->filearea = 'phpunit'; 1296 $filerecord->filepath = '/'; 1297 $filerecord->filename = 'testfile.txt'; 1298 $filerecord->itemid = 0; 1299 1300 return $filerecord; 1301 } 1302 1303 /** 1304 * @covers ::create_file_from_storedfile 1305 */ 1306 public function test_create_file_from_storedfile_file_invalid() { 1307 $this->resetAfterTest(true); 1308 1309 $filerecord = $this->generate_file_record(); 1310 1311 $fs = get_file_storage(); 1312 1313 // Create a file from a file id which doesn't exist. 1314 $this->expectException(file_exception::class); 1315 $fs->create_file_from_storedfile($filerecord, 9999); 1316 } 1317 1318 /** 1319 * @covers ::create_file_from_storedfile 1320 */ 1321 public function test_create_file_from_storedfile_contextid_invalid() { 1322 $this->resetAfterTest(true); 1323 1324 $filerecord = $this->generate_file_record(); 1325 1326 $fs = get_file_storage(); 1327 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1328 $this->assertInstanceOf('stored_file', $file1); 1329 1330 $filerecord->filename = 'invalid.txt'; 1331 $filerecord->contextid = 'invalid'; 1332 1333 $this->expectException(file_exception::class); 1334 $this->expectExceptionMessage('Invalid contextid'); 1335 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1336 } 1337 1338 /** 1339 * @covers ::create_file_from_storedfile 1340 */ 1341 public function test_create_file_from_storedfile_component_invalid() { 1342 $this->resetAfterTest(true); 1343 1344 $filerecord = $this->generate_file_record(); 1345 1346 $fs = get_file_storage(); 1347 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1348 $this->assertInstanceOf('stored_file', $file1); 1349 1350 $filerecord->filename = 'invalid.txt'; 1351 $filerecord->component = 'bad/component'; 1352 1353 $this->expectException(file_exception::class); 1354 $this->expectExceptionMessage('Invalid component'); 1355 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1356 } 1357 1358 /** 1359 * @covers ::create_file_from_storedfile 1360 */ 1361 public function test_create_file_from_storedfile_filearea_invalid() { 1362 $this->resetAfterTest(true); 1363 1364 $filerecord = $this->generate_file_record(); 1365 1366 $fs = get_file_storage(); 1367 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1368 $this->assertInstanceOf('stored_file', $file1); 1369 1370 $filerecord->filename = 'invalid.txt'; 1371 $filerecord->filearea = 'bad-filearea'; 1372 1373 $this->expectException(file_exception::class); 1374 $this->expectExceptionMessage('Invalid filearea'); 1375 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1376 } 1377 1378 /** 1379 * @covers ::create_file_from_storedfile 1380 */ 1381 public function test_create_file_from_storedfile_itemid_invalid() { 1382 $this->resetAfterTest(true); 1383 1384 $filerecord = $this->generate_file_record(); 1385 1386 $fs = get_file_storage(); 1387 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1388 $this->assertInstanceOf('stored_file', $file1); 1389 1390 $filerecord->filename = 'invalid.txt'; 1391 $filerecord->itemid = 'bad-itemid'; 1392 1393 $this->expectException(file_exception::class); 1394 $this->expectExceptionMessage('Invalid itemid'); 1395 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1396 } 1397 1398 /** 1399 * @covers ::create_file_from_storedfile 1400 */ 1401 public function test_create_file_from_storedfile_filepath_invalid() { 1402 $this->resetAfterTest(true); 1403 1404 $filerecord = $this->generate_file_record(); 1405 1406 $fs = get_file_storage(); 1407 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1408 $this->assertInstanceOf('stored_file', $file1); 1409 1410 $filerecord->filename = 'invalid.txt'; 1411 $filerecord->filepath = 'a-/bad/-filepath'; 1412 1413 $this->expectException(file_exception::class); 1414 $this->expectExceptionMessage('Invalid file path'); 1415 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1416 } 1417 1418 /** 1419 * @covers ::create_file_from_storedfile 1420 */ 1421 public function test_create_file_from_storedfile_filename_invalid() { 1422 $this->resetAfterTest(true); 1423 1424 $filerecord = $this->generate_file_record(); 1425 1426 $fs = get_file_storage(); 1427 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1428 $this->assertInstanceOf('stored_file', $file1); 1429 1430 $filerecord->filename = ''; 1431 1432 $this->expectException(file_exception::class); 1433 $this->expectExceptionMessage('Invalid file name'); 1434 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1435 } 1436 1437 /** 1438 * @covers ::create_file_from_storedfile 1439 */ 1440 public function test_create_file_from_storedfile_timecreated_invalid() { 1441 $this->resetAfterTest(true); 1442 1443 $filerecord = $this->generate_file_record(); 1444 1445 $fs = get_file_storage(); 1446 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1447 $this->assertInstanceOf('stored_file', $file1); 1448 1449 $filerecord->filename = 'invalid.txt'; 1450 $filerecord->timecreated = 'today'; 1451 1452 $this->expectException(file_exception::class); 1453 $this->expectExceptionMessage('Invalid file timecreated'); 1454 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1455 } 1456 1457 /** 1458 * @covers ::create_file_from_storedfile 1459 */ 1460 public function test_create_file_from_storedfile_timemodified_invalid() { 1461 $this->resetAfterTest(true); 1462 1463 $filerecord = $this->generate_file_record(); 1464 1465 $fs = get_file_storage(); 1466 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1467 $this->assertInstanceOf('stored_file', $file1); 1468 1469 $filerecord->filename = 'invalid.txt'; 1470 $filerecord->timemodified = 'today'; 1471 1472 $this->expectException(file_exception::class); 1473 $this->expectExceptionMessage('Invalid file timemodified'); 1474 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1475 } 1476 1477 /** 1478 * @covers ::create_file_from_storedfile 1479 */ 1480 public function test_create_file_from_storedfile_duplicate() { 1481 $this->resetAfterTest(true); 1482 1483 $filerecord = $this->generate_file_record(); 1484 1485 $fs = get_file_storage(); 1486 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1487 $this->assertInstanceOf('stored_file', $file1); 1488 1489 // Creating a file validating unique constraint. 1490 $this->expectException(stored_file_creation_exception::class); 1491 $this->expectExceptionMessage('Cannot create file 1/core/phpunit/0/testfile.txt'); 1492 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1493 } 1494 1495 /** 1496 * Tests for create_file_from_storedfile. 1497 * 1498 * @covers ::create_file_from_storedfile 1499 */ 1500 public function test_create_file_from_storedfile() { 1501 $this->resetAfterTest(true); 1502 1503 $syscontext = \context_system::instance(); 1504 1505 $filerecord = new \stdClass(); 1506 $filerecord->contextid = $syscontext->id; 1507 $filerecord->component = 'core'; 1508 $filerecord->filearea = 'phpunit'; 1509 $filerecord->filepath = '/'; 1510 $filerecord->filename = 'testfile.txt'; 1511 $filerecord->itemid = 0; 1512 1513 $fs = get_file_storage(); 1514 1515 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1516 $this->assertInstanceOf('stored_file', $file1); 1517 1518 $filerecord->filename = 'test-create-file-from-storedfile.txt'; 1519 $file2 = $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1520 $this->assertInstanceOf('stored_file', $file2); 1521 1522 // These will be normalised to current time.. 1523 $filerecord->timecreated = -100; 1524 $filerecord->timemodified= -100; 1525 $filerecord->filename = 'test-create-file-from-storedfile-bad-dates.txt'; 1526 1527 $file3 = $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1528 $this->assertInstanceOf('stored_file', $file3); 1529 1530 $this->assertNotEquals($file3->get_timemodified(), $filerecord->timemodified); 1531 $this->assertNotEquals($file3->get_timecreated(), $filerecord->timecreated); 1532 } 1533 1534 /** 1535 * @covers ::create_file_from_string 1536 */ 1537 public function test_create_file_from_string_contextid_invalid() { 1538 $this->resetAfterTest(true); 1539 1540 $filerecord = $this->generate_file_record(); 1541 $fs = get_file_storage(); 1542 1543 $filerecord->contextid = 'invalid'; 1544 1545 $this->expectException(file_exception::class); 1546 $this->expectExceptionMessage('Invalid contextid'); 1547 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1548 } 1549 1550 /** 1551 * @covers ::create_file_from_string 1552 */ 1553 public function test_create_file_from_string_component_invalid() { 1554 $this->resetAfterTest(true); 1555 1556 $filerecord = $this->generate_file_record(); 1557 $fs = get_file_storage(); 1558 1559 $filerecord->component = 'bad/component'; 1560 1561 $this->expectException(file_exception::class); 1562 $this->expectExceptionMessage('Invalid component'); 1563 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1564 } 1565 1566 /** 1567 * @covers ::create_file_from_string 1568 */ 1569 public function test_create_file_from_string_filearea_invalid() { 1570 $this->resetAfterTest(true); 1571 1572 $filerecord = $this->generate_file_record(); 1573 $fs = get_file_storage(); 1574 1575 $filerecord->filearea = 'bad-filearea'; 1576 1577 $this->expectException(file_exception::class); 1578 $this->expectExceptionMessage('Invalid filearea'); 1579 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1580 } 1581 1582 /** 1583 * @covers ::create_file_from_string 1584 */ 1585 public function test_create_file_from_string_itemid_invalid() { 1586 $this->resetAfterTest(true); 1587 1588 $filerecord = $this->generate_file_record(); 1589 $fs = get_file_storage(); 1590 1591 $filerecord->itemid = 'bad-itemid'; 1592 1593 $this->expectException(file_exception::class); 1594 $this->expectExceptionMessage('Invalid itemid'); 1595 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1596 } 1597 1598 /** 1599 * @covers ::create_file_from_string 1600 */ 1601 public function test_create_file_from_string_filepath_invalid() { 1602 $this->resetAfterTest(true); 1603 1604 $filerecord = $this->generate_file_record(); 1605 $fs = get_file_storage(); 1606 1607 $filerecord->filepath = 'a-/bad/-filepath'; 1608 1609 $this->expectException(file_exception::class); 1610 $this->expectExceptionMessage('Invalid file path'); 1611 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1612 } 1613 1614 /** 1615 * @covers ::create_file_from_string 1616 */ 1617 public function test_create_file_from_string_filename_invalid() { 1618 $this->resetAfterTest(true); 1619 1620 $filerecord = $this->generate_file_record(); 1621 $fs = get_file_storage(); 1622 1623 $filerecord->filename = ''; 1624 1625 $this->expectException(file_exception::class); 1626 $this->expectExceptionMessage('Invalid file name'); 1627 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1628 } 1629 1630 /** 1631 * @covers ::create_file_from_string 1632 */ 1633 public function test_create_file_from_string_timecreated_invalid() { 1634 $this->resetAfterTest(true); 1635 1636 $filerecord = $this->generate_file_record(); 1637 $fs = get_file_storage(); 1638 1639 $filerecord->timecreated = 'today'; 1640 1641 $this->expectException('file_exception'); 1642 $this->expectExceptionMessage('Invalid file timecreated'); 1643 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1644 } 1645 1646 /** 1647 * @covers ::create_file_from_string 1648 */ 1649 public function test_create_file_from_string_timemodified_invalid() { 1650 $this->resetAfterTest(true); 1651 1652 $filerecord = $this->generate_file_record(); 1653 $fs = get_file_storage(); 1654 1655 $filerecord->timemodified = 'today'; 1656 1657 $this->expectException(file_exception::class); 1658 $this->expectExceptionMessage('Invalid file timemodified'); 1659 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1660 } 1661 1662 /** 1663 * Tests for create_file_from_string with a duplicate string. 1664 * @covers ::create_file_from_string 1665 */ 1666 public function test_create_file_from_string_duplicate() { 1667 $this->resetAfterTest(true); 1668 1669 $filerecord = $this->generate_file_record(); 1670 $fs = get_file_storage(); 1671 1672 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1673 1674 // Creating a file validating unique constraint. 1675 $this->expectException('stored_file_creation_exception'); 1676 $file2 = $fs->create_file_from_string($filerecord, 'text contents'); 1677 } 1678 1679 /** 1680 * @covers ::create_file_from_pathname 1681 */ 1682 public function test_create_file_from_pathname_contextid_invalid() { 1683 global $CFG; 1684 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1685 1686 $this->resetAfterTest(true); 1687 1688 $filerecord = $this->generate_file_record(); 1689 $fs = get_file_storage(); 1690 1691 $filerecord->contextid = 'invalid'; 1692 1693 $this->expectException(file_exception::class); 1694 $this->expectExceptionMessage('Invalid contextid'); 1695 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1696 } 1697 1698 /** 1699 * @covers ::create_file_from_pathname 1700 */ 1701 public function test_create_file_from_pathname_component_invalid() { 1702 global $CFG; 1703 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1704 1705 $this->resetAfterTest(true); 1706 1707 $filerecord = $this->generate_file_record(); 1708 $fs = get_file_storage(); 1709 1710 $filerecord->component = 'bad/component'; 1711 1712 $this->expectException(file_exception::class); 1713 $this->expectExceptionMessage('Invalid component'); 1714 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1715 } 1716 1717 /** 1718 * @covers ::create_file_from_pathname 1719 */ 1720 public function test_create_file_from_pathname_filearea_invalid() { 1721 global $CFG; 1722 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1723 1724 $this->resetAfterTest(true); 1725 1726 $filerecord = $this->generate_file_record(); 1727 $fs = get_file_storage(); 1728 1729 $filerecord->filearea = 'bad-filearea'; 1730 1731 $this->expectException(file_exception::class); 1732 $this->expectExceptionMessage('Invalid filearea'); 1733 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1734 } 1735 1736 /** 1737 * @covers ::create_file_from_pathname 1738 */ 1739 public function test_create_file_from_pathname_itemid_invalid() { 1740 global $CFG; 1741 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1742 1743 $this->resetAfterTest(true); 1744 1745 $filerecord = $this->generate_file_record(); 1746 $fs = get_file_storage(); 1747 1748 $filerecord->itemid = 'bad-itemid'; 1749 1750 $this->expectException(file_exception::class); 1751 $this->expectExceptionMessage('Invalid itemid'); 1752 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1753 } 1754 1755 /** 1756 * @covers ::create_file_from_pathname 1757 */ 1758 public function test_create_file_from_pathname_filepath_invalid() { 1759 global $CFG; 1760 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1761 1762 $this->resetAfterTest(true); 1763 1764 $filerecord = $this->generate_file_record(); 1765 $fs = get_file_storage(); 1766 1767 $filerecord->filepath = 'a-/bad/-filepath'; 1768 1769 $this->expectException(file_exception::class); 1770 $this->expectExceptionMessage('Invalid file path'); 1771 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1772 } 1773 1774 /** 1775 * @covers ::create_file_from_pathname 1776 */ 1777 public function test_create_file_from_pathname_filename_invalid() { 1778 global $CFG; 1779 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1780 1781 $this->resetAfterTest(true); 1782 1783 $filerecord = $this->generate_file_record(); 1784 $fs = get_file_storage(); 1785 1786 $filerecord->filename = ''; 1787 1788 $this->expectException(file_exception::class); 1789 $this->expectExceptionMessage('Invalid file name'); 1790 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1791 } 1792 1793 /** 1794 * @covers ::create_file_from_pathname 1795 */ 1796 public function test_create_file_from_pathname_timecreated_invalid() { 1797 global $CFG; 1798 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1799 1800 $this->resetAfterTest(true); 1801 1802 $filerecord = $this->generate_file_record(); 1803 $fs = get_file_storage(); 1804 1805 $filerecord->timecreated = 'today'; 1806 1807 $this->expectException(file_exception::class); 1808 $this->expectExceptionMessage('Invalid file timecreated'); 1809 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1810 } 1811 1812 /** 1813 * @covers ::create_file_from_pathname 1814 */ 1815 public function test_create_file_from_pathname_timemodified_invalid() { 1816 global $CFG; 1817 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1818 1819 $this->resetAfterTest(true); 1820 1821 $filerecord = $this->generate_file_record(); 1822 $fs = get_file_storage(); 1823 1824 $filerecord->timemodified = 'today'; 1825 1826 $this->expectException(file_exception::class); 1827 $this->expectExceptionMessage('Invalid file timemodified'); 1828 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1829 } 1830 1831 /** 1832 * @covers ::create_file_from_pathname 1833 */ 1834 public function test_create_file_from_pathname_duplicate_file() { 1835 global $CFG; 1836 $this->resetAfterTest(true); 1837 1838 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1839 1840 $filerecord = $this->generate_file_record(); 1841 $fs = get_file_storage(); 1842 1843 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1844 $this->assertInstanceOf('stored_file', $file1); 1845 1846 // Creating a file validating unique constraint. 1847 $this->expectException(stored_file_creation_exception::class); 1848 $this->expectExceptionMessage('Cannot create file 1/core/phpunit/0/testfile.txt'); 1849 $file2 = $fs->create_file_from_pathname($filerecord, $path); 1850 } 1851 1852 /** 1853 * Calling \stored_file::delete_reference() on a non-reference file throws coding_exception 1854 * 1855 * @covers \stored_file::delete_reference 1856 */ 1857 public function test_delete_reference_on_nonreference() { 1858 1859 $this->resetAfterTest(true); 1860 $user = $this->setup_three_private_files(); 1861 $fs = get_file_storage(); 1862 $repos = repository::get_instances(array('type'=>'user')); 1863 $repo = reset($repos); 1864 1865 $file = null; 1866 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) { 1867 if (!$areafile->is_directory()) { 1868 $file = $areafile; 1869 break; 1870 } 1871 } 1872 $this->assertInstanceOf('stored_file', $file); 1873 $this->assertFalse($file->is_external_file()); 1874 1875 $this->expectException('coding_exception'); 1876 $file->delete_reference(); 1877 } 1878 1879 /** 1880 * Calling \stored_file::delete_reference() on a reference file does not affect other 1881 * symlinks to the same original 1882 * 1883 * @covers \stored_file::delete_reference 1884 */ 1885 public function test_delete_reference_one_symlink_does_not_rule_them_all() { 1886 1887 $this->resetAfterTest(true); 1888 $user = $this->setup_three_private_files(); 1889 $fs = get_file_storage(); 1890 $repos = repository::get_instances(array('type'=>'user')); 1891 $repo = reset($repos); 1892 1893 // Create two aliases linking the same original. 1894 1895 $originalfile = null; 1896 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) { 1897 if (!$areafile->is_directory()) { 1898 $originalfile = $areafile; 1899 break; 1900 } 1901 } 1902 $this->assertInstanceOf('stored_file', $originalfile); 1903 1904 // Calling delete_reference() on a non-reference file. 1905 1906 $originalrecord = array( 1907 'contextid' => $originalfile->get_contextid(), 1908 'component' => $originalfile->get_component(), 1909 'filearea' => $originalfile->get_filearea(), 1910 'itemid' => $originalfile->get_itemid(), 1911 'filepath' => $originalfile->get_filepath(), 1912 'filename' => $originalfile->get_filename(), 1913 ); 1914 1915 $aliasrecord = $this->generate_file_record(); 1916 $aliasrecord->filepath = '/A/'; 1917 $aliasrecord->filename = 'symlink.txt'; 1918 1919 $ref = $fs->pack_reference($originalrecord); 1920 $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref); 1921 1922 $aliasrecord->filepath = '/B/'; 1923 $aliasrecord->filename = 'symlink.txt'; 1924 $ref = $fs->pack_reference($originalrecord); 1925 $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref); 1926 1927 // Refetch A/symlink.txt file. 1928 $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 1929 $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt'); 1930 $this->assertTrue($symlink1->is_external_file()); 1931 1932 // Unlink the A/symlink.txt file. 1933 $symlink1->delete_reference(); 1934 $this->assertFalse($symlink1->is_external_file()); 1935 1936 // Make sure that B/symlink.txt has not been affected. 1937 $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 1938 $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt'); 1939 $this->assertTrue($symlink2->is_external_file()); 1940 } 1941 1942 /** 1943 * Make sure that when internal file is updated all references to it are 1944 * updated immediately. When it is deleted, the references are converted 1945 * to true copies. 1946 */ 1947 public function test_update_reference_internal() { 1948 purge_all_caches(); 1949 $this->resetAfterTest(true); 1950 $user = $this->setup_three_private_files(); 1951 $fs = get_file_storage(); 1952 $repos = repository::get_instances(array('type' => 'user')); 1953 $repo = reset($repos); 1954 1955 // Create two aliases linking the same original. 1956 1957 $areafiles = array_values($fs->get_area_files($user->ctxid, 'user', 'private', false, 'filename', false)); 1958 1959 $originalfile = $areafiles[0]; 1960 $this->assertInstanceOf('stored_file', $originalfile); 1961 $contenthash = $originalfile->get_contenthash(); 1962 $filesize = $originalfile->get_filesize(); 1963 1964 $substitutefile = $areafiles[1]; 1965 $this->assertInstanceOf('stored_file', $substitutefile); 1966 $newcontenthash = $substitutefile->get_contenthash(); 1967 $newfilesize = $substitutefile->get_filesize(); 1968 1969 $originalrecord = array( 1970 'contextid' => $originalfile->get_contextid(), 1971 'component' => $originalfile->get_component(), 1972 'filearea' => $originalfile->get_filearea(), 1973 'itemid' => $originalfile->get_itemid(), 1974 'filepath' => $originalfile->get_filepath(), 1975 'filename' => $originalfile->get_filename(), 1976 ); 1977 1978 $aliasrecord = $this->generate_file_record(); 1979 $aliasrecord->filepath = '/A/'; 1980 $aliasrecord->filename = 'symlink.txt'; 1981 1982 $ref = $fs->pack_reference($originalrecord); 1983 $symlink1 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref); 1984 // Make sure created alias is a reference and has the same size and contenthash as source. 1985 $this->assertEquals($contenthash, $symlink1->get_contenthash()); 1986 $this->assertEquals($filesize, $symlink1->get_filesize()); 1987 $this->assertEquals($repo->id, $symlink1->get_repository_id()); 1988 $this->assertNotEmpty($symlink1->get_referencefileid()); 1989 $referenceid = $symlink1->get_referencefileid(); 1990 1991 $aliasrecord->filepath = '/B/'; 1992 $aliasrecord->filename = 'symlink.txt'; 1993 $ref = $fs->pack_reference($originalrecord); 1994 $symlink2 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref); 1995 // Make sure created alias is a reference and has the same size and contenthash as source. 1996 $this->assertEquals($contenthash, $symlink2->get_contenthash()); 1997 $this->assertEquals($filesize, $symlink2->get_filesize()); 1998 $this->assertEquals($repo->id, $symlink2->get_repository_id()); 1999 // Make sure both aliases have the same reference id. 2000 $this->assertEquals($referenceid, $symlink2->get_referencefileid()); 2001 2002 // Overwrite ofiginal file. 2003 $originalfile->replace_file_with($substitutefile); 2004 $this->assertEquals($newcontenthash, $originalfile->get_contenthash()); 2005 $this->assertEquals($newfilesize, $originalfile->get_filesize()); 2006 2007 // References to the internal files must be synchronised immediately. 2008 // Refetch A/symlink.txt file. 2009 $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 2010 $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt'); 2011 $this->assertTrue($symlink1->is_external_file()); 2012 $this->assertEquals($newcontenthash, $symlink1->get_contenthash()); 2013 $this->assertEquals($newfilesize, $symlink1->get_filesize()); 2014 $this->assertEquals($repo->id, $symlink1->get_repository_id()); 2015 $this->assertEquals($referenceid, $symlink1->get_referencefileid()); 2016 2017 // Refetch B/symlink.txt file. 2018 $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 2019 $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt'); 2020 $this->assertTrue($symlink2->is_external_file()); 2021 $this->assertEquals($newcontenthash, $symlink2->get_contenthash()); 2022 $this->assertEquals($newfilesize, $symlink2->get_filesize()); 2023 $this->assertEquals($repo->id, $symlink2->get_repository_id()); 2024 $this->assertEquals($referenceid, $symlink2->get_referencefileid()); 2025 2026 // Remove original file. 2027 $originalfile->delete(); 2028 2029 // References must be converted to independend files. 2030 // Refetch A/symlink.txt file. 2031 $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 2032 $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt'); 2033 $this->assertFalse($symlink1->is_external_file()); 2034 $this->assertEquals($newcontenthash, $symlink1->get_contenthash()); 2035 $this->assertEquals($newfilesize, $symlink1->get_filesize()); 2036 $this->assertNull($symlink1->get_repository_id()); 2037 $this->assertNull($symlink1->get_referencefileid()); 2038 2039 // Refetch B/symlink.txt file. 2040 $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 2041 $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt'); 2042 $this->assertFalse($symlink2->is_external_file()); 2043 $this->assertEquals($newcontenthash, $symlink2->get_contenthash()); 2044 $this->assertEquals($newfilesize, $symlink2->get_filesize()); 2045 $this->assertNull($symlink2->get_repository_id()); 2046 $this->assertNull($symlink2->get_referencefileid()); 2047 } 2048 2049 /** 2050 * Tests for get_unused_filename. 2051 * 2052 * @covers ::get_unused_filename 2053 */ 2054 public function test_get_unused_filename() { 2055 global $USER; 2056 $this->resetAfterTest(true); 2057 2058 $fs = get_file_storage(); 2059 $this->setAdminUser(); 2060 $contextid = \context_user::instance($USER->id)->id; 2061 $component = 'user'; 2062 $filearea = 'private'; 2063 $itemid = 0; 2064 $filepath = '/'; 2065 2066 // Create some private files. 2067 $file = new \stdClass; 2068 $file->contextid = $contextid; 2069 $file->component = 'user'; 2070 $file->filearea = 'private'; 2071 $file->itemid = 0; 2072 $file->filepath = '/'; 2073 $file->source = 'test'; 2074 $filenames = array('foo.txt', 'foo (1).txt', 'foo (20).txt', 'foo (999)', 'bar.jpg', 'What (a cool file).jpg', 2075 'Hurray! (1).php', 'Hurray! (2).php', 'Hurray! (9a).php', 'Hurray! (abc).php'); 2076 foreach ($filenames as $key => $filename) { 2077 $file->filename = $filename; 2078 $userfile = $fs->create_file_from_string($file, "file $key $filename content"); 2079 $this->assertInstanceOf('stored_file', $userfile); 2080 } 2081 2082 // Asserting new generated names. 2083 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'unused.txt'); 2084 $this->assertEquals('unused.txt', $newfilename); 2085 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo.txt'); 2086 $this->assertEquals('foo (21).txt', $newfilename); 2087 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (1).txt'); 2088 $this->assertEquals('foo (21).txt', $newfilename); 2089 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (2).txt'); 2090 $this->assertEquals('foo (2).txt', $newfilename); 2091 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (20).txt'); 2092 $this->assertEquals('foo (21).txt', $newfilename); 2093 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo'); 2094 $this->assertEquals('foo', $newfilename); 2095 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (123)'); 2096 $this->assertEquals('foo (123)', $newfilename); 2097 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (999)'); 2098 $this->assertEquals('foo (1000)', $newfilename); 2099 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.png'); 2100 $this->assertEquals('bar.png', $newfilename); 2101 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (12).png'); 2102 $this->assertEquals('bar (12).png', $newfilename); 2103 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.jpg'); 2104 $this->assertEquals('bar (1).jpg', $newfilename); 2105 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (1).jpg'); 2106 $this->assertEquals('bar (1).jpg', $newfilename); 2107 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'What (a cool file).jpg'); 2108 $this->assertEquals('What (a cool file) (1).jpg', $newfilename); 2109 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'Hurray! (1).php'); 2110 $this->assertEquals('Hurray! (3).php', $newfilename); 2111 2112 $this->expectException('coding_exception'); 2113 $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, ''); 2114 } 2115 2116 /** 2117 * Test that mimetype_from_file returns appropriate output when the 2118 * file could not be found. 2119 * 2120 * @covers ::mimetype 2121 */ 2122 public function test_mimetype_not_found() { 2123 $mimetype = \file_storage::mimetype('/path/to/nonexistent/file'); 2124 $this->assertEquals('document/unknown', $mimetype); 2125 } 2126 2127 /** 2128 * Data provider to return fixture files and their expected mimetype 2129 * 2130 * @return array[] 2131 */ 2132 public function filepath_mimetype_provider(): array { 2133 return [ 2134 [__DIR__ . '/fixtures/testimage.jpg', 'image/jpeg'], 2135 [__DIR__ . '/fixtures/testimage.svg', 'image/svg+xml'], 2136 [__DIR__ . '/fixtures/testimage_basic.svg', 'image/svg+xml'], 2137 ]; 2138 } 2139 2140 /** 2141 * Test that mimetype returns appropriate output for a known file. 2142 * 2143 * Note: this is not intended to check that functions outside of this 2144 * file works. It is intended to validate the codepath contains no 2145 * errors and behaves as expected. 2146 * 2147 * @covers ::mimetype 2148 * 2149 * @param string $filepath 2150 * @param string $expectedmimetype 2151 * 2152 * @dataProvider filepath_mimetype_provider 2153 */ 2154 public function test_mimetype_known(string $filepath, string $expectedmimetype): void { 2155 $mimetype = \file_storage::mimetype($filepath); 2156 $this->assertEquals($expectedmimetype, $mimetype); 2157 } 2158 2159 /** 2160 * Test that mimetype_from_file returns appropriate output when the 2161 * file could not be found. 2162 * 2163 * @covers ::mimetype_from_file 2164 */ 2165 public function test_mimetype_from_file_not_found() { 2166 $mimetype = \file_storage::mimetype_from_file('/path/to/nonexistent/file'); 2167 $this->assertEquals('document/unknown', $mimetype); 2168 } 2169 2170 /** 2171 * Test that mimetype_from_file returns appropriate output for a known 2172 * file. 2173 * 2174 * Note: this is not intended to check that functions outside of this 2175 * file works. It is intended to validate the codepath contains no 2176 * errors and behaves as expected. 2177 * 2178 * @covers ::mimetype_from_file 2179 * 2180 * @param string $filepath 2181 * @param string $expectedmimetype 2182 * 2183 * @dataProvider filepath_mimetype_provider 2184 */ 2185 public function test_mimetype_from_file_known(string $filepath, string $expectedmimetype): void { 2186 $mimetype = \file_storage::mimetype_from_file($filepath); 2187 $this->assertEquals($expectedmimetype, $mimetype); 2188 } 2189 2190 /** 2191 * Test that get_pathname_hash returns the same file hash for pathnames 2192 * with and without trailing / leading slash. 2193 * 2194 * @covers ::get_pathname_hash 2195 * 2196 */ 2197 public function test_get_pathname_hash(): void { 2198 $contextid = 2; 2199 $component = 'mod_test'; 2200 $filearea = 'data'; 2201 $itemid = 0; 2202 $filepath1 = '/path'; 2203 $filepath2 = '/path/'; 2204 $filepath3 = 'path/'; 2205 $filename = 'example.jpg'; 2206 $hash1 = \file_storage::get_pathname_hash($contextid, $component, $filearea, $itemid, $filepath1, $filename); 2207 $hash2 = \file_storage::get_pathname_hash($contextid, $component, $filearea, $itemid, $filepath2, $filename); 2208 $hash3 = \file_storage::get_pathname_hash($contextid, $component, $filearea, $itemid, $filepath3, $filename); 2209 $this->assertEquals($hash1, $hash2); 2210 $this->assertEquals($hash2, $hash3); 2211 } 2212 2213 } 2214 2215 class test_stored_file_inspection extends stored_file { 2216 public static function get_pretected_pathname(stored_file $file) { 2217 return $file->get_pathname_by_contenthash(); 2218 } 2219 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body