See Release Notes
Long Term Support Release
Differences Between: [Versions 311 and 401]
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 namespace core_h5p; 18 19 use core_h5p\file_storage; 20 use core_h5p\local\library\autoloader; 21 use core_h5p\helper; 22 use file_archive; 23 use moodle_exception; 24 use ReflectionMethod; 25 use stored_file; 26 use zip_archive; 27 28 /** 29 * Test class covering the H5PFileStorage interface implementation. 30 * 31 * @package core_h5p 32 * @category test 33 * @copyright 2019 Victor Deniz <victor@moodle.com> 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 * @runTestsInSeparateProcesses 36 */ 37 class file_storage_test extends \advanced_testcase { 38 39 /** @var \core_h5p\file_storage H5P file storage instance */ 40 protected $h5p_file_storage; 41 /** @var \file_storage Core Moodle file_storage associated to the H5P file_storage */ 42 protected $h5p_fs_fs; 43 /** @var \context Moodle context of the H5P file_storage */ 44 protected $h5p_fs_context; 45 /** @var string Path to temp directory */ 46 protected $h5p_tempath; 47 /** @var \core_h5p_generator H5P generator instance */ 48 protected $h5p_generator; 49 /** @var array $files an array used in the cache tests. */ 50 protected $files = ['scripts' => [], 'styles' => []]; 51 /** @var int $libraryid an id for the library. */ 52 protected $libraryid = 1; 53 54 protected function setUp(): void { 55 parent::setUp(); 56 $this->resetAfterTest(true); 57 58 autoloader::register(); 59 60 // Fetch generator. 61 $generator = \testing_util::get_data_generator(); 62 $this->h5p_generator = $generator->get_plugin_generator('core_h5p'); 63 64 // Create file_storage_instance and create H5P temp directory. 65 $this->h5p_file_storage = new file_storage(); 66 $this->h5p_tempath = $this->h5p_file_storage->getTmpPath(); 67 check_dir_exists($this->h5p_tempath); 68 69 // Get value of protected properties. 70 $h5p_fs_rc = new \ReflectionClass(file_storage::class); 71 $h5p_file_storage_context = $h5p_fs_rc->getProperty('context'); 72 $h5p_file_storage_context->setAccessible(true); 73 $this->h5p_fs_context = $h5p_file_storage_context->getValue($this->h5p_file_storage); 74 75 $h5p_file_storage_fs = $h5p_fs_rc->getProperty('fs'); 76 $h5p_file_storage_fs->setAccessible(true); 77 $this->h5p_fs_fs = $h5p_file_storage_fs->getValue($this->h5p_file_storage); 78 } 79 80 /** 81 * Test that given the main directory of a library that all files are saved 82 * into the file system. 83 */ 84 public function test_saveLibrary(): void { 85 86 $machinename = 'TestLib'; 87 $majorversion = 1; 88 $minorversion = 0; 89 [$lib, $files] = $this->h5p_generator->create_library($this->h5p_tempath, $this->libraryid, $machinename, $majorversion, 90 $minorversion); 91 92 // Now run the API call. 93 $this->h5p_file_storage->saveLibrary($lib); 94 95 // Check that files are in the Moodle file system. 96 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT, 97 file_storage::LIBRARY_FILEAREA, '1', "/{$machinename}-{$majorversion}.{$minorversion}/", 'library.json'); 98 $filepath = "/{$machinename}-{$majorversion}.{$minorversion}/"; 99 $this->assertEquals($filepath, $file->get_filepath()); 100 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}/scripts/", 'testlib.min.js'); 103 $jsfilepath = "{$filepath}scripts/"; 104 $this->assertEquals($jsfilepath, $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}/styles/", 'testlib.min.css'); 108 $cssfilepath = "{$filepath}styles/"; 109 $this->assertEquals($cssfilepath, $file->get_filepath()); 110 } 111 112 /** 113 * Test that a content file can be saved. 114 */ 115 public function test_saveContent(): void { 116 117 $source = $this->h5p_tempath . '/' . 'content.json'; 118 $this->h5p_generator->create_file($source); 119 120 $this->h5p_file_storage->saveContent($this->h5p_tempath, ['id' => 5]); 121 122 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT, 123 file_storage::CONTENT_FILEAREA, '5', '/', 'content.json'); 124 $this->assertEquals(file_storage::CONTENT_FILEAREA, $file->get_filearea()); 125 $this->assertEquals('content.json', $file->get_filename()); 126 $this->assertEquals(5, $file->get_itemid()); 127 } 128 129 /** 130 * Test that content files located on the file system can be deleted. 131 */ 132 public function test_deleteContent(): void { 133 134 $source = $this->h5p_tempath . '/' . 'content.json'; 135 $this->h5p_generator->create_file($source); 136 137 $this->h5p_file_storage->saveContent($this->h5p_tempath, ['id' => 5]); 138 139 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT, 140 file_storage::CONTENT_FILEAREA, '5', '/', 'content.json'); 141 $this->assertEquals('content.json', $file->get_filename()); 142 143 // Now to delete the record. 144 $this->h5p_file_storage->deleteContent(['id' => 5]); 145 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT, 146 file_storage::CONTENT_FILEAREA, '5', '/', 'content.json'); 147 $this->assertFalse($file); 148 } 149 150 /** 151 * Test that returning a temp path returns what is expected by the h5p library. 152 */ 153 public function test_getTmpPath(): void { 154 155 $temparray = explode('/', $this->h5p_tempath); 156 $h5pdirectory = array_pop($temparray); 157 $this->assertTrue(stripos($h5pdirectory, 'h5p-') === 0); 158 } 159 160 /** 161 * Test that the content files can be exported to a specified location. 162 */ 163 public function test_exportContent(): void { 164 165 // Create a file to store. 166 $source = $this->h5p_tempath . '/' . 'content.json'; 167 $this->h5p_generator->create_file($source); 168 169 $this->h5p_file_storage->saveContent($this->h5p_tempath, ['id' => 5]); 170 171 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT, 172 file_storage::CONTENT_FILEAREA, '5', '/', 'content.json'); 173 $this->assertEquals('content.json', $file->get_filename()); 174 175 // Now export it. 176 $destinationdirectory = $this->h5p_tempath . '/' . 'testdir'; 177 check_dir_exists($destinationdirectory); 178 179 $this->h5p_file_storage->exportContent(5, $destinationdirectory); 180 // Check that there is a file now in that directory. 181 $contents = scandir($destinationdirectory); 182 $value = array_search('content.json', $contents); 183 $this->assertEquals('content.json', $contents[$value]); 184 } 185 186 /** 187 * Test that libraries on the file system can be exported to a specified location. 188 */ 189 public function test_exportLibrary(): void { 190 191 $machinename = 'TestLib'; 192 $majorversion = 1; 193 $minorversion = 0; 194 [$lib, $files] = $this->h5p_generator->create_library($this->h5p_tempath, $this->libraryid, $machinename, $majorversion, 195 $minorversion); 196 197 // Now run the API call. 198 $this->h5p_file_storage->saveLibrary($lib); 199 200 $destinationdirectory = $this->h5p_tempath . '/' . 'testdir'; 201 check_dir_exists($destinationdirectory); 202 203 $this->h5p_file_storage->exportLibrary($lib, $destinationdirectory); 204 205 $filepath = "/{$machinename}-{$majorversion}.{$minorversion}/"; 206 // There should be at least three items here (but could be more with . and ..). 207 $this->assertFileExists($destinationdirectory . $filepath . 'library.json'); 208 $this->assertFileExists($destinationdirectory . $filepath . 'scripts/' . 'testlib.min.js'); 209 $this->assertFileExists($destinationdirectory . $filepath . 'styles/' . 'testlib.min.css'); 210 } 211 212 /** 213 * Test that an export file can be saved into the file system. 214 */ 215 public function test_saveExport(): void { 216 217 $filename = 'someexportedfile.h5p'; 218 $source = $this->h5p_tempath . '/' . $filename; 219 $this->h5p_generator->create_file($source); 220 221 $this->h5p_file_storage->saveExport($source, $filename); 222 223 // Check out if the file is there. 224 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT, 225 file_storage::EXPORT_FILEAREA, '0', '/', $filename); 226 $this->assertEquals(file_storage::EXPORT_FILEAREA, $file->get_filearea()); 227 } 228 229 /** 230 * Test that an exort file can be deleted from the file system. 231 * @return [type] [description] 232 */ 233 public function test_deleteExport(): void { 234 235 $filename = 'someexportedfile.h5p'; 236 $source = $this->h5p_tempath . '/' . $filename; 237 $this->h5p_generator->create_file($source); 238 239 $this->h5p_file_storage->saveExport($source, $filename); 240 241 // Check out if the file is there. 242 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT, 243 file_storage::EXPORT_FILEAREA, '0', '/', $filename); 244 $this->assertEquals(file_storage::EXPORT_FILEAREA, $file->get_filearea()); 245 246 // Time to delete. 247 $this->h5p_file_storage->deleteExport($filename); 248 249 // Check out if the file is there. 250 $file = $this->h5p_fs_fs->get_file ($this->h5p_fs_context->id, file_storage::COMPONENT, 251 file_storage::EXPORT_FILEAREA, '0', '/', $filename); 252 $this->assertFalse($file); 253 } 254 255 /** 256 * Test to check if an export file already exists on the file system. 257 */ 258 public function test_hasExport(): void { 259 260 $filename = 'someexportedfile.h5p'; 261 $source = $this->h5p_tempath . '/' . $filename; 262 $this->h5p_generator->create_file($source); 263 264 // Check that it doesn't exist in the file system. 265 $this->assertFalse($this->h5p_file_storage->hasExport($filename)); 266 267 $this->h5p_file_storage->saveExport($source, $filename); 268 // Now it should be present. 269 $this->assertTrue($this->h5p_file_storage->hasExport($filename)); 270 } 271 272 /** 273 * Test that all the library files for an H5P activity can be concatenated into "cache" files. One for js and another for css. 274 */ 275 public function test_cacheAssets(): void { 276 277 $basedirectory = $this->h5p_tempath . '/' . 'test-1.0'; 278 279 $machinename = 'TestLib'; 280 $majorversion = 1; 281 $minorversion = 0; 282 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion, 283 $minorversion); 284 array_push($this->files['scripts'], ...$libfiles['scripts']); 285 array_push($this->files['styles'], ...$libfiles['styles']); 286 287 // Now run the API call. 288 $this->h5p_file_storage->saveLibrary($lib); 289 290 // Second library. 291 $basedirectory = $this->h5p_tempath . '/' . 'supertest-2.4'; 292 293 $this->libraryid++; 294 $machinename = 'SuperTest'; 295 $majorversion = 2; 296 $minorversion = 4; 297 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion, 298 $minorversion); 299 array_push($this->files['scripts'], ...$libfiles['scripts']); 300 array_push($this->files['styles'], ...$libfiles['styles']); 301 302 $this->h5p_file_storage->saveLibrary($lib); 303 304 $this->assertCount(2, $this->files['scripts']); 305 $this->assertCount(2, $this->files['styles']); 306 307 $key = 'testhashkey'; 308 309 $this->h5p_file_storage->cacheAssets($this->files, $key); 310 $this->assertCount(1, $this->files['scripts']); 311 $this->assertCount(1, $this->files['styles']); 312 313 314 $expectedfile = '/' . file_storage::CACHED_ASSETS_FILEAREA . '/' . $key . '.js'; 315 $this->assertEquals($expectedfile, $this->files['scripts'][0]->path); 316 $expectedfile = '/' . file_storage::CACHED_ASSETS_FILEAREA . '/' . $key . '.css'; 317 $this->assertEquals($expectedfile, $this->files['styles'][0]->path); 318 } 319 320 /** 321 * Test that cached files can be retrieved via a key. 322 */ 323 public function test_getCachedAssets() { 324 325 $basedirectory = $this->h5p_tempath . '/' . 'test-1.0'; 326 327 $machinename = 'TestLib'; 328 $majorversion = 1; 329 $minorversion = 0; 330 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion, 331 $minorversion); 332 array_push($this->files['scripts'], ...$libfiles['scripts']); 333 array_push($this->files['styles'], ...$libfiles['styles']); 334 335 // Now run the API call. 336 $this->h5p_file_storage->saveLibrary($lib); 337 338 // Second library. 339 $basedirectory = $this->h5p_tempath . '/' . 'supertest-2.4'; 340 341 $this->libraryid++; 342 $machinename = 'SuperTest'; 343 $majorversion = 2; 344 $minorversion = 4; 345 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion, 346 $minorversion); 347 array_push($this->files['scripts'], ...$libfiles['scripts']); 348 array_push($this->files['styles'], ...$libfiles['styles']); 349 350 $this->h5p_file_storage->saveLibrary($lib); 351 352 $this->assertCount(2, $this->files['scripts']); 353 $this->assertCount(2, $this->files['styles']); 354 355 $key = 'testhashkey'; 356 357 $this->h5p_file_storage->cacheAssets($this->files, $key); 358 359 $testarray = $this->h5p_file_storage->getCachedAssets($key); 360 $this->assertCount(1, $testarray['scripts']); 361 $this->assertCount(1, $testarray['styles']); 362 $expectedfile = '/' . file_storage::CACHED_ASSETS_FILEAREA . '/' . $key . '.js'; 363 $this->assertEquals($expectedfile, $testarray['scripts'][0]->path); 364 $expectedfile = '/' . file_storage::CACHED_ASSETS_FILEAREA . '/' . $key . '.css'; 365 $this->assertEquals($expectedfile, $testarray['styles'][0]->path); 366 } 367 368 /** 369 * Test that cache files in the files system can be removed. 370 */ 371 public function test_deleteCachedAssets(): void { 372 $basedirectory = $this->h5p_tempath . '/' . 'test-1.0'; 373 374 $machinename = 'TestLib'; 375 $majorversion = 1; 376 $minorversion = 0; 377 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion, 378 $minorversion); 379 array_push($this->files['scripts'], ...$libfiles['scripts']); 380 array_push($this->files['styles'], ...$libfiles['styles']); 381 382 // Now run the API call. 383 $this->h5p_file_storage->saveLibrary($lib); 384 385 // Second library. 386 $basedirectory = $this->h5p_tempath . '/' . 'supertest-2.4'; 387 388 $this->libraryid++; 389 $machinename = 'SuperTest'; 390 $majorversion = 2; 391 $minorversion = 4; 392 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion, 393 $minorversion); 394 array_push($this->files['scripts'], ...$libfiles['scripts']); 395 array_push($this->files['styles'], ...$libfiles['styles']); 396 397 $this->h5p_file_storage->saveLibrary($lib); 398 399 $this->assertCount(2, $this->files['scripts']); 400 $this->assertCount(2, $this->files['styles']); 401 402 $key = 'testhashkey'; 403 404 $this->h5p_file_storage->cacheAssets($this->files, $key); 405 406 $testarray = $this->h5p_file_storage->getCachedAssets($key); 407 $this->assertCount(1, $testarray['scripts']); 408 $this->assertCount(1, $testarray['styles']); 409 410 // Time to delete. 411 $this->h5p_file_storage->deleteCachedAssets([$key]); 412 $testarray = $this->h5p_file_storage->getCachedAssets($key); 413 $this->assertNull($testarray); 414 } 415 416 /** 417 * Retrieve content from a file given a specific path. 418 */ 419 public function test_getContent() { 420 $basedirectory = $this->h5p_tempath . '/' . 'test-1.0'; 421 422 $machinename = 'TestLib'; 423 $majorversion = 1; 424 $minorversion = 0; 425 [$lib, $libfiles] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion, 426 $minorversion); 427 array_push($this->files['scripts'], ...$libfiles['scripts']); 428 array_push($this->files['styles'], ...$libfiles['styles']); 429 430 // Now run the API call. 431 $this->h5p_file_storage->saveLibrary($lib); 432 433 $content = $this->h5p_file_storage->getContent($this->files['scripts'][0]->path); 434 // The file content is created based on the file system path (\core_h5p_generator::create_file). 435 $expectedcontent = hash("md5", $basedirectory. '/' . 'scripts' . '/' . 'testlib.min.js'); 436 437 $this->assertEquals($expectedcontent, $content); 438 } 439 440 /** 441 * Test that an upgrade script can be found on the file system. 442 */ 443 public function test_getUpgradeScript() { 444 // Upload an upgrade file. 445 $machinename = 'TestLib'; 446 $majorversion = 3; 447 $minorversion = 1; 448 $filepath = '/' . "{$machinename}-{$majorversion}.{$minorversion}" . '/'; 449 $fs = get_file_storage(); 450 $filerecord = [ 451 'contextid' => \context_system::instance()->id, 452 'component' => file_storage::COMPONENT, 453 'filearea' => file_storage::LIBRARY_FILEAREA, 454 'itemid' => 15, 455 'filepath' => $filepath, 456 'filename' => 'upgrade.js' 457 ]; 458 $filestorage = new file_storage(); 459 $fs->create_file_from_string($filerecord, 'test string info'); 460 $expectedfilepath = '/' . file_storage::LIBRARY_FILEAREA . $filepath . 'upgrade.js'; 461 $this->assertEquals($expectedfilepath, $filestorage->getUpgradeScript($machinename, $majorversion, $minorversion)); 462 $this->assertNull($filestorage->getUpgradeScript($machinename, $majorversion, 7)); 463 } 464 465 /** 466 * Test that information from a source can be saved to the specified path. 467 * The zip file has the following contents 468 * - h5ptest 469 * |- content 470 * | |- content.json 471 * |- testFont 472 * | |- testfont.min.css 473 * |- testJavaScript 474 * | |- testscript.min.js 475 * |- h5p.json 476 */ 477 public function test_saveFileFromZip() { 478 479 $ziparchive = new zip_archive(); 480 $path = __DIR__ . '/fixtures/h5ptest.zip'; 481 $result = $ziparchive->open($path, file_archive::OPEN); 482 483 $files = $ziparchive->list_files(); 484 foreach ($files as $file) { 485 if (!$file->is_directory) { 486 $stream = $ziparchive->get_stream($file->index); 487 $items = explode('/', $file->pathname); 488 array_shift($items); 489 $path = implode('/', $items); 490 $this->h5p_file_storage->saveFileFromZip($this->h5p_tempath, $path, $stream); 491 $filestocheck[] = $path; 492 } 493 } 494 $ziparchive->close(); 495 496 foreach ($filestocheck as $filetocheck) { 497 $pathtocheck = $this->h5p_tempath .'/'. $filetocheck; 498 $this->assertFileExists($pathtocheck); 499 } 500 } 501 502 /** 503 * Test that a library is fully deleted from the file system 504 */ 505 public function test_delete_library() { 506 507 $basedirectory = $this->h5p_tempath . '/' . 'test-1.0'; 508 509 $machinename = 'TestLib'; 510 $majorversion = 1; 511 $minorversion = 0; 512 [$lib, $files] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion, 513 $minorversion); 514 515 // Now run the API call. 516 $this->h5p_file_storage->saveLibrary($lib); 517 518 // Save a second library to ensure we aren't deleting all libraries, but just the one specified. 519 $basedirectory = $this->h5p_tempath . '/' . 'awesomelib-2.1'; 520 521 $this->libraryid++; 522 $machinename = 'AwesomeLib'; 523 $majorversion = 2; 524 $minorversion = 1; 525 [$lib2, $files2] = $this->h5p_generator->create_library($basedirectory, $this->libraryid, $machinename, $majorversion, 526 $minorversion); 527 528 // Now run the API call. 529 $this->h5p_file_storage->saveLibrary($lib2); 530 531 $files = $this->h5p_fs_fs->get_area_files($this->h5p_fs_context->id, file_storage::COMPONENT, 532 file_storage::LIBRARY_FILEAREA); 533 $this->assertCount(14, $files); 534 535 $this->h5p_file_storage->delete_library($lib); 536 537 // Let's look at the records. 538 $files = $this->h5p_fs_fs->get_area_files($this->h5p_fs_context->id, file_storage::COMPONENT, 539 file_storage::LIBRARY_FILEAREA); 540 $this->assertCount(7, $files); 541 542 // Check that the db count is still the same after setting the libraryId to false. 543 $lib['libraryId'] = false; 544 $this->h5p_file_storage->delete_library($lib); 545 546 $files = $this->h5p_fs_fs->get_area_files($this->h5p_fs_context->id, file_storage::COMPONENT, 547 file_storage::LIBRARY_FILEAREA); 548 $this->assertCount(7, $files); 549 } 550 551 /** 552 * Test get_icon_url() function behaviour. 553 * 554 * @dataProvider get_icon_url_provider 555 * @param string $filename The name of the H5P file to load. 556 * @param bool $expected Whether the icon should exist or not. 557 */ 558 public function test_get_icon_url(string $filename, bool $expected): void { 559 global $DB; 560 561 $this->resetAfterTest(); 562 $factory = new \core_h5p\factory(); 563 564 $admin = get_admin(); 565 566 // Prepare a valid .H5P file. 567 $path = __DIR__ . '/fixtures/'.$filename; 568 569 // Libraries can be updated when the file has been created by admin, even when the current user is not the admin. 570 $this->setUser($admin); 571 $file = helper::create_fake_stored_file_from_path($path, (int)$admin->id); 572 $factory->get_framework()->set_file($file); 573 $config = (object)[ 574 'frame' => 1, 575 'export' => 1, 576 'embed' => 0, 577 'copyright' => 0, 578 ]; 579 580 $h5pid = helper::save_h5p($factory, $file, $config); 581 $h5p = $DB->get_record('h5p', ['id' => $h5pid]); 582 $h5plib = $DB->get_record('h5p_libraries', ['id' => $h5p->mainlibraryid]); 583 $iconurl = $this->h5p_file_storage->get_icon_url( 584 $h5plib->id, 585 $h5plib->machinename, 586 $h5plib->majorversion, 587 $h5plib->minorversion 588 ); 589 if ($expected) { 590 $this->assertStringContainsString(file_storage::ICON_FILENAME, $iconurl); 591 } else { 592 $this->assertFalse($iconurl); 593 } 594 } 595 596 /** 597 * Data provider for test_get_icon_url(). 598 * 599 * @return array 600 */ 601 public function get_icon_url_provider(): array { 602 return [ 603 'Icon included' => [ 604 'filltheblanks.h5p', 605 true, 606 ], 607 'Icon not included' => [ 608 'greeting-card.h5p', 609 false, 610 ], 611 ]; 612 } 613 614 /** 615 * Test the private method get_file, a wrapper for getting an H5P content file. 616 */ 617 public function test_get_file(): void { 618 619 $this->setAdminUser(); 620 $file = 'img/fake.png'; 621 $h5pcontentid = 3; 622 623 // Add a file to a H5P content. 624 $this->h5p_generator->create_content_file($file, file_storage::CONTENT_FILEAREA, $h5pcontentid); 625 626 // Set get_file method accessibility. 627 $method = new ReflectionMethod(file_storage::class, 'get_file'); 628 $method->setAccessible(true); 629 630 $contentfile = $method->invoke(new file_storage(), file_storage::CONTENT_FILEAREA, $h5pcontentid, $file); 631 632 // Check that it returns an instance of store_file. 633 $this->assertInstanceOf('stored_file', $contentfile); 634 635 // Add a file to editor. 636 $this->h5p_generator->create_content_file($file, 'draft', $h5pcontentid); 637 638 $editorfile = $method->invoke(new file_storage(), 'draft', $h5pcontentid, $file); 639 640 // Check that it returns an instance of store_file. 641 $this->assertInstanceOf('stored_file', $editorfile); 642 } 643 644 /** 645 * Test that a single file is added to Moodle files. 646 */ 647 public function test_move_file(): void { 648 649 // Create temp folder. 650 $tempfolder = make_request_directory(false); 651 652 // Create H5P content folder. 653 $filepath = '/img/'; 654 $filename = 'fake.png'; 655 $h5pcontentfolder = $tempfolder . '/fakeH5Pcontent/content' . $filepath; 656 if (!check_dir_exists($h5pcontentfolder, true, true)) { 657 throw new moodle_exception('error_creating_temp_dir', 'error', $h5pcontentfolder); 658 } 659 660 $file = $h5pcontentfolder . $filename; 661 touch($file); 662 663 $h5pcontentid = 3; 664 665 // Check the file doesn't exist in Moodle files. 666 $this->assertFalse($this->h5p_fs_fs->file_exists($this->h5p_fs_context->id, file_storage::COMPONENT, 667 file_storage::CONTENT_FILEAREA, $h5pcontentid, $filepath, $filename)); 668 669 // Set get_file method accessibility. 670 $method = new ReflectionMethod(file_storage::class, 'move_file'); 671 $method->setAccessible(true); 672 673 $method->invoke(new file_storage(), $file, $h5pcontentid); 674 675 // Check the file exist in Moodle files. 676 $this->assertTrue($this->h5p_fs_fs->file_exists($this->h5p_fs_context->id, file_storage::COMPONENT, 677 file_storage::CONTENT_FILEAREA, $h5pcontentid, $filepath, $filename)); 678 } 679 680 /** 681 * Test that a file is copied from another H5P content or the H5P editor. 682 * 683 * @return void 684 */ 685 public function test_cloneContentFile(): void { 686 687 $admin = get_admin(); 688 $usercontext = \context_user::instance($admin->id); 689 $this->setUser($admin); 690 // Upload a file to the editor. 691 $file = 'images/fake.jpg'; 692 $filepath = '/'.dirname($file).'/'; 693 $filename = basename($file); 694 695 $content = 'abcd'; 696 697 $filerecord = array( 698 'contextid' => $usercontext->id, 699 'component' => 'user', 700 'filearea' => 'draft', 701 'itemid' => 0, 702 'filepath' => $filepath, 703 'filename' => $filename, 704 ); 705 706 $this->h5p_fs_fs->create_file_from_string($filerecord, $content); 707 708 // Target H5P content, where the file will be cloned. 709 $targetcontent = new \stdClass(); 710 $targetcontent->id = 999; 711 712 // Check the file doesn't exists before cloning. 713 $this->assertFalse($this->h5p_fs_fs->get_file($this->h5p_fs_context->id, file_storage::COMPONENT, 714 file_storage::CONTENT_FILEAREA, $targetcontent->id, $filepath, $filename)); 715 716 // Copy file from the editor. 717 $this->h5p_file_storage->cloneContentFile($file, 'editor', $targetcontent); 718 719 // Check the file exists after cloning. 720 $this->assertInstanceOf(\stored_file::class, $this->h5p_fs_fs->get_file($this->h5p_fs_context->id, file_storage::COMPONENT, 721 file_storage::CONTENT_FILEAREA, $targetcontent->id, $filepath, $filename)); 722 723 // Simulate that an H5P content, with id $sourcecontentid, has a file. 724 $file = 'images/fake2.jpg'; 725 $filepath = '/'.dirname($file).'/'; 726 $filename = basename($file); 727 728 $sourcecontentid = 111; 729 $filerecord['contextid'] = $this->h5p_fs_context->id; 730 $filerecord['component'] = file_storage::COMPONENT; 731 $filerecord['filearea'] = file_storage::CONTENT_FILEAREA; 732 $filerecord['itemid'] = $sourcecontentid; 733 $filerecord['filepath'] = $filepath; 734 $filerecord['filename'] = $filename; 735 736 $this->h5p_fs_fs->create_file_from_string($filerecord, $content); 737 738 // Check the file doesn't exists before cloning. 739 $this->assertFalse($this->h5p_fs_fs->get_file($this->h5p_fs_context->id, file_storage::COMPONENT, 740 file_storage::CONTENT_FILEAREA, $targetcontent->id, $filepath, $filename)); 741 742 // Copy file from another H5P content. 743 $this->h5p_file_storage->cloneContentFile($file, $sourcecontentid, $targetcontent); 744 745 // Check the file exists after cloning. 746 $this->assertInstanceOf(\stored_file::class, $this->h5p_fs_fs->get_file($this->h5p_fs_context->id, file_storage::COMPONENT, 747 file_storage::CONTENT_FILEAREA, $targetcontent->id, $filepath, $filename)); 748 } 749 750 /** 751 * Test that a given file exists in an H5P content. 752 * 753 * @return void 754 */ 755 public function test_getContentFile(): void { 756 757 $file = 'img/fake.png'; 758 $contentid = 3; 759 760 // Add a file to a H5P content. 761 $this->h5p_generator->create_content_file($file, file_storage::CONTENT_FILEAREA, $contentid); 762 763 // Get an existing file id. 764 $fileid = $this->h5p_file_storage->getContentFile($file, $contentid); 765 $this->assertNotNull($fileid); 766 767 // Try to get a nonexistent file. 768 $fileid = $this->h5p_file_storage->getContentFile($file, 5); 769 $this->assertNull($fileid); 770 } 771 772 /** 773 * Tests that the content folder of an H5P content is imported in the Moodle filesystem. 774 */ 775 public function test_moveContentDiretory(): void { 776 777 // Create temp folder. 778 $tempfolder = make_request_directory(false); 779 780 // Create H5P content folder. 781 $h5pcontentfolder = $tempfolder . '/fakeH5Pcontent'; 782 $contentfolder = $h5pcontentfolder . '/content'; 783 if (!check_dir_exists($contentfolder, true, true)) { 784 throw new moodle_exception('error_creating_temp_dir', 'error', $contentfolder); 785 } 786 787 // Add content.json file. 788 touch($contentfolder . 'content.json'); 789 790 // Create several folders and files inside content folder. 791 $filesexpected = array(); 792 $numfolders = random_int(2, 5); 793 for ($numfolder = 1; $numfolder < $numfolders; $numfolder++) { 794 $foldername = '/folder' . $numfolder; 795 $newfolder = $contentfolder . $foldername; 796 if (!check_dir_exists($newfolder, true, true)) { 797 throw new moodle_exception('error_creating_temp_dir', 'error', $newfolder); 798 } 799 $numfiles = random_int(2, 5); 800 for ($numfile = 1; $numfile < $numfiles; $numfile++) { 801 $filename = '/file' . $numfile . '.ext'; 802 touch($newfolder . $filename); 803 $filesexpected[] = $foldername . $filename; 804 } 805 } 806 807 $targeth5pcontentid = 111; 808 $this->h5p_file_storage->moveContentDirectory($h5pcontentfolder, $targeth5pcontentid); 809 810 // Get database records. 811 $files = $this->h5p_fs_fs->get_area_files( 812 $this->h5p_fs_context->id, 813 file_storage::COMPONENT, 814 file_storage::CONTENT_FILEAREA, 815 $targeth5pcontentid, 816 'filepath, filename', 817 false 818 ); 819 820 $filepaths = array_map(static function(stored_file $file): string { 821 return $file->get_filepath() . $file->get_filename(); 822 }, $files); 823 824 // Check that created files match with database records. 825 $this->assertEquals($filesexpected, array_values($filepaths)); 826 } 827 828 /** 829 * Test that an H5P content file is removed. 830 */ 831 public function test_removeContentFile(): void { 832 833 $file = 'img/fake.png'; 834 $filepath = '/' . dirname($file) . '/'; 835 $filename = basename($file); 836 $h5pcontentid = 3; 837 838 // Add a file to a H5P content. 839 $this->h5p_generator->create_content_file($file, file_storage::CONTENT_FILEAREA, $h5pcontentid); 840 841 // Check the file exists. 842 $this->assertTrue($this->h5p_fs_fs->file_exists($this->h5p_fs_context->id, file_storage::COMPONENT, 843 file_storage::CONTENT_FILEAREA, $h5pcontentid, $filepath, $filename)); 844 845 $this->h5p_file_storage->removeContentFile($file, $h5pcontentid); 846 847 // Check the file doesn't exists. 848 $this->assertFalse($this->h5p_fs_fs->file_exists($this->h5p_fs_context->id, file_storage::COMPONENT, 849 file_storage::CONTENT_FILEAREA, $h5pcontentid, $filepath, $filename)); 850 } 851 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body