Actualización
This commit is contained in:
327
plugin/h5pimport/src/H5pPackageTools.php
Normal file
327
plugin/h5pimport/src/H5pPackageTools.php
Normal file
@@ -0,0 +1,327 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user