2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Unit tests for /lib/filestorage/file_storage.php
22 * @copyright 2012 David Mudrak <david@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
29 require_once($CFG->libdir . '/filelib.php');
30 require_once($CFG->dirroot . '/repository/lib.php');
31 require_once($CFG->libdir . '/filestorage/stored_file.php');
33 class core_files_file_storage_testcase extends advanced_testcase {
36 * Files can be created from strings.
38 public function test_create_file_from_string() {
41 $this->resetAfterTest(true);
43 $this->assertEquals(0, $DB->count_records('files', array()));
46 $syscontext = context_system::instance();
48 'contextid' => $syscontext->id,
49 'component' => 'core',
50 'filearea' => 'unittest',
52 'filepath' => '/images/',
53 'filename' => 'testfile.txt',
55 $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']);
57 $fs = get_file_storage();
58 $file = $fs->create_file_from_string($filerecord, $content);
60 $this->assertInstanceOf('stored_file', $file);
61 $this->assertSame(sha1($content), $file->get_contenthash());
62 $this->assertSame($pathhash, $file->get_pathnamehash());
64 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>$pathhash)));
66 $location = test_stored_file_inspection::get_pretected_pathname($file);
68 $this->assertFileExists($location);
70 // Verify the dir placeholder files are created.
71 $this->assertEquals(3, $DB->count_records('files', array()));
72 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].'/.'))));
73 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].'.'))));
75 // Tests that missing content file is recreated.
78 $this->assertFileNotExists($location);
80 $filerecord['filename'] = 'testfile2.txt';
81 $file2 = $fs->create_file_from_string($filerecord, $content);
82 $this->assertInstanceOf('stored_file', $file2);
83 $this->assertSame($file->get_contenthash(), $file2->get_contenthash());
84 $this->assertFileExists($location);
86 $this->assertEquals(4, $DB->count_records('files', array()));
88 // Test that borked content file is recreated.
90 $this->assertSame(2, file_put_contents($location, 'xx'));
92 $filerecord['filename'] = 'testfile3.txt';
93 $file3 = $fs->create_file_from_string($filerecord, $content);
94 $this->assertInstanceOf('stored_file', $file3);
95 $this->assertSame($file->get_contenthash(), $file3->get_contenthash());
96 $this->assertFileExists($location);
98 $this->assertSame($content, file_get_contents($location));
99 $this->assertDebuggingCalled();
101 $this->assertEquals(5, $DB->count_records('files', array()));
105 * Local files can be added to the filepool
107 public function test_create_file_from_pathname() {
110 $this->resetAfterTest(true);
112 $filecount = $DB->count_records('files', array());
113 $this->assertEquals(0, $filecount);
115 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
116 $syscontext = context_system::instance();
118 'contextid' => $syscontext->id,
119 'component' => 'core',
120 'filearea' => 'unittest',
122 'filepath' => '/images/',
123 'filename' => 'testimage.jpg',
125 $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']);
127 $fs = get_file_storage();
128 $file = $fs->create_file_from_pathname($filerecord, $filepath);
130 $this->assertInstanceOf('stored_file', $file);
131 $this->assertSame(sha1_file($filepath), $file->get_contenthash());
133 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>$pathhash)));
135 $location = test_stored_file_inspection::get_pretected_pathname($file);
137 $this->assertFileExists($location);
139 // Verify the dir placeholder files are created.
140 $this->assertEquals(3, $DB->count_records('files', array()));
141 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].'/.'))));
142 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].'.'))));
144 // Tests that missing content file is recreated.
147 $this->assertFileNotExists($location);
149 $filerecord['filename'] = 'testfile2.jpg';
150 $file2 = $fs->create_file_from_pathname($filerecord, $filepath);
151 $this->assertInstanceOf('stored_file', $file2);
152 $this->assertSame($file->get_contenthash(), $file2->get_contenthash());
153 $this->assertFileExists($location);
155 $this->assertEquals(4, $DB->count_records('files', array()));
157 // Test that borked content file is recreated.
159 $this->assertSame(2, file_put_contents($location, 'xx'));
161 $filerecord['filename'] = 'testfile3.jpg';
162 $file3 = $fs->create_file_from_pathname($filerecord, $filepath);
163 $this->assertInstanceOf('stored_file', $file3);
164 $this->assertSame($file->get_contenthash(), $file3->get_contenthash());
165 $this->assertFileExists($location);
167 $this->assertSame(file_get_contents($filepath), file_get_contents($location));
168 $this->assertDebuggingCalled();
170 $this->assertEquals(5, $DB->count_records('files', array()));
172 // Test invalid file creation.
174 $filerecord['filename'] = 'testfile4.jpg';
176 $fs->create_file_from_pathname($filerecord, $filepath.'nonexistent');
177 $this->fail('Exception expected when trying to add non-existent stored file.');
178 } catch (Exception $e) {
179 $this->assertInstanceOf('file_exception', $e);
184 * Tests get get file.
186 public function test_get_file() {
189 $this->resetAfterTest(false);
191 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
192 $syscontext = context_system::instance();
194 'contextid' => $syscontext->id,
195 'component' => 'core',
196 'filearea' => 'unittest',
198 'filepath' => '/images/',
199 'filename' => 'testimage.jpg',
201 $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']);
203 $fs = get_file_storage();
204 $file = $fs->create_file_from_pathname($filerecord, $filepath);
206 $this->assertInstanceOf('stored_file', $file);
207 $this->assertEquals($syscontext->id, $file->get_contextid());
208 $this->assertEquals('core', $file->get_component());
209 $this->assertEquals('unittest', $file->get_filearea());
210 $this->assertEquals(0, $file->get_itemid());
211 $this->assertEquals('/images/', $file->get_filepath());
212 $this->assertEquals('testimage.jpg', $file->get_filename());
213 $this->assertEquals(filesize($filepath), $file->get_filesize());
214 $this->assertEquals($pathhash, $file->get_pathnamehash());
220 * Local images can be added to the filepool and their preview can be obtained
222 * @depends test_get_file
224 public function test_get_file_preview(stored_file $file) {
227 $this->resetAfterTest();
228 $fs = get_file_storage();
230 $previewtinyicon = $fs->get_file_preview($file, 'tinyicon');
231 $this->assertInstanceOf('stored_file', $previewtinyicon);
232 $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
234 $previewtinyicon = $fs->get_file_preview($file, 'thumb');
235 $this->assertInstanceOf('stored_file', $previewtinyicon);
236 $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
238 $this->setExpectedException('file_exception');
239 $fs->get_file_preview($file, 'amodewhichdoesntexist');
242 public function test_get_file_preview_nonimage() {
243 $this->resetAfterTest(true);
244 $syscontext = context_system::instance();
246 'contextid' => $syscontext->id,
247 'component' => 'core',
248 'filearea' => 'unittest',
250 'filepath' => '/textfiles/',
251 'filename' => 'testtext.txt',
254 $fs = get_file_storage();
255 $fs->create_file_from_string($filerecord, 'text contents');
256 $textfile = $fs->get_file($syscontext->id, $filerecord['component'], $filerecord['filearea'],
257 $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename']);
259 $preview = $fs->get_file_preview($textfile, 'thumb');
260 $this->assertFalse($preview);
264 * Make sure renaming is working
266 * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org}
268 public function test_file_renaming() {
271 $this->resetAfterTest();
272 $fs = get_file_storage();
273 $syscontext = context_system::instance();
275 $filearea = 'unittest';
278 $filename = 'test.txt';
281 'contextid' => $syscontext->id,
282 'component' => $component,
283 'filearea' => $filearea,
285 'filepath' => $filepath,
286 'filename' => $filename,
289 $originalfile = $fs->create_file_from_string($filerecord, 'Test content');
290 $this->assertInstanceOf('stored_file', $originalfile);
291 $contenthash = $originalfile->get_contenthash();
293 $newname = 'newtest.txt';
296 $originalfile->rename($newpath, $newname);
297 $file = $fs->get_file($syscontext->id, $component, $filearea, $itemid, $newpath, $newname);
298 $this->assertInstanceOf('stored_file', $file);
299 $this->assertEquals($contenthash, $file->get_contenthash());
302 $this->setExpectedException('file_exception');
303 // This shall throw exception.
304 $originalfile->rename($newpath, $newname);
308 * Create file from reference tests
310 * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org}
312 public function test_create_file_from_reference() {
315 $this->resetAfterTest();
317 $generator = $this->getDataGenerator();
318 $user = $generator->create_user();
319 $this->setUser($user);
320 $usercontext = context_user::instance($user->id);
321 $syscontext = context_system::instance();
323 $fs = get_file_storage();
325 $repositorypluginname = 'user';
326 // Override repository permission.
327 $capability = 'repository/' . $repositorypluginname . ':view';
328 $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
329 assign_capability($capability, CAP_ALLOW, $allroles['guest'], $syscontext->id, true);
332 $args['type'] = $repositorypluginname;
333 $repos = repository::get_instances($args);
334 $userrepository = reset($repos);
335 $this->assertInstanceOf('repository', $userrepository);
338 $filearea = 'private';
341 $filename = 'userfile.txt';
344 'contextid' => $usercontext->id,
345 'component' => $component,
346 'filearea' => $filearea,
348 'filepath' => $filepath,
349 'filename' => $filename,
352 $content = 'Test content';
353 $originalfile = $fs->create_file_from_string($filerecord, $content);
354 $this->assertInstanceOf('stored_file', $originalfile);
356 $newfilerecord = array(
357 'contextid' => $syscontext->id,
358 'component' => 'core',
359 'filearea' => 'phpunit',
361 'filepath' => $filepath,
362 'filename' => $filename,
364 $ref = $fs->pack_reference($filerecord);
365 $newstoredfile = $fs->create_file_from_reference($newfilerecord, $userrepository->id, $ref);
366 $this->assertInstanceOf('stored_file', $newstoredfile);
367 $this->assertEquals($userrepository->id, $newstoredfile->get_repository_id());
368 $this->assertEquals($originalfile->get_contenthash(), $newstoredfile->get_contenthash());
369 $this->assertEquals($originalfile->get_filesize(), $newstoredfile->get_filesize());
370 $this->assertRegExp('#' . $filename. '$#', $newstoredfile->get_reference_details());
372 // Test looking for references.
373 $count = $fs->get_references_count_by_storedfile($originalfile);
374 $this->assertEquals(1, $count);
375 $files = $fs->get_references_by_storedfile($originalfile);
376 $file = reset($files);
377 $this->assertEquals($file, $newstoredfile);
379 // Look for references by repository ID.
380 $files = $fs->get_external_files($userrepository->id);
381 $file = reset($files);
382 $this->assertEquals($file, $newstoredfile);
384 // Try convert reference to local file.
385 $importedfile = $fs->import_external_file($newstoredfile);
386 $this->assertFalse($importedfile->is_external_file());
387 $this->assertInstanceOf('stored_file', $importedfile);
389 $this->assertEquals($content, $importedfile->get_content());
392 private function setup_three_private_files() {
394 $this->resetAfterTest();
396 $generator = $this->getDataGenerator();
397 $user = $generator->create_user();
398 $this->setUser($user->id);
399 $usercontext = context_user::instance($user->id);
400 // Create a user private file.
401 $file1 = new stdClass;
402 $file1->contextid = $usercontext->id;
403 $file1->component = 'user';
404 $file1->filearea = 'private';
406 $file1->filepath = '/';
407 $file1->filename = '1.txt';
408 $file1->source = 'test';
410 $fs = get_file_storage();
411 $userfile1 = $fs->create_file_from_string($file1, 'file1 content');
412 $this->assertInstanceOf('stored_file', $userfile1);
414 $file2 = clone($file1);
415 $file2->filename = '2.txt';
416 $userfile2 = $fs->create_file_from_string($file2, 'file2 content');
417 $this->assertInstanceOf('stored_file', $userfile2);
419 $file3 = clone($file1);
420 $file3->filename = '3.txt';
421 $userfile3 = $fs->create_file_from_storedfile($file3, $userfile2);
422 $this->assertInstanceOf('stored_file', $userfile3);
424 $user->ctxid = $usercontext->id;
429 public function test_get_area_files() {
430 $user = $this->setup_three_private_files();
431 $fs = get_file_storage();
433 // Get area files with default options.
434 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
436 // Should be the two files we added plus the folder.
437 $this->assertEquals(4, count($areafiles));
440 foreach ($areafiles as $key => $file) {
441 $this->assertInstanceOf('stored_file', $file);
442 $this->assertEquals($key, $file->get_pathnamehash());
445 // Get area files without a folder.
446 $folderlessfiles = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'sortorder', false);
447 // Should be the two files without folder.
448 $this->assertEquals(3, count($folderlessfiles));
451 foreach ($folderlessfiles as $key => $file) {
452 $this->assertInstanceOf('stored_file', $file);
453 $this->assertEquals($key, $file->get_pathnamehash());
456 // Get area files ordered by id.
457 $filesbyid = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'id', false);
458 // Should be the two files without folder.
459 $this->assertEquals(3, count($filesbyid));
462 foreach ($filesbyid as $key => $file) {
463 $this->assertInstanceOf('stored_file', $file);
464 $this->assertEquals($key, $file->get_pathnamehash());
467 // Test with an itemid with no files.
468 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', 666, 'sortorder', false);
470 $this->assertEmpty($areafiles);
473 public function test_get_area_tree() {
474 $user = $this->setup_three_private_files();
475 $fs = get_file_storage();
477 // Get area files with default options.
478 $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0);
479 $this->assertEmpty($areatree['subdirs']);
480 $this->assertNotEmpty($areatree['files']);
481 $this->assertCount(3, $areatree['files']);
483 // Ensure an empty try with a fake itemid.
484 $emptytree = $fs->get_area_tree($user->ctxid, 'user', 'private', 666);
485 $this->assertEmpty($emptytree['subdirs']);
486 $this->assertEmpty($emptytree['files']);
489 $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/');
490 $this->assertInstanceOf('stored_file', $dir);
492 // Add a file to the subdir.
494 'contextid' => $user->ctxid,
495 'component' => 'user',
496 'filearea' => 'private',
498 'filepath' => '/testsubdir/',
499 'filename' => 'test-get-area-tree.txt',
502 $directoryfile = $fs->create_file_from_string($filerecord, 'Test content');
503 $this->assertInstanceOf('stored_file', $directoryfile);
505 $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0);
507 // At the top level there should still be 3 files.
508 $this->assertCount(3, $areatree['files']);
510 // There should now be a subdirectory.
511 $this->assertCount(1, $areatree['subdirs']);
513 // The test subdir is named testsubdir.
514 $subdir = $areatree['subdirs']['testsubdir'];
515 $this->assertNotEmpty($subdir);
516 // It should have one file we added.
517 $this->assertCount(1, $subdir['files']);
518 // And no subdirs itself.
519 $this->assertCount(0, $subdir['subdirs']);
521 // Verify the file is the one we added.
522 $subdirfile = reset($subdir['files']);
523 $this->assertInstanceOf('stored_file', $subdirfile);
524 $this->assertEquals($filerecord['filename'], $subdirfile->get_filename());
527 public function test_get_file_by_id() {
528 $user = $this->setup_three_private_files();
529 $fs = get_file_storage();
531 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
533 // Test get_file_by_id.
534 $filebyid = reset($areafiles);
535 $shouldbesame = $fs->get_file_by_id($filebyid->get_id());
536 $this->assertEquals($filebyid->get_contenthash(), $shouldbesame->get_contenthash());
538 // Test an id which doens't exist.
539 $doesntexist = $fs->get_file_by_id(99999);
540 $this->assertFalse($doesntexist);
543 public function test_get_file_by_hash() {
544 $user = $this->setup_three_private_files();
545 $fs = get_file_storage();
547 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
548 // Test get_file_by_hash.
549 $filebyhash = reset($areafiles);
550 $shouldbesame = $fs->get_file_by_hash($filebyhash->get_pathnamehash());
551 $this->assertEquals($filebyhash->get_id(), $shouldbesame->get_id());
553 // Test an hash which doens't exist.
554 $doesntexist = $fs->get_file_by_hash('DOESNTEXIST');
555 $this->assertFalse($doesntexist);
558 public function test_get_external_files() {
559 $user = $this->setup_three_private_files();
560 $fs = get_file_storage();
562 $repos = repository::get_instances(array('type'=>'user'));
563 $userrepository = reset($repos);
564 $this->assertInstanceOf('repository', $userrepository);
567 $exfiles = $fs->get_external_files($userrepository->id, 'id');
568 $this->assertEquals(array(), $exfiles);
570 // Create three aliases linking the same original: $aliasfile1 and $aliasfile2 are
571 // created via create_file_from_reference(), $aliasfile3 created from $aliasfile2.
572 $originalfile = null;
573 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
574 if (!$areafile->is_directory()) {
575 $originalfile = $areafile;
579 $this->assertInstanceOf('stored_file', $originalfile);
580 $originalrecord = array(
581 'contextid' => $originalfile->get_contextid(),
582 'component' => $originalfile->get_component(),
583 'filearea' => $originalfile->get_filearea(),
584 'itemid' => $originalfile->get_itemid(),
585 'filepath' => $originalfile->get_filepath(),
586 'filename' => $originalfile->get_filename(),
589 $aliasrecord = $this->generate_file_record();
590 $aliasrecord->filepath = '/foo/';
591 $aliasrecord->filename = 'one.txt';
593 $ref = $fs->pack_reference($originalrecord);
594 $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref);
596 $aliasrecord->filepath = '/bar/';
597 $aliasrecord->filename = 'uno.txt';
598 // Change the order of the items in the array to make sure that it does not matter.
599 ksort($originalrecord);
600 $ref = $fs->pack_reference($originalrecord);
601 $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref);
603 $aliasrecord->filepath = '/bar/';
604 $aliasrecord->filename = 'jedna.txt';
605 $aliasfile3 = $fs->create_file_from_storedfile($aliasrecord, $aliasfile2);
607 // Make sure we get three aliases now.
608 $exfiles = $fs->get_external_files($userrepository->id, 'id');
609 $this->assertEquals(3, count($exfiles));
610 foreach ($exfiles as $exfile) {
611 $this->assertTrue($exfile->is_external_file());
613 // Make sure they all link the same original (thence that all are linked with the same
614 // record in {files_reference}).
615 $this->assertEquals($aliasfile1->get_referencefileid(), $aliasfile2->get_referencefileid());
616 $this->assertEquals($aliasfile3->get_referencefileid(), $aliasfile2->get_referencefileid());
619 public function test_create_directory_contextid_negative() {
620 $fs = get_file_storage();
622 $this->setExpectedException('file_exception');
623 $fs->create_directory(-1, 'core', 'unittest', 0, '/');
626 public function test_create_directory_contextid_invalid() {
627 $fs = get_file_storage();
629 $this->setExpectedException('file_exception');
630 $fs->create_directory('not an int', 'core', 'unittest', 0, '/');
633 public function test_create_directory_component_invalid() {
634 $fs = get_file_storage();
635 $syscontext = context_system::instance();
637 $this->setExpectedException('file_exception');
638 $fs->create_directory($syscontext->id, 'bad/component', 'unittest', 0, '/');
641 public function test_create_directory_filearea_invalid() {
642 $fs = get_file_storage();
643 $syscontext = context_system::instance();
645 $this->setExpectedException('file_exception');
646 $fs->create_directory($syscontext->id, 'core', 'bad-filearea', 0, '/');
649 public function test_create_directory_itemid_negative() {
650 $fs = get_file_storage();
651 $syscontext = context_system::instance();
653 $this->setExpectedException('file_exception');
654 $fs->create_directory($syscontext->id, 'core', 'unittest', -1, '/');
657 public function test_create_directory_itemid_invalid() {
658 $fs = get_file_storage();
659 $syscontext = context_system::instance();
661 $this->setExpectedException('file_exception');
662 $fs->create_directory($syscontext->id, 'core', 'unittest', 'notanint', '/');
665 public function test_create_directory_filepath_invalid() {
666 $fs = get_file_storage();
667 $syscontext = context_system::instance();
669 $this->setExpectedException('file_exception');
670 $fs->create_directory($syscontext->id, 'core', 'unittest', 0, '/not-with-trailing/or-leading-slash');
673 public function test_get_directory_files() {
674 $user = $this->setup_three_private_files();
675 $fs = get_file_storage();
677 $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/');
678 $this->assertInstanceOf('stored_file', $dir);
680 // Add a file to the subdir.
682 'contextid' => $user->ctxid,
683 'component' => 'user',
684 'filearea' => 'private',
686 'filepath' => '/testsubdir/',
687 'filename' => 'test-get-area-tree.txt',
690 $directoryfile = $fs->create_file_from_string($filerecord, 'Test content');
691 $this->assertInstanceOf('stored_file', $directoryfile);
693 // Don't recurse without dirs.
694 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, false, 'id');
696 $this->assertCount(3, $files);
697 foreach ($files as $key => $file) {
698 $this->assertInstanceOf('stored_file', $file);
699 $this->assertEquals($key, $file->get_pathnamehash());
702 // Don't recurse with dirs.
703 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, true, 'id');
704 // 3 files + 1 directory.
705 $this->assertCount(4, $files);
706 foreach ($files as $key => $file) {
707 $this->assertInstanceOf('stored_file', $file);
708 $this->assertEquals($key, $file->get_pathnamehash());
711 // Recurse with dirs.
712 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, true, 'id');
713 // 3 files + 1 directory + 1 subdir file.
714 $this->assertCount(5, $files);
715 foreach ($files as $key => $file) {
716 $this->assertInstanceOf('stored_file', $file);
717 $this->assertEquals($key, $file->get_pathnamehash());
720 // Recurse without dirs.
721 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, false, 'id');
722 // 3 files + 1 subdir file.
723 $this->assertCount(4, $files);
724 foreach ($files as $key => $file) {
725 $this->assertInstanceOf('stored_file', $file);
726 $this->assertEquals($key, $file->get_pathnamehash());
730 public function test_search_references() {
731 $user = $this->setup_three_private_files();
732 $fs = get_file_storage();
733 $repos = repository::get_instances(array('type'=>'user'));
734 $repo = reset($repos);
737 'contextid' => $user->ctxid,
738 'component' => 'user',
739 'filearea' => 'private',
741 'filepath' => '/aliases/',
742 'filename' => 'alias-to-1.txt'
746 'contextid' => $user->ctxid,
747 'component' => 'user',
748 'filearea' => 'private',
750 'filepath' => '/aliases/',
751 'filename' => 'another-alias-to-1.txt'
754 $reference = file_storage::pack_reference(array(
755 'contextid' => $user->ctxid,
756 'component' => 'user',
757 'filearea' => 'private',
760 'filename' => '1.txt'
763 // There are no aliases now.
764 $result = $fs->search_references($reference);
765 $this->assertEquals(array(), $result);
767 $result = $fs->search_references_count($reference);
768 $this->assertSame($result, 0);
770 // Create two aliases and make sure they are returned.
771 $fs->create_file_from_reference($alias1, $repo->id, $reference);
772 $fs->create_file_from_reference($alias2, $repo->id, $reference);
774 $result = $fs->search_references($reference);
775 $this->assertTrue(is_array($result));
776 $this->assertEquals(count($result), 2);
777 foreach ($result as $alias) {
778 $this->assertTrue($alias instanceof stored_file);
781 $result = $fs->search_references_count($reference);
782 $this->assertSame($result, 2);
784 // The method can't be used for references to files outside the filepool.
785 $exceptionthrown = false;
787 $fs->search_references('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg');
788 } catch (file_reference_exception $e) {
789 $exceptionthrown = true;
791 $this->assertTrue($exceptionthrown);
793 $exceptionthrown = false;
795 $fs->search_references_count('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg');
796 } catch (file_reference_exception $e) {
797 $exceptionthrown = true;
799 $this->assertTrue($exceptionthrown);
802 public function test_delete_area_files() {
803 $user = $this->setup_three_private_files();
804 $fs = get_file_storage();
806 // Get area files with default options.
807 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
808 // Should be the two files we added plus the folder.
809 $this->assertEquals(4, count($areafiles));
810 $fs->delete_area_files($user->ctxid, 'user', 'private');
812 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
813 // Should be the two files we added plus the folder.
814 $this->assertEquals(0, count($areafiles));
817 public function test_delete_area_files_itemid() {
818 $user = $this->setup_three_private_files();
819 $fs = get_file_storage();
821 // Get area files with default options.
822 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
823 // Should be the two files we added plus the folder.
824 $this->assertEquals(4, count($areafiles));
825 $fs->delete_area_files($user->ctxid, 'user', 'private', 9999);
827 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
828 $this->assertEquals(4, count($areafiles));
831 public function test_delete_area_files_select() {
832 $user = $this->setup_three_private_files();
833 $fs = get_file_storage();
835 // Get area files with default options.
836 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
837 // Should be the two files we added plus the folder.
838 $this->assertEquals(4, count($areafiles));
839 $fs->delete_area_files_select($user->ctxid, 'user', 'private', '!= :notitemid', array('notitemid'=>9999));
841 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
842 // Should be the two files we added plus the folder.
843 $this->assertEquals(0, count($areafiles));
846 public function test_delete_component_files() {
847 $user = $this->setup_three_private_files();
848 $fs = get_file_storage();
850 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
851 $this->assertEquals(4, count($areafiles));
852 $fs->delete_component_files('user');
853 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
854 $this->assertEquals(0, count($areafiles));
857 public function test_create_file_from_url() {
858 $this->resetAfterTest(true);
860 $syscontext = context_system::instance();
862 'contextid' => $syscontext->id,
863 'component' => 'core',
864 'filearea' => 'unittest',
866 'filepath' => '/downloadtest/',
868 $url = 'http://download.moodle.org/unittest/test.html';
870 $fs = get_file_storage();
872 // Test creating file without filename.
873 $file1 = $fs->create_file_from_url($filerecord, $url);
874 $this->assertInstanceOf('stored_file', $file1);
877 $filerecord['filename'] = 'unit-test-filename.html';
878 $file2 = $fs->create_file_from_url($filerecord, $url);
879 $this->assertInstanceOf('stored_file', $file2);
881 // Use temporary file.
882 $filerecord['filename'] = 'unit-test-with-temp-file.html';
883 $file3 = $fs->create_file_from_url($filerecord, $url, null, true);
884 $file3 = $this->assertInstanceOf('stored_file', $file3);
887 public function test_cron() {
888 $this->resetAfterTest(true);
890 // Note: this is only testing DB compatibility atm, rather than
891 // that work is done.
892 $fs = get_file_storage();
894 $this->expectOutputRegex('/Cleaning up/');
898 public function test_is_area_empty() {
899 $user = $this->setup_three_private_files();
900 $fs = get_file_storage();
902 $this->assertFalse($fs->is_area_empty($user->ctxid, 'user', 'private'));
904 // File area with madeup itemid should be empty.
905 $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999));
906 // Still empty with dirs included.
907 $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999, false));
910 public function test_move_area_files_to_new_context() {
911 $this->resetAfterTest(true);
913 // Create a course with a page resource.
914 $course = $this->getDataGenerator()->create_course();
915 $page1 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
916 $page1context = context_module::instance($page1->cmid);
918 // Add a file to the page.
919 $fs = get_file_storage();
921 'contextid' => $page1context->id,
922 'component' => 'mod_page',
923 'filearea' => 'content',
926 'filename' => 'unit-test-file.txt',
929 $originalfile = $fs->create_file_from_string($filerecord, 'Test content');
930 $this->assertInstanceOf('stored_file', $originalfile);
932 $pagefiles = $fs->get_area_files($page1context->id, 'mod_page', 'content', 0, 'sortorder', false);
933 // Should be one file in filearea.
934 $this->assertFalse($fs->is_area_empty($page1context->id, 'mod_page', 'content'));
936 // Create a new page.
937 $page2 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
938 $page2context = context_module::instance($page2->cmid);
940 // Newly created page area is empty.
941 $this->assertTrue($fs->is_area_empty($page2context->id, 'mod_page', 'content'));
944 $fs->move_area_files_to_new_context($page1context->id, $page2context->id, 'mod_page', 'content');
946 // Page2 filearea should no longer be empty.
947 $this->assertFalse($fs->is_area_empty($page2context->id, 'mod_page', 'content'));
949 // Page1 filearea should now be empty.
950 $this->assertTrue($fs->is_area_empty($page1context->id, 'mod_page', 'content'));
952 $page2files = $fs->get_area_files($page2context->id, 'mod_page', 'content', 0, 'sortorder', false);
953 $movedfile = reset($page2files);
955 // The two files should have the same content hash.
956 $this->assertEquals($movedfile->get_contenthash(), $originalfile->get_contenthash());
959 public function test_convert_image() {
962 $this->resetAfterTest(false);
964 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
965 $syscontext = context_system::instance();
967 'contextid' => $syscontext->id,
968 'component' => 'core',
969 'filearea' => 'unittest',
971 'filepath' => '/images/',
972 'filename' => 'testimage.jpg',
975 $fs = get_file_storage();
976 $original = $fs->create_file_from_pathname($filerecord, $filepath);
978 $filerecord['filename'] = 'testimage-converted-10x10.jpg';
979 $converted = $fs->convert_image($filerecord, $original, 10, 10, true, 100);
980 $this->assertInstanceOf('stored_file', $converted);
982 $filerecord['filename'] = 'testimage-convereted-nosize.jpg';
983 $converted = $fs->convert_image($filerecord, $original);
984 $this->assertInstanceOf('stored_file', $converted);
987 private function generate_file_record() {
988 $syscontext = context_system::instance();
989 $filerecord = new stdClass();
990 $filerecord->contextid = $syscontext->id;
991 $filerecord->component = 'core';
992 $filerecord->filearea = 'phpunit';
993 $filerecord->filepath = '/';
994 $filerecord->filename = 'testfile.txt';
995 $filerecord->itemid = 0;
1000 public function test_create_file_from_storedfile_file_invalid() {
1001 $this->resetAfterTest(true);
1003 $filerecord = $this->generate_file_record();
1005 $fs = get_file_storage();
1006 $this->setExpectedException('file_exception');
1007 // Create a file from a file id which doesn't exist.
1008 $fs->create_file_from_storedfile($filerecord, 9999);
1011 public function test_create_file_from_storedfile_contextid_invalid() {
1012 $this->resetAfterTest(true);
1014 $filerecord = $this->generate_file_record();
1016 $fs = get_file_storage();
1017 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1018 $this->assertInstanceOf('stored_file', $file1);
1020 $filerecord->filename = 'invalid.txt';
1021 $filerecord->contextid = 'invalid';
1023 $this->setExpectedException('file_exception', 'Invalid contextid');
1024 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1027 public function test_create_file_from_storedfile_component_invalid() {
1028 $this->resetAfterTest(true);
1030 $filerecord = $this->generate_file_record();
1032 $fs = get_file_storage();
1033 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1034 $this->assertInstanceOf('stored_file', $file1);
1036 $filerecord->filename = 'invalid.txt';
1037 $filerecord->component = 'bad/component';
1039 $this->setExpectedException('file_exception', 'Invalid component');
1040 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1043 public function test_create_file_from_storedfile_filearea_invalid() {
1044 $this->resetAfterTest(true);
1046 $filerecord = $this->generate_file_record();
1048 $fs = get_file_storage();
1049 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1050 $this->assertInstanceOf('stored_file', $file1);
1052 $filerecord->filename = 'invalid.txt';
1053 $filerecord->filearea = 'bad-filearea';
1055 $this->setExpectedException('file_exception', 'Invalid filearea');
1056 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1059 public function test_create_file_from_storedfile_itemid_invalid() {
1060 $this->resetAfterTest(true);
1062 $filerecord = $this->generate_file_record();
1064 $fs = get_file_storage();
1065 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1066 $this->assertInstanceOf('stored_file', $file1);
1068 $filerecord->filename = 'invalid.txt';
1069 $filerecord->itemid = 'bad-itemid';
1071 $this->setExpectedException('file_exception', 'Invalid itemid');
1072 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1075 public function test_create_file_from_storedfile_filepath_invalid() {
1076 $this->resetAfterTest(true);
1078 $filerecord = $this->generate_file_record();
1080 $fs = get_file_storage();
1081 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1082 $this->assertInstanceOf('stored_file', $file1);
1084 $filerecord->filename = 'invalid.txt';
1085 $filerecord->filepath = 'a-/bad/-filepath';
1087 $this->setExpectedException('file_exception', 'Invalid file path');
1088 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1091 public function test_create_file_from_storedfile_filename_invalid() {
1092 $this->resetAfterTest(true);
1094 $filerecord = $this->generate_file_record();
1096 $fs = get_file_storage();
1097 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1098 $this->assertInstanceOf('stored_file', $file1);
1100 $filerecord->filename = '';
1102 $this->setExpectedException('file_exception', 'Invalid file name');
1103 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1106 public function test_create_file_from_storedfile_timecreated_invalid() {
1107 $this->resetAfterTest(true);
1109 $filerecord = $this->generate_file_record();
1111 $fs = get_file_storage();
1112 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1113 $this->assertInstanceOf('stored_file', $file1);
1115 $filerecord->filename = 'invalid.txt';
1116 $filerecord->timecreated = 'today';
1118 $this->setExpectedException('file_exception', 'Invalid file timecreated');
1119 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1122 public function test_create_file_from_storedfile_timemodified_invalid() {
1123 $this->resetAfterTest(true);
1125 $filerecord = $this->generate_file_record();
1127 $fs = get_file_storage();
1128 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1129 $this->assertInstanceOf('stored_file', $file1);
1131 $filerecord->filename = 'invalid.txt';
1132 $filerecord->timemodified = 'today';
1134 $this->setExpectedException('file_exception', 'Invalid file timemodified');
1135 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1138 public function test_create_file_from_storedfile_duplicate() {
1139 $this->resetAfterTest(true);
1141 $filerecord = $this->generate_file_record();
1143 $fs = get_file_storage();
1144 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1145 $this->assertInstanceOf('stored_file', $file1);
1147 // Creating a file validating unique constraint.
1148 $this->setExpectedException('stored_file_creation_exception');
1149 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1152 public function test_create_file_from_storedfile() {
1153 $this->resetAfterTest(true);
1155 $syscontext = context_system::instance();
1157 $filerecord = new stdClass();
1158 $filerecord->contextid = $syscontext->id;
1159 $filerecord->component = 'core';
1160 $filerecord->filearea = 'phpunit';
1161 $filerecord->filepath = '/';
1162 $filerecord->filename = 'testfile.txt';
1163 $filerecord->itemid = 0;
1165 $fs = get_file_storage();
1167 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1168 $this->assertInstanceOf('stored_file', $file1);
1170 $filerecord->filename = 'test-create-file-from-storedfile.txt';
1171 $file2 = $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1172 $this->assertInstanceOf('stored_file', $file2);
1174 // These will be normalised to current time..
1175 $filerecord->timecreated = -100;
1176 $filerecord->timemodified= -100;
1177 $filerecord->filename = 'test-create-file-from-storedfile-bad-dates.txt';
1179 $file3 = $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1180 $this->assertInstanceOf('stored_file', $file3);
1182 $this->assertNotEquals($file3->get_timemodified(), $filerecord->timemodified);
1183 $this->assertNotEquals($file3->get_timecreated(), $filerecord->timecreated);
1186 public function test_create_file_from_string_contextid_invalid() {
1187 $this->resetAfterTest(true);
1189 $filerecord = $this->generate_file_record();
1190 $fs = get_file_storage();
1192 $filerecord->contextid = 'invalid';
1194 $this->setExpectedException('file_exception', 'Invalid contextid');
1195 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1198 public function test_create_file_from_string_component_invalid() {
1199 $this->resetAfterTest(true);
1201 $filerecord = $this->generate_file_record();
1202 $fs = get_file_storage();
1204 $filerecord->component = 'bad/component';
1206 $this->setExpectedException('file_exception', 'Invalid component');
1207 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1210 public function test_create_file_from_string_filearea_invalid() {
1211 $this->resetAfterTest(true);
1213 $filerecord = $this->generate_file_record();
1214 $fs = get_file_storage();
1216 $filerecord->filearea = 'bad-filearea';
1218 $this->setExpectedException('file_exception', 'Invalid filearea');
1219 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1222 public function test_create_file_from_string_itemid_invalid() {
1223 $this->resetAfterTest(true);
1225 $filerecord = $this->generate_file_record();
1226 $fs = get_file_storage();
1228 $filerecord->itemid = 'bad-itemid';
1230 $this->setExpectedException('file_exception', 'Invalid itemid');
1231 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1234 public function test_create_file_from_string_filepath_invalid() {
1235 $this->resetAfterTest(true);
1237 $filerecord = $this->generate_file_record();
1238 $fs = get_file_storage();
1240 $filerecord->filepath = 'a-/bad/-filepath';
1242 $this->setExpectedException('file_exception', 'Invalid file path');
1243 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1246 public function test_create_file_from_string_filename_invalid() {
1247 $this->resetAfterTest(true);
1249 $filerecord = $this->generate_file_record();
1250 $fs = get_file_storage();
1252 $filerecord->filename = '';
1254 $this->setExpectedException('file_exception', 'Invalid file name');
1255 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1258 public function test_create_file_from_string_timecreated_invalid() {
1259 $this->resetAfterTest(true);
1261 $filerecord = $this->generate_file_record();
1262 $fs = get_file_storage();
1264 $filerecord->timecreated = 'today';
1266 $this->setExpectedException('file_exception', 'Invalid file timecreated');
1267 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1270 public function test_create_file_from_string_timemodified_invalid() {
1271 $this->resetAfterTest(true);
1273 $filerecord = $this->generate_file_record();
1274 $fs = get_file_storage();
1276 $filerecord->timemodified = 'today';
1278 $this->setExpectedException('file_exception', 'Invalid file timemodified');
1279 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1282 public function test_create_file_from_string_duplicate() {
1283 $this->resetAfterTest(true);
1285 $filerecord = $this->generate_file_record();
1286 $fs = get_file_storage();
1288 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1290 // Creating a file validating unique constraint.
1291 $this->setExpectedException('stored_file_creation_exception');
1292 $file2 = $fs->create_file_from_string($filerecord, 'text contents');
1295 public function test_create_file_from_pathname_contextid_invalid() {
1297 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1299 $this->resetAfterTest(true);
1301 $filerecord = $this->generate_file_record();
1302 $fs = get_file_storage();
1304 $filerecord->contextid = 'invalid';
1306 $this->setExpectedException('file_exception', 'Invalid contextid');
1307 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1310 public function test_create_file_from_pathname_component_invalid() {
1312 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1314 $this->resetAfterTest(true);
1316 $filerecord = $this->generate_file_record();
1317 $fs = get_file_storage();
1319 $filerecord->component = 'bad/component';
1321 $this->setExpectedException('file_exception', 'Invalid component');
1322 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1325 public function test_create_file_from_pathname_filearea_invalid() {
1327 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1329 $this->resetAfterTest(true);
1331 $filerecord = $this->generate_file_record();
1332 $fs = get_file_storage();
1334 $filerecord->filearea = 'bad-filearea';
1336 $this->setExpectedException('file_exception', 'Invalid filearea');
1337 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1340 public function test_create_file_from_pathname_itemid_invalid() {
1342 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1344 $this->resetAfterTest(true);
1346 $filerecord = $this->generate_file_record();
1347 $fs = get_file_storage();
1349 $filerecord->itemid = 'bad-itemid';
1351 $this->setExpectedException('file_exception', 'Invalid itemid');
1352 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1355 public function test_create_file_from_pathname_filepath_invalid() {
1357 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1359 $this->resetAfterTest(true);
1361 $filerecord = $this->generate_file_record();
1362 $fs = get_file_storage();
1364 $filerecord->filepath = 'a-/bad/-filepath';
1366 $this->setExpectedException('file_exception', 'Invalid file path');
1367 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1370 public function test_create_file_from_pathname_filename_invalid() {
1372 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1374 $this->resetAfterTest(true);
1376 $filerecord = $this->generate_file_record();
1377 $fs = get_file_storage();
1379 $filerecord->filename = '';
1381 $this->setExpectedException('file_exception', 'Invalid file name');
1382 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1385 public function test_create_file_from_pathname_timecreated_invalid() {
1387 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1389 $this->resetAfterTest(true);
1391 $filerecord = $this->generate_file_record();
1392 $fs = get_file_storage();
1394 $filerecord->timecreated = 'today';
1396 $this->setExpectedException('file_exception', 'Invalid file timecreated');
1397 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1400 public function test_create_file_from_pathname_timemodified_invalid() {
1402 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1404 $this->resetAfterTest(true);
1406 $filerecord = $this->generate_file_record();
1407 $fs = get_file_storage();
1409 $filerecord->timemodified = 'today';
1411 $this->setExpectedException('file_exception', 'Invalid file timemodified');
1412 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1415 public function test_create_file_from_pathname_duplicate_file() {
1417 $this->resetAfterTest(true);
1419 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1421 $filerecord = $this->generate_file_record();
1422 $fs = get_file_storage();
1424 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1425 $this->assertInstanceOf('stored_file', $file1);
1427 // Creating a file validating unique constraint.
1428 $this->setExpectedException('stored_file_creation_exception');
1429 $file2 = $fs->create_file_from_pathname($filerecord, $path);
1433 * Calling stored_file::delete_reference() on a non-reference file throws coding_exception
1435 public function test_delete_reference_on_nonreference() {
1437 $this->resetAfterTest(true);
1438 $user = $this->setup_three_private_files();
1439 $fs = get_file_storage();
1440 $repos = repository::get_instances(array('type'=>'user'));
1441 $repo = reset($repos);
1444 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
1445 if (!$areafile->is_directory()) {
1450 $this->assertInstanceOf('stored_file', $file);
1451 $this->assertFalse($file->is_external_file());
1453 $this->setExpectedException('coding_exception');
1454 $file->delete_reference();
1458 * Calling stored_file::delete_reference() on a reference file does not affect other
1459 * symlinks to the same original
1461 public function test_delete_reference_one_symlink_does_not_rule_them_all() {
1463 $this->resetAfterTest(true);
1464 $user = $this->setup_three_private_files();
1465 $fs = get_file_storage();
1466 $repos = repository::get_instances(array('type'=>'user'));
1467 $repo = reset($repos);
1469 // Create two aliases linking the same original.
1471 $originalfile = null;
1472 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
1473 if (!$areafile->is_directory()) {
1474 $originalfile = $areafile;
1478 $this->assertInstanceOf('stored_file', $originalfile);
1480 // Calling delete_reference() on a non-reference file.
1482 $originalrecord = array(
1483 'contextid' => $originalfile->get_contextid(),
1484 'component' => $originalfile->get_component(),
1485 'filearea' => $originalfile->get_filearea(),
1486 'itemid' => $originalfile->get_itemid(),
1487 'filepath' => $originalfile->get_filepath(),
1488 'filename' => $originalfile->get_filename(),
1491 $aliasrecord = $this->generate_file_record();
1492 $aliasrecord->filepath = '/A/';
1493 $aliasrecord->filename = 'symlink.txt';
1495 $ref = $fs->pack_reference($originalrecord);
1496 $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1498 $aliasrecord->filepath = '/B/';
1499 $aliasrecord->filename = 'symlink.txt';
1500 $ref = $fs->pack_reference($originalrecord);
1501 $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1503 // Refetch A/symlink.txt file.
1504 $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1505 $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt');
1506 $this->assertTrue($symlink1->is_external_file());
1508 // Unlink the A/symlink.txt file.
1509 $symlink1->delete_reference();
1510 $this->assertFalse($symlink1->is_external_file());
1512 // Make sure that B/symlink.txt has not been affected.
1513 $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1514 $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt');
1515 $this->assertTrue($symlink2->is_external_file());
1518 public function test_get_unused_filename() {
1520 $this->resetAfterTest(true);
1522 $fs = get_file_storage();
1523 $this->setAdminUser();
1524 $contextid = context_user::instance($USER->id)->id;
1525 $component = 'user';
1526 $filearea = 'private';
1530 // Create some private files.
1531 $file = new stdClass;
1532 $file->contextid = $contextid;
1533 $file->component = 'user';
1534 $file->filearea = 'private';
1536 $file->filepath = '/';
1537 $file->source = 'test';
1538 $filenames = array('foo.txt', 'foo (1).txt', 'foo (20).txt', 'foo (999)', 'bar.jpg', 'What (a cool file).jpg',
1539 'Hurray! (1).php', 'Hurray! (2).php', 'Hurray! (9a).php', 'Hurray! (abc).php');
1540 foreach ($filenames as $key => $filename) {
1541 $file->filename = $filename;
1542 $userfile = $fs->create_file_from_string($file, "file $key $filename content");
1543 $this->assertInstanceOf('stored_file', $userfile);
1546 // Asserting new generated names.
1547 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'unused.txt');
1548 $this->assertEquals('unused.txt', $newfilename);
1549 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo.txt');
1550 $this->assertEquals('foo (21).txt', $newfilename);
1551 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (1).txt');
1552 $this->assertEquals('foo (21).txt', $newfilename);
1553 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (2).txt');
1554 $this->assertEquals('foo (2).txt', $newfilename);
1555 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (20).txt');
1556 $this->assertEquals('foo (21).txt', $newfilename);
1557 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo');
1558 $this->assertEquals('foo', $newfilename);
1559 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (123)');
1560 $this->assertEquals('foo (123)', $newfilename);
1561 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (999)');
1562 $this->assertEquals('foo (1000)', $newfilename);
1563 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.png');
1564 $this->assertEquals('bar.png', $newfilename);
1565 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (12).png');
1566 $this->assertEquals('bar (12).png', $newfilename);
1567 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.jpg');
1568 $this->assertEquals('bar (1).jpg', $newfilename);
1569 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (1).jpg');
1570 $this->assertEquals('bar (1).jpg', $newfilename);
1571 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'What (a cool file).jpg');
1572 $this->assertEquals('What (a cool file) (1).jpg', $newfilename);
1573 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'Hurray! (1).php');
1574 $this->assertEquals('Hurray! (3).php', $newfilename);
1576 $this->setExpectedException('coding_exception');
1577 $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, '');
1581 class test_stored_file_inspection extends stored_file {
1582 public static function get_pretected_pathname(stored_file $file) {
1583 return $file->get_pathname_by_contenthash();