Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
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 /** @var \stored_file $originalfile */ 718 $originalfile = null; 719 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) { 720 if (!$areafile->is_directory()) { 721 $originalfile = $areafile; 722 break; 723 } 724 } 725 $this->assertInstanceOf('stored_file', $originalfile); 726 $originalrecord = array( 727 'contextid' => $originalfile->get_contextid(), 728 'component' => $originalfile->get_component(), 729 'filearea' => $originalfile->get_filearea(), 730 'itemid' => $originalfile->get_itemid(), 731 'filepath' => $originalfile->get_filepath(), 732 'filename' => $originalfile->get_filename(), 733 ); 734 735 $aliasrecord = $this->generate_file_record(); 736 $aliasrecord->filepath = '/foo/'; 737 $aliasrecord->filename = 'one.txt'; 738 739 $ref = $fs->pack_reference($originalrecord); 740 $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref); 741 742 $aliasrecord->filepath = '/bar/'; 743 $aliasrecord->filename = 'uno.txt'; 744 // Change the order of the items in the array to make sure that it does not matter. 745 ksort($originalrecord); 746 $ref = $fs->pack_reference($originalrecord); 747 $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref); 748 749 $aliasrecord->filepath = '/bar/'; 750 $aliasrecord->filename = 'jedna.txt'; 751 $aliasfile3 = $fs->create_file_from_storedfile($aliasrecord, $aliasfile2); 752 753 // Make sure we get three aliases now. 754 $exfiles = $fs->get_external_files($userrepository->id, 'id'); 755 $this->assertEquals(3, count($exfiles)); 756 foreach ($exfiles as $exfile) { 757 $this->assertTrue($exfile->is_external_file()); 758 } 759 // Make sure they all link the same original (thence that all are linked with the same 760 // record in {files_reference}). 761 $this->assertEquals($aliasfile1->get_referencefileid(), $aliasfile2->get_referencefileid()); 762 $this->assertEquals($aliasfile3->get_referencefileid(), $aliasfile2->get_referencefileid()); 763 } 764 765 /** 766 * Tests for create_directory with a negative contextid. 767 * 768 * @covers ::create_directory 769 */ 770 public function test_create_directory_contextid_negative() { 771 $fs = get_file_storage(); 772 773 $this->expectException('file_exception'); 774 $fs->create_directory(-1, 'core', 'unittest', 0, '/'); 775 } 776 777 /** 778 * Tests for create_directory with an invalid contextid. 779 * 780 * @covers ::create_directory 781 */ 782 public function test_create_directory_contextid_invalid() { 783 $fs = get_file_storage(); 784 785 $this->expectException('file_exception'); 786 $fs->create_directory('not an int', 'core', 'unittest', 0, '/'); 787 } 788 789 /** 790 * Tests for create_directory with an invalid component. 791 * 792 * @covers ::create_directory 793 */ 794 public function test_create_directory_component_invalid() { 795 $fs = get_file_storage(); 796 $syscontext = \context_system::instance(); 797 798 $this->expectException('file_exception'); 799 $fs->create_directory($syscontext->id, 'bad/component', 'unittest', 0, '/'); 800 } 801 802 /** 803 * Tests for create_directory with an invalid filearea. 804 * 805 * @covers ::create_directory 806 */ 807 public function test_create_directory_filearea_invalid() { 808 $fs = get_file_storage(); 809 $syscontext = \context_system::instance(); 810 811 $this->expectException('file_exception'); 812 $fs->create_directory($syscontext->id, 'core', 'bad-filearea', 0, '/'); 813 } 814 815 /** 816 * Tests for create_directory with a negative itemid 817 * 818 * @covers ::create_directory 819 */ 820 public function test_create_directory_itemid_negative() { 821 $fs = get_file_storage(); 822 $syscontext = \context_system::instance(); 823 824 $this->expectException('file_exception'); 825 $fs->create_directory($syscontext->id, 'core', 'unittest', -1, '/'); 826 } 827 828 /** 829 * Tests for create_directory with an invalid itemid 830 * 831 * @covers ::create_directory 832 */ 833 public function test_create_directory_itemid_invalid() { 834 $fs = get_file_storage(); 835 $syscontext = \context_system::instance(); 836 837 $this->expectException('file_exception'); 838 $fs->create_directory($syscontext->id, 'core', 'unittest', 'notanint', '/'); 839 } 840 841 /** 842 * Tests for create_directory with an invalid filepath 843 * 844 * @covers ::create_directory 845 */ 846 public function test_create_directory_filepath_invalid() { 847 $fs = get_file_storage(); 848 $syscontext = \context_system::instance(); 849 850 $this->expectException('file_exception'); 851 $fs->create_directory($syscontext->id, 'core', 'unittest', 0, '/not-with-trailing/or-leading-slash'); 852 } 853 854 /** 855 * Tests for get_directory_files. 856 * 857 * @covers ::get_directory_files 858 */ 859 public function test_get_directory_files() { 860 $user = $this->setup_three_private_files(); 861 $fs = get_file_storage(); 862 863 $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/'); 864 $this->assertInstanceOf('stored_file', $dir); 865 866 // Add a file to the subdir. 867 $filerecord = array( 868 'contextid' => $user->ctxid, 869 'component' => 'user', 870 'filearea' => 'private', 871 'itemid' => 0, 872 'filepath' => '/testsubdir/', 873 'filename' => 'test-get-area-tree.txt', 874 ); 875 876 $directoryfile = $fs->create_file_from_string($filerecord, 'Test content'); 877 $this->assertInstanceOf('stored_file', $directoryfile); 878 879 // Don't recurse without dirs. 880 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, false, 'id'); 881 // 3 files only. 882 $this->assertCount(3, $files); 883 foreach ($files as $key => $file) { 884 $this->assertInstanceOf('stored_file', $file); 885 $this->assertEquals($key, $file->get_pathnamehash()); 886 } 887 888 // Don't recurse with dirs. 889 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, true, 'id'); 890 // 3 files + 1 directory. 891 $this->assertCount(4, $files); 892 foreach ($files as $key => $file) { 893 $this->assertInstanceOf('stored_file', $file); 894 $this->assertEquals($key, $file->get_pathnamehash()); 895 } 896 897 // Recurse with dirs. 898 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, true, 'id'); 899 // 3 files + 1 directory + 1 subdir file. 900 $this->assertCount(5, $files); 901 foreach ($files as $key => $file) { 902 $this->assertInstanceOf('stored_file', $file); 903 $this->assertEquals($key, $file->get_pathnamehash()); 904 } 905 906 // Recurse without dirs. 907 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, false, 'id'); 908 // 3 files + 1 subdir file. 909 $this->assertCount(4, $files); 910 foreach ($files as $key => $file) { 911 $this->assertInstanceOf('stored_file', $file); 912 $this->assertEquals($key, $file->get_pathnamehash()); 913 } 914 } 915 916 /** 917 * Tests for search_references. 918 * 919 * @covers ::search_references 920 */ 921 public function test_search_references() { 922 $user = $this->setup_three_private_files(); 923 $fs = get_file_storage(); 924 $repos = repository::get_instances(array('type'=>'user')); 925 $repo = reset($repos); 926 927 $alias1 = array( 928 'contextid' => $user->ctxid, 929 'component' => 'user', 930 'filearea' => 'private', 931 'itemid' => 0, 932 'filepath' => '/aliases/', 933 'filename' => 'alias-to-1.txt' 934 ); 935 936 $alias2 = array( 937 'contextid' => $user->ctxid, 938 'component' => 'user', 939 'filearea' => 'private', 940 'itemid' => 0, 941 'filepath' => '/aliases/', 942 'filename' => 'another-alias-to-1.txt' 943 ); 944 945 $reference = \file_storage::pack_reference(array( 946 'contextid' => $user->ctxid, 947 'component' => 'user', 948 'filearea' => 'private', 949 'itemid' => 0, 950 'filepath' => '/', 951 'filename' => '1.txt' 952 )); 953 954 // There are no aliases now. 955 $result = $fs->search_references($reference); 956 $this->assertEquals(array(), $result); 957 958 $result = $fs->search_references_count($reference); 959 $this->assertSame($result, 0); 960 961 // Create two aliases and make sure they are returned. 962 $fs->create_file_from_reference($alias1, $repo->id, $reference); 963 $fs->create_file_from_reference($alias2, $repo->id, $reference); 964 965 $result = $fs->search_references($reference); 966 $this->assertTrue(is_array($result)); 967 $this->assertEquals(count($result), 2); 968 foreach ($result as $alias) { 969 $this->assertTrue($alias instanceof stored_file); 970 } 971 972 $result = $fs->search_references_count($reference); 973 $this->assertSame($result, 2); 974 975 // The method can't be used for references to files outside the filepool. 976 $exceptionthrown = false; 977 try { 978 $fs->search_references('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg'); 979 } catch (file_reference_exception $e) { 980 $exceptionthrown = true; 981 } 982 $this->assertTrue($exceptionthrown); 983 984 $exceptionthrown = false; 985 try { 986 $fs->search_references_count('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg'); 987 } catch (file_reference_exception $e) { 988 $exceptionthrown = true; 989 } 990 $this->assertTrue($exceptionthrown); 991 } 992 993 /** 994 * Tests for delete_area_files. 995 * 996 * @covers ::delete_area_files 997 */ 998 public function test_delete_area_files() { 999 $user = $this->setup_three_private_files(); 1000 $fs = get_file_storage(); 1001 1002 // Get area files with default options. 1003 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1004 // Should be the two files we added plus the folder. 1005 $this->assertEquals(4, count($areafiles)); 1006 $fs->delete_area_files($user->ctxid, 'user', 'private'); 1007 1008 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1009 // Should be the two files we added plus the folder. 1010 $this->assertEquals(0, count($areafiles)); 1011 } 1012 1013 /** 1014 * Tests for delete_area_files using an itemid. 1015 * 1016 * @covers ::delete_area_files 1017 */ 1018 public function test_delete_area_files_itemid() { 1019 $user = $this->setup_three_private_files(); 1020 $fs = get_file_storage(); 1021 1022 // Get area files with default options. 1023 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1024 // Should be the two files we added plus the folder. 1025 $this->assertEquals(4, count($areafiles)); 1026 $fs->delete_area_files($user->ctxid, 'user', 'private', 9999); 1027 1028 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1029 $this->assertEquals(4, count($areafiles)); 1030 } 1031 1032 /** 1033 * Tests for delete_area_files_select. 1034 * 1035 * @covers ::delete_area_files_select 1036 */ 1037 public function test_delete_area_files_select() { 1038 $user = $this->setup_three_private_files(); 1039 $fs = get_file_storage(); 1040 1041 // Get area files with default options. 1042 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1043 // Should be the two files we added plus the folder. 1044 $this->assertEquals(4, count($areafiles)); 1045 $fs->delete_area_files_select($user->ctxid, 'user', 'private', '!= :notitemid', array('notitemid'=>9999)); 1046 1047 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1048 // Should be the two files we added plus the folder. 1049 $this->assertEquals(0, count($areafiles)); 1050 } 1051 1052 /** 1053 * Tests for delete_component_files. 1054 * 1055 * @covers ::delete_component_files 1056 */ 1057 public function test_delete_component_files() { 1058 $user = $this->setup_three_private_files(); 1059 $fs = get_file_storage(); 1060 1061 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1062 $this->assertEquals(4, count($areafiles)); 1063 $fs->delete_component_files('user'); 1064 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); 1065 $this->assertEquals(0, count($areafiles)); 1066 } 1067 1068 /** 1069 * Tests for create_file_from_url. 1070 * 1071 * @covers ::create_file_from_url 1072 */ 1073 public function test_create_file_from_url() { 1074 $this->resetAfterTest(true); 1075 1076 $syscontext = \context_system::instance(); 1077 $filerecord = array( 1078 'contextid' => $syscontext->id, 1079 'component' => 'core', 1080 'filearea' => 'unittest', 1081 'itemid' => 0, 1082 'filepath' => '/downloadtest/', 1083 ); 1084 $url = $this->getExternalTestFileUrl('/test.html'); 1085 1086 $fs = get_file_storage(); 1087 1088 // Test creating file without filename. 1089 $file1 = $fs->create_file_from_url($filerecord, $url); 1090 $this->assertInstanceOf('stored_file', $file1); 1091 1092 // Set filename. 1093 $filerecord['filename'] = 'unit-test-filename.html'; 1094 $file2 = $fs->create_file_from_url($filerecord, $url); 1095 $this->assertInstanceOf('stored_file', $file2); 1096 1097 // Use temporary file. 1098 $filerecord['filename'] = 'unit-test-with-temp-file.html'; 1099 $file3 = $fs->create_file_from_url($filerecord, $url, null, true); 1100 $file3 = $this->assertInstanceOf('stored_file', $file3); 1101 } 1102 1103 /** 1104 * Tests for cron. 1105 * 1106 * @covers ::cron 1107 */ 1108 public function test_cron() { 1109 $this->resetAfterTest(true); 1110 1111 // Note: this is only testing DB compatibility atm, rather than 1112 // that work is done. 1113 $fs = get_file_storage(); 1114 1115 $this->expectOutputRegex('/Cleaning up/'); 1116 $fs->cron(); 1117 } 1118 1119 /** 1120 * Tests for is_area_empty. 1121 * 1122 * @covers ::is_area_empty 1123 */ 1124 public function test_is_area_empty() { 1125 $user = $this->setup_three_private_files(); 1126 $fs = get_file_storage(); 1127 1128 $this->assertFalse($fs->is_area_empty($user->ctxid, 'user', 'private')); 1129 1130 // File area with madeup itemid should be empty. 1131 $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999)); 1132 // Still empty with dirs included. 1133 $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999, false)); 1134 } 1135 1136 /** 1137 * Tests for move_area_files_to_new_context. 1138 * 1139 * @covers ::move_area_files_to_new_context 1140 */ 1141 public function test_move_area_files_to_new_context() { 1142 $this->resetAfterTest(true); 1143 1144 // Create a course with a page resource. 1145 $course = $this->getDataGenerator()->create_course(); 1146 $page1 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id)); 1147 $page1context = \context_module::instance($page1->cmid); 1148 1149 // Add a file to the page. 1150 $fs = get_file_storage(); 1151 $filerecord = array( 1152 'contextid' => $page1context->id, 1153 'component' => 'mod_page', 1154 'filearea' => 'content', 1155 'itemid' => 0, 1156 'filepath' => '/', 1157 'filename' => 'unit-test-file.txt', 1158 ); 1159 1160 $originalfile = $fs->create_file_from_string($filerecord, 'Test content'); 1161 $this->assertInstanceOf('stored_file', $originalfile); 1162 1163 $pagefiles = $fs->get_area_files($page1context->id, 'mod_page', 'content', 0, 'sortorder', false); 1164 // Should be one file in filearea. 1165 $this->assertFalse($fs->is_area_empty($page1context->id, 'mod_page', 'content')); 1166 1167 // Create a new page. 1168 $page2 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id)); 1169 $page2context = \context_module::instance($page2->cmid); 1170 1171 // Newly created page area is empty. 1172 $this->assertTrue($fs->is_area_empty($page2context->id, 'mod_page', 'content')); 1173 1174 // Move the files. 1175 $fs->move_area_files_to_new_context($page1context->id, $page2context->id, 'mod_page', 'content'); 1176 1177 // Page2 filearea should no longer be empty. 1178 $this->assertFalse($fs->is_area_empty($page2context->id, 'mod_page', 'content')); 1179 1180 // Page1 filearea should now be empty. 1181 $this->assertTrue($fs->is_area_empty($page1context->id, 'mod_page', 'content')); 1182 1183 $page2files = $fs->get_area_files($page2context->id, 'mod_page', 'content', 0, 'sortorder', false); 1184 $movedfile = reset($page2files); 1185 1186 // The two files should have the same content hash. 1187 $this->assertEquals($movedfile->get_contenthash(), $originalfile->get_contenthash()); 1188 } 1189 1190 /** 1191 * Tests for convert_image. 1192 * 1193 * @covers ::convert_image 1194 */ 1195 public function test_convert_image() { 1196 global $CFG; 1197 1198 $this->resetAfterTest(false); 1199 1200 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1201 $syscontext = \context_system::instance(); 1202 $filerecord = array( 1203 'contextid' => $syscontext->id, 1204 'component' => 'core', 1205 'filearea' => 'unittest', 1206 'itemid' => 0, 1207 'filepath' => '/images/', 1208 'filename' => 'testimage.jpg', 1209 ); 1210 1211 $fs = get_file_storage(); 1212 $original = $fs->create_file_from_pathname($filerecord, $filepath); 1213 1214 $filerecord['filename'] = 'testimage-converted-10x10.jpg'; 1215 $converted = $fs->convert_image($filerecord, $original, 10, 10, true, 100); 1216 $this->assertInstanceOf('stored_file', $converted); 1217 1218 $filerecord['filename'] = 'testimage-convereted-nosize.jpg'; 1219 $converted = $fs->convert_image($filerecord, $original); 1220 $this->assertInstanceOf('stored_file', $converted); 1221 } 1222 1223 /** 1224 * Tests for convert_image with a PNG. 1225 * 1226 * @covers ::convert_image 1227 */ 1228 public function test_convert_image_png() { 1229 global $CFG; 1230 1231 $this->resetAfterTest(false); 1232 1233 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.png'; 1234 $syscontext = \context_system::instance(); 1235 $filerecord = array( 1236 'contextid' => $syscontext->id, 1237 'component' => 'core', 1238 'filearea' => 'unittest', 1239 'itemid' => 0, 1240 'filepath' => '/images/', 1241 'filename' => 'testimage.png', 1242 ); 1243 1244 $fs = get_file_storage(); 1245 $original = $fs->create_file_from_pathname($filerecord, $filepath); 1246 1247 // Vanilla test. 1248 $filerecord['filename'] = 'testimage-converted-nosize.png'; 1249 $vanilla = $fs->convert_image($filerecord, $original); 1250 $this->assertInstanceOf('stored_file', $vanilla); 1251 // Assert that byte 25 has the ascii value 6 for PNG-24. 1252 $this->assertTrue(ord(substr($vanilla->get_content(), 25, 1)) == 6); 1253 1254 // 10x10 resize test; also testing for a ridiculous quality setting, which 1255 // we should if necessary scale to the 0 - 9 range. 1256 $filerecord['filename'] = 'testimage-converted-10x10.png'; 1257 $converted = $fs->convert_image($filerecord, $original, 10, 10, true, 100); 1258 $this->assertInstanceOf('stored_file', $converted); 1259 // Assert that byte 25 has the ascii value 6 for PNG-24. 1260 $this->assertTrue(ord(substr($converted->get_content(), 25, 1)) == 6); 1261 1262 // Transparency test. 1263 $filerecord['filename'] = 'testimage-converted-102x31.png'; 1264 $converted = $fs->convert_image($filerecord, $original, 102, 31, true, 9); 1265 $this->assertInstanceOf('stored_file', $converted); 1266 // Assert that byte 25 has the ascii value 6 for PNG-24. 1267 $this->assertTrue(ord(substr($converted->get_content(), 25, 1)) == 6); 1268 1269 $originalfile = imagecreatefromstring($original->get_content()); 1270 $convertedfile = imagecreatefromstring($converted->get_content()); 1271 $vanillafile = imagecreatefromstring($vanilla->get_content()); 1272 1273 $originalcolors = imagecolorsforindex($originalfile, imagecolorat($originalfile, 0, 0)); 1274 $convertedcolors = imagecolorsforindex($convertedfile, imagecolorat($convertedfile, 0, 0)); 1275 $vanillacolors = imagecolorsforindex($vanillafile, imagecolorat($vanillafile, 0, 0)); 1276 $this->assertEquals(count($originalcolors), 4); 1277 $this->assertEquals(count($convertedcolors), 4); 1278 $this->assertEquals(count($vanillacolors), 4); 1279 $this->assertEquals($originalcolors['red'], $convertedcolors['red']); 1280 $this->assertEquals($originalcolors['green'], $convertedcolors['green']); 1281 $this->assertEquals($originalcolors['blue'], $convertedcolors['blue']); 1282 $this->assertEquals($originalcolors['alpha'], $convertedcolors['alpha']); 1283 $this->assertEquals($originalcolors['red'], $vanillacolors['red']); 1284 $this->assertEquals($originalcolors['green'], $vanillacolors['green']); 1285 $this->assertEquals($originalcolors['blue'], $vanillacolors['blue']); 1286 $this->assertEquals($originalcolors['alpha'], $vanillacolors['alpha']); 1287 $this->assertEquals($originalcolors['alpha'], 127); 1288 1289 } 1290 1291 private function generate_file_record() { 1292 $syscontext = \context_system::instance(); 1293 $filerecord = new \stdClass(); 1294 $filerecord->contextid = $syscontext->id; 1295 $filerecord->component = 'core'; 1296 $filerecord->filearea = 'phpunit'; 1297 $filerecord->filepath = '/'; 1298 $filerecord->filename = 'testfile.txt'; 1299 $filerecord->itemid = 0; 1300 1301 return $filerecord; 1302 } 1303 1304 /** 1305 * @covers ::create_file_from_storedfile 1306 */ 1307 public function test_create_file_from_storedfile_file_invalid() { 1308 $this->resetAfterTest(true); 1309 1310 $filerecord = $this->generate_file_record(); 1311 1312 $fs = get_file_storage(); 1313 1314 // Create a file from a file id which doesn't exist. 1315 $this->expectException(file_exception::class); 1316 $fs->create_file_from_storedfile($filerecord, 9999); 1317 } 1318 1319 /** 1320 * @covers ::create_file_from_storedfile 1321 */ 1322 public function test_create_file_from_storedfile_contextid_invalid() { 1323 $this->resetAfterTest(true); 1324 1325 $filerecord = $this->generate_file_record(); 1326 1327 $fs = get_file_storage(); 1328 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1329 $this->assertInstanceOf('stored_file', $file1); 1330 1331 $filerecord->filename = 'invalid.txt'; 1332 $filerecord->contextid = 'invalid'; 1333 1334 $this->expectException(file_exception::class); 1335 $this->expectExceptionMessage('Invalid contextid'); 1336 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1337 } 1338 1339 /** 1340 * @covers ::create_file_from_storedfile 1341 */ 1342 public function test_create_file_from_storedfile_component_invalid() { 1343 $this->resetAfterTest(true); 1344 1345 $filerecord = $this->generate_file_record(); 1346 1347 $fs = get_file_storage(); 1348 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1349 $this->assertInstanceOf('stored_file', $file1); 1350 1351 $filerecord->filename = 'invalid.txt'; 1352 $filerecord->component = 'bad/component'; 1353 1354 $this->expectException(file_exception::class); 1355 $this->expectExceptionMessage('Invalid component'); 1356 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1357 } 1358 1359 /** 1360 * @covers ::create_file_from_storedfile 1361 */ 1362 public function test_create_file_from_storedfile_filearea_invalid() { 1363 $this->resetAfterTest(true); 1364 1365 $filerecord = $this->generate_file_record(); 1366 1367 $fs = get_file_storage(); 1368 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1369 $this->assertInstanceOf('stored_file', $file1); 1370 1371 $filerecord->filename = 'invalid.txt'; 1372 $filerecord->filearea = 'bad-filearea'; 1373 1374 $this->expectException(file_exception::class); 1375 $this->expectExceptionMessage('Invalid filearea'); 1376 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1377 } 1378 1379 /** 1380 * @covers ::create_file_from_storedfile 1381 */ 1382 public function test_create_file_from_storedfile_itemid_invalid() { 1383 $this->resetAfterTest(true); 1384 1385 $filerecord = $this->generate_file_record(); 1386 1387 $fs = get_file_storage(); 1388 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1389 $this->assertInstanceOf('stored_file', $file1); 1390 1391 $filerecord->filename = 'invalid.txt'; 1392 $filerecord->itemid = 'bad-itemid'; 1393 1394 $this->expectException(file_exception::class); 1395 $this->expectExceptionMessage('Invalid itemid'); 1396 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1397 } 1398 1399 /** 1400 * @covers ::create_file_from_storedfile 1401 */ 1402 public function test_create_file_from_storedfile_filepath_invalid() { 1403 $this->resetAfterTest(true); 1404 1405 $filerecord = $this->generate_file_record(); 1406 1407 $fs = get_file_storage(); 1408 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1409 $this->assertInstanceOf('stored_file', $file1); 1410 1411 $filerecord->filename = 'invalid.txt'; 1412 $filerecord->filepath = 'a-/bad/-filepath'; 1413 1414 $this->expectException(file_exception::class); 1415 $this->expectExceptionMessage('Invalid file path'); 1416 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1417 } 1418 1419 /** 1420 * @covers ::create_file_from_storedfile 1421 */ 1422 public function test_create_file_from_storedfile_filename_invalid() { 1423 $this->resetAfterTest(true); 1424 1425 $filerecord = $this->generate_file_record(); 1426 1427 $fs = get_file_storage(); 1428 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1429 $this->assertInstanceOf('stored_file', $file1); 1430 1431 $filerecord->filename = ''; 1432 1433 $this->expectException(file_exception::class); 1434 $this->expectExceptionMessage('Invalid file name'); 1435 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1436 } 1437 1438 /** 1439 * @covers ::create_file_from_storedfile 1440 */ 1441 public function test_create_file_from_storedfile_timecreated_invalid() { 1442 $this->resetAfterTest(true); 1443 1444 $filerecord = $this->generate_file_record(); 1445 1446 $fs = get_file_storage(); 1447 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1448 $this->assertInstanceOf('stored_file', $file1); 1449 1450 $filerecord->filename = 'invalid.txt'; 1451 $filerecord->timecreated = 'today'; 1452 1453 $this->expectException(file_exception::class); 1454 $this->expectExceptionMessage('Invalid file timecreated'); 1455 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1456 } 1457 1458 /** 1459 * @covers ::create_file_from_storedfile 1460 */ 1461 public function test_create_file_from_storedfile_timemodified_invalid() { 1462 $this->resetAfterTest(true); 1463 1464 $filerecord = $this->generate_file_record(); 1465 1466 $fs = get_file_storage(); 1467 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1468 $this->assertInstanceOf('stored_file', $file1); 1469 1470 $filerecord->filename = 'invalid.txt'; 1471 $filerecord->timemodified = 'today'; 1472 1473 $this->expectException(file_exception::class); 1474 $this->expectExceptionMessage('Invalid file timemodified'); 1475 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1476 } 1477 1478 /** 1479 * @covers ::create_file_from_storedfile 1480 */ 1481 public function test_create_file_from_storedfile_duplicate() { 1482 $this->resetAfterTest(true); 1483 1484 $filerecord = $this->generate_file_record(); 1485 1486 $fs = get_file_storage(); 1487 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1488 $this->assertInstanceOf('stored_file', $file1); 1489 1490 // Creating a file validating unique constraint. 1491 $this->expectException(stored_file_creation_exception::class); 1492 $this->expectExceptionMessage('Cannot create file 1/core/phpunit/0/testfile.txt'); 1493 $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1494 } 1495 1496 /** 1497 * Tests for create_file_from_storedfile. 1498 * 1499 * @covers ::create_file_from_storedfile 1500 */ 1501 public function test_create_file_from_storedfile() { 1502 $this->resetAfterTest(true); 1503 1504 $syscontext = \context_system::instance(); 1505 1506 $filerecord = new \stdClass(); 1507 $filerecord->contextid = $syscontext->id; 1508 $filerecord->component = 'core'; 1509 $filerecord->filearea = 'phpunit'; 1510 $filerecord->filepath = '/'; 1511 $filerecord->filename = 'testfile.txt'; 1512 $filerecord->itemid = 0; 1513 1514 $fs = get_file_storage(); 1515 1516 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1517 $this->assertInstanceOf('stored_file', $file1); 1518 1519 $filerecord->filename = 'test-create-file-from-storedfile.txt'; 1520 $file2 = $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1521 $this->assertInstanceOf('stored_file', $file2); 1522 1523 // These will be normalised to current time.. 1524 $filerecord->timecreated = -100; 1525 $filerecord->timemodified= -100; 1526 $filerecord->filename = 'test-create-file-from-storedfile-bad-dates.txt'; 1527 1528 $file3 = $fs->create_file_from_storedfile($filerecord, $file1->get_id()); 1529 $this->assertInstanceOf('stored_file', $file3); 1530 1531 $this->assertNotEquals($file3->get_timemodified(), $filerecord->timemodified); 1532 $this->assertNotEquals($file3->get_timecreated(), $filerecord->timecreated); 1533 } 1534 1535 /** 1536 * @covers ::create_file_from_string 1537 */ 1538 public function test_create_file_from_string_contextid_invalid() { 1539 $this->resetAfterTest(true); 1540 1541 $filerecord = $this->generate_file_record(); 1542 $fs = get_file_storage(); 1543 1544 $filerecord->contextid = 'invalid'; 1545 1546 $this->expectException(file_exception::class); 1547 $this->expectExceptionMessage('Invalid contextid'); 1548 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1549 } 1550 1551 /** 1552 * @covers ::create_file_from_string 1553 */ 1554 public function test_create_file_from_string_component_invalid() { 1555 $this->resetAfterTest(true); 1556 1557 $filerecord = $this->generate_file_record(); 1558 $fs = get_file_storage(); 1559 1560 $filerecord->component = 'bad/component'; 1561 1562 $this->expectException(file_exception::class); 1563 $this->expectExceptionMessage('Invalid component'); 1564 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1565 } 1566 1567 /** 1568 * @covers ::create_file_from_string 1569 */ 1570 public function test_create_file_from_string_filearea_invalid() { 1571 $this->resetAfterTest(true); 1572 1573 $filerecord = $this->generate_file_record(); 1574 $fs = get_file_storage(); 1575 1576 $filerecord->filearea = 'bad-filearea'; 1577 1578 $this->expectException(file_exception::class); 1579 $this->expectExceptionMessage('Invalid filearea'); 1580 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1581 } 1582 1583 /** 1584 * @covers ::create_file_from_string 1585 */ 1586 public function test_create_file_from_string_itemid_invalid() { 1587 $this->resetAfterTest(true); 1588 1589 $filerecord = $this->generate_file_record(); 1590 $fs = get_file_storage(); 1591 1592 $filerecord->itemid = 'bad-itemid'; 1593 1594 $this->expectException(file_exception::class); 1595 $this->expectExceptionMessage('Invalid itemid'); 1596 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1597 } 1598 1599 /** 1600 * @covers ::create_file_from_string 1601 */ 1602 public function test_create_file_from_string_filepath_invalid() { 1603 $this->resetAfterTest(true); 1604 1605 $filerecord = $this->generate_file_record(); 1606 $fs = get_file_storage(); 1607 1608 $filerecord->filepath = 'a-/bad/-filepath'; 1609 1610 $this->expectException(file_exception::class); 1611 $this->expectExceptionMessage('Invalid file path'); 1612 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1613 } 1614 1615 /** 1616 * @covers ::create_file_from_string 1617 */ 1618 public function test_create_file_from_string_filename_invalid() { 1619 $this->resetAfterTest(true); 1620 1621 $filerecord = $this->generate_file_record(); 1622 $fs = get_file_storage(); 1623 1624 $filerecord->filename = ''; 1625 1626 $this->expectException(file_exception::class); 1627 $this->expectExceptionMessage('Invalid file name'); 1628 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1629 } 1630 1631 /** 1632 * @covers ::create_file_from_string 1633 */ 1634 public function test_create_file_from_string_timecreated_invalid() { 1635 $this->resetAfterTest(true); 1636 1637 $filerecord = $this->generate_file_record(); 1638 $fs = get_file_storage(); 1639 1640 $filerecord->timecreated = 'today'; 1641 1642 $this->expectException('file_exception'); 1643 $this->expectExceptionMessage('Invalid file timecreated'); 1644 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1645 } 1646 1647 /** 1648 * @covers ::create_file_from_string 1649 */ 1650 public function test_create_file_from_string_timemodified_invalid() { 1651 $this->resetAfterTest(true); 1652 1653 $filerecord = $this->generate_file_record(); 1654 $fs = get_file_storage(); 1655 1656 $filerecord->timemodified = 'today'; 1657 1658 $this->expectException(file_exception::class); 1659 $this->expectExceptionMessage('Invalid file timemodified'); 1660 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1661 } 1662 1663 /** 1664 * Tests for create_file_from_string with a duplicate string. 1665 * @covers ::create_file_from_string 1666 */ 1667 public function test_create_file_from_string_duplicate() { 1668 $this->resetAfterTest(true); 1669 1670 $filerecord = $this->generate_file_record(); 1671 $fs = get_file_storage(); 1672 1673 $file1 = $fs->create_file_from_string($filerecord, 'text contents'); 1674 1675 // Creating a file validating unique constraint. 1676 $this->expectException('stored_file_creation_exception'); 1677 $file2 = $fs->create_file_from_string($filerecord, 'text contents'); 1678 } 1679 1680 /** 1681 * @covers ::create_file_from_pathname 1682 */ 1683 public function test_create_file_from_pathname_contextid_invalid() { 1684 global $CFG; 1685 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1686 1687 $this->resetAfterTest(true); 1688 1689 $filerecord = $this->generate_file_record(); 1690 $fs = get_file_storage(); 1691 1692 $filerecord->contextid = 'invalid'; 1693 1694 $this->expectException(file_exception::class); 1695 $this->expectExceptionMessage('Invalid contextid'); 1696 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1697 } 1698 1699 /** 1700 * @covers ::create_file_from_pathname 1701 */ 1702 public function test_create_file_from_pathname_component_invalid() { 1703 global $CFG; 1704 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1705 1706 $this->resetAfterTest(true); 1707 1708 $filerecord = $this->generate_file_record(); 1709 $fs = get_file_storage(); 1710 1711 $filerecord->component = 'bad/component'; 1712 1713 $this->expectException(file_exception::class); 1714 $this->expectExceptionMessage('Invalid component'); 1715 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1716 } 1717 1718 /** 1719 * @covers ::create_file_from_pathname 1720 */ 1721 public function test_create_file_from_pathname_filearea_invalid() { 1722 global $CFG; 1723 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1724 1725 $this->resetAfterTest(true); 1726 1727 $filerecord = $this->generate_file_record(); 1728 $fs = get_file_storage(); 1729 1730 $filerecord->filearea = 'bad-filearea'; 1731 1732 $this->expectException(file_exception::class); 1733 $this->expectExceptionMessage('Invalid filearea'); 1734 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1735 } 1736 1737 /** 1738 * @covers ::create_file_from_pathname 1739 */ 1740 public function test_create_file_from_pathname_itemid_invalid() { 1741 global $CFG; 1742 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1743 1744 $this->resetAfterTest(true); 1745 1746 $filerecord = $this->generate_file_record(); 1747 $fs = get_file_storage(); 1748 1749 $filerecord->itemid = 'bad-itemid'; 1750 1751 $this->expectException(file_exception::class); 1752 $this->expectExceptionMessage('Invalid itemid'); 1753 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1754 } 1755 1756 /** 1757 * @covers ::create_file_from_pathname 1758 */ 1759 public function test_create_file_from_pathname_filepath_invalid() { 1760 global $CFG; 1761 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1762 1763 $this->resetAfterTest(true); 1764 1765 $filerecord = $this->generate_file_record(); 1766 $fs = get_file_storage(); 1767 1768 $filerecord->filepath = 'a-/bad/-filepath'; 1769 1770 $this->expectException(file_exception::class); 1771 $this->expectExceptionMessage('Invalid file path'); 1772 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1773 } 1774 1775 /** 1776 * @covers ::create_file_from_pathname 1777 */ 1778 public function test_create_file_from_pathname_filename_invalid() { 1779 global $CFG; 1780 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1781 1782 $this->resetAfterTest(true); 1783 1784 $filerecord = $this->generate_file_record(); 1785 $fs = get_file_storage(); 1786 1787 $filerecord->filename = ''; 1788 1789 $this->expectException(file_exception::class); 1790 $this->expectExceptionMessage('Invalid file name'); 1791 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1792 } 1793 1794 /** 1795 * @covers ::create_file_from_pathname 1796 */ 1797 public function test_create_file_from_pathname_timecreated_invalid() { 1798 global $CFG; 1799 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1800 1801 $this->resetAfterTest(true); 1802 1803 $filerecord = $this->generate_file_record(); 1804 $fs = get_file_storage(); 1805 1806 $filerecord->timecreated = 'today'; 1807 1808 $this->expectException(file_exception::class); 1809 $this->expectExceptionMessage('Invalid file timecreated'); 1810 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1811 } 1812 1813 /** 1814 * @covers ::create_file_from_pathname 1815 */ 1816 public function test_create_file_from_pathname_timemodified_invalid() { 1817 global $CFG; 1818 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1819 1820 $this->resetAfterTest(true); 1821 1822 $filerecord = $this->generate_file_record(); 1823 $fs = get_file_storage(); 1824 1825 $filerecord->timemodified = 'today'; 1826 1827 $this->expectException(file_exception::class); 1828 $this->expectExceptionMessage('Invalid file timemodified'); 1829 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1830 } 1831 1832 /** 1833 * @covers ::create_file_from_pathname 1834 */ 1835 public function test_create_file_from_pathname_duplicate_file() { 1836 global $CFG; 1837 $this->resetAfterTest(true); 1838 1839 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; 1840 1841 $filerecord = $this->generate_file_record(); 1842 $fs = get_file_storage(); 1843 1844 $file1 = $fs->create_file_from_pathname($filerecord, $path); 1845 $this->assertInstanceOf('stored_file', $file1); 1846 1847 // Creating a file validating unique constraint. 1848 $this->expectException(stored_file_creation_exception::class); 1849 $this->expectExceptionMessage('Cannot create file 1/core/phpunit/0/testfile.txt'); 1850 $file2 = $fs->create_file_from_pathname($filerecord, $path); 1851 } 1852 1853 /** 1854 * Calling \stored_file::delete_reference() on a non-reference file throws coding_exception 1855 * 1856 * @covers \stored_file::delete_reference 1857 */ 1858 public function test_delete_reference_on_nonreference() { 1859 1860 $this->resetAfterTest(true); 1861 $user = $this->setup_three_private_files(); 1862 $fs = get_file_storage(); 1863 $repos = repository::get_instances(array('type'=>'user')); 1864 $repo = reset($repos); 1865 1866 /** @var \stored_file $file */ 1867 $file = null; 1868 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) { 1869 if (!$areafile->is_directory()) { 1870 $file = $areafile; 1871 break; 1872 } 1873 } 1874 $this->assertInstanceOf('stored_file', $file); 1875 $this->assertFalse($file->is_external_file()); 1876 1877 $this->expectException('coding_exception'); 1878 $file->delete_reference(); 1879 } 1880 1881 /** 1882 * Calling \stored_file::delete_reference() on a reference file does not affect other 1883 * symlinks to the same original 1884 * 1885 * @covers \stored_file::delete_reference 1886 */ 1887 public function test_delete_reference_one_symlink_does_not_rule_them_all() { 1888 1889 $this->resetAfterTest(true); 1890 $user = $this->setup_three_private_files(); 1891 $fs = get_file_storage(); 1892 $repos = repository::get_instances(array('type'=>'user')); 1893 $repo = reset($repos); 1894 1895 // Create two aliases linking the same original. 1896 1897 /** @var \stored_file $originalfile */ 1898 $originalfile = null; 1899 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) { 1900 if (!$areafile->is_directory()) { 1901 $originalfile = $areafile; 1902 break; 1903 } 1904 } 1905 $this->assertInstanceOf('stored_file', $originalfile); 1906 1907 // Calling delete_reference() on a non-reference file. 1908 1909 $originalrecord = array( 1910 'contextid' => $originalfile->get_contextid(), 1911 'component' => $originalfile->get_component(), 1912 'filearea' => $originalfile->get_filearea(), 1913 'itemid' => $originalfile->get_itemid(), 1914 'filepath' => $originalfile->get_filepath(), 1915 'filename' => $originalfile->get_filename(), 1916 ); 1917 1918 $aliasrecord = $this->generate_file_record(); 1919 $aliasrecord->filepath = '/A/'; 1920 $aliasrecord->filename = 'symlink.txt'; 1921 1922 $ref = $fs->pack_reference($originalrecord); 1923 $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref); 1924 1925 $aliasrecord->filepath = '/B/'; 1926 $aliasrecord->filename = 'symlink.txt'; 1927 $ref = $fs->pack_reference($originalrecord); 1928 $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref); 1929 1930 // Refetch A/symlink.txt file. 1931 $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 1932 $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt'); 1933 $this->assertTrue($symlink1->is_external_file()); 1934 1935 // Unlink the A/symlink.txt file. 1936 $symlink1->delete_reference(); 1937 $this->assertFalse($symlink1->is_external_file()); 1938 1939 // Make sure that B/symlink.txt has not been affected. 1940 $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 1941 $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt'); 1942 $this->assertTrue($symlink2->is_external_file()); 1943 } 1944 1945 /** 1946 * Make sure that when internal file is updated all references to it are 1947 * updated immediately. When it is deleted, the references are converted 1948 * to true copies. 1949 */ 1950 public function test_update_reference_internal() { 1951 purge_all_caches(); 1952 $this->resetAfterTest(true); 1953 $user = $this->setup_three_private_files(); 1954 $fs = get_file_storage(); 1955 $repos = repository::get_instances(array('type' => 'user')); 1956 $repo = reset($repos); 1957 1958 // Create two aliases linking the same original. 1959 1960 $areafiles = array_values($fs->get_area_files($user->ctxid, 'user', 'private', false, 'filename', false)); 1961 1962 $originalfile = $areafiles[0]; 1963 $this->assertInstanceOf('stored_file', $originalfile); 1964 $contenthash = $originalfile->get_contenthash(); 1965 $filesize = $originalfile->get_filesize(); 1966 1967 $substitutefile = $areafiles[1]; 1968 $this->assertInstanceOf('stored_file', $substitutefile); 1969 $newcontenthash = $substitutefile->get_contenthash(); 1970 $newfilesize = $substitutefile->get_filesize(); 1971 1972 $originalrecord = array( 1973 'contextid' => $originalfile->get_contextid(), 1974 'component' => $originalfile->get_component(), 1975 'filearea' => $originalfile->get_filearea(), 1976 'itemid' => $originalfile->get_itemid(), 1977 'filepath' => $originalfile->get_filepath(), 1978 'filename' => $originalfile->get_filename(), 1979 ); 1980 1981 $aliasrecord = $this->generate_file_record(); 1982 $aliasrecord->filepath = '/A/'; 1983 $aliasrecord->filename = 'symlink.txt'; 1984 1985 $ref = $fs->pack_reference($originalrecord); 1986 $symlink1 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref); 1987 // Make sure created alias is a reference and has the same size and contenthash as source. 1988 $this->assertEquals($contenthash, $symlink1->get_contenthash()); 1989 $this->assertEquals($filesize, $symlink1->get_filesize()); 1990 $this->assertEquals($repo->id, $symlink1->get_repository_id()); 1991 $this->assertNotEmpty($symlink1->get_referencefileid()); 1992 $referenceid = $symlink1->get_referencefileid(); 1993 1994 $aliasrecord->filepath = '/B/'; 1995 $aliasrecord->filename = 'symlink.txt'; 1996 $ref = $fs->pack_reference($originalrecord); 1997 $symlink2 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref); 1998 // Make sure created alias is a reference and has the same size and contenthash as source. 1999 $this->assertEquals($contenthash, $symlink2->get_contenthash()); 2000 $this->assertEquals($filesize, $symlink2->get_filesize()); 2001 $this->assertEquals($repo->id, $symlink2->get_repository_id()); 2002 // Make sure both aliases have the same reference id. 2003 $this->assertEquals($referenceid, $symlink2->get_referencefileid()); 2004 2005 // Overwrite ofiginal file. 2006 $originalfile->replace_file_with($substitutefile); 2007 $this->assertEquals($newcontenthash, $originalfile->get_contenthash()); 2008 $this->assertEquals($newfilesize, $originalfile->get_filesize()); 2009 2010 // References to the internal files must be synchronised immediately. 2011 // Refetch A/symlink.txt file. 2012 $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 2013 $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt'); 2014 $this->assertTrue($symlink1->is_external_file()); 2015 $this->assertEquals($newcontenthash, $symlink1->get_contenthash()); 2016 $this->assertEquals($newfilesize, $symlink1->get_filesize()); 2017 $this->assertEquals($repo->id, $symlink1->get_repository_id()); 2018 $this->assertEquals($referenceid, $symlink1->get_referencefileid()); 2019 2020 // Refetch B/symlink.txt file. 2021 $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 2022 $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt'); 2023 $this->assertTrue($symlink2->is_external_file()); 2024 $this->assertEquals($newcontenthash, $symlink2->get_contenthash()); 2025 $this->assertEquals($newfilesize, $symlink2->get_filesize()); 2026 $this->assertEquals($repo->id, $symlink2->get_repository_id()); 2027 $this->assertEquals($referenceid, $symlink2->get_referencefileid()); 2028 2029 // Remove original file. 2030 $originalfile->delete(); 2031 2032 // References must be converted to independend files. 2033 // Refetch A/symlink.txt file. 2034 $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 2035 $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt'); 2036 $this->assertFalse($symlink1->is_external_file()); 2037 $this->assertEquals($newcontenthash, $symlink1->get_contenthash()); 2038 $this->assertEquals($newfilesize, $symlink1->get_filesize()); 2039 $this->assertNull($symlink1->get_repository_id()); 2040 $this->assertNull($symlink1->get_referencefileid()); 2041 2042 // Refetch B/symlink.txt file. 2043 $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component, 2044 $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt'); 2045 $this->assertFalse($symlink2->is_external_file()); 2046 $this->assertEquals($newcontenthash, $symlink2->get_contenthash()); 2047 $this->assertEquals($newfilesize, $symlink2->get_filesize()); 2048 $this->assertNull($symlink2->get_repository_id()); 2049 $this->assertNull($symlink2->get_referencefileid()); 2050 } 2051 2052 /** 2053 * Tests for get_unused_filename. 2054 * 2055 * @covers ::get_unused_filename 2056 */ 2057 public function test_get_unused_filename() { 2058 global $USER; 2059 $this->resetAfterTest(true); 2060 2061 $fs = get_file_storage(); 2062 $this->setAdminUser(); 2063 $contextid = \context_user::instance($USER->id)->id; 2064 $component = 'user'; 2065 $filearea = 'private'; 2066 $itemid = 0; 2067 $filepath = '/'; 2068 2069 // Create some private files. 2070 $file = new \stdClass; 2071 $file->contextid = $contextid; 2072 $file->component = 'user'; 2073 $file->filearea = 'private'; 2074 $file->itemid = 0; 2075 $file->filepath = '/'; 2076 $file->source = 'test'; 2077 $filenames = array('foo.txt', 'foo (1).txt', 'foo (20).txt', 'foo (999)', 'bar.jpg', 'What (a cool file).jpg', 2078 'Hurray! (1).php', 'Hurray! (2).php', 'Hurray! (9a).php', 'Hurray! (abc).php'); 2079 foreach ($filenames as $key => $filename) { 2080 $file->filename = $filename; 2081 $userfile = $fs->create_file_from_string($file, "file $key $filename content"); 2082 $this->assertInstanceOf('stored_file', $userfile); 2083 } 2084 2085 // Asserting new generated names. 2086 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'unused.txt'); 2087 $this->assertEquals('unused.txt', $newfilename); 2088 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo.txt'); 2089 $this->assertEquals('foo (21).txt', $newfilename); 2090 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (1).txt'); 2091 $this->assertEquals('foo (21).txt', $newfilename); 2092 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (2).txt'); 2093 $this->assertEquals('foo (2).txt', $newfilename); 2094 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (20).txt'); 2095 $this->assertEquals('foo (21).txt', $newfilename); 2096 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo'); 2097 $this->assertEquals('foo', $newfilename); 2098 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (123)'); 2099 $this->assertEquals('foo (123)', $newfilename); 2100 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (999)'); 2101 $this->assertEquals('foo (1000)', $newfilename); 2102 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.png'); 2103 $this->assertEquals('bar.png', $newfilename); 2104 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (12).png'); 2105 $this->assertEquals('bar (12).png', $newfilename); 2106 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.jpg'); 2107 $this->assertEquals('bar (1).jpg', $newfilename); 2108 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (1).jpg'); 2109 $this->assertEquals('bar (1).jpg', $newfilename); 2110 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'What (a cool file).jpg'); 2111 $this->assertEquals('What (a cool file) (1).jpg', $newfilename); 2112 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'Hurray! (1).php'); 2113 $this->assertEquals('Hurray! (3).php', $newfilename); 2114 2115 $this->expectException('coding_exception'); 2116 $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, ''); 2117 } 2118 2119 /** 2120 * Test that mimetype_from_file returns appropriate output when the 2121 * file could not be found. 2122 * 2123 * @covers ::mimetype 2124 */ 2125 public function test_mimetype_not_found() { 2126 $mimetype = \file_storage::mimetype('/path/to/nonexistent/file'); 2127 $this->assertEquals('document/unknown', $mimetype); 2128 } 2129 2130 /** 2131 * Data provider to return fixture files and their expected mimetype 2132 * 2133 * @return array[] 2134 */ 2135 public function filepath_mimetype_provider(): array { 2136 return [ 2137 [__DIR__ . '/fixtures/testimage.jpg', 'image/jpeg'], 2138 [__DIR__ . '/fixtures/testimage.svg', 'image/svg+xml'], 2139 [__DIR__ . '/fixtures/testimage_basic.svg', 'image/svg+xml'], 2140 ]; 2141 } 2142 2143 /** 2144 * Test that mimetype returns appropriate output for a known file. 2145 * 2146 * Note: this is not intended to check that functions outside of this 2147 * file works. It is intended to validate the codepath contains no 2148 * errors and behaves as expected. 2149 * 2150 * @covers ::mimetype 2151 * 2152 * @param string $filepath 2153 * @param string $expectedmimetype 2154 * 2155 * @dataProvider filepath_mimetype_provider 2156 */ 2157 public function test_mimetype_known(string $filepath, string $expectedmimetype): void { 2158 $mimetype = \file_storage::mimetype($filepath); 2159 $this->assertEquals($expectedmimetype, $mimetype); 2160 } 2161 2162 /** 2163 * Test that mimetype_from_file returns appropriate output when the 2164 * file could not be found. 2165 * 2166 * @covers ::mimetype_from_file 2167 */ 2168 public function test_mimetype_from_file_not_found() { 2169 $mimetype = \file_storage::mimetype_from_file('/path/to/nonexistent/file'); 2170 $this->assertEquals('document/unknown', $mimetype); 2171 } 2172 2173 /** 2174 * Test that mimetype_from_file returns appropriate output for a known 2175 * file. 2176 * 2177 * Note: this is not intended to check that functions outside of this 2178 * file works. It is intended to validate the codepath contains no 2179 * errors and behaves as expected. 2180 * 2181 * @covers ::mimetype_from_file 2182 * 2183 * @param string $filepath 2184 * @param string $expectedmimetype 2185 * 2186 * @dataProvider filepath_mimetype_provider 2187 */ 2188 public function test_mimetype_from_file_known(string $filepath, string $expectedmimetype): void { 2189 $mimetype = \file_storage::mimetype_from_file($filepath); 2190 $this->assertEquals($expectedmimetype, $mimetype); 2191 } 2192 2193 /** 2194 * Test that get_pathname_hash returns the same file hash for pathnames 2195 * with and without trailing / leading slash. 2196 * 2197 * @covers ::get_pathname_hash 2198 * 2199 */ 2200 public function test_get_pathname_hash(): void { 2201 $contextid = 2; 2202 $component = 'mod_test'; 2203 $filearea = 'data'; 2204 $itemid = 0; 2205 $filepath1 = '/path'; 2206 $filepath2 = '/path/'; 2207 $filepath3 = 'path/'; 2208 $filename = 'example.jpg'; 2209 $hash1 = \file_storage::get_pathname_hash($contextid, $component, $filearea, $itemid, $filepath1, $filename); 2210 $hash2 = \file_storage::get_pathname_hash($contextid, $component, $filearea, $itemid, $filepath2, $filename); 2211 $hash3 = \file_storage::get_pathname_hash($contextid, $component, $filearea, $itemid, $filepath3, $filename); 2212 $this->assertEquals($hash1, $hash2); 2213 $this->assertEquals($hash2, $hash3); 2214 } 2215 2216 } 2217 2218 class test_stored_file_inspection extends stored_file { 2219 public static function get_pretected_pathname(stored_file $file) { 2220 return $file->get_pathname_by_contenthash(); 2221 } 2222 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body