MDL-41022 cleanup core_files_file_storage_testcase
[moodle.git] / lib / filestorage / tests / file_storage_test.php
CommitLineData
8f110835 1<?php
8f110835
DM
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Unit tests for /lib/filestorage/file_storage.php
19 *
4c34571b
PS
20 * @package core_files
21 * @category phpunit
8f110835
DM
22 * @copyright 2012 David Mudrak <david@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28global $CFG;
29require_once($CFG->libdir . '/filelib.php');
ac29403e 30require_once($CFG->dirroot . '/repository/lib.php');
fd4592bb 31require_once($CFG->libdir . '/filestorage/stored_file.php');
8f110835 32
8252b7c2 33class core_files_file_storage_testcase extends advanced_testcase {
8f110835 34
fd4592bb
PS
35 /**
36 * Files can be created from strings.
37 */
38 public function test_create_file_from_string() {
39 global $DB;
40
41 $this->resetAfterTest(true);
42
43 $this->assertEquals(0, $DB->count_records('files', array()));
44
45 $content = 'abcd';
46 $syscontext = context_system::instance();
47 $filerecord = array(
48 'contextid' => $syscontext->id,
49 'component' => 'core',
50 'filearea' => 'unittest',
51 'itemid' => 0,
52 'filepath' => '/images/',
53 'filename' => 'testfile.txt',
54 );
55 $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']);
56
57 $fs = get_file_storage();
58 $file = $fs->create_file_from_string($filerecord, $content);
59
60 $this->assertInstanceOf('stored_file', $file);
61 $this->assertSame(sha1($content), $file->get_contenthash());
62 $this->assertSame($pathhash, $file->get_pathnamehash());
63
64 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>$pathhash)));
65
66 $location = test_stored_file_inspection::get_pretected_pathname($file);
67
68 $this->assertFileExists($location);
69
fd4592bb
PS
70 // Verify the dir placeholder files are created.
71 $this->assertEquals(3, $DB->count_records('files', array()));
72 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].'/.'))));
73 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].'.'))));
74
fd4592bb
PS
75 // Tests that missing content file is recreated.
76
77 unlink($location);
78 $this->assertFileNotExists($location);
79
80 $filerecord['filename'] = 'testfile2.txt';
81 $file2 = $fs->create_file_from_string($filerecord, $content);
82 $this->assertInstanceOf('stored_file', $file2);
83 $this->assertSame($file->get_contenthash(), $file2->get_contenthash());
84 $this->assertFileExists($location);
85
86 $this->assertEquals(4, $DB->count_records('files', array()));
87
fd4592bb
PS
88 // Test that borked content file is recreated.
89
90 $this->assertSame(2, file_put_contents($location, 'xx'));
91
92 $filerecord['filename'] = 'testfile3.txt';
93 $file3 = $fs->create_file_from_string($filerecord, $content);
94 $this->assertInstanceOf('stored_file', $file3);
95 $this->assertSame($file->get_contenthash(), $file3->get_contenthash());
96 $this->assertFileExists($location);
97
98 $this->assertSame($content, file_get_contents($location));
99 $this->assertDebuggingCalled();
100
101 $this->assertEquals(5, $DB->count_records('files', array()));
102 }
103
8f110835
DM
104 /**
105 * Local files can be added to the filepool
106 */
107 public function test_create_file_from_pathname() {
fd4592bb
PS
108 global $CFG, $DB;
109
110 $this->resetAfterTest(true);
111
112 $filecount = $DB->count_records('files', array());
113 $this->assertEquals(0, $filecount);
114
115 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
116 $syscontext = context_system::instance();
117 $filerecord = array(
118 'contextid' => $syscontext->id,
119 'component' => 'core',
120 'filearea' => 'unittest',
121 'itemid' => 0,
122 'filepath' => '/images/',
123 'filename' => 'testimage.jpg',
124 );
125 $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']);
126
127 $fs = get_file_storage();
128 $file = $fs->create_file_from_pathname($filerecord, $filepath);
129
130 $this->assertInstanceOf('stored_file', $file);
131 $this->assertSame(sha1_file($filepath), $file->get_contenthash());
132
133 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>$pathhash)));
134
135 $location = test_stored_file_inspection::get_pretected_pathname($file);
136
137 $this->assertFileExists($location);
138
fd4592bb
PS
139 // Verify the dir placeholder files are created.
140 $this->assertEquals(3, $DB->count_records('files', array()));
141 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].'/.'))));
142 $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].'.'))));
143
fd4592bb
PS
144 // Tests that missing content file is recreated.
145
146 unlink($location);
147 $this->assertFileNotExists($location);
148
149 $filerecord['filename'] = 'testfile2.jpg';
150 $file2 = $fs->create_file_from_pathname($filerecord, $filepath);
151 $this->assertInstanceOf('stored_file', $file2);
152 $this->assertSame($file->get_contenthash(), $file2->get_contenthash());
153 $this->assertFileExists($location);
154
155 $this->assertEquals(4, $DB->count_records('files', array()));
156
fd4592bb
PS
157 // Test that borked content file is recreated.
158
159 $this->assertSame(2, file_put_contents($location, 'xx'));
160
161 $filerecord['filename'] = 'testfile3.jpg';
162 $file3 = $fs->create_file_from_pathname($filerecord, $filepath);
163 $this->assertInstanceOf('stored_file', $file3);
164 $this->assertSame($file->get_contenthash(), $file3->get_contenthash());
165 $this->assertFileExists($location);
166
167 $this->assertSame(file_get_contents($filepath), file_get_contents($location));
168 $this->assertDebuggingCalled();
169
170 $this->assertEquals(5, $DB->count_records('files', array()));
171
172 // Test invalid file creation.
173
174 $filerecord['filename'] = 'testfile4.jpg';
175 try {
176 $fs->create_file_from_pathname($filerecord, $filepath.'nonexistent');
177 $this->fail('Exception expected when trying to add non-existent stored file.');
178 } catch (Exception $e) {
179 $this->assertInstanceOf('file_exception', $e);
180 }
181 }
182
183 /**
184 * Tests get get file.
185 */
186 public function test_get_file() {
8f110835
DM
187 global $CFG;
188
189 $this->resetAfterTest(false);
190
191 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
192 $syscontext = context_system::instance();
193 $filerecord = array(
194 'contextid' => $syscontext->id,
195 'component' => 'core',
196 'filearea' => 'unittest',
197 'itemid' => 0,
198 'filepath' => '/images/',
199 'filename' => 'testimage.jpg',
200 );
fd4592bb 201 $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']);
8f110835
DM
202
203 $fs = get_file_storage();
fd4592bb 204 $file = $fs->create_file_from_pathname($filerecord, $filepath);
8f110835 205
fd4592bb
PS
206 $this->assertInstanceOf('stored_file', $file);
207 $this->assertEquals($syscontext->id, $file->get_contextid());
208 $this->assertEquals('core', $file->get_component());
209 $this->assertEquals('unittest', $file->get_filearea());
210 $this->assertEquals(0, $file->get_itemid());
211 $this->assertEquals('/images/', $file->get_filepath());
212 $this->assertEquals('testimage.jpg', $file->get_filename());
213 $this->assertEquals(filesize($filepath), $file->get_filesize());
214 $this->assertEquals($pathhash, $file->get_pathnamehash());
215
216 return $file;
8f110835
DM
217 }
218
219 /**
220 * Local images can be added to the filepool and their preview can be obtained
221 *
fd4592bb 222 * @depends test_get_file
8f110835
DM
223 */
224 public function test_get_file_preview(stored_file $file) {
225 global $CFG;
226
4c34571b 227 $this->resetAfterTest();
8f110835
DM
228 $fs = get_file_storage();
229
230 $previewtinyicon = $fs->get_file_preview($file, 'tinyicon');
231 $this->assertInstanceOf('stored_file', $previewtinyicon);
232 $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
233
234 $previewtinyicon = $fs->get_file_preview($file, 'thumb');
235 $this->assertInstanceOf('stored_file', $previewtinyicon);
236 $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
7c89a18f
DP
237
238 $this->setExpectedException('file_exception');
239 $fs->get_file_preview($file, 'amodewhichdoesntexist');
240 }
241
242 public function test_get_file_preview_nonimage() {
243 $this->resetAfterTest(true);
244 $syscontext = context_system::instance();
245 $filerecord = array(
246 'contextid' => $syscontext->id,
247 'component' => 'core',
248 'filearea' => 'unittest',
249 'itemid' => 0,
250 'filepath' => '/textfiles/',
251 'filename' => 'testtext.txt',
252 );
253
254 $fs = get_file_storage();
255 $fs->create_file_from_string($filerecord, 'text contents');
256 $textfile = $fs->get_file($syscontext->id, $filerecord['component'], $filerecord['filearea'],
257 $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename']);
258
259 $preview = $fs->get_file_preview($textfile, 'thumb');
260 $this->assertFalse($preview);
8f110835 261 }
67233725
DC
262
263 /**
264 * Make sure renaming is working
265 *
266 * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org}
267 */
268 public function test_file_renaming() {
269 global $CFG;
270
4c34571b 271 $this->resetAfterTest();
67233725
DC
272 $fs = get_file_storage();
273 $syscontext = context_system::instance();
274 $component = 'core';
275 $filearea = 'unittest';
276 $itemid = 0;
277 $filepath = '/';
278 $filename = 'test.txt';
279
280 $filerecord = array(
281 'contextid' => $syscontext->id,
282 'component' => $component,
283 'filearea' => $filearea,
284 'itemid' => $itemid,
285 'filepath' => $filepath,
286 'filename' => $filename,
287 );
288
289 $originalfile = $fs->create_file_from_string($filerecord, 'Test content');
290 $this->assertInstanceOf('stored_file', $originalfile);
291 $contenthash = $originalfile->get_contenthash();
292 $newpath = '/test/';
293 $newname = 'newtest.txt';
61506a0a 294
4c34571b 295 // This should work.
67233725 296 $originalfile->rename($newpath, $newname);
67233725
DC
297 $file = $fs->get_file($syscontext->id, $component, $filearea, $itemid, $newpath, $newname);
298 $this->assertInstanceOf('stored_file', $file);
299 $this->assertEquals($contenthash, $file->get_contenthash());
61506a0a 300
4c34571b 301 // Try break it.
61506a0a 302 $this->setExpectedException('file_exception');
4c34571b 303 // This shall throw exception.
61506a0a 304 $originalfile->rename($newpath, $newname);
67233725
DC
305 }
306
307 /**
308 * Create file from reference tests
309 *
310 * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org}
311 */
312 public function test_create_file_from_reference() {
313 global $CFG, $DB;
314
4c34571b
PS
315 $this->resetAfterTest();
316 // Create user.
67233725
DC
317 $generator = $this->getDataGenerator();
318 $user = $generator->create_user();
cfc4db40 319 $this->setUser($user);
67233725
DC
320 $usercontext = context_user::instance($user->id);
321 $syscontext = context_system::instance();
67233725
DC
322
323 $fs = get_file_storage();
324
325 $repositorypluginname = 'user';
4c34571b 326 // Override repository permission.
67233725
DC
327 $capability = 'repository/' . $repositorypluginname . ':view';
328 $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
329 assign_capability($capability, CAP_ALLOW, $allroles['guest'], $syscontext->id, true);
330
67233725
DC
331 $args = array();
332 $args['type'] = $repositorypluginname;
333 $repos = repository::get_instances($args);
334 $userrepository = reset($repos);
335 $this->assertInstanceOf('repository', $userrepository);
336
337 $component = 'user';
338 $filearea = 'private';
339 $itemid = 0;
340 $filepath = '/';
341 $filename = 'userfile.txt';
342
343 $filerecord = array(
344 'contextid' => $usercontext->id,
345 'component' => $component,
346 'filearea' => $filearea,
347 'itemid' => $itemid,
348 'filepath' => $filepath,
349 'filename' => $filename,
350 );
351
352 $content = 'Test content';
353 $originalfile = $fs->create_file_from_string($filerecord, $content);
354 $this->assertInstanceOf('stored_file', $originalfile);
355
356 $newfilerecord = array(
357 'contextid' => $syscontext->id,
358 'component' => 'core',
359 'filearea' => 'phpunit',
360 'itemid' => 0,
361 'filepath' => $filepath,
362 'filename' => $filename,
363 );
364 $ref = $fs->pack_reference($filerecord);
365 $newstoredfile = $fs->create_file_from_reference($newfilerecord, $userrepository->id, $ref);
366 $this->assertInstanceOf('stored_file', $newstoredfile);
291a3d1f 367 $this->assertEquals($userrepository->id, $newstoredfile->get_repository_id());
67233725
DC
368 $this->assertEquals($originalfile->get_contenthash(), $newstoredfile->get_contenthash());
369 $this->assertEquals($originalfile->get_filesize(), $newstoredfile->get_filesize());
370 $this->assertRegExp('#' . $filename. '$#', $newstoredfile->get_reference_details());
371
4c34571b 372 // Test looking for references.
67233725
DC
373 $count = $fs->get_references_count_by_storedfile($originalfile);
374 $this->assertEquals(1, $count);
375 $files = $fs->get_references_by_storedfile($originalfile);
376 $file = reset($files);
377 $this->assertEquals($file, $newstoredfile);
378
4c34571b 379 // Look for references by repository ID.
67233725
DC
380 $files = $fs->get_external_files($userrepository->id);
381 $file = reset($files);
382 $this->assertEquals($file, $newstoredfile);
383
4c34571b 384 // Try convert reference to local file.
67233725
DC
385 $importedfile = $fs->import_external_file($newstoredfile);
386 $this->assertFalse($importedfile->is_external_file());
387 $this->assertInstanceOf('stored_file', $importedfile);
4c34571b 388 // Still readable?
67233725
DC
389 $this->assertEquals($content, $importedfile->get_content());
390 }
ac29403e 391
ac29403e 392 private function setup_three_private_files() {
ac29403e 393
4c34571b 394 $this->resetAfterTest();
ac29403e
DP
395
396 $generator = $this->getDataGenerator();
397 $user = $generator->create_user();
7c89a18f 398 $this->setUser($user->id);
ac29403e 399 $usercontext = context_user::instance($user->id);
4c34571b 400 // Create a user private file.
ac29403e
DP
401 $file1 = new stdClass;
402 $file1->contextid = $usercontext->id;
403 $file1->component = 'user';
404 $file1->filearea = 'private';
405 $file1->itemid = 0;
406 $file1->filepath = '/';
407 $file1->filename = '1.txt';
408 $file1->source = 'test';
409
410 $fs = get_file_storage();
411 $userfile1 = $fs->create_file_from_string($file1, 'file1 content');
7c89a18f
DP
412 $this->assertInstanceOf('stored_file', $userfile1);
413
ac29403e
DP
414 $file2 = clone($file1);
415 $file2->filename = '2.txt';
416 $userfile2 = $fs->create_file_from_string($file2, 'file2 content');
7c89a18f 417 $this->assertInstanceOf('stored_file', $userfile2);
ac29403e
DP
418
419 $file3 = clone($file1);
420 $file3->filename = '3.txt';
421 $userfile3 = $fs->create_file_from_storedfile($file3, $userfile2);
7c89a18f 422 $this->assertInstanceOf('stored_file', $userfile3);
ac29403e
DP
423
424 $user->ctxid = $usercontext->id;
425
426 return $user;
427 }
428
ac29403e
DP
429 public function test_get_area_files() {
430 $user = $this->setup_three_private_files();
431 $fs = get_file_storage();
432
433 // Get area files with default options.
434 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
7c89a18f 435
ac29403e
DP
436 // Should be the two files we added plus the folder.
437 $this->assertEquals(4, count($areafiles));
438
7c89a18f 439 // Verify structure.
294d976e 440 foreach ($areafiles as $key => $file) {
7c89a18f
DP
441 $this->assertInstanceOf('stored_file', $file);
442 $this->assertEquals($key, $file->get_pathnamehash());
443 }
444
ac29403e 445 // Get area files without a folder.
7c89a18f 446 $folderlessfiles = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'sortorder', false);
ac29403e 447 // Should be the two files without folder.
7c89a18f
DP
448 $this->assertEquals(3, count($folderlessfiles));
449
450 // Verify structure.
294d976e 451 foreach ($folderlessfiles as $key => $file) {
7c89a18f
DP
452 $this->assertInstanceOf('stored_file', $file);
453 $this->assertEquals($key, $file->get_pathnamehash());
454 }
ac29403e 455
d83ce953 456 // Get area files ordered by id.
7c89a18f 457 $filesbyid = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'id', false);
ac29403e 458 // Should be the two files without folder.
7c89a18f
DP
459 $this->assertEquals(3, count($filesbyid));
460
461 // Verify structure.
294d976e 462 foreach ($filesbyid as $key => $file) {
7c89a18f
DP
463 $this->assertInstanceOf('stored_file', $file);
464 $this->assertEquals($key, $file->get_pathnamehash());
465 }
ac29403e 466
4c34571b 467 // Test with an itemid with no files.
ac29403e 468 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', 666, 'sortorder', false);
294d976e 469 // Should be none.
7c89a18f 470 $this->assertEmpty($areafiles);
ac29403e
DP
471 }
472
473 public function test_get_area_tree() {
474 $user = $this->setup_three_private_files();
475 $fs = get_file_storage();
476
477 // Get area files with default options.
7c89a18f
DP
478 $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0);
479 $this->assertEmpty($areatree['subdirs']);
480 $this->assertNotEmpty($areatree['files']);
481 $this->assertCount(3, $areatree['files']);
482
483 // Ensure an empty try with a fake itemid.
484 $emptytree = $fs->get_area_tree($user->ctxid, 'user', 'private', 666);
485 $this->assertEmpty($emptytree['subdirs']);
486 $this->assertEmpty($emptytree['files']);
487
294d976e 488 // Create a subdir.
7c89a18f
DP
489 $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/');
490 $this->assertInstanceOf('stored_file', $dir);
491
492 // Add a file to the subdir.
493 $filerecord = array(
494 'contextid' => $user->ctxid,
495 'component' => 'user',
496 'filearea' => 'private',
497 'itemid' => 0,
498 'filepath' => '/testsubdir/',
499 'filename' => 'test-get-area-tree.txt',
500 );
501
502 $directoryfile = $fs->create_file_from_string($filerecord, 'Test content');
503 $this->assertInstanceOf('stored_file', $directoryfile);
504
505 $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0);
506
507 // At the top level there should still be 3 files.
508 $this->assertCount(3, $areatree['files']);
509
510 // There should now be a subdirectory.
511 $this->assertCount(1, $areatree['subdirs']);
512
513 // The test subdir is named testsubdir.
514 $subdir = $areatree['subdirs']['testsubdir'];
515 $this->assertNotEmpty($subdir);
516 // It should have one file we added.
517 $this->assertCount(1, $subdir['files']);
518 // And no subdirs itself.
519 $this->assertCount(0, $subdir['subdirs']);
520
294d976e 521 // Verify the file is the one we added.
7c89a18f
DP
522 $subdirfile = reset($subdir['files']);
523 $this->assertInstanceOf('stored_file', $subdirfile);
524 $this->assertEquals($filerecord['filename'], $subdirfile->get_filename());
ac29403e
DP
525 }
526
527 public function test_get_file_by_id() {
528 $user = $this->setup_three_private_files();
529 $fs = get_file_storage();
530
531 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
532
533 // Test get_file_by_id.
534 $filebyid = reset($areafiles);
535 $shouldbesame = $fs->get_file_by_id($filebyid->get_id());
536 $this->assertEquals($filebyid->get_contenthash(), $shouldbesame->get_contenthash());
7c89a18f
DP
537
538 // Test an id which doens't exist.
539 $doesntexist = $fs->get_file_by_id(99999);
540 $this->assertFalse($doesntexist);
ac29403e
DP
541 }
542
543 public function test_get_file_by_hash() {
544 $user = $this->setup_three_private_files();
545 $fs = get_file_storage();
546
547 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
4c34571b 548 // Test get_file_by_hash.
ac29403e
DP
549 $filebyhash = reset($areafiles);
550 $shouldbesame = $fs->get_file_by_hash($filebyhash->get_pathnamehash());
551 $this->assertEquals($filebyhash->get_id(), $shouldbesame->get_id());
7c89a18f
DP
552
553 // Test an hash which doens't exist.
554 $doesntexist = $fs->get_file_by_hash('DOESNTEXIST');
555 $this->assertFalse($doesntexist);
ac29403e
DP
556 }
557
ac29403e
DP
558 public function test_get_external_files() {
559 $user = $this->setup_three_private_files();
560 $fs = get_file_storage();
561
562 $repos = repository::get_instances(array('type'=>'user'));
563 $userrepository = reset($repos);
564 $this->assertInstanceOf('repository', $userrepository);
565
4c34571b 566 // No aliases yet.
d83ce953
DM
567 $exfiles = $fs->get_external_files($userrepository->id, 'id');
568 $this->assertEquals(array(), $exfiles);
569
4c34571b
PS
570 // Create three aliases linking the same original: $aliasfile1 and $aliasfile2 are
571 // created via create_file_from_reference(), $aliasfile3 created from $aliasfile2.
d83ce953
DM
572 $originalfile = null;
573 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
574 if (!$areafile->is_directory()) {
575 $originalfile = $areafile;
576 break;
577 }
578 }
579 $this->assertInstanceOf('stored_file', $originalfile);
580 $originalrecord = array(
581 'contextid' => $originalfile->get_contextid(),
582 'component' => $originalfile->get_component(),
583 'filearea' => $originalfile->get_filearea(),
584 'itemid' => $originalfile->get_itemid(),
585 'filepath' => $originalfile->get_filepath(),
586 'filename' => $originalfile->get_filename(),
587 );
588
589 $aliasrecord = $this->generate_file_record();
590 $aliasrecord->filepath = '/foo/';
591 $aliasrecord->filename = 'one.txt';
592
593 $ref = $fs->pack_reference($originalrecord);
594 $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref);
595
596 $aliasrecord->filepath = '/bar/';
597 $aliasrecord->filename = 'uno.txt';
4c34571b 598 // Change the order of the items in the array to make sure that it does not matter.
d83ce953
DM
599 ksort($originalrecord);
600 $ref = $fs->pack_reference($originalrecord);
601 $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref);
602
603 $aliasrecord->filepath = '/bar/';
604 $aliasrecord->filename = 'jedna.txt';
605 $aliasfile3 = $fs->create_file_from_storedfile($aliasrecord, $aliasfile2);
606
4c34571b 607 // Make sure we get three aliases now.
d83ce953
DM
608 $exfiles = $fs->get_external_files($userrepository->id, 'id');
609 $this->assertEquals(3, count($exfiles));
610 foreach ($exfiles as $exfile) {
611 $this->assertTrue($exfile->is_external_file());
612 }
4c34571b
PS
613 // Make sure they all link the same original (thence that all are linked with the same
614 // record in {files_reference}).
d83ce953
DM
615 $this->assertEquals($aliasfile1->get_referencefileid(), $aliasfile2->get_referencefileid());
616 $this->assertEquals($aliasfile3->get_referencefileid(), $aliasfile2->get_referencefileid());
7c89a18f
DP
617 }
618
619 public function test_create_directory_contextid_negative() {
620 $fs = get_file_storage();
621
622 $this->setExpectedException('file_exception');
623 $fs->create_directory(-1, 'core', 'unittest', 0, '/');
624 }
625
626 public function test_create_directory_contextid_invalid() {
627 $fs = get_file_storage();
628
629 $this->setExpectedException('file_exception');
630 $fs->create_directory('not an int', 'core', 'unittest', 0, '/');
631 }
632
633 public function test_create_directory_component_invalid() {
634 $fs = get_file_storage();
635 $syscontext = context_system::instance();
636
637 $this->setExpectedException('file_exception');
638 $fs->create_directory($syscontext->id, 'bad/component', 'unittest', 0, '/');
639 }
640
641 public function test_create_directory_filearea_invalid() {
642 $fs = get_file_storage();
643 $syscontext = context_system::instance();
644
645 $this->setExpectedException('file_exception');
646 $fs->create_directory($syscontext->id, 'core', 'bad-filearea', 0, '/');
647 }
648
649 public function test_create_directory_itemid_negative() {
650 $fs = get_file_storage();
651 $syscontext = context_system::instance();
652
653 $this->setExpectedException('file_exception');
654 $fs->create_directory($syscontext->id, 'core', 'unittest', -1, '/');
655 }
656
657 public function test_create_directory_itemid_invalid() {
658 $fs = get_file_storage();
659 $syscontext = context_system::instance();
660
661 $this->setExpectedException('file_exception');
662 $fs->create_directory($syscontext->id, 'core', 'unittest', 'notanint', '/');
663 }
664
665 public function test_create_directory_filepath_invalid() {
666 $fs = get_file_storage();
667 $syscontext = context_system::instance();
668
669 $this->setExpectedException('file_exception');
670 $fs->create_directory($syscontext->id, 'core', 'unittest', 0, '/not-with-trailing/or-leading-slash');
671 }
ac29403e
DP
672
673 public function test_get_directory_files() {
674 $user = $this->setup_three_private_files();
675 $fs = get_file_storage();
676
7c89a18f
DP
677 $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/');
678 $this->assertInstanceOf('stored_file', $dir);
ac29403e 679
7c89a18f
DP
680 // Add a file to the subdir.
681 $filerecord = array(
682 'contextid' => $user->ctxid,
683 'component' => 'user',
684 'filearea' => 'private',
685 'itemid' => 0,
686 'filepath' => '/testsubdir/',
687 'filename' => 'test-get-area-tree.txt',
688 );
689
690 $directoryfile = $fs->create_file_from_string($filerecord, 'Test content');
691 $this->assertInstanceOf('stored_file', $directoryfile);
ac29403e 692
4c34571b 693 // Don't recurse without dirs.
7c89a18f
DP
694 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, false, 'id');
695 // 3 files only.
696 $this->assertCount(3, $files);
294d976e 697 foreach ($files as $key => $file) {
7c89a18f
DP
698 $this->assertInstanceOf('stored_file', $file);
699 $this->assertEquals($key, $file->get_pathnamehash());
700 }
701
294d976e 702 // Don't recurse with dirs.
7c89a18f 703 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, true, 'id');
294d976e 704 // 3 files + 1 directory.
7c89a18f 705 $this->assertCount(4, $files);
294d976e 706 foreach ($files as $key => $file) {
7c89a18f
DP
707 $this->assertInstanceOf('stored_file', $file);
708 $this->assertEquals($key, $file->get_pathnamehash());
709 }
ac29403e 710
294d976e 711 // Recurse with dirs.
7c89a18f 712 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, true, 'id');
294d976e 713 // 3 files + 1 directory + 1 subdir file.
7c89a18f 714 $this->assertCount(5, $files);
294d976e 715 foreach ($files as $key => $file) {
7c89a18f
DP
716 $this->assertInstanceOf('stored_file', $file);
717 $this->assertEquals($key, $file->get_pathnamehash());
718 }
719
294d976e 720 // Recurse without dirs.
7c89a18f 721 $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, false, 'id');
294d976e 722 // 3 files + 1 subdir file.
7c89a18f 723 $this->assertCount(4, $files);
294d976e 724 foreach ($files as $key => $file) {
7c89a18f
DP
725 $this->assertInstanceOf('stored_file', $file);
726 $this->assertEquals($key, $file->get_pathnamehash());
727 }
ac29403e
DP
728 }
729
730 public function test_search_references() {
483afa44 731 $user = $this->setup_three_private_files();
ac29403e 732 $fs = get_file_storage();
483afa44
DM
733 $repos = repository::get_instances(array('type'=>'user'));
734 $repo = reset($repos);
ac29403e 735
483afa44
DM
736 $alias1 = array(
737 'contextid' => $user->ctxid,
738 'component' => 'user',
739 'filearea' => 'private',
740 'itemid' => 0,
741 'filepath' => '/aliases/',
742 'filename' => 'alias-to-1.txt'
743 );
744
745 $alias2 = array(
746 'contextid' => $user->ctxid,
747 'component' => 'user',
748 'filearea' => 'private',
749 'itemid' => 0,
750 'filepath' => '/aliases/',
751 'filename' => 'another-alias-to-1.txt'
752 );
753
754 $reference = file_storage::pack_reference(array(
755 'contextid' => $user->ctxid,
756 'component' => 'user',
757 'filearea' => 'private',
758 'itemid' => 0,
759 'filepath' => '/',
760 'filename' => '1.txt'
761 ));
762
763 // There are no aliases now.
764 $result = $fs->search_references($reference);
765 $this->assertEquals(array(), $result);
766
767 $result = $fs->search_references_count($reference);
768 $this->assertSame($result, 0);
769
770 // Create two aliases and make sure they are returned.
771 $fs->create_file_from_reference($alias1, $repo->id, $reference);
772 $fs->create_file_from_reference($alias2, $repo->id, $reference);
773
774 $result = $fs->search_references($reference);
775 $this->assertTrue(is_array($result));
776 $this->assertEquals(count($result), 2);
777 foreach ($result as $alias) {
778 $this->assertTrue($alias instanceof stored_file);
779 }
780
781 $result = $fs->search_references_count($reference);
782 $this->assertSame($result, 2);
783
4c34571b 784 // The method can't be used for references to files outside the filepool.
483afa44
DM
785 $exceptionthrown = false;
786 try {
787 $fs->search_references('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg');
788 } catch (file_reference_exception $e) {
789 $exceptionthrown = true;
790 }
791 $this->assertTrue($exceptionthrown);
792
793 $exceptionthrown = false;
794 try {
795 $fs->search_references_count('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg');
796 } catch (file_reference_exception $e) {
797 $exceptionthrown = true;
798 }
799 $this->assertTrue($exceptionthrown);
ac29403e
DP
800 }
801
802 public function test_delete_area_files() {
803 $user = $this->setup_three_private_files();
804 $fs = get_file_storage();
805
806 // Get area files with default options.
807 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
808 // Should be the two files we added plus the folder.
809 $this->assertEquals(4, count($areafiles));
810 $fs->delete_area_files($user->ctxid, 'user', 'private');
811
812 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
813 // Should be the two files we added plus the folder.
814 $this->assertEquals(0, count($areafiles));
815 }
816
7c89a18f
DP
817 public function test_delete_area_files_itemid() {
818 $user = $this->setup_three_private_files();
819 $fs = get_file_storage();
820
821 // Get area files with default options.
822 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
823 // Should be the two files we added plus the folder.
824 $this->assertEquals(4, count($areafiles));
825 $fs->delete_area_files($user->ctxid, 'user', 'private', 9999);
826
827 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
828 $this->assertEquals(4, count($areafiles));
829 }
830
ac29403e
DP
831 public function test_delete_area_files_select() {
832 $user = $this->setup_three_private_files();
833 $fs = get_file_storage();
834
835 // Get area files with default options.
836 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
837 // Should be the two files we added plus the folder.
838 $this->assertEquals(4, count($areafiles));
839 $fs->delete_area_files_select($user->ctxid, 'user', 'private', '!= :notitemid', array('notitemid'=>9999));
840
841 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
842 // Should be the two files we added plus the folder.
843 $this->assertEquals(0, count($areafiles));
844 }
996f8b64 845
546b8864
DM
846 public function test_delete_component_files() {
847 $user = $this->setup_three_private_files();
848 $fs = get_file_storage();
849
850 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
851 $this->assertEquals(4, count($areafiles));
852 $fs->delete_component_files('user');
853 $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
854 $this->assertEquals(0, count($areafiles));
855 }
856
996f8b64
DP
857 public function test_create_file_from_url() {
858 $this->resetAfterTest(true);
859
860 $syscontext = context_system::instance();
861 $filerecord = array(
862 'contextid' => $syscontext->id,
863 'component' => 'core',
864 'filearea' => 'unittest',
865 'itemid' => 0,
866 'filepath' => '/downloadtest/',
867 );
868 $url = 'http://download.moodle.org/unittest/test.html';
869
870 $fs = get_file_storage();
871
872 // Test creating file without filename.
873 $file1 = $fs->create_file_from_url($filerecord, $url);
874 $this->assertInstanceOf('stored_file', $file1);
875
876 // Set filename.
877 $filerecord['filename'] = 'unit-test-filename.html';
878 $file2 = $fs->create_file_from_url($filerecord, $url);
879 $this->assertInstanceOf('stored_file', $file2);
880
881 // Use temporary file.
882 $filerecord['filename'] = 'unit-test-with-temp-file.html';
883 $file3 = $fs->create_file_from_url($filerecord, $url, null, true);
884 $file3 = $this->assertInstanceOf('stored_file', $file3);
885 }
886
887 public function test_cron() {
888 $this->resetAfterTest(true);
889
890 // Note: this is only testing DB compatibility atm, rather than
294d976e 891 // that work is done.
996f8b64
DP
892 $fs = get_file_storage();
893
894 $this->expectOutputRegex('/Cleaning up/');
895 $fs->cron();
896 }
897
898 public function test_is_area_empty() {
899 $user = $this->setup_three_private_files();
900 $fs = get_file_storage();
901
902 $this->assertFalse($fs->is_area_empty($user->ctxid, 'user', 'private'));
903
904 // File area with madeup itemid should be empty.
905 $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999));
906 // Still empty with dirs included.
907 $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999, false));
908 }
909
910 public function test_move_area_files_to_new_context() {
911 $this->resetAfterTest(true);
912
913 // Create a course with a page resource.
914 $course = $this->getDataGenerator()->create_course();
915 $page1 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
916 $page1context = context_module::instance($page1->cmid);
917
996f8b64
DP
918 // Add a file to the page.
919 $fs = get_file_storage();
920 $filerecord = array(
921 'contextid' => $page1context->id,
922 'component' => 'mod_page',
923 'filearea' => 'content',
924 'itemid' => 0,
925 'filepath' => '/',
926 'filename' => 'unit-test-file.txt',
927 );
928
929 $originalfile = $fs->create_file_from_string($filerecord, 'Test content');
930 $this->assertInstanceOf('stored_file', $originalfile);
931
932 $pagefiles = $fs->get_area_files($page1context->id, 'mod_page', 'content', 0, 'sortorder', false);
933 // Should be one file in filearea.
934 $this->assertFalse($fs->is_area_empty($page1context->id, 'mod_page', 'content'));
935
936 // Create a new page.
937 $page2 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
938 $page2context = context_module::instance($page2->cmid);
939
940 // Newly created page area is empty.
941 $this->assertTrue($fs->is_area_empty($page2context->id, 'mod_page', 'content'));
942
943 // Move the files.
944 $fs->move_area_files_to_new_context($page1context->id, $page2context->id, 'mod_page', 'content');
945
294d976e 946 // Page2 filearea should no longer be empty.
996f8b64
DP
947 $this->assertFalse($fs->is_area_empty($page2context->id, 'mod_page', 'content'));
948
294d976e 949 // Page1 filearea should now be empty.
996f8b64
DP
950 $this->assertTrue($fs->is_area_empty($page1context->id, 'mod_page', 'content'));
951
952 $page2files = $fs->get_area_files($page2context->id, 'mod_page', 'content', 0, 'sortorder', false);
953 $movedfile = reset($page2files);
954
294d976e 955 // The two files should have the same content hash.
996f8b64
DP
956 $this->assertEquals($movedfile->get_contenthash(), $originalfile->get_contenthash());
957 }
958
959 public function test_convert_image() {
960 global $CFG;
961
962 $this->resetAfterTest(false);
963
964 $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
965 $syscontext = context_system::instance();
966 $filerecord = array(
967 'contextid' => $syscontext->id,
968 'component' => 'core',
969 'filearea' => 'unittest',
970 'itemid' => 0,
971 'filepath' => '/images/',
972 'filename' => 'testimage.jpg',
973 );
974
975 $fs = get_file_storage();
976 $original = $fs->create_file_from_pathname($filerecord, $filepath);
977
978 $filerecord['filename'] = 'testimage-converted-10x10.jpg';
979 $converted = $fs->convert_image($filerecord, $original, 10, 10, true, 100);
980 $this->assertInstanceOf('stored_file', $converted);
981
982 $filerecord['filename'] = 'testimage-convereted-nosize.jpg';
983 $converted = $fs->convert_image($filerecord, $original);
984 $this->assertInstanceOf('stored_file', $converted);
985 }
986
987 private function generate_file_record() {
988 $syscontext = context_system::instance();
989 $filerecord = new stdClass();
990 $filerecord->contextid = $syscontext->id;
991 $filerecord->component = 'core';
992 $filerecord->filearea = 'phpunit';
993 $filerecord->filepath = '/';
994 $filerecord->filename = 'testfile.txt';
995 $filerecord->itemid = 0;
996
997 return $filerecord;
998 }
999
1000 public function test_create_file_from_storedfile_file_invalid() {
1001 $this->resetAfterTest(true);
1002
1003 $filerecord = $this->generate_file_record();
1004
1005 $fs = get_file_storage();
1006 $this->setExpectedException('file_exception');
1007 // Create a file from a file id which doesn't exist.
1008 $fs->create_file_from_storedfile($filerecord, 9999);
1009 }
1010
1011 public function test_create_file_from_storedfile_contextid_invalid() {
1012 $this->resetAfterTest(true);
1013
1014 $filerecord = $this->generate_file_record();
1015
1016 $fs = get_file_storage();
1017 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1018 $this->assertInstanceOf('stored_file', $file1);
1019
1020 $filerecord->filename = 'invalid.txt';
1021 $filerecord->contextid = 'invalid';
1022
1023 $this->setExpectedException('file_exception', 'Invalid contextid');
1024 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1025 }
1026
1027 public function test_create_file_from_storedfile_component_invalid() {
1028 $this->resetAfterTest(true);
1029
1030 $filerecord = $this->generate_file_record();
1031
1032 $fs = get_file_storage();
1033 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1034 $this->assertInstanceOf('stored_file', $file1);
1035
1036 $filerecord->filename = 'invalid.txt';
1037 $filerecord->component = 'bad/component';
1038
1039 $this->setExpectedException('file_exception', 'Invalid component');
1040 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1041 }
1042
1043 public function test_create_file_from_storedfile_filearea_invalid() {
1044 $this->resetAfterTest(true);
1045
1046 $filerecord = $this->generate_file_record();
1047
1048 $fs = get_file_storage();
1049 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1050 $this->assertInstanceOf('stored_file', $file1);
1051
1052 $filerecord->filename = 'invalid.txt';
1053 $filerecord->filearea = 'bad-filearea';
1054
1055 $this->setExpectedException('file_exception', 'Invalid filearea');
1056 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1057 }
1058
1059 public function test_create_file_from_storedfile_itemid_invalid() {
1060 $this->resetAfterTest(true);
1061
1062 $filerecord = $this->generate_file_record();
1063
1064 $fs = get_file_storage();
1065 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1066 $this->assertInstanceOf('stored_file', $file1);
1067
1068 $filerecord->filename = 'invalid.txt';
1069 $filerecord->itemid = 'bad-itemid';
1070
1071 $this->setExpectedException('file_exception', 'Invalid itemid');
1072 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1073 }
1074
1075 public function test_create_file_from_storedfile_filepath_invalid() {
1076 $this->resetAfterTest(true);
1077
1078 $filerecord = $this->generate_file_record();
1079
1080 $fs = get_file_storage();
1081 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1082 $this->assertInstanceOf('stored_file', $file1);
1083
1084 $filerecord->filename = 'invalid.txt';
1085 $filerecord->filepath = 'a-/bad/-filepath';
1086
1087 $this->setExpectedException('file_exception', 'Invalid file path');
1088 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1089 }
1090
1091 public function test_create_file_from_storedfile_filename_invalid() {
1092 $this->resetAfterTest(true);
1093
1094 $filerecord = $this->generate_file_record();
1095
1096 $fs = get_file_storage();
1097 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1098 $this->assertInstanceOf('stored_file', $file1);
1099
1100 $filerecord->filename = '';
1101
1102 $this->setExpectedException('file_exception', 'Invalid file name');
1103 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1104 }
1105
1106 public function test_create_file_from_storedfile_timecreated_invalid() {
1107 $this->resetAfterTest(true);
1108
1109 $filerecord = $this->generate_file_record();
1110
1111 $fs = get_file_storage();
1112 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1113 $this->assertInstanceOf('stored_file', $file1);
1114
1115 $filerecord->filename = 'invalid.txt';
1116 $filerecord->timecreated = 'today';
1117
1118 $this->setExpectedException('file_exception', 'Invalid file timecreated');
1119 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1120 }
1121
1122 public function test_create_file_from_storedfile_timemodified_invalid() {
1123 $this->resetAfterTest(true);
1124
1125 $filerecord = $this->generate_file_record();
1126
1127 $fs = get_file_storage();
1128 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1129 $this->assertInstanceOf('stored_file', $file1);
1130
1131 $filerecord->filename = 'invalid.txt';
1132 $filerecord->timemodified = 'today';
1133
1134 $this->setExpectedException('file_exception', 'Invalid file timemodified');
1135 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1136 }
1137
1138 public function test_create_file_from_storedfile_duplicate() {
1139 $this->resetAfterTest(true);
1140
1141 $filerecord = $this->generate_file_record();
1142
1143 $fs = get_file_storage();
1144 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1145 $this->assertInstanceOf('stored_file', $file1);
1146
1147 // Creating a file validating unique constraint.
1148 $this->setExpectedException('stored_file_creation_exception');
1149 $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1150 }
1151
1152 public function test_create_file_from_storedfile() {
1153 $this->resetAfterTest(true);
1154
1155 $syscontext = context_system::instance();
1156
1157 $filerecord = new stdClass();
1158 $filerecord->contextid = $syscontext->id;
1159 $filerecord->component = 'core';
1160 $filerecord->filearea = 'phpunit';
1161 $filerecord->filepath = '/';
1162 $filerecord->filename = 'testfile.txt';
1163 $filerecord->itemid = 0;
1164
1165 $fs = get_file_storage();
1166
1167 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1168 $this->assertInstanceOf('stored_file', $file1);
1169
1170 $filerecord->filename = 'test-create-file-from-storedfile.txt';
1171 $file2 = $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1172 $this->assertInstanceOf('stored_file', $file2);
1173
1174 // These will be normalised to current time..
1175 $filerecord->timecreated = -100;
1176 $filerecord->timemodified= -100;
1177 $filerecord->filename = 'test-create-file-from-storedfile-bad-dates.txt';
1178
1179 $file3 = $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1180 $this->assertInstanceOf('stored_file', $file3);
1181
1182 $this->assertNotEquals($file3->get_timemodified(), $filerecord->timemodified);
1183 $this->assertNotEquals($file3->get_timecreated(), $filerecord->timecreated);
1184 }
1185
1186 public function test_create_file_from_string_contextid_invalid() {
1187 $this->resetAfterTest(true);
1188
1189 $filerecord = $this->generate_file_record();
1190 $fs = get_file_storage();
1191
1192 $filerecord->contextid = 'invalid';
1193
1194 $this->setExpectedException('file_exception', 'Invalid contextid');
1195 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1196 }
1197
1198 public function test_create_file_from_string_component_invalid() {
1199 $this->resetAfterTest(true);
1200
1201 $filerecord = $this->generate_file_record();
1202 $fs = get_file_storage();
1203
1204 $filerecord->component = 'bad/component';
1205
1206 $this->setExpectedException('file_exception', 'Invalid component');
1207 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1208 }
1209
1210 public function test_create_file_from_string_filearea_invalid() {
1211 $this->resetAfterTest(true);
1212
1213 $filerecord = $this->generate_file_record();
1214 $fs = get_file_storage();
1215
1216 $filerecord->filearea = 'bad-filearea';
1217
1218 $this->setExpectedException('file_exception', 'Invalid filearea');
1219 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1220 }
1221
1222 public function test_create_file_from_string_itemid_invalid() {
1223 $this->resetAfterTest(true);
1224
1225 $filerecord = $this->generate_file_record();
1226 $fs = get_file_storage();
1227
1228 $filerecord->itemid = 'bad-itemid';
1229
1230 $this->setExpectedException('file_exception', 'Invalid itemid');
1231 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1232 }
1233
1234 public function test_create_file_from_string_filepath_invalid() {
1235 $this->resetAfterTest(true);
1236
1237 $filerecord = $this->generate_file_record();
1238 $fs = get_file_storage();
1239
1240 $filerecord->filepath = 'a-/bad/-filepath';
1241
1242 $this->setExpectedException('file_exception', 'Invalid file path');
1243 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1244 }
1245
1246 public function test_create_file_from_string_filename_invalid() {
1247 $this->resetAfterTest(true);
1248
1249 $filerecord = $this->generate_file_record();
1250 $fs = get_file_storage();
1251
1252 $filerecord->filename = '';
1253
1254 $this->setExpectedException('file_exception', 'Invalid file name');
1255 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1256 }
1257
1258 public function test_create_file_from_string_timecreated_invalid() {
1259 $this->resetAfterTest(true);
1260
1261 $filerecord = $this->generate_file_record();
1262 $fs = get_file_storage();
1263
1264 $filerecord->timecreated = 'today';
1265
1266 $this->setExpectedException('file_exception', 'Invalid file timecreated');
1267 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1268 }
1269
1270 public function test_create_file_from_string_timemodified_invalid() {
1271 $this->resetAfterTest(true);
1272
1273 $filerecord = $this->generate_file_record();
1274 $fs = get_file_storage();
1275
1276 $filerecord->timemodified = 'today';
1277
1278 $this->setExpectedException('file_exception', 'Invalid file timemodified');
1279 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1280 }
1281
1282 public function test_create_file_from_string_duplicate() {
1283 $this->resetAfterTest(true);
1284
1285 $filerecord = $this->generate_file_record();
1286 $fs = get_file_storage();
1287
1288 $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1289
1290 // Creating a file validating unique constraint.
1291 $this->setExpectedException('stored_file_creation_exception');
1292 $file2 = $fs->create_file_from_string($filerecord, 'text contents');
1293 }
1294
1295 public function test_create_file_from_pathname_contextid_invalid() {
1296 global $CFG;
1297 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1298
1299 $this->resetAfterTest(true);
1300
1301 $filerecord = $this->generate_file_record();
1302 $fs = get_file_storage();
1303
1304 $filerecord->contextid = 'invalid';
1305
1306 $this->setExpectedException('file_exception', 'Invalid contextid');
1307 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1308 }
1309
1310 public function test_create_file_from_pathname_component_invalid() {
1311 global $CFG;
1312 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1313
1314 $this->resetAfterTest(true);
1315
1316 $filerecord = $this->generate_file_record();
1317 $fs = get_file_storage();
1318
1319 $filerecord->component = 'bad/component';
1320
1321 $this->setExpectedException('file_exception', 'Invalid component');
1322 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1323 }
1324
1325 public function test_create_file_from_pathname_filearea_invalid() {
1326 global $CFG;
1327 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1328
1329 $this->resetAfterTest(true);
1330
1331 $filerecord = $this->generate_file_record();
1332 $fs = get_file_storage();
1333
1334 $filerecord->filearea = 'bad-filearea';
1335
1336 $this->setExpectedException('file_exception', 'Invalid filearea');
1337 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1338 }
1339
1340 public function test_create_file_from_pathname_itemid_invalid() {
1341 global $CFG;
1342 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1343
1344 $this->resetAfterTest(true);
1345
1346 $filerecord = $this->generate_file_record();
1347 $fs = get_file_storage();
1348
1349 $filerecord->itemid = 'bad-itemid';
1350
1351 $this->setExpectedException('file_exception', 'Invalid itemid');
1352 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1353 }
1354
1355 public function test_create_file_from_pathname_filepath_invalid() {
1356 global $CFG;
1357 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1358
1359 $this->resetAfterTest(true);
1360
1361 $filerecord = $this->generate_file_record();
1362 $fs = get_file_storage();
1363
1364 $filerecord->filepath = 'a-/bad/-filepath';
1365
1366 $this->setExpectedException('file_exception', 'Invalid file path');
1367 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1368 }
1369
1370 public function test_create_file_from_pathname_filename_invalid() {
1371 global $CFG;
1372 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1373
1374 $this->resetAfterTest(true);
1375
1376 $filerecord = $this->generate_file_record();
1377 $fs = get_file_storage();
1378
1379 $filerecord->filename = '';
1380
1381 $this->setExpectedException('file_exception', 'Invalid file name');
1382 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1383 }
1384
1385 public function test_create_file_from_pathname_timecreated_invalid() {
1386 global $CFG;
1387 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1388
1389 $this->resetAfterTest(true);
1390
1391 $filerecord = $this->generate_file_record();
1392 $fs = get_file_storage();
1393
1394 $filerecord->timecreated = 'today';
1395
1396 $this->setExpectedException('file_exception', 'Invalid file timecreated');
1397 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1398 }
1399
1400 public function test_create_file_from_pathname_timemodified_invalid() {
1401 global $CFG;
1402 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1403
1404 $this->resetAfterTest(true);
1405
1406 $filerecord = $this->generate_file_record();
1407 $fs = get_file_storage();
1408
1409 $filerecord->timemodified = 'today';
1410
1411 $this->setExpectedException('file_exception', 'Invalid file timemodified');
1412 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1413 }
1414
1415 public function test_create_file_from_pathname_duplicate_file() {
1416 global $CFG;
1417 $this->resetAfterTest(true);
1418
1419 $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1420
1421 $filerecord = $this->generate_file_record();
1422 $fs = get_file_storage();
1423
1424 $file1 = $fs->create_file_from_pathname($filerecord, $path);
1425 $this->assertInstanceOf('stored_file', $file1);
1426
1427 // Creating a file validating unique constraint.
1428 $this->setExpectedException('stored_file_creation_exception');
1429 $file2 = $fs->create_file_from_pathname($filerecord, $path);
1430 }
2d2c194b
DM
1431
1432 /**
1433 * Calling stored_file::delete_reference() on a non-reference file throws coding_exception
1434 */
1435 public function test_delete_reference_on_nonreference() {
1436
1437 $this->resetAfterTest(true);
1438 $user = $this->setup_three_private_files();
1439 $fs = get_file_storage();
1440 $repos = repository::get_instances(array('type'=>'user'));
1441 $repo = reset($repos);
1442
1443 $file = null;
1444 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
1445 if (!$areafile->is_directory()) {
1446 $file = $areafile;
1447 break;
1448 }
1449 }
1450 $this->assertInstanceOf('stored_file', $file);
1451 $this->assertFalse($file->is_external_file());
1452
1453 $this->setExpectedException('coding_exception');
1454 $file->delete_reference();
1455 }
1456
1457 /**
1458 * Calling stored_file::delete_reference() on a reference file does not affect other
1459 * symlinks to the same original
1460 */
1461 public function test_delete_reference_one_symlink_does_not_rule_them_all() {
1462
1463 $this->resetAfterTest(true);
1464 $user = $this->setup_three_private_files();
1465 $fs = get_file_storage();
1466 $repos = repository::get_instances(array('type'=>'user'));
1467 $repo = reset($repos);
1468
4c34571b 1469 // Create two aliases linking the same original.
2d2c194b
DM
1470
1471 $originalfile = null;
1472 foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
1473 if (!$areafile->is_directory()) {
1474 $originalfile = $areafile;
1475 break;
1476 }
1477 }
1478 $this->assertInstanceOf('stored_file', $originalfile);
1479
4c34571b 1480 // Calling delete_reference() on a non-reference file.
2d2c194b
DM
1481
1482 $originalrecord = array(
1483 'contextid' => $originalfile->get_contextid(),
1484 'component' => $originalfile->get_component(),
1485 'filearea' => $originalfile->get_filearea(),
1486 'itemid' => $originalfile->get_itemid(),
1487 'filepath' => $originalfile->get_filepath(),
1488 'filename' => $originalfile->get_filename(),
1489 );
1490
1491 $aliasrecord = $this->generate_file_record();
1492 $aliasrecord->filepath = '/A/';
1493 $aliasrecord->filename = 'symlink.txt';
1494
1495 $ref = $fs->pack_reference($originalrecord);
1496 $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1497
1498 $aliasrecord->filepath = '/B/';
1499 $aliasrecord->filename = 'symlink.txt';
1500 $ref = $fs->pack_reference($originalrecord);
1501 $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1502
4c34571b 1503 // Refetch A/symlink.txt file.
2d2c194b
DM
1504 $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1505 $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt');
1506 $this->assertTrue($symlink1->is_external_file());
1507
4c34571b 1508 // Unlink the A/symlink.txt file.
2d2c194b
DM
1509 $symlink1->delete_reference();
1510 $this->assertFalse($symlink1->is_external_file());
1511
4c34571b 1512 // Make sure that B/symlink.txt has not been affected.
2d2c194b
DM
1513 $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1514 $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt');
1515 $this->assertTrue($symlink2->is_external_file());
1516 }
3385a89c
FM
1517
1518 public function test_get_unused_filename() {
1519 global $USER;
1520 $this->resetAfterTest(true);
1521
1522 $fs = get_file_storage();
1523 $this->setAdminUser();
1524 $contextid = context_user::instance($USER->id)->id;
1525 $component = 'user';
1526 $filearea = 'private';
1527 $itemid = 0;
1528 $filepath = '/';
1529
1530 // Create some private files.
1531 $file = new stdClass;
1532 $file->contextid = $contextid;
1533 $file->component = 'user';
1534 $file->filearea = 'private';
1535 $file->itemid = 0;
1536 $file->filepath = '/';
1537 $file->source = 'test';
1538 $filenames = array('foo.txt', 'foo (1).txt', 'foo (20).txt', 'foo (999)', 'bar.jpg', 'What (a cool file).jpg',
1539 'Hurray! (1).php', 'Hurray! (2).php', 'Hurray! (9a).php', 'Hurray! (abc).php');
1540 foreach ($filenames as $key => $filename) {
1541 $file->filename = $filename;
1542 $userfile = $fs->create_file_from_string($file, "file $key $filename content");
1543 $this->assertInstanceOf('stored_file', $userfile);
1544 }
1545
1546 // Asserting new generated names.
1547 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'unused.txt');
1548 $this->assertEquals('unused.txt', $newfilename);
1549 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo.txt');
1550 $this->assertEquals('foo (21).txt', $newfilename);
1551 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (1).txt');
1552 $this->assertEquals('foo (21).txt', $newfilename);
1553 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (2).txt');
1554 $this->assertEquals('foo (2).txt', $newfilename);
1555 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (20).txt');
1556 $this->assertEquals('foo (21).txt', $newfilename);
1557 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo');
1558 $this->assertEquals('foo', $newfilename);
1559 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (123)');
1560 $this->assertEquals('foo (123)', $newfilename);
1561 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (999)');
1562 $this->assertEquals('foo (1000)', $newfilename);
1563 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.png');
1564 $this->assertEquals('bar.png', $newfilename);
1565 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (12).png');
1566 $this->assertEquals('bar (12).png', $newfilename);
1567 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.jpg');
1568 $this->assertEquals('bar (1).jpg', $newfilename);
1569 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (1).jpg');
1570 $this->assertEquals('bar (1).jpg', $newfilename);
1571 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'What (a cool file).jpg');
1572 $this->assertEquals('What (a cool file) (1).jpg', $newfilename);
1573 $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'Hurray! (1).php');
1574 $this->assertEquals('Hurray! (3).php', $newfilename);
1575
1576 $this->setExpectedException('coding_exception');
1577 $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, '');
1578 }
fd4592bb 1579}
3385a89c 1580
fd4592bb
PS
1581class test_stored_file_inspection extends stored_file {
1582 public static function get_pretected_pathname(stored_file $file) {
1583 return $file->get_pathname_by_contenthash();
1584 }
8f110835 1585}