328 lines
12 KiB
PHP
328 lines
12 KiB
PHP
<?php
|
|
|
|
// For licensing terms, see /license.txt
|
|
|
|
namespace Chamilo\PluginBundle\H5pImport\H5pImporter;
|
|
|
|
use Chamilo\CoreBundle\Entity\Course;
|
|
use Chamilo\CoreBundle\Entity\Session;
|
|
use Chamilo\PluginBundle\Entity\H5pImport\H5pImport;
|
|
use Chamilo\PluginBundle\Entity\H5pImport\H5pImportLibrary;
|
|
use Database;
|
|
use H5PCore;
|
|
use Symfony\Component\Filesystem\Filesystem;
|
|
|
|
class H5pPackageTools
|
|
{
|
|
/**
|
|
* Help read JSON from the archive.
|
|
*
|
|
* @return mixed JSON content if valid or FALSE for invalid
|
|
*/
|
|
public static function getJson(string $file, bool $assoc = false)
|
|
{
|
|
$fs = new Filesystem();
|
|
$json = false;
|
|
|
|
if ($fs->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' => '<iframe src="'.api_get_course_url().'h5p/embed/'.$h5pNode['mainId'].'" width=":w" height=":h" frameborder="0" allowfullscreen="allowfullscreen" allow="geolocation *; microphone *; camera *; midi *; encrypted-media *" title="'.$h5pNode['title'].'"></iframe>',
|
|
'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;
|
|
}
|
|
}
|