MDL-39087 Delete all component files in uninstall_plugin()
[moodle.git] / lib / filestorage / tests / file_storage_test.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * Unit tests for /lib/filestorage/file_storage.php
20  *
21  * @package   core
22  * @category  test
23  * @copyright 2012 David Mudrak <david@moodle.com>
24  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25  */
27 defined('MOODLE_INTERNAL') || die();
29 global $CFG;
30 require_once($CFG->libdir . '/filelib.php');
31 require_once($CFG->dirroot . '/repository/lib.php');
33 class filestoragelib_testcase extends advanced_testcase {
35     /**
36      * Local files can be added to the filepool
37      */
38     public function test_create_file_from_pathname() {
39         global $CFG;
41         $this->resetAfterTest(false);
43         $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
44         $syscontext = context_system::instance();
45         $filerecord = array(
46             'contextid' => $syscontext->id,
47             'component' => 'core',
48             'filearea'  => 'unittest',
49             'itemid'    => 0,
50             'filepath'  => '/images/',
51             'filename'  => 'testimage.jpg',
52         );
54         $fs = get_file_storage();
55         $fs->create_file_from_pathname($filerecord, $filepath);
57         $this->assertTrue($fs->file_exists($syscontext->id, 'core', 'unittest', 0, '/images/', 'testimage.jpg'));
59         return $fs->get_file($syscontext->id, 'core', 'unittest', 0, '/images/', 'testimage.jpg');
60     }
62     /**
63      * Local images can be added to the filepool and their preview can be obtained
64      *
65      * @depends test_create_file_from_pathname
66      */
67     public function test_get_file_preview(stored_file $file) {
68         global $CFG;
70         $this->resetAfterTest(true);
71         $fs = get_file_storage();
73         $previewtinyicon = $fs->get_file_preview($file, 'tinyicon');
74         $this->assertInstanceOf('stored_file', $previewtinyicon);
75         $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
77         $previewtinyicon = $fs->get_file_preview($file, 'thumb');
78         $this->assertInstanceOf('stored_file', $previewtinyicon);
79         $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
81         $this->setExpectedException('file_exception');
82         $fs->get_file_preview($file, 'amodewhichdoesntexist');
83     }
85     public function test_get_file_preview_nonimage() {
86         $this->resetAfterTest(true);
87         $syscontext = context_system::instance();
88         $filerecord = array(
89             'contextid' => $syscontext->id,
90             'component' => 'core',
91             'filearea'  => 'unittest',
92             'itemid'    => 0,
93             'filepath'  => '/textfiles/',
94             'filename'  => 'testtext.txt',
95         );
97         $fs = get_file_storage();
98         $fs->create_file_from_string($filerecord, 'text contents');
99         $textfile = $fs->get_file($syscontext->id, $filerecord['component'], $filerecord['filearea'],
100             $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename']);
102         $preview = $fs->get_file_preview($textfile, 'thumb');
103         $this->assertFalse($preview);
104     }
106     /**
107      * Make sure renaming is working
108      *
109      * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org}
110      */
111     public function test_file_renaming() {
112         global $CFG;
114         $this->resetAfterTest(true);
115         $fs = get_file_storage();
116         $syscontext = context_system::instance();
117         $component = 'core';
118         $filearea  = 'unittest';
119         $itemid    = 0;
120         $filepath  = '/';
121         $filename  = 'test.txt';
123         $filerecord = array(
124             'contextid' => $syscontext->id,
125             'component' => $component,
126             'filearea'  => $filearea,
127             'itemid'    => $itemid,
128             'filepath'  => $filepath,
129             'filename'  => $filename,
130         );
132         $originalfile = $fs->create_file_from_string($filerecord, 'Test content');
133         $this->assertInstanceOf('stored_file', $originalfile);
134         $contenthash = $originalfile->get_contenthash();
135         $newpath = '/test/';
136         $newname = 'newtest.txt';
138         // this should work
139         $originalfile->rename($newpath, $newname);
140         $file = $fs->get_file($syscontext->id, $component, $filearea, $itemid, $newpath, $newname);
141         $this->assertInstanceOf('stored_file', $file);
142         $this->assertEquals($contenthash, $file->get_contenthash());
144         // try break it
145         $this->setExpectedException('file_exception');
146         // this shall throw exception
147         $originalfile->rename($newpath, $newname);
148     }
150     /**
151      * Create file from reference tests
152      *
153      * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org}
154      */
155     public function test_create_file_from_reference() {
156         global $CFG, $DB;
158         $this->resetAfterTest(true);
159         // create user
160         $generator = $this->getDataGenerator();
161         $user = $generator->create_user();
162         $this->setUser($user);
163         $usercontext = context_user::instance($user->id);
164         $syscontext = context_system::instance();
166         $fs = get_file_storage();
168         $repositorypluginname = 'user';
169         // override repository permission
170         $capability = 'repository/' . $repositorypluginname . ':view';
171         $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
172         assign_capability($capability, CAP_ALLOW, $allroles['guest'], $syscontext->id, true);
175         $args = array();
176         $args['type'] = $repositorypluginname;
177         $repos = repository::get_instances($args);
178         $userrepository = reset($repos);
179         $this->assertInstanceOf('repository', $userrepository);
181         $component = 'user';
182         $filearea  = 'private';
183         $itemid    = 0;
184         $filepath  = '/';
185         $filename  = 'userfile.txt';
187         $filerecord = array(
188             'contextid' => $usercontext->id,
189             'component' => $component,
190             'filearea'  => $filearea,
191             'itemid'    => $itemid,
192             'filepath'  => $filepath,
193             'filename'  => $filename,
194         );
196         $content = 'Test content';
197         $originalfile = $fs->create_file_from_string($filerecord, $content);
198         $this->assertInstanceOf('stored_file', $originalfile);
200         $newfilerecord = array(
201             'contextid' => $syscontext->id,
202             'component' => 'core',
203             'filearea'  => 'phpunit',
204             'itemid'    => 0,
205             'filepath'  => $filepath,
206             'filename'  => $filename,
207         );
208         $ref = $fs->pack_reference($filerecord);
209         $newstoredfile = $fs->create_file_from_reference($newfilerecord, $userrepository->id, $ref);
210         $this->assertInstanceOf('stored_file', $newstoredfile);
211         $this->assertEquals($userrepository->id, $newstoredfile->get_repository_id());
212         $this->assertEquals($originalfile->get_contenthash(), $newstoredfile->get_contenthash());
213         $this->assertEquals($originalfile->get_filesize(), $newstoredfile->get_filesize());
214         $this->assertRegExp('#' . $filename. '$#', $newstoredfile->get_reference_details());
216         // Test looking for references
217         $count = $fs->get_references_count_by_storedfile($originalfile);
218         $this->assertEquals(1, $count);
219         $files = $fs->get_references_by_storedfile($originalfile);
220         $file = reset($files);
221         $this->assertEquals($file, $newstoredfile);
223         // Look for references by repository ID
224         $files = $fs->get_external_files($userrepository->id);
225         $file = reset($files);
226         $this->assertEquals($file, $newstoredfile);
228         // Try convert reference to local file
229         $importedfile = $fs->import_external_file($newstoredfile);
230         $this->assertFalse($importedfile->is_external_file());
231         $this->assertInstanceOf('stored_file', $importedfile);
232         // still readable?
233         $this->assertEquals($content, $importedfile->get_content());
234     }
236     private function setup_three_private_files() {
238         $this->resetAfterTest(true);
240         $generator = $this->getDataGenerator();
241         $user = $generator->create_user();
242         $this->setUser($user->id);
243         $usercontext = context_user::instance($user->id);
244         // create a user private file
245         $file1 = new stdClass;
246         $file1->contextid = $usercontext->id;
247         $file1->component = 'user';
248         $file1->filearea  = 'private';
249         $file1->itemid    = 0;
250         $file1->filepath  = '/';
251         $file1->filename  = '1.txt';
252         $file1->source    = 'test';
254         $fs = get_file_storage();
255         $userfile1 = $fs->create_file_from_string($file1, 'file1 content');
256         $this->assertInstanceOf('stored_file', $userfile1);
258         $file2 = clone($file1);
259         $file2->filename = '2.txt';
260         $userfile2 = $fs->create_file_from_string($file2, 'file2 content');
261         $this->assertInstanceOf('stored_file', $userfile2);
263         $file3 = clone($file1);
264         $file3->filename = '3.txt';
265         $userfile3 = $fs->create_file_from_storedfile($file3, $userfile2);
266         $this->assertInstanceOf('stored_file', $userfile3);
268         $user->ctxid = $usercontext->id;
270         return $user;
271     }
273     public function test_get_area_files() {
274         $user = $this->setup_three_private_files();
275         $fs = get_file_storage();
277         // Get area files with default options.
278         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
280         // Should be the two files we added plus the folder.
281         $this->assertEquals(4, count($areafiles));
283         // Verify structure.
284         foreach ($areafiles as $key => $file) {
285             $this->assertInstanceOf('stored_file', $file);
286             $this->assertEquals($key, $file->get_pathnamehash());
287         }
289         // Get area files without a folder.
290         $folderlessfiles = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'sortorder', false);
291         // Should be the two files without folder.
292         $this->assertEquals(3, count($folderlessfiles));
294         // Verify structure.
295         foreach ($folderlessfiles as $key => $file) {
296             $this->assertInstanceOf('stored_file', $file);
297             $this->assertEquals($key, $file->get_pathnamehash());
298         }
300         // Get area files ordered by id.
301         $filesbyid  = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'id', false);
302         // Should be the two files without folder.
303         $this->assertEquals(3, count($filesbyid));
305         // Verify structure.
306         foreach ($filesbyid as $key => $file) {
307             $this->assertInstanceOf('stored_file', $file);
308             $this->assertEquals($key, $file->get_pathnamehash());
309         }
311         // Test with an itemid with no files
312         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', 666, 'sortorder', false);
313         // Should be none.
314         $this->assertEmpty($areafiles);
315     }
317     public function test_get_area_tree() {
318         $user = $this->setup_three_private_files();
319         $fs = get_file_storage();
322         // Get area files with default options.
323         $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0);
324         $this->assertEmpty($areatree['subdirs']);
325         $this->assertNotEmpty($areatree['files']);
326         $this->assertCount(3, $areatree['files']);
328         // Ensure an empty try with a fake itemid.
329         $emptytree = $fs->get_area_tree($user->ctxid, 'user', 'private', 666);
330         $this->assertEmpty($emptytree['subdirs']);
331         $this->assertEmpty($emptytree['files']);
333         // Create a subdir.
334         $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/');
335         $this->assertInstanceOf('stored_file', $dir);
337         // Add a file to the subdir.
338         $filerecord = array(
339             'contextid' => $user->ctxid,
340             'component' => 'user',
341             'filearea'  => 'private',
342             'itemid'    => 0,
343             'filepath'  => '/testsubdir/',
344             'filename'  => 'test-get-area-tree.txt',
345         );
347         $directoryfile = $fs->create_file_from_string($filerecord, 'Test content');
348         $this->assertInstanceOf('stored_file', $directoryfile);
350         $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0);
352         // At the top level there should still be 3 files.
353         $this->assertCount(3, $areatree['files']);
355         // There should now be a subdirectory.
356         $this->assertCount(1, $areatree['subdirs']);
358         // The test subdir is named testsubdir.
359         $subdir = $areatree['subdirs']['testsubdir'];
360         $this->assertNotEmpty($subdir);
361         // It should have one file we added.
362         $this->assertCount(1, $subdir['files']);
363         // And no subdirs itself.
364         $this->assertCount(0, $subdir['subdirs']);
366         // Verify the file is the one we added.
367         $subdirfile = reset($subdir['files']);
368         $this->assertInstanceOf('stored_file', $subdirfile);
369         $this->assertEquals($filerecord['filename'], $subdirfile->get_filename());
370     }
372     public function test_get_file_by_id() {
373         $user = $this->setup_three_private_files();
374         $fs = get_file_storage();
376         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
378         // Test get_file_by_id.
379         $filebyid = reset($areafiles);
380         $shouldbesame = $fs->get_file_by_id($filebyid->get_id());
381         $this->assertEquals($filebyid->get_contenthash(), $shouldbesame->get_contenthash());
383         // Test an id which doens't exist.
384         $doesntexist = $fs->get_file_by_id(99999);
385         $this->assertFalse($doesntexist);
386     }
388     public function test_get_file_by_hash() {
389         $user = $this->setup_three_private_files();
390         $fs = get_file_storage();
392         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
393         // Test get_file_by_hash
394         $filebyhash = reset($areafiles);
395         $shouldbesame = $fs->get_file_by_hash($filebyhash->get_pathnamehash());
396         $this->assertEquals($filebyhash->get_id(), $shouldbesame->get_id());
398         // Test an hash which doens't exist.
399         $doesntexist = $fs->get_file_by_hash('DOESNTEXIST');
400         $this->assertFalse($doesntexist);
401     }
403     public function test_get_external_files() {
404         $user = $this->setup_three_private_files();
405         $fs = get_file_storage();
407         $repos = repository::get_instances(array('type'=>'user'));
408         $userrepository = reset($repos);
409         $this->assertInstanceOf('repository', $userrepository);
411         // no aliases yet
412         $exfiles = $fs->get_external_files($userrepository->id, 'id');
413         $this->assertEquals(array(), $exfiles);
415         // create three aliases linking the same original: $aliasfile1 and $aliasfile2 are
416         // created via create_file_from_reference(), $aliasfile3 created from $aliasfile2
417         $originalfile = null;
418         foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
419             if (!$areafile->is_directory()) {
420                 $originalfile = $areafile;
421                 break;
422             }
423         }
424         $this->assertInstanceOf('stored_file', $originalfile);
425         $originalrecord = array(
426             'contextid' => $originalfile->get_contextid(),
427             'component' => $originalfile->get_component(),
428             'filearea'  => $originalfile->get_filearea(),
429             'itemid'    => $originalfile->get_itemid(),
430             'filepath'  => $originalfile->get_filepath(),
431             'filename'  => $originalfile->get_filename(),
432         );
434         $aliasrecord = $this->generate_file_record();
435         $aliasrecord->filepath = '/foo/';
436         $aliasrecord->filename = 'one.txt';
438         $ref = $fs->pack_reference($originalrecord);
439         $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref);
441         $aliasrecord->filepath = '/bar/';
442         $aliasrecord->filename = 'uno.txt';
443         // change the order of the items in the array to make sure that it does not matter
444         ksort($originalrecord);
445         $ref = $fs->pack_reference($originalrecord);
446         $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref);
448         $aliasrecord->filepath = '/bar/';
449         $aliasrecord->filename = 'jedna.txt';
450         $aliasfile3 = $fs->create_file_from_storedfile($aliasrecord, $aliasfile2);
452         // make sure we get three aliases now
453         $exfiles = $fs->get_external_files($userrepository->id, 'id');
454         $this->assertEquals(3, count($exfiles));
455         foreach ($exfiles as $exfile) {
456             $this->assertTrue($exfile->is_external_file());
457         }
458         // make sure they all link the same original (thence that all are linked with the same
459         // record in {files_reference})
460         $this->assertEquals($aliasfile1->get_referencefileid(), $aliasfile2->get_referencefileid());
461         $this->assertEquals($aliasfile3->get_referencefileid(), $aliasfile2->get_referencefileid());
462     }
464     public function test_create_directory_contextid_negative() {
465         $fs = get_file_storage();
467         $this->setExpectedException('file_exception');
468         $fs->create_directory(-1, 'core', 'unittest', 0, '/');
469     }
471     public function test_create_directory_contextid_invalid() {
472         $fs = get_file_storage();
474         $this->setExpectedException('file_exception');
475         $fs->create_directory('not an int', 'core', 'unittest', 0, '/');
476     }
478     public function test_create_directory_component_invalid() {
479         $fs = get_file_storage();
480         $syscontext = context_system::instance();
482         $this->setExpectedException('file_exception');
483         $fs->create_directory($syscontext->id, 'bad/component', 'unittest', 0, '/');
484     }
486     public function test_create_directory_filearea_invalid() {
487         $fs = get_file_storage();
488         $syscontext = context_system::instance();
490         $this->setExpectedException('file_exception');
491         $fs->create_directory($syscontext->id, 'core', 'bad-filearea', 0, '/');
492     }
494     public function test_create_directory_itemid_negative() {
495         $fs = get_file_storage();
496         $syscontext = context_system::instance();
498         $this->setExpectedException('file_exception');
499         $fs->create_directory($syscontext->id, 'core', 'unittest', -1, '/');
500     }
502     public function test_create_directory_itemid_invalid() {
503         $fs = get_file_storage();
504         $syscontext = context_system::instance();
506         $this->setExpectedException('file_exception');
507         $fs->create_directory($syscontext->id, 'core', 'unittest', 'notanint', '/');
508     }
510     public function test_create_directory_filepath_invalid() {
511         $fs = get_file_storage();
512         $syscontext = context_system::instance();
514         $this->setExpectedException('file_exception');
515         $fs->create_directory($syscontext->id, 'core', 'unittest', 0, '/not-with-trailing/or-leading-slash');
516     }
518     public function test_get_directory_files() {
519         $user = $this->setup_three_private_files();
520         $fs = get_file_storage();
522         $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/');
523         $this->assertInstanceOf('stored_file', $dir);
525         // Add a file to the subdir.
526         $filerecord = array(
527             'contextid' => $user->ctxid,
528             'component' => 'user',
529             'filearea'  => 'private',
530             'itemid'    => 0,
531             'filepath'  => '/testsubdir/',
532             'filename'  => 'test-get-area-tree.txt',
533         );
535         $directoryfile = $fs->create_file_from_string($filerecord, 'Test content');
536         $this->assertInstanceOf('stored_file', $directoryfile);
538         // Don't recurse without dirs
539         $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, false, 'id');
540         // 3 files only.
541         $this->assertCount(3, $files);
542         foreach ($files as $key => $file) {
543             $this->assertInstanceOf('stored_file', $file);
544             $this->assertEquals($key, $file->get_pathnamehash());
545         }
547         // Don't recurse with dirs.
548         $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, true, 'id');
549         // 3 files + 1 directory.
550         $this->assertCount(4, $files);
551         foreach ($files as $key => $file) {
552             $this->assertInstanceOf('stored_file', $file);
553             $this->assertEquals($key, $file->get_pathnamehash());
554         }
556         // Recurse with dirs.
557         $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, true, 'id');
558         // 3 files + 1 directory +  1 subdir file.
559         $this->assertCount(5, $files);
560         foreach ($files as $key => $file) {
561             $this->assertInstanceOf('stored_file', $file);
562             $this->assertEquals($key, $file->get_pathnamehash());
563         }
565         // Recurse without dirs.
566         $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, false, 'id');
567         // 3 files +  1 subdir file.
568         $this->assertCount(4, $files);
569         foreach ($files as $key => $file) {
570             $this->assertInstanceOf('stored_file', $file);
571             $this->assertEquals($key, $file->get_pathnamehash());
572         }
573     }
575     public function test_search_references() {
576         $user = $this->setup_three_private_files();
577         $fs = get_file_storage();
578         $repos = repository::get_instances(array('type'=>'user'));
579         $repo = reset($repos);
581         $alias1 = array(
582             'contextid' => $user->ctxid,
583             'component' => 'user',
584             'filearea'  => 'private',
585             'itemid'    => 0,
586             'filepath'  => '/aliases/',
587             'filename'  => 'alias-to-1.txt'
588         );
590         $alias2 = array(
591             'contextid' => $user->ctxid,
592             'component' => 'user',
593             'filearea'  => 'private',
594             'itemid'    => 0,
595             'filepath'  => '/aliases/',
596             'filename'  => 'another-alias-to-1.txt'
597         );
599         $reference = file_storage::pack_reference(array(
600             'contextid' => $user->ctxid,
601             'component' => 'user',
602             'filearea'  => 'private',
603             'itemid'    => 0,
604             'filepath'  => '/',
605             'filename'  => '1.txt'
606         ));
608         // There are no aliases now.
609         $result = $fs->search_references($reference);
610         $this->assertEquals(array(), $result);
612         $result = $fs->search_references_count($reference);
613         $this->assertSame($result, 0);
615         // Create two aliases and make sure they are returned.
616         $fs->create_file_from_reference($alias1, $repo->id, $reference);
617         $fs->create_file_from_reference($alias2, $repo->id, $reference);
619         $result = $fs->search_references($reference);
620         $this->assertTrue(is_array($result));
621         $this->assertEquals(count($result), 2);
622         foreach ($result as $alias) {
623             $this->assertTrue($alias instanceof stored_file);
624         }
626         $result = $fs->search_references_count($reference);
627         $this->assertSame($result, 2);
629         // The method can't be used for references to files outside the filepool
630         $exceptionthrown = false;
631         try {
632             $fs->search_references('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg');
633         } catch (file_reference_exception $e) {
634             $exceptionthrown = true;
635         }
636         $this->assertTrue($exceptionthrown);
638         $exceptionthrown = false;
639         try {
640             $fs->search_references_count('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg');
641         } catch (file_reference_exception $e) {
642             $exceptionthrown = true;
643         }
644         $this->assertTrue($exceptionthrown);
645     }
647     public function test_delete_area_files() {
648         $user = $this->setup_three_private_files();
649         $fs = get_file_storage();
651         // Get area files with default options.
652         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
653         // Should be the two files we added plus the folder.
654         $this->assertEquals(4, count($areafiles));
655         $fs->delete_area_files($user->ctxid, 'user', 'private');
657         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
658         // Should be the two files we added plus the folder.
659         $this->assertEquals(0, count($areafiles));
660     }
662     public function test_delete_area_files_itemid() {
663         $user = $this->setup_three_private_files();
664         $fs = get_file_storage();
666         // Get area files with default options.
667         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
668         // Should be the two files we added plus the folder.
669         $this->assertEquals(4, count($areafiles));
670         $fs->delete_area_files($user->ctxid, 'user', 'private', 9999);
672         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
673         $this->assertEquals(4, count($areafiles));
674     }
676     public function test_delete_area_files_select() {
677         $user = $this->setup_three_private_files();
678         $fs = get_file_storage();
680         // Get area files with default options.
681         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
682         // Should be the two files we added plus the folder.
683         $this->assertEquals(4, count($areafiles));
684         $fs->delete_area_files_select($user->ctxid, 'user', 'private', '!= :notitemid', array('notitemid'=>9999));
686         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
687         // Should be the two files we added plus the folder.
688         $this->assertEquals(0, count($areafiles));
689     }
691     public function test_delete_component_files() {
692         $user = $this->setup_three_private_files();
693         $fs = get_file_storage();
695         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
696         $this->assertEquals(4, count($areafiles));
697         $fs->delete_component_files('user');
698         $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
699         $this->assertEquals(0, count($areafiles));
700     }
702     public function test_create_file_from_url() {
703         $this->resetAfterTest(true);
705         $syscontext = context_system::instance();
706         $filerecord = array(
707             'contextid' => $syscontext->id,
708             'component' => 'core',
709             'filearea'  => 'unittest',
710             'itemid'    => 0,
711             'filepath'  => '/downloadtest/',
712         );
713         $url = 'http://download.moodle.org/unittest/test.html';
715         $fs = get_file_storage();
717         // Test creating file without filename.
718         $file1 = $fs->create_file_from_url($filerecord, $url);
719         $this->assertInstanceOf('stored_file', $file1);
721         // Set filename.
722         $filerecord['filename'] = 'unit-test-filename.html';
723         $file2 = $fs->create_file_from_url($filerecord, $url);
724         $this->assertInstanceOf('stored_file', $file2);
726         // Use temporary file.
727         $filerecord['filename'] = 'unit-test-with-temp-file.html';
728         $file3 = $fs->create_file_from_url($filerecord, $url, null, true);
729         $file3 = $this->assertInstanceOf('stored_file', $file3);
730     }
732     public function test_cron() {
733         $this->resetAfterTest(true);
735         // Note: this is only testing DB compatibility atm, rather than
736         // that work is done.
737         $fs = get_file_storage();
739         $this->expectOutputRegex('/Cleaning up/');
740         $fs->cron();
741     }
743     public function test_is_area_empty() {
744         $user = $this->setup_three_private_files();
745         $fs = get_file_storage();
747         $this->assertFalse($fs->is_area_empty($user->ctxid, 'user', 'private'));
749         // File area with madeup itemid should be empty.
750         $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999));
751         // Still empty with dirs included.
752         $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999, false));
753     }
755     public function test_move_area_files_to_new_context() {
756         $this->resetAfterTest(true);
758         // Create a course with a page resource.
759         $course = $this->getDataGenerator()->create_course();
760         $page1 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
761         $page1context = context_module::instance($page1->cmid);
763         // Add a file to the page.
764         $fs = get_file_storage();
765         $filerecord = array(
766             'contextid' => $page1context->id,
767             'component' => 'mod_page',
768             'filearea'  => 'content',
769             'itemid'    => 0,
770             'filepath'  => '/',
771             'filename'  => 'unit-test-file.txt',
772         );
774         $originalfile = $fs->create_file_from_string($filerecord, 'Test content');
775         $this->assertInstanceOf('stored_file', $originalfile);
777         $pagefiles = $fs->get_area_files($page1context->id, 'mod_page', 'content', 0, 'sortorder', false);
778         // Should be one file in filearea.
779         $this->assertFalse($fs->is_area_empty($page1context->id, 'mod_page', 'content'));
781         // Create a new page.
782         $page2 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
783         $page2context = context_module::instance($page2->cmid);
785         // Newly created page area is empty.
786         $this->assertTrue($fs->is_area_empty($page2context->id, 'mod_page', 'content'));
788         // Move the files.
789         $fs->move_area_files_to_new_context($page1context->id, $page2context->id, 'mod_page', 'content');
791         // Page2 filearea should no longer be empty.
792         $this->assertFalse($fs->is_area_empty($page2context->id, 'mod_page', 'content'));
794         // Page1 filearea should now be empty.
795         $this->assertTrue($fs->is_area_empty($page1context->id, 'mod_page', 'content'));
797         $page2files = $fs->get_area_files($page2context->id, 'mod_page', 'content', 0, 'sortorder', false);
798         $movedfile = reset($page2files);
800         // The two files should have the same content hash.
801         $this->assertEquals($movedfile->get_contenthash(), $originalfile->get_contenthash());
802     }
804     public function test_convert_image() {
805         global $CFG;
807         $this->resetAfterTest(false);
809         $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
810         $syscontext = context_system::instance();
811         $filerecord = array(
812             'contextid' => $syscontext->id,
813             'component' => 'core',
814             'filearea'  => 'unittest',
815             'itemid'    => 0,
816             'filepath'  => '/images/',
817             'filename'  => 'testimage.jpg',
818         );
820         $fs = get_file_storage();
821         $original = $fs->create_file_from_pathname($filerecord, $filepath);
823         $filerecord['filename'] = 'testimage-converted-10x10.jpg';
824         $converted = $fs->convert_image($filerecord, $original, 10, 10, true, 100);
825         $this->assertInstanceOf('stored_file', $converted);
827         $filerecord['filename'] = 'testimage-convereted-nosize.jpg';
828         $converted = $fs->convert_image($filerecord, $original);
829         $this->assertInstanceOf('stored_file', $converted);
830     }
832     private function generate_file_record() {
833         $syscontext = context_system::instance();
834         $filerecord = new stdClass();
835         $filerecord->contextid = $syscontext->id;
836         $filerecord->component = 'core';
837         $filerecord->filearea = 'phpunit';
838         $filerecord->filepath = '/';
839         $filerecord->filename = 'testfile.txt';
840         $filerecord->itemid = 0;
842         return $filerecord;
843     }
845     public function test_create_file_from_storedfile_file_invalid() {
846         $this->resetAfterTest(true);
848         $filerecord = $this->generate_file_record();
850         $fs = get_file_storage();
851         $this->setExpectedException('file_exception');
852         // Create a file from a file id which doesn't exist.
853         $fs->create_file_from_storedfile($filerecord,  9999);
854     }
856     public function test_create_file_from_storedfile_contextid_invalid() {
857         $this->resetAfterTest(true);
859         $filerecord = $this->generate_file_record();
861         $fs = get_file_storage();
862         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
863         $this->assertInstanceOf('stored_file', $file1);
865         $filerecord->filename = 'invalid.txt';
866         $filerecord->contextid = 'invalid';
868         $this->setExpectedException('file_exception', 'Invalid contextid');
869         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
870     }
872     public function test_create_file_from_storedfile_component_invalid() {
873         $this->resetAfterTest(true);
875         $filerecord = $this->generate_file_record();
877         $fs = get_file_storage();
878         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
879         $this->assertInstanceOf('stored_file', $file1);
881         $filerecord->filename = 'invalid.txt';
882         $filerecord->component = 'bad/component';
884         $this->setExpectedException('file_exception', 'Invalid component');
885         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
886     }
888     public function test_create_file_from_storedfile_filearea_invalid() {
889         $this->resetAfterTest(true);
891         $filerecord = $this->generate_file_record();
893         $fs = get_file_storage();
894         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
895         $this->assertInstanceOf('stored_file', $file1);
897         $filerecord->filename = 'invalid.txt';
898         $filerecord->filearea = 'bad-filearea';
900         $this->setExpectedException('file_exception', 'Invalid filearea');
901         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
902     }
904     public function test_create_file_from_storedfile_itemid_invalid() {
905         $this->resetAfterTest(true);
907         $filerecord = $this->generate_file_record();
909         $fs = get_file_storage();
910         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
911         $this->assertInstanceOf('stored_file', $file1);
913         $filerecord->filename = 'invalid.txt';
914         $filerecord->itemid = 'bad-itemid';
916         $this->setExpectedException('file_exception', 'Invalid itemid');
917         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
918     }
920     public function test_create_file_from_storedfile_filepath_invalid() {
921         $this->resetAfterTest(true);
923         $filerecord = $this->generate_file_record();
925         $fs = get_file_storage();
926         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
927         $this->assertInstanceOf('stored_file', $file1);
929         $filerecord->filename = 'invalid.txt';
930         $filerecord->filepath = 'a-/bad/-filepath';
932         $this->setExpectedException('file_exception', 'Invalid file path');
933         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
934     }
936     public function test_create_file_from_storedfile_filename_invalid() {
937         $this->resetAfterTest(true);
939         $filerecord = $this->generate_file_record();
941         $fs = get_file_storage();
942         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
943         $this->assertInstanceOf('stored_file', $file1);
945         $filerecord->filename = '';
947         $this->setExpectedException('file_exception', 'Invalid file name');
948         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
949     }
951     public function test_create_file_from_storedfile_timecreated_invalid() {
952         $this->resetAfterTest(true);
954         $filerecord = $this->generate_file_record();
956         $fs = get_file_storage();
957         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
958         $this->assertInstanceOf('stored_file', $file1);
960         $filerecord->filename = 'invalid.txt';
961         $filerecord->timecreated = 'today';
963         $this->setExpectedException('file_exception', 'Invalid file timecreated');
964         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
965     }
967     public function test_create_file_from_storedfile_timemodified_invalid() {
968         $this->resetAfterTest(true);
970         $filerecord = $this->generate_file_record();
972         $fs = get_file_storage();
973         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
974         $this->assertInstanceOf('stored_file', $file1);
976         $filerecord->filename = 'invalid.txt';
977         $filerecord->timemodified  = 'today';
979         $this->setExpectedException('file_exception', 'Invalid file timemodified');
980         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
981     }
983     public function test_create_file_from_storedfile_duplicate() {
984         $this->resetAfterTest(true);
986         $filerecord = $this->generate_file_record();
988         $fs = get_file_storage();
989         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
990         $this->assertInstanceOf('stored_file', $file1);
992         // Creating a file validating unique constraint.
993         $this->setExpectedException('stored_file_creation_exception');
994         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
995     }
997     public function test_create_file_from_storedfile() {
998         $this->resetAfterTest(true);
1000         $syscontext = context_system::instance();
1002         $filerecord = new stdClass();
1003         $filerecord->contextid = $syscontext->id;
1004         $filerecord->component = 'core';
1005         $filerecord->filearea = 'phpunit';
1006         $filerecord->filepath = '/';
1007         $filerecord->filename = 'testfile.txt';
1008         $filerecord->itemid = 0;
1010         $fs = get_file_storage();
1012         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1013         $this->assertInstanceOf('stored_file', $file1);
1015         $filerecord->filename = 'test-create-file-from-storedfile.txt';
1016         $file2 = $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1017         $this->assertInstanceOf('stored_file', $file2);
1019         // These will be normalised to current time..
1020         $filerecord->timecreated = -100;
1021         $filerecord->timemodified= -100;
1022         $filerecord->filename = 'test-create-file-from-storedfile-bad-dates.txt';
1024         $file3 = $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1025         $this->assertInstanceOf('stored_file', $file3);
1027         $this->assertNotEquals($file3->get_timemodified(), $filerecord->timemodified);
1028         $this->assertNotEquals($file3->get_timecreated(), $filerecord->timecreated);
1029     }
1031     public function test_create_file_from_string_contextid_invalid() {
1032         $this->resetAfterTest(true);
1034         $filerecord = $this->generate_file_record();
1035         $fs = get_file_storage();
1037         $filerecord->contextid = 'invalid';
1039         $this->setExpectedException('file_exception', 'Invalid contextid');
1040         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1041     }
1043     public function test_create_file_from_string_component_invalid() {
1044         $this->resetAfterTest(true);
1046         $filerecord = $this->generate_file_record();
1047         $fs = get_file_storage();
1049         $filerecord->component = 'bad/component';
1051         $this->setExpectedException('file_exception', 'Invalid component');
1052         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1053     }
1055     public function test_create_file_from_string_filearea_invalid() {
1056         $this->resetAfterTest(true);
1058         $filerecord = $this->generate_file_record();
1059         $fs = get_file_storage();
1061         $filerecord->filearea = 'bad-filearea';
1063         $this->setExpectedException('file_exception', 'Invalid filearea');
1064         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1065     }
1067     public function test_create_file_from_string_itemid_invalid() {
1068         $this->resetAfterTest(true);
1070         $filerecord = $this->generate_file_record();
1071         $fs = get_file_storage();
1073         $filerecord->itemid = 'bad-itemid';
1075         $this->setExpectedException('file_exception', 'Invalid itemid');
1076         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1077     }
1079     public function test_create_file_from_string_filepath_invalid() {
1080         $this->resetAfterTest(true);
1082         $filerecord = $this->generate_file_record();
1083         $fs = get_file_storage();
1085         $filerecord->filepath = 'a-/bad/-filepath';
1087         $this->setExpectedException('file_exception', 'Invalid file path');
1088         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1089     }
1091     public function test_create_file_from_string_filename_invalid() {
1092         $this->resetAfterTest(true);
1094         $filerecord = $this->generate_file_record();
1095         $fs = get_file_storage();
1097         $filerecord->filename = '';
1099         $this->setExpectedException('file_exception', 'Invalid file name');
1100         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1101     }
1103     public function test_create_file_from_string_timecreated_invalid() {
1104         $this->resetAfterTest(true);
1106         $filerecord = $this->generate_file_record();
1107         $fs = get_file_storage();
1109         $filerecord->timecreated = 'today';
1111         $this->setExpectedException('file_exception', 'Invalid file timecreated');
1112         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1113     }
1115     public function test_create_file_from_string_timemodified_invalid() {
1116         $this->resetAfterTest(true);
1118         $filerecord = $this->generate_file_record();
1119         $fs = get_file_storage();
1121         $filerecord->timemodified  = 'today';
1123         $this->setExpectedException('file_exception', 'Invalid file timemodified');
1124         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1125     }
1127     public function test_create_file_from_string_duplicate() {
1128         $this->resetAfterTest(true);
1130         $filerecord = $this->generate_file_record();
1131         $fs = get_file_storage();
1133         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1135         // Creating a file validating unique constraint.
1136         $this->setExpectedException('stored_file_creation_exception');
1137         $file2 = $fs->create_file_from_string($filerecord, 'text contents');
1138     }
1140     public function test_create_file_from_pathname_contextid_invalid() {
1141         global $CFG;
1142         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1144         $this->resetAfterTest(true);
1146         $filerecord = $this->generate_file_record();
1147         $fs = get_file_storage();
1149         $filerecord->contextid = 'invalid';
1151         $this->setExpectedException('file_exception', 'Invalid contextid');
1152         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1153     }
1155     public function test_create_file_from_pathname_component_invalid() {
1156         global $CFG;
1157         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1159         $this->resetAfterTest(true);
1161         $filerecord = $this->generate_file_record();
1162         $fs = get_file_storage();
1164         $filerecord->component = 'bad/component';
1166         $this->setExpectedException('file_exception', 'Invalid component');
1167         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1168     }
1170     public function test_create_file_from_pathname_filearea_invalid() {
1171         global $CFG;
1172         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1174         $this->resetAfterTest(true);
1176         $filerecord = $this->generate_file_record();
1177         $fs = get_file_storage();
1179         $filerecord->filearea = 'bad-filearea';
1181         $this->setExpectedException('file_exception', 'Invalid filearea');
1182         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1183     }
1185     public function test_create_file_from_pathname_itemid_invalid() {
1186         global $CFG;
1187         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1189         $this->resetAfterTest(true);
1191         $filerecord = $this->generate_file_record();
1192         $fs = get_file_storage();
1194         $filerecord->itemid = 'bad-itemid';
1196         $this->setExpectedException('file_exception', 'Invalid itemid');
1197         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1198     }
1200     public function test_create_file_from_pathname_filepath_invalid() {
1201         global $CFG;
1202         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1204         $this->resetAfterTest(true);
1206         $filerecord = $this->generate_file_record();
1207         $fs = get_file_storage();
1209         $filerecord->filepath = 'a-/bad/-filepath';
1211         $this->setExpectedException('file_exception', 'Invalid file path');
1212         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1213     }
1215     public function test_create_file_from_pathname_filename_invalid() {
1216         global $CFG;
1217         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1219         $this->resetAfterTest(true);
1221         $filerecord = $this->generate_file_record();
1222         $fs = get_file_storage();
1224         $filerecord->filename = '';
1226         $this->setExpectedException('file_exception', 'Invalid file name');
1227         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1228     }
1230     public function test_create_file_from_pathname_timecreated_invalid() {
1231         global $CFG;
1232         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1234         $this->resetAfterTest(true);
1236         $filerecord = $this->generate_file_record();
1237         $fs = get_file_storage();
1239         $filerecord->timecreated = 'today';
1241         $this->setExpectedException('file_exception', 'Invalid file timecreated');
1242         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1243     }
1245     public function test_create_file_from_pathname_timemodified_invalid() {
1246         global $CFG;
1247         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1249         $this->resetAfterTest(true);
1251         $filerecord = $this->generate_file_record();
1252         $fs = get_file_storage();
1254         $filerecord->timemodified  = 'today';
1256         $this->setExpectedException('file_exception', 'Invalid file timemodified');
1257         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1258     }
1260     public function test_create_file_from_pathname_duplicate_file() {
1261         global $CFG;
1262         $this->resetAfterTest(true);
1264         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1266         $filerecord = $this->generate_file_record();
1267         $fs = get_file_storage();
1269         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1270         $this->assertInstanceOf('stored_file', $file1);
1272         // Creating a file validating unique constraint.
1273         $this->setExpectedException('stored_file_creation_exception');
1274         $file2 = $fs->create_file_from_pathname($filerecord, $path);
1275     }
1277     /**
1278      * Calling stored_file::delete_reference() on a non-reference file throws coding_exception
1279      */
1280     public function test_delete_reference_on_nonreference() {
1282         $this->resetAfterTest(true);
1283         $user = $this->setup_three_private_files();
1284         $fs = get_file_storage();
1285         $repos = repository::get_instances(array('type'=>'user'));
1286         $repo = reset($repos);
1288         $file = null;
1289         foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
1290             if (!$areafile->is_directory()) {
1291                 $file = $areafile;
1292                 break;
1293             }
1294         }
1295         $this->assertInstanceOf('stored_file', $file);
1296         $this->assertFalse($file->is_external_file());
1298         $this->setExpectedException('coding_exception');
1299         $file->delete_reference();
1300     }
1302     /**
1303      * Calling stored_file::delete_reference() on a reference file does not affect other
1304      * symlinks to the same original
1305      */
1306     public function test_delete_reference_one_symlink_does_not_rule_them_all() {
1308         $this->resetAfterTest(true);
1309         $user = $this->setup_three_private_files();
1310         $fs = get_file_storage();
1311         $repos = repository::get_instances(array('type'=>'user'));
1312         $repo = reset($repos);
1314         // create two aliases linking the same original
1316         $originalfile = null;
1317         foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
1318             if (!$areafile->is_directory()) {
1319                 $originalfile = $areafile;
1320                 break;
1321             }
1322         }
1323         $this->assertInstanceOf('stored_file', $originalfile);
1325         // calling delete_reference() on a non-reference file
1327         $originalrecord = array(
1328             'contextid' => $originalfile->get_contextid(),
1329             'component' => $originalfile->get_component(),
1330             'filearea'  => $originalfile->get_filearea(),
1331             'itemid'    => $originalfile->get_itemid(),
1332             'filepath'  => $originalfile->get_filepath(),
1333             'filename'  => $originalfile->get_filename(),
1334         );
1336         $aliasrecord = $this->generate_file_record();
1337         $aliasrecord->filepath = '/A/';
1338         $aliasrecord->filename = 'symlink.txt';
1340         $ref = $fs->pack_reference($originalrecord);
1341         $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1343         $aliasrecord->filepath = '/B/';
1344         $aliasrecord->filename = 'symlink.txt';
1345         $ref = $fs->pack_reference($originalrecord);
1346         $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1348         // refetch A/symlink.txt
1349         $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1350             $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt');
1351         $this->assertTrue($symlink1->is_external_file());
1353         // unlink the A/symlink.txt
1354         $symlink1->delete_reference();
1355         $this->assertFalse($symlink1->is_external_file());
1357         // make sure that B/symlink.txt has not been affected
1358         $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1359             $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt');
1360         $this->assertTrue($symlink2->is_external_file());
1361     }
1363     public function test_get_unused_filename() {
1364         global $USER;
1365         $this->resetAfterTest(true);
1367         $fs = get_file_storage();
1368         $this->setAdminUser();
1369         $contextid = context_user::instance($USER->id)->id;
1370         $component = 'user';
1371         $filearea = 'private';
1372         $itemid = 0;
1373         $filepath = '/';
1375         // Create some private files.
1376         $file = new stdClass;
1377         $file->contextid = $contextid;
1378         $file->component = 'user';
1379         $file->filearea  = 'private';
1380         $file->itemid    = 0;
1381         $file->filepath  = '/';
1382         $file->source    = 'test';
1383         $filenames = array('foo.txt', 'foo (1).txt', 'foo (20).txt', 'foo (999)', 'bar.jpg', 'What (a cool file).jpg',
1384                 'Hurray! (1).php', 'Hurray! (2).php', 'Hurray! (9a).php', 'Hurray! (abc).php');
1385         foreach ($filenames as $key => $filename) {
1386             $file->filename = $filename;
1387             $userfile = $fs->create_file_from_string($file, "file $key $filename content");
1388             $this->assertInstanceOf('stored_file', $userfile);
1389         }
1391         // Asserting new generated names.
1392         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'unused.txt');
1393         $this->assertEquals('unused.txt', $newfilename);
1394         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo.txt');
1395         $this->assertEquals('foo (21).txt', $newfilename);
1396         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (1).txt');
1397         $this->assertEquals('foo (21).txt', $newfilename);
1398         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (2).txt');
1399         $this->assertEquals('foo (2).txt', $newfilename);
1400         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (20).txt');
1401         $this->assertEquals('foo (21).txt', $newfilename);
1402         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo');
1403         $this->assertEquals('foo', $newfilename);
1404         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (123)');
1405         $this->assertEquals('foo (123)', $newfilename);
1406         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (999)');
1407         $this->assertEquals('foo (1000)', $newfilename);
1408         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.png');
1409         $this->assertEquals('bar.png', $newfilename);
1410         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (12).png');
1411         $this->assertEquals('bar (12).png', $newfilename);
1412         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.jpg');
1413         $this->assertEquals('bar (1).jpg', $newfilename);
1414         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (1).jpg');
1415         $this->assertEquals('bar (1).jpg', $newfilename);
1416         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'What (a cool file).jpg');
1417         $this->assertEquals('What (a cool file) (1).jpg', $newfilename);
1418         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'Hurray! (1).php');
1419         $this->assertEquals('Hurray! (3).php', $newfilename);
1421         $this->setExpectedException('coding_exception');
1422         $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, '');
1423     }