38e0eb1f59fd41aa5f6967e9f2d7ce2123bfb7a9
[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_create_file_from_url() {
692         $this->resetAfterTest(true);
694         $syscontext = context_system::instance();
695         $filerecord = array(
696             'contextid' => $syscontext->id,
697             'component' => 'core',
698             'filearea'  => 'unittest',
699             'itemid'    => 0,
700             'filepath'  => '/downloadtest/',
701         );
702         $url = 'http://download.moodle.org/unittest/test.html';
704         $fs = get_file_storage();
706         // Test creating file without filename.
707         $file1 = $fs->create_file_from_url($filerecord, $url);
708         $this->assertInstanceOf('stored_file', $file1);
710         // Set filename.
711         $filerecord['filename'] = 'unit-test-filename.html';
712         $file2 = $fs->create_file_from_url($filerecord, $url);
713         $this->assertInstanceOf('stored_file', $file2);
715         // Use temporary file.
716         $filerecord['filename'] = 'unit-test-with-temp-file.html';
717         $file3 = $fs->create_file_from_url($filerecord, $url, null, true);
718         $file3 = $this->assertInstanceOf('stored_file', $file3);
719     }
721     public function test_cron() {
722         $this->resetAfterTest(true);
724         // Note: this is only testing DB compatibility atm, rather than
725         // that work is done.
726         $fs = get_file_storage();
728         $this->expectOutputRegex('/Cleaning up/');
729         $fs->cron();
730     }
732     public function test_is_area_empty() {
733         $user = $this->setup_three_private_files();
734         $fs = get_file_storage();
736         $this->assertFalse($fs->is_area_empty($user->ctxid, 'user', 'private'));
738         // File area with madeup itemid should be empty.
739         $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999));
740         // Still empty with dirs included.
741         $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999, false));
742     }
744     public function test_move_area_files_to_new_context() {
745         $this->resetAfterTest(true);
747         // Create a course with a page resource.
748         $course = $this->getDataGenerator()->create_course();
749         $page1 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
750         $page1context = context_module::instance($page1->cmid);
752         // Add a file to the page.
753         $fs = get_file_storage();
754         $filerecord = array(
755             'contextid' => $page1context->id,
756             'component' => 'mod_page',
757             'filearea'  => 'content',
758             'itemid'    => 0,
759             'filepath'  => '/',
760             'filename'  => 'unit-test-file.txt',
761         );
763         $originalfile = $fs->create_file_from_string($filerecord, 'Test content');
764         $this->assertInstanceOf('stored_file', $originalfile);
766         $pagefiles = $fs->get_area_files($page1context->id, 'mod_page', 'content', 0, 'sortorder', false);
767         // Should be one file in filearea.
768         $this->assertFalse($fs->is_area_empty($page1context->id, 'mod_page', 'content'));
770         // Create a new page.
771         $page2 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
772         $page2context = context_module::instance($page2->cmid);
774         // Newly created page area is empty.
775         $this->assertTrue($fs->is_area_empty($page2context->id, 'mod_page', 'content'));
777         // Move the files.
778         $fs->move_area_files_to_new_context($page1context->id, $page2context->id, 'mod_page', 'content');
780         // Page2 filearea should no longer be empty.
781         $this->assertFalse($fs->is_area_empty($page2context->id, 'mod_page', 'content'));
783         // Page1 filearea should now be empty.
784         $this->assertTrue($fs->is_area_empty($page1context->id, 'mod_page', 'content'));
786         $page2files = $fs->get_area_files($page2context->id, 'mod_page', 'content', 0, 'sortorder', false);
787         $movedfile = reset($page2files);
789         // The two files should have the same content hash.
790         $this->assertEquals($movedfile->get_contenthash(), $originalfile->get_contenthash());
791     }
793     public function test_convert_image() {
794         global $CFG;
796         $this->resetAfterTest(false);
798         $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
799         $syscontext = context_system::instance();
800         $filerecord = array(
801             'contextid' => $syscontext->id,
802             'component' => 'core',
803             'filearea'  => 'unittest',
804             'itemid'    => 0,
805             'filepath'  => '/images/',
806             'filename'  => 'testimage.jpg',
807         );
809         $fs = get_file_storage();
810         $original = $fs->create_file_from_pathname($filerecord, $filepath);
812         $filerecord['filename'] = 'testimage-converted-10x10.jpg';
813         $converted = $fs->convert_image($filerecord, $original, 10, 10, true, 100);
814         $this->assertInstanceOf('stored_file', $converted);
816         $filerecord['filename'] = 'testimage-convereted-nosize.jpg';
817         $converted = $fs->convert_image($filerecord, $original);
818         $this->assertInstanceOf('stored_file', $converted);
819     }
821     private function generate_file_record() {
822         $syscontext = context_system::instance();
823         $filerecord = new stdClass();
824         $filerecord->contextid = $syscontext->id;
825         $filerecord->component = 'core';
826         $filerecord->filearea = 'phpunit';
827         $filerecord->filepath = '/';
828         $filerecord->filename = 'testfile.txt';
829         $filerecord->itemid = 0;
831         return $filerecord;
832     }
834     public function test_create_file_from_storedfile_file_invalid() {
835         $this->resetAfterTest(true);
837         $filerecord = $this->generate_file_record();
839         $fs = get_file_storage();
840         $this->setExpectedException('file_exception');
841         // Create a file from a file id which doesn't exist.
842         $fs->create_file_from_storedfile($filerecord,  9999);
843     }
845     public function test_create_file_from_storedfile_contextid_invalid() {
846         $this->resetAfterTest(true);
848         $filerecord = $this->generate_file_record();
850         $fs = get_file_storage();
851         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
852         $this->assertInstanceOf('stored_file', $file1);
854         $filerecord->filename = 'invalid.txt';
855         $filerecord->contextid = 'invalid';
857         $this->setExpectedException('file_exception', 'Invalid contextid');
858         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
859     }
861     public function test_create_file_from_storedfile_component_invalid() {
862         $this->resetAfterTest(true);
864         $filerecord = $this->generate_file_record();
866         $fs = get_file_storage();
867         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
868         $this->assertInstanceOf('stored_file', $file1);
870         $filerecord->filename = 'invalid.txt';
871         $filerecord->component = 'bad/component';
873         $this->setExpectedException('file_exception', 'Invalid component');
874         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
875     }
877     public function test_create_file_from_storedfile_filearea_invalid() {
878         $this->resetAfterTest(true);
880         $filerecord = $this->generate_file_record();
882         $fs = get_file_storage();
883         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
884         $this->assertInstanceOf('stored_file', $file1);
886         $filerecord->filename = 'invalid.txt';
887         $filerecord->filearea = 'bad-filearea';
889         $this->setExpectedException('file_exception', 'Invalid filearea');
890         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
891     }
893     public function test_create_file_from_storedfile_itemid_invalid() {
894         $this->resetAfterTest(true);
896         $filerecord = $this->generate_file_record();
898         $fs = get_file_storage();
899         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
900         $this->assertInstanceOf('stored_file', $file1);
902         $filerecord->filename = 'invalid.txt';
903         $filerecord->itemid = 'bad-itemid';
905         $this->setExpectedException('file_exception', 'Invalid itemid');
906         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
907     }
909     public function test_create_file_from_storedfile_filepath_invalid() {
910         $this->resetAfterTest(true);
912         $filerecord = $this->generate_file_record();
914         $fs = get_file_storage();
915         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
916         $this->assertInstanceOf('stored_file', $file1);
918         $filerecord->filename = 'invalid.txt';
919         $filerecord->filepath = 'a-/bad/-filepath';
921         $this->setExpectedException('file_exception', 'Invalid file path');
922         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
923     }
925     public function test_create_file_from_storedfile_filename_invalid() {
926         $this->resetAfterTest(true);
928         $filerecord = $this->generate_file_record();
930         $fs = get_file_storage();
931         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
932         $this->assertInstanceOf('stored_file', $file1);
934         $filerecord->filename = '';
936         $this->setExpectedException('file_exception', 'Invalid file name');
937         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
938     }
940     public function test_create_file_from_storedfile_timecreated_invalid() {
941         $this->resetAfterTest(true);
943         $filerecord = $this->generate_file_record();
945         $fs = get_file_storage();
946         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
947         $this->assertInstanceOf('stored_file', $file1);
949         $filerecord->filename = 'invalid.txt';
950         $filerecord->timecreated = 'today';
952         $this->setExpectedException('file_exception', 'Invalid file timecreated');
953         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
954     }
956     public function test_create_file_from_storedfile_timemodified_invalid() {
957         $this->resetAfterTest(true);
959         $filerecord = $this->generate_file_record();
961         $fs = get_file_storage();
962         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
963         $this->assertInstanceOf('stored_file', $file1);
965         $filerecord->filename = 'invalid.txt';
966         $filerecord->timemodified  = 'today';
968         $this->setExpectedException('file_exception', 'Invalid file timemodified');
969         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
970     }
972     public function test_create_file_from_storedfile_duplicate() {
973         $this->resetAfterTest(true);
975         $filerecord = $this->generate_file_record();
977         $fs = get_file_storage();
978         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
979         $this->assertInstanceOf('stored_file', $file1);
981         // Creating a file validating unique constraint.
982         $this->setExpectedException('stored_file_creation_exception');
983         $fs->create_file_from_storedfile($filerecord, $file1->get_id());
984     }
986     public function test_create_file_from_storedfile() {
987         $this->resetAfterTest(true);
989         $syscontext = context_system::instance();
991         $filerecord = new stdClass();
992         $filerecord->contextid = $syscontext->id;
993         $filerecord->component = 'core';
994         $filerecord->filearea = 'phpunit';
995         $filerecord->filepath = '/';
996         $filerecord->filename = 'testfile.txt';
997         $filerecord->itemid = 0;
999         $fs = get_file_storage();
1001         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1002         $this->assertInstanceOf('stored_file', $file1);
1004         $filerecord->filename = 'test-create-file-from-storedfile.txt';
1005         $file2 = $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1006         $this->assertInstanceOf('stored_file', $file2);
1008         // These will be normalised to current time..
1009         $filerecord->timecreated = -100;
1010         $filerecord->timemodified= -100;
1011         $filerecord->filename = 'test-create-file-from-storedfile-bad-dates.txt';
1013         $file3 = $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1014         $this->assertInstanceOf('stored_file', $file3);
1016         $this->assertNotEquals($file3->get_timemodified(), $filerecord->timemodified);
1017         $this->assertNotEquals($file3->get_timecreated(), $filerecord->timecreated);
1018     }
1020     public function test_create_file_from_string_contextid_invalid() {
1021         $this->resetAfterTest(true);
1023         $filerecord = $this->generate_file_record();
1024         $fs = get_file_storage();
1026         $filerecord->contextid = 'invalid';
1028         $this->setExpectedException('file_exception', 'Invalid contextid');
1029         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1030     }
1032     public function test_create_file_from_string_component_invalid() {
1033         $this->resetAfterTest(true);
1035         $filerecord = $this->generate_file_record();
1036         $fs = get_file_storage();
1038         $filerecord->component = 'bad/component';
1040         $this->setExpectedException('file_exception', 'Invalid component');
1041         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1042     }
1044     public function test_create_file_from_string_filearea_invalid() {
1045         $this->resetAfterTest(true);
1047         $filerecord = $this->generate_file_record();
1048         $fs = get_file_storage();
1050         $filerecord->filearea = 'bad-filearea';
1052         $this->setExpectedException('file_exception', 'Invalid filearea');
1053         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1054     }
1056     public function test_create_file_from_string_itemid_invalid() {
1057         $this->resetAfterTest(true);
1059         $filerecord = $this->generate_file_record();
1060         $fs = get_file_storage();
1062         $filerecord->itemid = 'bad-itemid';
1064         $this->setExpectedException('file_exception', 'Invalid itemid');
1065         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1066     }
1068     public function test_create_file_from_string_filepath_invalid() {
1069         $this->resetAfterTest(true);
1071         $filerecord = $this->generate_file_record();
1072         $fs = get_file_storage();
1074         $filerecord->filepath = 'a-/bad/-filepath';
1076         $this->setExpectedException('file_exception', 'Invalid file path');
1077         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1078     }
1080     public function test_create_file_from_string_filename_invalid() {
1081         $this->resetAfterTest(true);
1083         $filerecord = $this->generate_file_record();
1084         $fs = get_file_storage();
1086         $filerecord->filename = '';
1088         $this->setExpectedException('file_exception', 'Invalid file name');
1089         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1090     }
1092     public function test_create_file_from_string_timecreated_invalid() {
1093         $this->resetAfterTest(true);
1095         $filerecord = $this->generate_file_record();
1096         $fs = get_file_storage();
1098         $filerecord->timecreated = 'today';
1100         $this->setExpectedException('file_exception', 'Invalid file timecreated');
1101         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1102     }
1104     public function test_create_file_from_string_timemodified_invalid() {
1105         $this->resetAfterTest(true);
1107         $filerecord = $this->generate_file_record();
1108         $fs = get_file_storage();
1110         $filerecord->timemodified  = 'today';
1112         $this->setExpectedException('file_exception', 'Invalid file timemodified');
1113         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1114     }
1116     public function test_create_file_from_string_duplicate() {
1117         $this->resetAfterTest(true);
1119         $filerecord = $this->generate_file_record();
1120         $fs = get_file_storage();
1122         $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1124         // Creating a file validating unique constraint.
1125         $this->setExpectedException('stored_file_creation_exception');
1126         $file2 = $fs->create_file_from_string($filerecord, 'text contents');
1127     }
1129     public function test_create_file_from_pathname_contextid_invalid() {
1130         global $CFG;
1131         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1133         $this->resetAfterTest(true);
1135         $filerecord = $this->generate_file_record();
1136         $fs = get_file_storage();
1138         $filerecord->contextid = 'invalid';
1140         $this->setExpectedException('file_exception', 'Invalid contextid');
1141         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1142     }
1144     public function test_create_file_from_pathname_component_invalid() {
1145         global $CFG;
1146         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1148         $this->resetAfterTest(true);
1150         $filerecord = $this->generate_file_record();
1151         $fs = get_file_storage();
1153         $filerecord->component = 'bad/component';
1155         $this->setExpectedException('file_exception', 'Invalid component');
1156         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1157     }
1159     public function test_create_file_from_pathname_filearea_invalid() {
1160         global $CFG;
1161         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1163         $this->resetAfterTest(true);
1165         $filerecord = $this->generate_file_record();
1166         $fs = get_file_storage();
1168         $filerecord->filearea = 'bad-filearea';
1170         $this->setExpectedException('file_exception', 'Invalid filearea');
1171         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1172     }
1174     public function test_create_file_from_pathname_itemid_invalid() {
1175         global $CFG;
1176         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1178         $this->resetAfterTest(true);
1180         $filerecord = $this->generate_file_record();
1181         $fs = get_file_storage();
1183         $filerecord->itemid = 'bad-itemid';
1185         $this->setExpectedException('file_exception', 'Invalid itemid');
1186         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1187     }
1189     public function test_create_file_from_pathname_filepath_invalid() {
1190         global $CFG;
1191         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1193         $this->resetAfterTest(true);
1195         $filerecord = $this->generate_file_record();
1196         $fs = get_file_storage();
1198         $filerecord->filepath = 'a-/bad/-filepath';
1200         $this->setExpectedException('file_exception', 'Invalid file path');
1201         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1202     }
1204     public function test_create_file_from_pathname_filename_invalid() {
1205         global $CFG;
1206         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1208         $this->resetAfterTest(true);
1210         $filerecord = $this->generate_file_record();
1211         $fs = get_file_storage();
1213         $filerecord->filename = '';
1215         $this->setExpectedException('file_exception', 'Invalid file name');
1216         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1217     }
1219     public function test_create_file_from_pathname_timecreated_invalid() {
1220         global $CFG;
1221         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1223         $this->resetAfterTest(true);
1225         $filerecord = $this->generate_file_record();
1226         $fs = get_file_storage();
1228         $filerecord->timecreated = 'today';
1230         $this->setExpectedException('file_exception', 'Invalid file timecreated');
1231         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1232     }
1234     public function test_create_file_from_pathname_timemodified_invalid() {
1235         global $CFG;
1236         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1238         $this->resetAfterTest(true);
1240         $filerecord = $this->generate_file_record();
1241         $fs = get_file_storage();
1243         $filerecord->timemodified  = 'today';
1245         $this->setExpectedException('file_exception', 'Invalid file timemodified');
1246         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1247     }
1249     public function test_create_file_from_pathname_duplicate_file() {
1250         global $CFG;
1251         $this->resetAfterTest(true);
1253         $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1255         $filerecord = $this->generate_file_record();
1256         $fs = get_file_storage();
1258         $file1 = $fs->create_file_from_pathname($filerecord, $path);
1259         $this->assertInstanceOf('stored_file', $file1);
1261         // Creating a file validating unique constraint.
1262         $this->setExpectedException('stored_file_creation_exception');
1263         $file2 = $fs->create_file_from_pathname($filerecord, $path);
1264     }
1266     /**
1267      * Calling stored_file::delete_reference() on a non-reference file throws coding_exception
1268      */
1269     public function test_delete_reference_on_nonreference() {
1271         $this->resetAfterTest(true);
1272         $user = $this->setup_three_private_files();
1273         $fs = get_file_storage();
1274         $repos = repository::get_instances(array('type'=>'user'));
1275         $repo = reset($repos);
1277         $file = null;
1278         foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
1279             if (!$areafile->is_directory()) {
1280                 $file = $areafile;
1281                 break;
1282             }
1283         }
1284         $this->assertInstanceOf('stored_file', $file);
1285         $this->assertFalse($file->is_external_file());
1287         $this->setExpectedException('coding_exception');
1288         $file->delete_reference();
1289     }
1291     /**
1292      * Calling stored_file::delete_reference() on a reference file does not affect other
1293      * symlinks to the same original
1294      */
1295     public function test_delete_reference_one_symlink_does_not_rule_them_all() {
1297         $this->resetAfterTest(true);
1298         $user = $this->setup_three_private_files();
1299         $fs = get_file_storage();
1300         $repos = repository::get_instances(array('type'=>'user'));
1301         $repo = reset($repos);
1303         // create two aliases linking the same original
1305         $originalfile = null;
1306         foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
1307             if (!$areafile->is_directory()) {
1308                 $originalfile = $areafile;
1309                 break;
1310             }
1311         }
1312         $this->assertInstanceOf('stored_file', $originalfile);
1314         // calling delete_reference() on a non-reference file
1316         $originalrecord = array(
1317             'contextid' => $originalfile->get_contextid(),
1318             'component' => $originalfile->get_component(),
1319             'filearea'  => $originalfile->get_filearea(),
1320             'itemid'    => $originalfile->get_itemid(),
1321             'filepath'  => $originalfile->get_filepath(),
1322             'filename'  => $originalfile->get_filename(),
1323         );
1325         $aliasrecord = $this->generate_file_record();
1326         $aliasrecord->filepath = '/A/';
1327         $aliasrecord->filename = 'symlink.txt';
1329         $ref = $fs->pack_reference($originalrecord);
1330         $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1332         $aliasrecord->filepath = '/B/';
1333         $aliasrecord->filename = 'symlink.txt';
1334         $ref = $fs->pack_reference($originalrecord);
1335         $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1337         // refetch A/symlink.txt
1338         $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1339             $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt');
1340         $this->assertTrue($symlink1->is_external_file());
1342         // unlink the A/symlink.txt
1343         $symlink1->delete_reference();
1344         $this->assertFalse($symlink1->is_external_file());
1346         // make sure that B/symlink.txt has not been affected
1347         $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1348             $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt');
1349         $this->assertTrue($symlink2->is_external_file());
1350     }
1352     public function test_get_unused_filename() {
1353         global $USER;
1354         $this->resetAfterTest(true);
1356         $fs = get_file_storage();
1357         $this->setAdminUser();
1358         $contextid = context_user::instance($USER->id)->id;
1359         $component = 'user';
1360         $filearea = 'private';
1361         $itemid = 0;
1362         $filepath = '/';
1364         // Create some private files.
1365         $file = new stdClass;
1366         $file->contextid = $contextid;
1367         $file->component = 'user';
1368         $file->filearea  = 'private';
1369         $file->itemid    = 0;
1370         $file->filepath  = '/';
1371         $file->source    = 'test';
1372         $filenames = array('foo.txt', 'foo (1).txt', 'foo (20).txt', 'foo (999)', 'bar.jpg', 'What (a cool file).jpg',
1373                 'Hurray! (1).php', 'Hurray! (2).php', 'Hurray! (9a).php', 'Hurray! (abc).php');
1374         foreach ($filenames as $key => $filename) {
1375             $file->filename = $filename;
1376             $userfile = $fs->create_file_from_string($file, "file $key $filename content");
1377             $this->assertInstanceOf('stored_file', $userfile);
1378         }
1380         // Asserting new generated names.
1381         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'unused.txt');
1382         $this->assertEquals('unused.txt', $newfilename);
1383         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo.txt');
1384         $this->assertEquals('foo (21).txt', $newfilename);
1385         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (1).txt');
1386         $this->assertEquals('foo (21).txt', $newfilename);
1387         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (2).txt');
1388         $this->assertEquals('foo (2).txt', $newfilename);
1389         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (20).txt');
1390         $this->assertEquals('foo (21).txt', $newfilename);
1391         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo');
1392         $this->assertEquals('foo', $newfilename);
1393         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (123)');
1394         $this->assertEquals('foo (123)', $newfilename);
1395         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (999)');
1396         $this->assertEquals('foo (1000)', $newfilename);
1397         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.png');
1398         $this->assertEquals('bar.png', $newfilename);
1399         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (12).png');
1400         $this->assertEquals('bar (12).png', $newfilename);
1401         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.jpg');
1402         $this->assertEquals('bar (1).jpg', $newfilename);
1403         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (1).jpg');
1404         $this->assertEquals('bar (1).jpg', $newfilename);
1405         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'What (a cool file).jpg');
1406         $this->assertEquals('What (a cool file) (1).jpg', $newfilename);
1407         $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'Hurray! (1).php');
1408         $this->assertEquals('Hurray! (3).php', $newfilename);
1410         $this->setExpectedException('coding_exception');
1411         $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, '');
1412     }