MDL-67100 core_h5p: Add autoloader to the h5p_file_storage_test
[moodle.git] / h5p / tests / h5p_file_storage_test.php
CommitLineData
9ea303e7
AG
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Testing the H5P H5PFileStorage interface implementation.
19 *
20 * @package core_h5p
21 * @category test
22 * @copyright 2019 Victor Deniz <victor@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26namespace core_h5p\local\tests;
27
28use core_h5p\file_storage;
ca7de4b6 29use core_h5p\autoloader;
9ea303e7
AG
30use file_archive;
31use zip_archive;
32
33defined('MOODLE_INTERNAL') || die();
34
35/**
36 * Test class covering the H5PFileStorage interface implementation.
37 *
38 * @package core_h5p
39 * @copyright 2019 Victor Deniz <victor@moodle.com>
40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41 */
42class h5p_file_storage_testcase extends \advanced_testcase {
43
44 /** @var \core_h5p\file_storage H5P file storage instance */
45 protected $h5p_file_storage;
46 /** @var \file_storage Core Moodle file_storage associated to the H5P file_storage */
47 protected $h5p_fs_fs;
48 /** @var \context Moodle context of the H5P file_storage */
49 protected $h5p_fs_context;
50 /** @var string Path to temp directory */
51 protected $h5p_tempath;
52 /** @var \core_h5p_generator H5P generator instance */
53 protected $h5p_generator;
54 /** @var array $files an array used in the cache tests. */
55 protected $files = ['scripts' => [], 'styles' => []];
56 /** @var int $libraryid an id for the library. */
57 protected $libraryid = 1;
58
59 protected function setUp() {
60 parent::setUp();
61 $this->resetAfterTest(true);
62
ca7de4b6
SA
63 autoloader::register();
64
9ea303e7
AG
65 // Fetch generator.
66 $generator = \testing_util::get_data_generator();
67 $this->h5p_generator = $generator->get_plugin_generator('core_h5p');
68
69 // Create file_storage_instance and create H5P temp directory.
70 $this->h5p_file_storage = new file_storage();
71 $this->h5p_tempath = $this->h5p_file_storage->getTmpPath();
72 check_dir_exists($this->h5p_tempath);
73
74 // Get value of protected properties.
75 $h5p_fs_rc = new \ReflectionClass(file_storage::class);
76 $h5p_file_storage_context = $h5p_fs_rc->getProperty('context');
77 $h5p_file_storage_context->setAccessible(true);
78 $this->h5p_fs_context = $h5p_file_storage_context->getValue($this->h5p_file_storage);
79
80 $h5p_file_storage_fs = $h5p_fs_rc->getProperty('fs');
81 $h5p_file_storage_fs->setAccessible(true);
82 $this->h5p_fs_fs = $h5p_file_storage_fs->getValue($this->h5p_file_storage);
83 }
84
85 /**
86 * Test that given the main directory of a library that all files are saved
87 * into the file system.
88 */
89 public function test_saveLibrary(): void {
90
91 $machinename = 'TestLib';
92 $majorversion = 1;
93 $minorversion = 0;
94 [$lib, $files] = $this->h5p_generator->create_library($this->h5p_tempath, $this->libraryid, $machinename, $majorversion,
95 $minorversion);
96
97 // Now run the API call.
98 $this->h5p_file_storage->saveLibrary($lib);
99
100 // Check that files are in the Moodle file system.
101 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT,
102 file_storage::LIBRARY_FILEAREA, '1', "/{$machinename}-{$majorversion}.{$minorversion}/", 'library.json');
103 $filepath = "/{$machinename}-{$majorversion}.{$minorversion}/";
104 $this->assertEquals($filepath, $file->get_filepath());
105
106 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT,
107 file_storage::LIBRARY_FILEAREA, '1', "/{$machinename}-{$majorversion}.{$minorversion}/scripts/", 'testlib.min.js');
108 $jsfilepath = "{$filepath}scripts/";
109 $this->assertEquals($jsfilepath, $file->get_filepath());
110
111 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT,
112 file_storage::LIBRARY_FILEAREA, '1', "/{$machinename}-{$majorversion}.{$minorversion}/styles/", 'testlib.min.css');
113 $cssfilepath = "{$filepath}styles/";
114 $this->assertEquals($cssfilepath, $file->get_filepath());
115 }
116
117 /**
118 * Test that a content file can be saved.
119 */
120 public function test_saveContent(): void {
121
122 $source = $this->h5p_tempath . '/' . 'content.json';
123 $this->h5p_generator->create_file($source);
124
125 $this->h5p_file_storage->saveContent($this->h5p_tempath, ['id' => 5]);
126
127 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT,
128 file_storage::CONTENT_FILEAREA, '5', '/', 'content.json');
129 $this->assertEquals(file_storage::CONTENT_FILEAREA, $file->get_filearea());
130 $this->assertEquals('content.json', $file->get_filename());
131 $this->assertEquals(5, $file->get_itemid());
132 }
133
134 /**
135 * Test that content files located on the file system can be deleted.
136 */
137 public function test_deleteContent(): void {
138
139 $source = $this->h5p_tempath . '/' . 'content.json';
140 $this->h5p_generator->create_file($source);
141
142 $this->h5p_file_storage->saveContent($this->h5p_tempath, ['id' => 5]);
143
144 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT,
145 file_storage::CONTENT_FILEAREA, '5', '/', 'content.json');
146 $this->assertEquals('content.json', $file->get_filename());
147
148 // Now to delete the record.
149 $this->h5p_file_storage->deleteContent(['id' => 5]);
150 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT,
151 file_storage::CONTENT_FILEAREA, '5', '/', 'content.json');
152 $this->assertFalse($file);
153 }
154
155 /**
156 * Test that returning a temp path returns what is expected by the h5p library.
157 */
158 public function test_getTmpPath(): void {
159
160 $temparray = explode('/', $this->h5p_tempath);
161 $h5pdirectory = array_pop($temparray);
162 $this->assertTrue(stripos($h5pdirectory, 'h5p-') === 0);
163 }
164
165 /**
166 * Test that the content files can be exported to a specified location.
167 */
168 public function test_exportContent(): void {
169
170 // Create a file to store.
171 $source = $this->h5p_tempath . '/' . 'content.json';
172 $this->h5p_generator->create_file($source);
173
174 $this->h5p_file_storage->saveContent($this->h5p_tempath, ['id' => 5]);
175
176 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT,
177 file_storage::CONTENT_FILEAREA, '5', '/', 'content.json');
178 $this->assertEquals('content.json', $file->get_filename());
179
180 // Now export it.
181 $destinationdirectory = $this->h5p_tempath . '/' . 'testdir';
182 check_dir_exists($destinationdirectory);
183
184 $this->h5p_file_storage->exportContent(5, $destinationdirectory);
185 // Check that there is a file now in that directory.
186 $contents = scandir($destinationdirectory);
187 $value = array_search('content.json', $contents);
188 $this->assertEquals('content.json', $contents[$value]);
189 }
190
191 /**
192 * Test that libraries on the file system can be exported to a specified location.
193 */
194 public function test_exportLibrary(): void {
195
196 $machinename = 'TestLib';
197 $majorversion = 1;
198 $minorversion = 0;
199 [$lib, $files] = $this->h5p_generator->create_library($this->h5p_tempath, $this->libraryid, $machinename, $majorversion,
200 $minorversion);
201
202 // Now run the API call.
203 $this->h5p_file_storage->saveLibrary($lib);
204
205 $destinationdirectory = $this->h5p_tempath . '/' . 'testdir';
206 check_dir_exists($destinationdirectory);
207
208 $this->h5p_file_storage->exportLibrary($lib, $destinationdirectory);
209
210 $filepath = "/{$machinename}-{$majorversion}.{$minorversion}/";
211 // There should be at least three items here (but could be more with . and ..).
212 $this->assertFileExists($destinationdirectory . $filepath . 'library.json');
213 $this->assertFileExists($destinationdirectory . $filepath . 'scripts/' . 'testlib.min.js');
214 $this->assertFileExists($destinationdirectory . $filepath . 'styles/' . 'testlib.min.css');
215 }
216
217 /**
218 * Test that an export file can be saved into the file system.
219 */
220 public function test_saveExport(): void {
221
222 $filename = 'someexportedfile.h5p';
223 $source = $this->h5p_tempath . '/' . $filename;
224 $this->h5p_generator->create_file($source);
225
226 $this->h5p_file_storage->saveExport($source, $filename);
227
228 // Check out if the file is there.
229 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT,
230 file_storage::EXPORT_FILEAREA, '0', '/', $filename);
231 $this->assertEquals(file_storage::EXPORT_FILEAREA, $file->get_filearea());
232 }
233
234 /**
235 * Test that an exort file can be deleted from the file system.
236 * @return [type] [description]
237 */
238 public function test_deleteExport(): void {
239
240 $filename = 'someexportedfile.h5p';
241 $source = $this->h5p_tempath . '/' . $filename;
242 $this->h5p_generator->create_file($source);
243
244 $this->h5p_file_storage->saveExport($source, $filename);
245
246 // Check out if the file is there.
247 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT,
248 file_storage::EXPORT_FILEAREA, '0', '/', $filename);
249 $this->assertEquals(file_storage::EXPORT_FILEAREA, $file->get_filearea());
250
251 // Time to delete.
252 $this->h5p_file_storage->deleteExport($filename);
253
254 // Check out if the file is there.
255 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT,
256 file_storage::EXPORT_FILEAREA, '0', '/', $filename);
257 $this->assertFalse($file);
258 }
259
260 /**
261 * Test to check if an export file already exists on the file system.
262 */
263 public function test_hasExport(): void {
264
265 $filename = 'someexportedfile.h5p';
266 $source = $this->h5p_tempath . '/' . $filename;
267 $this->h5p_generator->create_file($source);
268
269 // Check that it doesn't exist in the file system.
270 $this->assertFalse($this->h5p_file_storage->hasExport($filename));
271
272 $this->h5p_file_storage->saveExport($source, $filename);
273 // Now it should be present.
274 $this->assertTrue($this->h5p_file_storage->hasExport($filename));
275 }
276
277 /**
278 * Test that all the library files for an H5P activity can be concatenated into "cache" files. One for js and another for css.
279 */
280 public function test_cacheAssets(): void {
281
282 $basedirectory = $this->h5p_tempath . '/' . 'test-1.0';
283
284 $machinename = 'TestLib';
285 $majorversion = 1;
286 $minorversion = 0;
287 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion,
288 $minorversion);
289 array_push($this->files['scripts'], ...$libfiles['scripts']);
290 array_push($this->files['styles'], ...$libfiles['styles']);
291
292 // Now run the API call.
293 $this->h5p_file_storage->saveLibrary($lib);
294
295 // Second library.
296 $basedirectory = $this->h5p_tempath . '/' . 'supertest-2.4';
297
298 $this->libraryid++;
299 $machinename = 'SuperTest';
300 $majorversion = 2;
301 $minorversion = 4;
302 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion,
303 $minorversion);
304 array_push($this->files['scripts'], ...$libfiles['scripts']);
305 array_push($this->files['styles'], ...$libfiles['styles']);
306
307 $this->h5p_file_storage->saveLibrary($lib);
308
309 $this->assertCount(2, $this->files['scripts']);
310 $this->assertCount(2, $this->files['styles']);
311
312 $key = 'testhashkey';
313
314 $this->h5p_file_storage->cacheAssets($this->files, $key);
315 $this->assertCount(1, $this->files['scripts']);
316 $this->assertCount(1, $this->files['styles']);
317
318
319 $expectedfile = '/' . file_storage::CACHED_ASSETS_FILEAREA . '/' . $key . '.js';
320 $this->assertEquals($expectedfile, $this->files['scripts'][0]->path);
321 $expectedfile = '/' . file_storage::CACHED_ASSETS_FILEAREA . '/' . $key . '.css';
322 $this->assertEquals($expectedfile, $this->files['styles'][0]->path);
323 }
324
325 /**
326 * Test that cached files can be retrieved via a key.
327 */
328 public function test_getCachedAssets() {
329
330 $basedirectory = $this->h5p_tempath . '/' . 'test-1.0';
331
332 $machinename = 'TestLib';
333 $majorversion = 1;
334 $minorversion = 0;
335 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion,
336 $minorversion);
337 array_push($this->files['scripts'], ...$libfiles['scripts']);
338 array_push($this->files['styles'], ...$libfiles['styles']);
339
340 // Now run the API call.
341 $this->h5p_file_storage->saveLibrary($lib);
342
343 // Second library.
344 $basedirectory = $this->h5p_tempath . '/' . 'supertest-2.4';
345
346 $this->libraryid++;
347 $machinename = 'SuperTest';
348 $majorversion = 2;
349 $minorversion = 4;
350 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion,
351 $minorversion);
352 array_push($this->files['scripts'], ...$libfiles['scripts']);
353 array_push($this->files['styles'], ...$libfiles['styles']);
354
355 $this->h5p_file_storage->saveLibrary($lib);
356
357 $this->assertCount(2, $this->files['scripts']);
358 $this->assertCount(2, $this->files['styles']);
359
360 $key = 'testhashkey';
361
362 $this->h5p_file_storage->cacheAssets($this->files, $key);
363
364 $testarray = $this->h5p_file_storage->getCachedAssets($key);
365 $this->assertCount(1, $testarray['scripts']);
366 $this->assertCount(1, $testarray['styles']);
367 $expectedfile = '/' . file_storage::CACHED_ASSETS_FILEAREA . '/' . $key . '.js';
368 $this->assertEquals($expectedfile, $testarray['scripts'][0]->path);
369 $expectedfile = '/' . file_storage::CACHED_ASSETS_FILEAREA . '/' . $key . '.css';
370 $this->assertEquals($expectedfile, $testarray['styles'][0]->path);
371 }
372
373 /**
374 * Test that cache files in the files system can be removed.
375 */
376 public function test_deleteCachedAssets(): void {
377 $basedirectory = $this->h5p_tempath . '/' . 'test-1.0';
378
379 $machinename = 'TestLib';
380 $majorversion = 1;
381 $minorversion = 0;
382 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion,
383 $minorversion);
384 array_push($this->files['scripts'], ...$libfiles['scripts']);
385 array_push($this->files['styles'], ...$libfiles['styles']);
386
387 // Now run the API call.
388 $this->h5p_file_storage->saveLibrary($lib);
389
390 // Second library.
391 $basedirectory = $this->h5p_tempath . '/' . 'supertest-2.4';
392
393 $this->libraryid++;
394 $machinename = 'SuperTest';
395 $majorversion = 2;
396 $minorversion = 4;
397 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion,
398 $minorversion);
399 array_push($this->files['scripts'], ...$libfiles['scripts']);
400 array_push($this->files['styles'], ...$libfiles['styles']);
401
402 $this->h5p_file_storage->saveLibrary($lib);
403
404 $this->assertCount(2, $this->files['scripts']);
405 $this->assertCount(2, $this->files['styles']);
406
407 $key = 'testhashkey';
408
409 $this->h5p_file_storage->cacheAssets($this->files, $key);
410
411 $testarray = $this->h5p_file_storage->getCachedAssets($key);
412 $this->assertCount(1, $testarray['scripts']);
413 $this->assertCount(1, $testarray['styles']);
414
415 // Time to delete.
416 $this->h5p_file_storage->deleteCachedAssets([$key]);
417 $testarray = $this->h5p_file_storage->getCachedAssets($key);
418 $this->assertNull($testarray);
419 }
420
421 /**
422 * Retrieve content from a file given a specific path.
423 */
424 public function test_getContent() {
425 $basedirectory = $this->h5p_tempath . '/' . 'test-1.0';
426
427 $machinename = 'TestLib';
428 $majorversion = 1;
429 $minorversion = 0;
430 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion,
431 $minorversion);
432 array_push($this->files['scripts'], ...$libfiles['scripts']);
433 array_push($this->files['styles'], ...$libfiles['styles']);
434
435 // Now run the API call.
436 $this->h5p_file_storage->saveLibrary($lib);
437
438 $content = $this->h5p_file_storage->getContent($this->files['scripts'][0]->path);
439 // The file content is created based on the file system path (\core_h5p_generator::create_file).
440 $expectedcontent = hash("md5", $basedirectory. '/' . 'scripts' . '/' . 'testlib.min.js');
441
442 $this->assertEquals($expectedcontent, $content);
443 }
444
445 /**
446 * Test that an upgrade script can be found on the file system.
447 */
448 public function test_getUpgradeScript() {
449 // Upload an upgrade file.
450 $machinename = 'TestLib';
451 $majorversion = 3;
452 $minorversion = 1;
453 $filepath = '/' . "{$machinename}-{$majorversion}.{$minorversion}" . '/';
454 $fs = get_file_storage();
455 $filerecord = [
456 'contextid' => \context_system::instance()->id,
457 'component' => file_storage::COMPONENT,
458 'filearea' => file_storage::LIBRARY_FILEAREA,
459 'itemid' => 15,
460 'filepath' => $filepath,
461 'filename' => 'upgrade.js'
462 ];
463 $filestorage = new file_storage();
464 $fs->create_file_from_string($filerecord, 'test string info');
465 $expectedfilepath = DIRECTORY_SEPARATOR . file_storage::LIBRARY_FILEAREA . $filepath . 'upgrade.js';
466 $this->assertEquals($expectedfilepath, $filestorage->getUpgradeScript($machinename, $majorversion, $minorversion));
467 $this->assertNull($filestorage->getUpgradeScript($machinename, $majorversion, 7));
468 }
469
470 /**
471 * Test that information from a source can be saved to the specified path.
472 * The zip file has the following contents
473 * - h5ptest
474 * |- content
475 * | |- content.json
476 * |- testFont
477 * | |- testfont.min.css
478 * |- testJavaScript
479 * | |- testscript.min.js
480 * |- h5p.json
481 */
482 public function test_saveFileFromZip() {
483
484 $ziparchive = new zip_archive();
485 $path = __DIR__ . '/fixtures/h5ptest.zip';
486 $result = $ziparchive->open($path, file_archive::OPEN);
487
488 $files = $ziparchive->list_files();
489 foreach ($files as $file) {
490 if (!$file->is_directory) {
491 $stream = $ziparchive->get_stream($file->index);
492 $items = explode(DIRECTORY_SEPARATOR, $file->pathname);
493 array_shift($items);
494 $path = implode(DIRECTORY_SEPARATOR, $items);
495 $this->h5p_file_storage->saveFileFromZip($this->h5p_tempath, $path, $stream);
496 $filestocheck[] = $path;
497 }
498 }
499 $ziparchive->close();
500
501 foreach ($filestocheck as $filetocheck) {
502 $pathtocheck = $this->h5p_tempath .'/'. $filetocheck;
503 $this->assertFileExists($pathtocheck);
504 }
505 }
506
507 /**
508 * Test that a library is fully deleted from the file system
509 */
510 public function test_delete_library() {
511
512 $basedirectory = $this->h5p_tempath . '/' . 'test-1.0';
513
514 $machinename = 'TestLib';
515 $majorversion = 1;
516 $minorversion = 0;
517 [$lib, $files] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion,
518 $minorversion);
519
520 // Now run the API call.
521 $this->h5p_file_storage->saveLibrary($lib);
522
523 // Save a second library to ensure we aren't deleting all libraries, but just the one specified.
524 $basedirectory = $this->h5p_tempath . '/' . 'awesomelib-2.1';
525
526 $this->libraryid++;
527 $machinename = 'AwesomeLib';
528 $majorversion = 2;
529 $minorversion = 1;
530 [$lib2, $files2] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion,
531 $minorversion);
532
533 // Now run the API call.
534 $this->h5p_file_storage->saveLibrary($lib2);
535
536 $files = $this->h5p_fs_fs->get_area_files($this->h5p_fs_context->id, file_storage::COMPONENT,
537 file_storage::LIBRARY_FILEAREA);
538 $this->assertCount(14, $files);
539
540 $this->h5p_file_storage->delete_library($lib);
541
542 // Let's look at the records.
543 $files = $this->h5p_fs_fs->get_area_files($this->h5p_fs_context->id, file_storage::COMPONENT,
544 file_storage::LIBRARY_FILEAREA);
545 $this->assertCount(7, $files);
546
547 // Check that the db count is still the same after setting the libraryId to false.
548 $lib['libraryId'] = false;
549 $this->h5p_file_storage->delete_library($lib);
550
551 $files = $this->h5p_fs_fs->get_area_files($this->h5p_fs_context->id, file_storage::COMPONENT,
552 file_storage::LIBRARY_FILEAREA);
553 $this->assertCount(7, $files);
554 }
555}