exists($file)) { $contents = file_get_contents($file); // Decode the data $json = json_decode($contents, $assoc); if (null === $json) { // JSON cannot be decoded or the recursion limit has been reached. return false; } } return $json; } /** * Checks the integrity of an H5P package by verifying the existence of libraries * and moves them to the "libraries" directory. * * @param object $h5pJson the H5P JSON object * @param string $extractedDir the path to the extracted directory * * @return bool true if the package integrity is valid, false otherwise */ public static function checkPackageIntegrity(object $h5pJson, string $extractedDir): bool { $filesystem = new Filesystem(); $h5pDir = dirname($extractedDir, 2); $sharedLibrariesDir = $h5pDir.'/libraries'; // Move 'content' directory one level back (H5P specification) $filesystem->mirror($extractedDir.'/content', $extractedDir, null, ['override' => true]); $filesystem->remove($extractedDir.'/content'); // Get the list of preloaded dependencies $preloadedDependencies = $h5pJson->preloadedDependencies; // Check the existence of each library in the extracted directory foreach ($preloadedDependencies as $dependency) { $libraryName = $dependency->machineName; $majorVersion = $dependency->majorVersion; $minorVersion = $dependency->minorVersion; $libraryFolderName = api_replace_dangerous_char($libraryName.'-'.$majorVersion.'.'.$minorVersion); $libraryPath = $extractedDir.'/'.$libraryFolderName; // Check if the library folder exists if (!$filesystem->exists($libraryPath)) { return false; } // Move the entire folder to the "libraries" directory $targetPath = $sharedLibrariesDir.'/'.$libraryFolderName; $filesystem->rename($libraryPath, $targetPath, true); } return true; } /** * Stores the H5P package information in the database. * * @param string $packagePath the path to the H5P package file * @param object $h5pJson the parsed H5P JSON object * @param Course $course the course entity related to the package * @param Session|null $session the session entity related to the package * @param array|null $values the advance options in upload form */ public static function storeH5pPackage( string $packagePath, object $h5pJson, Course $course, Session $session = null, array $values = null ) { $entityManager = \Database::getManager(); // Go back 2 directories $h5pDir = dirname($packagePath, 2); $sharedLibrariesDir = $h5pDir.'/libraries'; $mainLibraryName = $h5pJson->mainLibrary; $relativePath = api_get_path(REL_COURSE_PATH).$course->getDirectory().'/h5p/'; $h5pImport = new H5pImport(); $h5pImport->setName($h5pJson->title); $h5pImport->setPath($packagePath); if ($values) { $h5pImport->setDescription($values['description']); } $h5pImport->setRelativePath($relativePath); $h5pImport->setCourse($course); $h5pImport->setSession($session); $entityManager->persist($h5pImport); $libraries = $h5pJson->preloadedDependencies; foreach ($libraries as $libraryData) { $library = $entityManager ->getRepository(H5pImportLibrary::class) ->findOneBy( [ 'machineName' => $libraryData->machineName, 'majorVersion' => $libraryData->majorVersion, 'minorVersion' => $libraryData->minorVersion, 'course' => $course, ] ) ; if (null === $library) { $auxFullName = $libraryData->machineName.'-'.$libraryData->majorVersion.'.'.$libraryData->minorVersion; $libraryOwnJson = self::getJson($sharedLibrariesDir.'/'.$auxFullName.'/library.json'); $library = new H5pImportLibrary(); $library->setMachineName($libraryData->machineName); $library->setTitle($libraryOwnJson->title); $library->setMajorVersion($libraryData->majorVersion); $library->setMinorVersion($libraryData->minorVersion); $library->setPatchVersion($libraryOwnJson->patchVersion); $library->setRunnable($libraryOwnJson->runnable); $library->setEmbedTypes($libraryOwnJson->embedTypes); $library->setPreloadedJs($libraryOwnJson->preloadedJs); $library->setPreloadedCss($libraryOwnJson->preloadedCss); $library->setLibraryPath($sharedLibrariesDir.'/'.$auxFullName); $library->setCourse($course); $entityManager->persist($library); $entityManager->flush(); } $h5pImport->addLibraries($library); if ($mainLibraryName === $libraryData->machineName) { $h5pImport->setMainLibrary($library); } $entityManager->persist($h5pImport); $entityManager->flush(); } } /** * Deletes an H5P package from the database and the disk. * * @param H5pImport $h5pImport the H5P import entity representing the package to delete * * @return bool true if the package was successfully deleted, false otherwise */ public static function deleteH5pPackage(H5pImport $h5pImport): bool { $packagePath = $h5pImport->getPath(); $entityManager = \Database::getManager(); $entityManager->remove($h5pImport); $entityManager->flush(); $filesystem = new Filesystem(); if ($filesystem->exists($packagePath)) { try { $filesystem->remove($packagePath); } catch (\Exception $e) { return false; } } return true; } /** * Get core settings for H5P content. * * @param H5pImport $h5pImport the H5pImport object * @param \H5PCore $h5pCore the H5PCore object * * @return array the core settings for H5P content */ public static function getCoreSettings(H5pImport $h5pImport, H5PCore $h5pCore): array { $originIsLearnpath = 'learnpath' === api_get_origin(); $settings = [ 'baseUrl' => api_get_path(WEB_PATH), 'url' => $h5pImport->getRelativePath(), 'postUserStatistics' => true, 'ajax' => [ 'setFinished' => api_get_path(WEB_PLUGIN_PATH).'h5pimport/src/ajax.php?action=set_finished&h5pId='.$h5pImport->getIid().'&learnpath='.$originIsLearnpath.'&token='.\H5PCore::createToken('result'), 'contentUserData' => api_get_path(WEB_PLUGIN_PATH).'h5pimport/src/ajax.php?action=content_user_data&h5pId='.$h5pImport->getIid().'&token='.\H5PCore::createToken('content'), ], 'saveFreq' => false, 'l10n' => [ 'H5P' => $h5pCore->getLocalization(), ], // 'hubIsEnabled' => variable_get('h5p_hub_is_enabled', TRUE) ? TRUE : FALSE, 'crossorigin' => false, // 'crossoriginCacheBuster' => variable_get('h5p_crossorigin_cache_buster', NULL), // 'libraryConfig' => $core->h5pF->getLibraryConfig(), 'pluginCacheBuster' => '?0', 'libraryUrl' => $h5pImport->getMainLibrary()->getLibraryPath().'/js', ]; $loggedUser = api_get_user_info(); if ($loggedUser) { $settings['user'] = [ 'name' => $loggedUser['complete_name'], 'mail' => $loggedUser['email'], ]; } return $settings; } /** * Get the core assets. * * @return array[]|bool an array containing CSS and JS assets or false if some core assets missing */ public static function getCoreAssets() { $assets = [ 'css' => [], 'js' => [], ]; // Add CSS assets foreach (\H5PCore::$styles as $style) { $auxAssetPath = 'vendor/h5p/h5p-core/'.$style; $assets['css'][] = api_get_path(WEB_PATH).$auxAssetPath; if (!file_exists(api_get_path(SYS_PATH).$auxAssetPath)) { return false; } } // Add JS assets foreach (\H5PCore::$scripts as $script) { $auxAssetPath = 'vendor/h5p/h5p-core/'.$script; $auxUrl = api_get_path(WEB_PATH).$auxAssetPath; $assets['js'][] = $auxUrl; if (!file_exists(api_get_path(SYS_PATH).$auxAssetPath)) { return false; } } return $assets; } /** * Return the content body for the H5PIntegration javascript object. * * @param mixed $h5pNode */ public static function getContentSettings($h5pNode, H5PCore $h5pCore): array { $filtered = $h5pCore->filterParameters($h5pNode); $contentUserData = [ 0 => [ 'state' => '{}', ], ]; // ToDo Use $h5pCore->getDisplayOptionsForView() function $displayOptions = [ 'frame' => api_get_course_plugin_setting('h5pimport', 'frame'), 'embed' => api_get_course_plugin_setting('h5pimport', 'embed'), 'copyright' => api_get_course_plugin_setting('h5pimport', 'copyright'), 'icon' => api_get_course_plugin_setting('h5pimport', 'icon'), ]; return [ 'library' => \H5PCore::libraryToString($h5pNode['library']), 'jsonContent' => $h5pNode['params'], 'fullScreen' => $h5pNode['library']['fullscreen'], 'exportUrl' => '', 'language' => 'en', 'filtered' => $filtered, 'embedCode' => '', 'resizeCode' => '', 'mainId' => $h5pNode['mainId'], 'url' => $h5pNode['url'], 'contentUserData' => $contentUserData, 'displayOptions' => $displayOptions, 'metadata' => $h5pNode['metadata'], ]; } /** * Convert H5P dependencies to a library list. * * @param array $dependencies the H5P dependencies * * @return array the library list with machine names as keys and version information as values */ public static function h5pDependenciesToLibraryList(array $dependencies): array { $libraryList = []; foreach ($dependencies as $dependency) { $libraryList[$dependency['machineName']] = [ 'majorVersion' => $dependency['majorVersion'], 'minorVersion' => $dependency['minorVersion'], ]; } return $libraryList; } }