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