mirror of
https://gh.llkk.cc/https://github.com/h5p/moodle-mod_hvp.git
synced 2026-03-04 13:36:41 +08:00
1461 lines
53 KiB
PHP
1461 lines
53 KiB
PHP
<?php
|
|
// This file is part of Moodle - http://moodle.org/
|
|
//
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
/**
|
|
* \mod_hvp\framework class
|
|
*
|
|
* @package mod_hvp
|
|
* @copyright 2016 Joubel AS
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
|
|
namespace mod_hvp;
|
|
|
|
defined('MOODLE_INTERNAL') || die();
|
|
|
|
global $CFG;
|
|
require_once(__DIR__ . '/../autoloader.php');
|
|
require_once($CFG->libdir . '/filelib.php');
|
|
require_once($CFG->libdir . '/adminlib.php');
|
|
|
|
/**
|
|
* Moodle's implementation of the H5P framework interface.
|
|
*
|
|
* @package mod_hvp
|
|
* @copyright 2016 Joubel AS
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*
|
|
* @SuppressWarnings(PHPMD)
|
|
*/
|
|
class framework implements \H5PFrameworkInterface {
|
|
|
|
/**
|
|
* Get type of hvp instance
|
|
*
|
|
* @param string $type Type of hvp instance to get
|
|
* @return \H5PContentValidator|\H5PCore|\H5PStorage|\H5PValidator|\mod_hvp\framework|\H5peditor
|
|
*/
|
|
public static function instance($type = null) {
|
|
global $CFG;
|
|
static $interface, $core, $editor, $editorinterface, $editorajaxinterface;
|
|
|
|
if (!isset($interface)) {
|
|
$interface = new \mod_hvp\framework();
|
|
|
|
$fs = new \mod_hvp\file_storage();
|
|
|
|
$context = \context_system::instance();
|
|
$url = "{$CFG->httpswwwroot}/pluginfile.php/{$context->id}/mod_hvp";
|
|
|
|
$language = self::get_language();
|
|
|
|
$export = !(isset($CFG->mod_hvp_export) && $CFG->mod_hvp_export === '0');
|
|
|
|
$core = new \H5PCore($interface, $fs, $url, $language, $export);
|
|
$core->aggregateAssets = !(isset($CFG->mod_hvp_aggregate_assets) && $CFG->mod_hvp_aggregate_assets === '0');
|
|
}
|
|
|
|
switch ($type) {
|
|
case 'validator':
|
|
return new \H5PValidator($interface, $core);
|
|
case 'storage':
|
|
return new \H5PStorage($interface, $core);
|
|
case 'contentvalidator':
|
|
return new \H5PContentValidator($interface, $core);
|
|
case 'interface':
|
|
return $interface;
|
|
case 'editor':
|
|
if (empty($editorinterface)) {
|
|
$editorinterface = new \mod_hvp\editor_framework();
|
|
}
|
|
|
|
if (empty($editorajaxinterface)) {
|
|
$editorajaxinterface = new editor_ajax();
|
|
}
|
|
|
|
if (empty($editor)) {
|
|
$editor = new \H5peditor($core, $editorinterface, $editorajaxinterface);
|
|
}
|
|
return $editor;
|
|
case 'core':
|
|
default:
|
|
return $core;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if the current user has editor access, if not then return the
|
|
* given error message.
|
|
*
|
|
* @param string $error
|
|
* @return boolean
|
|
*/
|
|
public static function has_editor_access($error) {
|
|
$context = \context::instance_by_id(required_param('contextId', PARAM_RAW));
|
|
$cap = ($context->contextlevel === CONTEXT_COURSE ? 'addinstance' : 'manage');
|
|
|
|
if (!has_capability("mod/hvp:$cap", $context)) {
|
|
\H5PCore::ajaxError(get_string($error, 'hvp'));
|
|
http_response_code(403);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get current H5P language code.
|
|
*
|
|
* @return string Language Code
|
|
*/
|
|
public static function get_language() {
|
|
static $map;
|
|
|
|
if (empty($map)) {
|
|
// Create mapping for "converting" language codes.
|
|
$map = array(
|
|
'no' => 'nb'
|
|
);
|
|
}
|
|
|
|
// Get current language in Moodle.
|
|
$language = str_replace('_', '-', strtolower(\current_language()));
|
|
|
|
// Try to map.
|
|
return isset($map[$language]) ? $map[$language] : $language;
|
|
}
|
|
|
|
/**
|
|
* Implements getPlatformInfo
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getPlatformInfo() {
|
|
global $CFG;
|
|
|
|
return array(
|
|
'name' => 'Moodle',
|
|
'version' => $CFG->version,
|
|
'h5pVersion' => get_component_version('mod_hvp'),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function fetchExternalData($url, $data = null, $blocking = true, $stream = null) {
|
|
global $CFG;
|
|
|
|
if ($stream !== null) {
|
|
// Download file.
|
|
@set_time_limit(0);
|
|
|
|
// Generate local tmp file path.
|
|
$localfolder = $CFG->tempdir . uniqid('/hvp-');
|
|
$stream = $localfolder . '.h5p';
|
|
|
|
// Add folder and file paths to H5P Core.
|
|
$interface = self::instance('interface');
|
|
$interface->getUploadedH5pFolderPath($localfolder);
|
|
$interface->getUploadedH5pPath($stream);
|
|
}
|
|
|
|
$response = download_file_content($url, null, $data, true, 300, 20, false, $stream);
|
|
|
|
if (empty($response->error)) {
|
|
return $response->results;
|
|
} else {
|
|
$this->setErrorMessage($response->error, 'failed-fetching-external-data');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements setLibraryTutorialUrl
|
|
*
|
|
* Set the tutorial URL for a library. All versions of the library is set
|
|
*
|
|
* @param string $libraryname
|
|
* @param string $url
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function setLibraryTutorialUrl($libraryname, $url) {
|
|
global $DB;
|
|
|
|
$DB->execute("UPDATE {hvp_libraries} SET tutorial_url = ? WHERE machine_name = ?", array($url, $libraryname));
|
|
}
|
|
|
|
/**
|
|
* Implements setErrorMessage
|
|
*
|
|
* @param string $message translated error message
|
|
* @param string $code
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function setErrorMessage($message, $code = null) {
|
|
if ($message !== null) {
|
|
self::messages('error', $message, $code);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements setInfoMessage
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function setInfoMessage($message) {
|
|
if ($message !== null) {
|
|
self::messages('info', $message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Store messages until they can be printed to the current user
|
|
*
|
|
* @param string $type Type of messages, e.g. 'info' or 'error'
|
|
* @param string $newmessage Optional
|
|
* @param string $code
|
|
* @return array Array of stored messages
|
|
*/
|
|
public static function messages($type, $newmessage = null, $code = null) {
|
|
static $m = 'mod_hvp_messages';
|
|
|
|
if ($newmessage === null) {
|
|
// Return and reset messages.
|
|
$messages = isset($_SESSION[$m][$type]) ? $_SESSION[$m][$type] : array();
|
|
unset($_SESSION[$m][$type]);
|
|
if (empty($_SESSION[$m])) {
|
|
unset($_SESSION[$m]);
|
|
}
|
|
return $messages;
|
|
}
|
|
|
|
// We expect to get out an array of strings when getting info
|
|
// and an array of objects when getting errors for consistency across platforms.
|
|
// This implementation should be improved for consistency across the data type returned here.
|
|
if ($type === 'error') {
|
|
$_SESSION[$m][$type][] = (object)array(
|
|
'code' => $code,
|
|
'message' => $newmessage
|
|
);
|
|
} else {
|
|
$_SESSION[$m][$type][] = $newmessage;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Simple print of given messages.
|
|
*
|
|
* @param string $type One of error|info
|
|
* @param array $messages
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public static function printMessages($type, $messages) {
|
|
global $OUTPUT;
|
|
foreach ($messages as $message) {
|
|
$out = $type === 'error' ? $message->message : $message;
|
|
print $OUTPUT->notification($out, ($type === 'error' ? 'notifyproblem' : 'notifymessage'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements getMessages
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getMessages($type) {
|
|
return self::messages($type);
|
|
}
|
|
|
|
/**
|
|
* Implements t
|
|
*/
|
|
public function t($message, $replacements = array()) {
|
|
static $translationsmap;
|
|
|
|
if (empty($translationsmap)) {
|
|
// Create mapping.
|
|
// @codingStandardsIgnoreStart
|
|
$translationsmap = [
|
|
'Your PHP version does not support ZipArchive.' => 'noziparchive',
|
|
'The file you uploaded is not a valid HTML5 Package (It does not have the .h5p file extension)' => 'noextension',
|
|
'The file you uploaded is not a valid HTML5 Package (We are unable to unzip it)' => 'nounzip',
|
|
'Could not parse the main h5p.json file' => 'noparse',
|
|
'The main h5p.json file is not valid' => 'nojson',
|
|
'Invalid content folder' => 'invalidcontentfolder',
|
|
'Could not find or parse the content.json file' => 'nocontent',
|
|
'Library directory name must match machineName or machineName-majorVersion.minorVersion (from library.json). (Directory: %directoryName , machineName: %machineName, majorVersion: %majorVersion, minorVersion: %minorVersion)' => 'librarydirectoryerror',
|
|
'A valid content folder is missing' => 'missingcontentfolder',
|
|
'A valid main h5p.json file is missing' => 'invalidmainjson',
|
|
'Missing required library @library' => 'missinglibrary',
|
|
"Note that the libraries may exist in the file you uploaded, but you're not allowed to upload new libraries. Contact the site administrator about this." => 'missinguploadpermissions',
|
|
'Invalid library name: %name' => 'invalidlibraryname',
|
|
'Could not find library.json file with valid json format for library %name' => 'missinglibraryjson',
|
|
'Invalid semantics.json file has been included in the library %name' => 'invalidsemanticsjson',
|
|
'Invalid language file %file in library %library' => 'invalidlanguagefile',
|
|
'Invalid language file %languageFile has been included in the library %name' => 'invalidlanguagefile2',
|
|
'The file "%file" is missing from library: "%name"' => 'missinglibraryfile',
|
|
'The system was unable to install the <em>%component</em> component from the package, it requires a newer version of the H5P plugin. This site is currently running version %current, whereas the required version is %required or higher. You should consider upgrading and then try again.' => 'missingcoreversion',
|
|
"Invalid data provided for %property in %library. Boolean expected." => 'invalidlibrarydataboolean',
|
|
"Invalid data provided for %property in %library" => 'invalidlibrarydata',
|
|
"Can't read the property %property in %library" => 'invalidlibraryproperty',
|
|
'The required property %property is missing from %library' => 'missinglibraryproperty',
|
|
'Illegal option %option in %library' => 'invalidlibraryoption',
|
|
'Added %new new H5P library and updated %old old one.' => 'addedandupdatedss',
|
|
'Added %new new H5P library and updated %old old ones.' => 'addedandupdatedsp',
|
|
'Added %new new H5P libraries and updated %old old one.' => 'addedandupdatedps',
|
|
'Added %new new H5P libraries and updated %old old ones.' => 'addedandupdatedpp',
|
|
'Added %new new H5P library.' => 'addednewlibrary',
|
|
'Added %new new H5P libraries.' => 'addednewlibraries',
|
|
'Updated %old H5P library.' => 'updatedlibrary',
|
|
'Updated %old H5P libraries.' => 'updatedlibraries',
|
|
'Missing dependency @dep required by @lib.' => 'missingdependency',
|
|
'Provided string is not valid according to regexp in semantics. (value: \"%value\", regexp: \"%regexp\")' => 'invalidstring',
|
|
'File "%filename" not allowed. Only files with the following extensions are allowed: %files-allowed.' => 'invalidfile',
|
|
'Invalid selected option in multi-select.' => 'invalidmultiselectoption',
|
|
'Invalid selected option in select.' => 'invalidselectoption',
|
|
'H5P internal error: unknown content type "@type" in semantics. Removing content!' => 'invalidsemanticstype',
|
|
'Copyright information' => 'copyrightinfo',
|
|
'Title' => 'title',
|
|
'Author' => 'author',
|
|
'Year(s)' => 'years',
|
|
'Year' => 'year',
|
|
'Source' => 'source',
|
|
'License' => 'license',
|
|
'Undisclosed' => 'undisclosed',
|
|
'Attribution 4.0' => 'attribution',
|
|
'Attribution-ShareAlike 4.0' => 'attributionsa',
|
|
'Attribution-NoDerivs 4.0' => 'attributionnd',
|
|
'Attribution-NonCommercial 4.0' => 'attributionnc',
|
|
'Attribution-NonCommercial-ShareAlike 4.0' => 'attributionncsa',
|
|
'Attribution-NonCommercial-NoDerivs 4.0' => 'attributionncnd',
|
|
'Attribution' => 'noversionattribution',
|
|
'Attribution-ShareAlike' => 'noversionattributionsa',
|
|
'Attribution-NoDerivs' => 'noversionattributionnd',
|
|
'Attribution-NonCommercial' => 'noversionattributionnc',
|
|
'Attribution-NonCommercial-ShareAlike' => 'noversionattributionncsa',
|
|
'Attribution-NonCommercial-NoDerivs' => 'noversionattributionncnd',
|
|
'General Public License v3' => 'gpl',
|
|
'Public Domain' => 'pd',
|
|
'Public Domain Dedication and Licence' => 'pddl',
|
|
'Public Domain Mark' => 'pdm',
|
|
'Copyright' => 'copyrightstring',
|
|
'Unable to create directory.' => 'unabletocreatedir',
|
|
'Unable to get field type.' => 'unabletogetfieldtype',
|
|
"File type isn't allowed." => 'filetypenotallowed',
|
|
'Invalid field type.' => 'invalidfieldtype',
|
|
'Invalid image file format. Use jpg, png or gif.' => 'invalidimageformat',
|
|
'File is not an image.' => 'filenotimage',
|
|
'Invalid audio file format. Use mp3 or wav.' => 'invalidaudioformat',
|
|
'Invalid video file format. Use mp4 or webm.' => 'invalidvideoformat',
|
|
'Could not save file.' => 'couldnotsave',
|
|
'Could not copy file.' => 'couldnotcopy',
|
|
'The mbstring PHP extension is not loaded. H5P need this to function properly' => 'missingmbstring',
|
|
'The version of the H5P library %machineName used in this content is not valid. Content contains %contentLibrary, but it should be %semanticsLibrary.' => 'wrongversion',
|
|
'The H5P library %library used in the content is not valid' => 'invalidlibrarynamed',
|
|
'Your PHP version is outdated. H5P requires version 5.2 to function properly. Version 5.6 or later is recommended.' => 'oldphpversion',
|
|
'Your PHP max upload size is quite small. With your current setup, you may not upload files larger than %number MB. This might be a problem when trying to upload H5Ps, images and videos. Please consider to increase it to more than 5MB.' => 'maxuploadsizetoosmall',
|
|
'Your PHP max post size is quite small. With your current setup, you may not upload files larger than %number MB. This might be a problem when trying to upload H5Ps, images and videos. Please consider to increase it to more than 5MB' => 'maxpostsizetoosmall',
|
|
'Your server does not have SSL enabled. SSL should be enabled to ensure a secure connection with the H5P hub.' => 'sslnotenabled',
|
|
'H5P hub communication has been disabled because one or more H5P requirements failed.' => 'hubcommunicationdisabled',
|
|
'When you have revised your server setup you may re-enable H5P hub communication in H5P Settings.' => 'reviseserversetupandretry',
|
|
'A problem with the server write access was detected. Please make sure that your server can write to your data folder.' => 'nowriteaccess',
|
|
'Your PHP max upload size is bigger than your max post size. This is known to cause issues in some installations.' => 'uploadsizelargerthanpostsize',
|
|
'Library cache was successfully updated!' => 'ctcachesuccess',
|
|
'No content types were received from the H5P Hub. Please try again later.' => 'ctcachenolibraries',
|
|
"Couldn't communicate with the H5P Hub. Please try again later." => 'ctcacheconnectionfailed',
|
|
'The hub is disabled. You can re-enable it in the H5P settings.' => 'hubisdisabled',
|
|
'File not found on server. Check file upload settings.' => 'filenotfoundonserver',
|
|
'Invalid security token.' => 'invalidtoken',
|
|
'No content type was specified.' => 'nocontenttype',
|
|
'The chosen content type is invalid.' => 'invalidcontenttype',
|
|
'You do not have permission to install content types. Contact the administrator of your site.' => 'installdenied',
|
|
'You do not have permission to install content types.' => 'installdenied',
|
|
'Validating h5p package failed.' => 'validatingh5pfailed',
|
|
'Failed to download the requested H5P.' => 'failedtodownloadh5p',
|
|
'A post message is required to access the given endpoint' => 'postmessagerequired',
|
|
'Could not get posted H5P.' => 'invalidh5ppost',
|
|
'Site could not be registered with the hub. Please contact your site administrator.' => 'sitecouldnotberegistered',
|
|
'The H5P Hub has been disabled until this problem can be resolved. You may still upload libraries through the "H5P Libraries" page.' => 'hubisdisableduploadlibraries',
|
|
'Your site was successfully registered with the H5P Hub.' => 'successfullyregisteredwithhub',
|
|
'You have been provided a unique key that identifies you with the Hub when receiving new updates. The key is available for viewing in the "H5P Settings" page.' => 'sitekeyregistered',
|
|
'Fullscreen' => 'fullscreen',
|
|
'Disable fullscreen' => 'disablefullscreen',
|
|
'Download' => 'download',
|
|
'Rights of use' => 'copyright',
|
|
'Embed' => 'embed',
|
|
'Size' => 'size',
|
|
'Show advanced' => 'showadvanced',
|
|
'Hide advanced' => 'hideadvanced',
|
|
'Include this script on your website if you want dynamic sizing of the embedded content:' => 'resizescript',
|
|
'Close' => 'close',
|
|
'Thumbnail' => 'thumbnail',
|
|
'No copyright information available for this content.' => 'nocopyright',
|
|
'Download this content as a H5P file.' => 'downloadtitle',
|
|
'View copyright information for this content.' => 'copyrighttitle',
|
|
'View the embed code for this content.' => 'embedtitle',
|
|
'Visit H5P.org to check out more cool content.' => 'h5ptitle',
|
|
'This content has changed since you last used it.' => 'contentchanged',
|
|
"You'll be starting over." => 'startingover',
|
|
'by' => 'by',
|
|
'Show more' => 'showmore',
|
|
'Show less' => 'showless',
|
|
'Sublevel' => 'sublevel',
|
|
'Confirm action' => 'confirmdialogheader',
|
|
'Please confirm that you wish to proceed. This action is not reversible.' => 'confirmdialogbody',
|
|
'Cancel' => 'cancellabel',
|
|
'Confirm' => 'confirmlabel',
|
|
'4.0 International' => 'licenseCC40',
|
|
'3.0 Unported' => 'licenseCC30',
|
|
'2.5 Generic' => 'licenseCC25',
|
|
'2.0 Generic' => 'licenseCC20',
|
|
'1.0 Generic' => 'licenseCC10',
|
|
'General Public License' => 'licenseGPL',
|
|
'Version 3' => 'licenseV3',
|
|
'Version 2' => 'licenseV2',
|
|
'Version 1' => 'licenseV1',
|
|
'CC0 1.0 Universal (CC0 1.0) Public Domain Dedication' => 'licenseCC010',
|
|
'CC0 1.0 Universal' => 'licenseCC010U',
|
|
'License Version' => 'licenseversion',
|
|
];
|
|
// @codingStandardsIgnoreEnd
|
|
}
|
|
|
|
return get_string($translationsmap[$message], 'hvp', $replacements);
|
|
}
|
|
|
|
/**
|
|
* Implements getH5PPath
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getH5pPath() {
|
|
global $CFG;
|
|
|
|
return $CFG->dirroot . '/mod/hvp/files';
|
|
}
|
|
|
|
/**
|
|
* Implements getLibraryFileUrl
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getLibraryFileUrl($libraryfoldername, $fileName) {
|
|
global $CFG;
|
|
$context = \context_system::instance();
|
|
$basepath = $CFG->httpswwwroot . '/';
|
|
return "{$basepath}pluginfile.php/{$context->id}/mod_hvp/libraries/{$libraryfoldername}/{$fileName}";
|
|
}
|
|
|
|
/**
|
|
* Implements getUploadedH5PFolderPath
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getUploadedH5pFolderPath($setpath = null) {
|
|
static $path;
|
|
|
|
if ($setpath !== null) {
|
|
$path = $setpath;
|
|
}
|
|
|
|
if (!isset($path)) {
|
|
throw new \coding_exception('Using getUploadedH5pFolderPath() before path is set');
|
|
}
|
|
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Implements getUploadedH5PPath
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getUploadedH5pPath($setpath = null) {
|
|
static $path;
|
|
|
|
if ($setpath !== null) {
|
|
$path = $setpath;
|
|
}
|
|
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Implements loadLibraries
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function loadLibraries() {
|
|
global $DB;
|
|
|
|
$results = $DB->get_records_sql(
|
|
"SELECT id, machine_name, title, major_version, minor_version,
|
|
patch_version, runnable, restricted
|
|
FROM {hvp_libraries}
|
|
ORDER BY title ASC, major_version ASC, minor_version ASC");
|
|
|
|
$libraries = array();
|
|
foreach ($results as $library) {
|
|
$libraries[$library->machine_name][] = $library;
|
|
}
|
|
|
|
return $libraries;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function setUnsupportedLibraries($libraries) {
|
|
// Not supported.
|
|
}
|
|
|
|
/**
|
|
* Implements getUnsupportedLibraries.
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getUnsupportedLibraries() {
|
|
// Not supported.
|
|
}
|
|
|
|
/**
|
|
* Implements getAdminUrl.
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getAdminUrl() {
|
|
// Not supported.
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getLibraryId($machinename, $majorversion = null, $minorversion = null) {
|
|
global $DB;
|
|
|
|
// Look for specific library.
|
|
$sqlwhere = 'WHERE machine_name = ?';
|
|
$sqlargs = array($machinename);
|
|
|
|
if ($majorversion !== null) {
|
|
// Look for major version.
|
|
$sqlwhere .= ' AND major_version = ?';
|
|
$sqlargs[] = $majorversion;
|
|
if ($minorversion !== null) {
|
|
// Look for minor version.
|
|
$sqlwhere .= ' AND minor_version = ?';
|
|
$sqlargs[] = $minorversion;
|
|
}
|
|
}
|
|
|
|
// Get the lastest version which matches the input parameters.
|
|
$libraries = $DB->get_records_sql("
|
|
SELECT id
|
|
FROM {hvp_libraries}
|
|
{$sqlwhere}
|
|
ORDER BY major_version DESC,
|
|
minor_version DESC,
|
|
patch_version DESC
|
|
", $sqlargs, 0, 1);
|
|
if ($libraries) {
|
|
$library = reset($libraries);
|
|
return $library ? $library->id : false;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements isPatchedLibrary
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function isPatchedLibrary($library) {
|
|
global $DB, $CFG;
|
|
|
|
if (isset($CFG->mod_hvp_dev) && $CFG->mod_hvp_dev) {
|
|
// Makes sure libraries are updated, patch version does not matter.
|
|
return true;
|
|
}
|
|
|
|
$operator = $this->isInDevMode() ? '<=' : '<';
|
|
$library = $DB->get_record_sql(
|
|
'SELECT id
|
|
FROM {hvp_libraries}
|
|
WHERE machine_name = ?
|
|
AND major_version = ?
|
|
AND minor_version = ?
|
|
AND patch_version ' . $operator . ' ?',
|
|
array($library['machineName'],
|
|
$library['majorVersion'],
|
|
$library['minorVersion'],
|
|
$library['patchVersion'])
|
|
);
|
|
|
|
return $library ? true : false;
|
|
}
|
|
|
|
/**
|
|
* Implements isInDevMode
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function isInDevMode() {
|
|
return false; // Not supported (Files in moodle not editable).
|
|
}
|
|
|
|
/**
|
|
* Implements mayUpdateLibraries
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function mayUpdateLibraries($allow = false) {
|
|
static $override;
|
|
|
|
// Allow overriding the permission check. Needed when installing.
|
|
// since caps hasn't been set.
|
|
if ($allow) {
|
|
$override = true;
|
|
}
|
|
if ($override) {
|
|
return true;
|
|
}
|
|
|
|
// Check permissions.
|
|
$context = \context_system::instance();
|
|
if (!has_capability('mod/hvp:updatelibraries', $context)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Implements getLibraryUsage
|
|
*
|
|
* Get number of content/nodes using a library, and the number of
|
|
* dependencies to other libraries
|
|
*
|
|
* @param int $id
|
|
* @param boolean $skipcontent Optional. Set as true to get number of content instances for library.
|
|
* @return array The array contains two elements, keyed by 'content' and 'libraries'.
|
|
* Each element contains a number
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getLibraryUsage($id, $skipcontent = false) {
|
|
global $DB;
|
|
|
|
if ($skipcontent) {
|
|
$content = -1;
|
|
} else {
|
|
$content = intval($DB->get_field_sql(
|
|
"SELECT COUNT(distinct c.id)
|
|
FROM {hvp_libraries} l
|
|
JOIN {hvp_contents_libraries} cl ON l.id = cl.library_id
|
|
JOIN {hvp} c ON cl.hvp_id = c.id
|
|
WHERE l.id = ?", array($id)
|
|
));
|
|
}
|
|
|
|
$libraries = intval($DB->get_field_sql(
|
|
"SELECT COUNT(*)
|
|
FROM {hvp_libraries_libraries}
|
|
WHERE required_library_id = ?", array($id)
|
|
));
|
|
|
|
return array(
|
|
'content' => $content,
|
|
'libraries' => $libraries,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Implements getLibraryContentCount
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getLibraryContentCount() {
|
|
global $DB;
|
|
$contentcount = array();
|
|
|
|
// Count content using the same content type.
|
|
$res = $DB->get_records_sql(
|
|
"SELECT c.main_library_id,
|
|
l.machine_name,
|
|
l.major_version,
|
|
l.minor_version,
|
|
c.count
|
|
FROM (SELECT main_library_id,
|
|
count(id) as count
|
|
FROM {hvp}
|
|
GROUP BY main_library_id) c,
|
|
{hvp_libraries} l
|
|
WHERE c.main_library_id = l.id"
|
|
);
|
|
|
|
// Extract results.
|
|
foreach ($res as $lib) {
|
|
$contentcount["{$lib->machine_name} {$lib->major_version}.{$lib->minor_version}"] = $lib->count;
|
|
}
|
|
|
|
return $contentcount;
|
|
}
|
|
|
|
/**
|
|
* Implements saveLibraryData
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function saveLibraryData(&$librarydata, $new = true) {
|
|
global $DB;
|
|
|
|
// Some special properties needs some checking and converting before they can be saved.
|
|
$preloadedjs = $this->pathsToCsv($librarydata, 'preloadedJs');
|
|
$preloadedcss = $this->pathsToCsv($librarydata, 'preloadedCss');
|
|
$droplibrarycss = '';
|
|
|
|
if (isset($librarydata['dropLibraryCss'])) {
|
|
$libs = array();
|
|
foreach ($librarydata['dropLibraryCss'] as $lib) {
|
|
$libs[] = $lib['machineName'];
|
|
}
|
|
$droplibrarycss = implode(', ', $libs);
|
|
}
|
|
|
|
$embedtypes = '';
|
|
if (isset($librarydata['embedTypes'])) {
|
|
$embedtypes = implode(', ', $librarydata['embedTypes']);
|
|
}
|
|
if (!isset($librarydata['semantics'])) {
|
|
$librarydata['semantics'] = '';
|
|
}
|
|
if (!isset($librarydata['fullscreen'])) {
|
|
$librarydata['fullscreen'] = 0;
|
|
}
|
|
if (!isset($librarydata['hasIcon'])) {
|
|
$librarydata['hasIcon'] = 0;
|
|
}
|
|
// TODO: Can we move the above code to H5PCore? It's the same for multiple
|
|
// implementations. Perhaps core can update the data objects before calling
|
|
// this function?
|
|
// I think maybe it's best to do this when classes are created for
|
|
// library, content, etc.
|
|
|
|
$library = (object) array(
|
|
'title' => $librarydata['title'],
|
|
'machine_name' => $librarydata['machineName'],
|
|
'major_version' => $librarydata['majorVersion'],
|
|
'minor_version' => $librarydata['minorVersion'],
|
|
'patch_version' => $librarydata['patchVersion'],
|
|
'runnable' => $librarydata['runnable'],
|
|
'fullscreen' => $librarydata['fullscreen'],
|
|
'embed_types' => $embedtypes,
|
|
'preloaded_js' => $preloadedjs,
|
|
'preloaded_css' => $preloadedcss,
|
|
'drop_library_css' => $droplibrarycss,
|
|
'semantics' => $librarydata['semantics'],
|
|
'has_icon' => $librarydata['hasIcon'],
|
|
);
|
|
|
|
if ($new) {
|
|
// Create new library and keep track of id.
|
|
$library->id = $DB->insert_record('hvp_libraries', $library);
|
|
$librarydata['libraryId'] = $library->id;
|
|
} else {
|
|
// Update library data.
|
|
$library->id = $librarydata['libraryId'];
|
|
|
|
// Save library data.
|
|
$DB->update_record('hvp_libraries', (object) $library);
|
|
|
|
// Remove old dependencies.
|
|
$this->deleteLibraryDependencies($librarydata['libraryId']);
|
|
}
|
|
|
|
// Log library successfully installed/upgraded.
|
|
new \mod_hvp\event(
|
|
'library', ($new ? 'create' : 'update'),
|
|
null, null,
|
|
$library->machine_name, $library->major_version . '.' . $library->minor_version
|
|
);
|
|
|
|
// Update library translations.
|
|
$DB->delete_records('hvp_libraries_languages', array('library_id' => $librarydata['libraryId']));
|
|
if (isset($librarydata['language'])) {
|
|
foreach ($librarydata['language'] as $languagecode => $languagejson) {
|
|
$DB->insert_record('hvp_libraries_languages', array(
|
|
'library_id' => $librarydata['libraryId'],
|
|
'language_code' => $languagecode,
|
|
'language_json' => $languagejson,
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert list of file paths to csv
|
|
*
|
|
* @param array $librarydata
|
|
* Library data as found in library.json files
|
|
* @param string $key
|
|
* Key that should be found in $librarydata
|
|
* @return string
|
|
* file paths separated by ', '
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
private function pathsToCsv($librarydata, $key) {
|
|
if (isset($librarydata[$key])) {
|
|
$paths = array();
|
|
foreach ($librarydata[$key] as $file) {
|
|
$paths[] = $file['path'];
|
|
}
|
|
return implode(', ', $paths);
|
|
}
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Implements lockDependencyStorage
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function lockDependencyStorage() {
|
|
// Library development mode not supported.
|
|
}
|
|
|
|
/**
|
|
* Implements unlockDependencyStorage
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function unlockDependencyStorage() {
|
|
// Library development mode not supported.
|
|
}
|
|
|
|
/**
|
|
* Implements deleteLibrary
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function deleteLibrary($library) {
|
|
global $DB;
|
|
|
|
// Delete library files.
|
|
$librarybase = $this->getH5pPath() . '/libraries/';
|
|
$libname = "{$library->name}-{$library->major_version}.{$library->minor_version}";
|
|
\H5PCore::deleteFileTree("{$librarybase}{$libname}");
|
|
|
|
// Remove library data from database.
|
|
$DB->delete('hvp_libraries_libraries', array('library_id' => $library->id));
|
|
$DB->delete('hvp_libraries_languages', array('library_id' => $library->id));
|
|
$DB->delete('hvp_libraries', array('id' => $library->id));
|
|
}
|
|
|
|
/**
|
|
* Implements saveLibraryDependencies
|
|
*
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function saveLibraryDependencies($libraryid, $dependencies, $dependencytype) {
|
|
global $DB;
|
|
|
|
foreach ($dependencies as $dependency) {
|
|
// Find dependency library.
|
|
$dependencylibrary = $DB->get_record('hvp_libraries', array(
|
|
'machine_name' => $dependency['machineName'],
|
|
'major_version' => $dependency['majorVersion'],
|
|
'minor_version' => $dependency['minorVersion']
|
|
));
|
|
|
|
// Create relation.
|
|
$DB->insert_record('hvp_libraries_libraries', array(
|
|
'library_id' => $libraryid,
|
|
'required_library_id' => $dependencylibrary->id,
|
|
'dependency_type' => $dependencytype
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function updateContent($content, $contentmainid = null) {
|
|
global $DB;
|
|
|
|
if (!isset($content['disable'])) {
|
|
$content['disable'] = \H5PCore::DISABLE_NONE;
|
|
}
|
|
|
|
$data = array(
|
|
'name' => $content['name'],
|
|
'course' => $content['course'],
|
|
'intro' => $content['intro'],
|
|
'introformat' => $content['introformat'],
|
|
'json_content' => $content['params'],
|
|
'embed_type' => 'div',
|
|
'main_library_id' => $content['library']['libraryId'],
|
|
'filtered' => '',
|
|
'disable' => $content['disable'],
|
|
'timemodified' => time()
|
|
);
|
|
|
|
if (!isset($content['id'])) {
|
|
$data['slug'] = '';
|
|
$data['timecreated'] = $data['timemodified'];
|
|
$eventtype = 'create';
|
|
$id = $DB->insert_record('hvp', $data);
|
|
} else {
|
|
$data['id'] = $content['id'];
|
|
$DB->update_record('hvp', $data);
|
|
$eventtype = 'update';
|
|
$id = $data['id'];
|
|
}
|
|
|
|
// Log content create/update/upload.
|
|
if (!empty($content['uploaded'])) {
|
|
$eventtype .= ' upload';
|
|
}
|
|
new \mod_hvp\event(
|
|
'content', $eventtype,
|
|
$id, $content['name'],
|
|
$content['library']['machineName'],
|
|
$content['library']['majorVersion'] . '.' . $content['library']['minorVersion']
|
|
);
|
|
|
|
return $id;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function insertContent($content, $contentmainid = null) {
|
|
return $this->updateContent($content);
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function resetContentUserData($contentid) {
|
|
global $DB;
|
|
|
|
// Reset user data for this content.
|
|
$DB->execute("UPDATE {hvp_content_user_data}
|
|
SET data = 'RESET'
|
|
WHERE hvp_id = ?
|
|
AND delete_on_content_change = 1",
|
|
array($contentid));
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getWhitelist($islibrary, $defaultcontentwhitelist, $defaultlibrarywhitelist) {
|
|
return $defaultcontentwhitelist . ($islibrary ? ' ' . $defaultlibrarywhitelist : '');
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function copyLibraryUsage($contentid, $copyfromid, $contentmainid = null) {
|
|
global $DB;
|
|
|
|
$libraryusage = $DB->get_record('hvp_contents_libraries', array(
|
|
'id' => $copyfromid
|
|
));
|
|
|
|
$libraryusage->id = $contentid;
|
|
$DB->insert_record_raw('hvp_contents_libraries', (array)$libraryusage, false, false, true);
|
|
|
|
// TODO: This must be verified at a later time.
|
|
// Currently in Moodle copyLibraryUsage() will never be called.
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function loadLibrarySemantics($name, $majorversion, $minorversion) {
|
|
global $DB;
|
|
|
|
$semantics = $DB->get_field_sql(
|
|
"SELECT semantics
|
|
FROM {hvp_libraries}
|
|
WHERE machine_name = ?
|
|
AND major_version = ?
|
|
AND minor_version = ?",
|
|
array($name, $majorversion, $minorversion));
|
|
|
|
return ($semantics === false ? null : $semantics);
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function alterLibrarySemantics(&$semantics, $name, $majorversion, $minorversion) {
|
|
global $PAGE;
|
|
|
|
$PAGE->set_context(null);
|
|
|
|
$renderer = $PAGE->get_renderer('mod_hvp');
|
|
$renderer->hvp_alter_semantics($semantics, $name, $majorversion, $minorversion);
|
|
}
|
|
|
|
/**
|
|
* Implements loadContent
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function loadContent($id) {
|
|
global $DB;
|
|
|
|
$data = $DB->get_record_sql(
|
|
"SELECT hc.id
|
|
, hc.name
|
|
, hc.intro
|
|
, hc.introformat
|
|
, hc.json_content
|
|
, hc.filtered
|
|
, hc.slug
|
|
, hc.embed_type
|
|
, hc.disable
|
|
, hl.id AS library_id
|
|
, hl.machine_name
|
|
, hl.major_version
|
|
, hl.minor_version
|
|
, hl.embed_types
|
|
, hl.fullscreen
|
|
FROM {hvp} hc
|
|
JOIN {hvp_libraries} hl ON hl.id = hc.main_library_id
|
|
WHERE hc.id = ?", array($id));
|
|
|
|
// Return null if not found.
|
|
if ($data === false) {
|
|
return null;
|
|
}
|
|
|
|
// Some databases do not support camelCase, so we need to manually
|
|
// map the values to the camelCase names used by the H5P core.
|
|
$content = array(
|
|
'id' => $data->id,
|
|
'title' => $data->name,
|
|
'intro' => $data->intro,
|
|
'introformat' => $data->introformat,
|
|
'params' => $data->json_content,
|
|
'filtered' => $data->filtered,
|
|
'slug' => $data->slug,
|
|
'embedType' => $data->embed_type,
|
|
'disable' => $data->disable,
|
|
'libraryId' => $data->library_id,
|
|
'libraryName' => $data->machine_name,
|
|
'libraryMajorVersion' => $data->major_version,
|
|
'libraryMinorVersion' => $data->minor_version,
|
|
'libraryEmbedTypes' => $data->embed_types,
|
|
'libraryFullscreen' => $data->fullscreen,
|
|
);
|
|
|
|
return $content;
|
|
}
|
|
|
|
/**
|
|
* Implements loadContentDependencies
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function loadContentDependencies($id, $type = null) {
|
|
global $DB;
|
|
|
|
$query = "SELECT hcl.id AS unidepid
|
|
, hl.id
|
|
, hl.machine_name
|
|
, hl.major_version
|
|
, hl.minor_version
|
|
, hl.patch_version
|
|
, hl.preloaded_css
|
|
, hl.preloaded_js
|
|
, hcl.drop_css
|
|
, hcl.dependency_type
|
|
FROM {hvp_contents_libraries} hcl
|
|
JOIN {hvp_libraries} hl ON hcl.library_id = hl.id
|
|
WHERE hcl.hvp_id = ?";
|
|
$queryargs = array($id);
|
|
|
|
if ($type !== null) {
|
|
$query .= " AND hcl.dependency_type = ?";
|
|
$queryargs[] = $type;
|
|
}
|
|
|
|
$query .= " ORDER BY hcl.weight";
|
|
$data = $DB->get_records_sql($query, $queryargs);
|
|
|
|
$dependencies = array();
|
|
foreach ($data as $dependency) {
|
|
unset($dependency->unidepid);
|
|
$dependencies[$dependency->machine_name] = \H5PCore::snakeToCamel($dependency);
|
|
}
|
|
|
|
return $dependencies;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getOption($name, $default = false) {
|
|
$value = get_config('mod_hvp', $name);
|
|
if ($value === false) {
|
|
return $default;
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Implements setOption().
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function setOption($name, $value) {
|
|
set_config($name, $value, 'mod_hvp');
|
|
}
|
|
|
|
/**
|
|
* Implements updateContentFields().
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function updateContentFields($id, $fields) {
|
|
global $DB;
|
|
|
|
$content = new \stdClass();
|
|
$content->id = $id;
|
|
|
|
foreach ($fields as $name => $value) {
|
|
$content->$name = $value;
|
|
}
|
|
|
|
$DB->update_record('hvp', $content);
|
|
}
|
|
|
|
/**
|
|
* Implements deleteLibraryDependencies
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function deleteLibraryDependencies($libraryid) {
|
|
global $DB;
|
|
|
|
$DB->delete_records('hvp_libraries_libraries', array('library_id' => $libraryid));
|
|
}
|
|
|
|
/**
|
|
* Implements deleteContentData
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function deleteContentData($contentid) {
|
|
global $DB;
|
|
|
|
// Remove content.
|
|
$DB->delete_records('hvp', array('id' => $contentid));
|
|
|
|
// Remove content library dependencies.
|
|
$this->deleteLibraryUsage($contentid);
|
|
|
|
// Remove user data for content.
|
|
$DB->delete_records('hvp_content_user_data', array('hvp_id' => $contentid));
|
|
}
|
|
|
|
/**
|
|
* Implements deleteLibraryUsage
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function deleteLibraryUsage($contentid) {
|
|
global $DB;
|
|
|
|
$DB->delete_records('hvp_contents_libraries', array('hvp_id' => $contentid));
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function saveLibraryUsage($contentid, $librariesinuse) {
|
|
global $DB;
|
|
|
|
$droplibrarycsslist = array();
|
|
foreach ($librariesinuse as $dependency) {
|
|
if (!empty($dependency['library']['dropLibraryCss'])) {
|
|
$droplibrarycsslist = array_merge($droplibrarycsslist, explode(', ', $dependency['library']['dropLibraryCss']));
|
|
}
|
|
}
|
|
// TODO: Consider moving the above code to core. Same for all impl.
|
|
|
|
foreach ($librariesinuse as $dependency) {
|
|
$dropcss = in_array($dependency['library']['machineName'], $droplibrarycsslist) ? 1 : 0;
|
|
$DB->insert_record('hvp_contents_libraries', array(
|
|
'hvp_id' => $contentid,
|
|
'library_id' => $dependency['library']['libraryId'],
|
|
'dependency_type' => $dependency['type'],
|
|
'drop_css' => $dropcss,
|
|
'weight' => $dependency['weight']
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements loadLibrary
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function loadLibrary($machinename, $majorversion, $minorversion) {
|
|
global $DB;
|
|
|
|
$library = $DB->get_record('hvp_libraries', array(
|
|
'machine_name' => $machinename,
|
|
'major_version' => $majorversion,
|
|
'minor_version' => $minorversion
|
|
));
|
|
|
|
$librarydata = array(
|
|
'libraryId' => $library->id,
|
|
'machineName' => $library->machine_name,
|
|
'title' => $library->title,
|
|
'majorVersion' => $library->major_version,
|
|
'minorVersion' => $library->minor_version,
|
|
'patchVersion' => $library->patch_version,
|
|
'embedTypes' => $library->embed_types,
|
|
'preloadedJs' => $library->preloaded_js,
|
|
'preloadedCss' => $library->preloaded_css,
|
|
'dropLibraryCss' => $library->drop_library_css,
|
|
'fullscreen' => $library->fullscreen,
|
|
'runnable' => $library->runnable,
|
|
'semantics' => $library->semantics,
|
|
'restricted' => $library->restricted,
|
|
'hasIcon' => $library->has_icon
|
|
);
|
|
|
|
$dependencies = $DB->get_records_sql(
|
|
'SELECT hl.id, hl.machine_name, hl.major_version, hl.minor_version, hll.dependency_type
|
|
FROM {hvp_libraries_libraries} hll
|
|
JOIN {hvp_libraries} hl ON hll.required_library_id = hl.id
|
|
WHERE hll.library_id = ?', array($library->id));
|
|
foreach ($dependencies as $dependency) {
|
|
$librarydata[$dependency->dependency_type . 'Dependencies'][] = array(
|
|
'machineName' => $dependency->machine_name,
|
|
'majorVersion' => $dependency->major_version,
|
|
'minorVersion' => $dependency->minor_version
|
|
);
|
|
}
|
|
|
|
return $librarydata;
|
|
}
|
|
|
|
/**
|
|
* Implements clearFilteredParameters().
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function clearFilteredParameters($libraryid) {
|
|
global $DB;
|
|
|
|
$DB->execute("UPDATE {hvp} SET filtered = null WHERE main_library_id = ?", array($libraryid));
|
|
}
|
|
|
|
/**
|
|
* Implements getNumNotFiltered().
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getNumNotFiltered() {
|
|
global $DB;
|
|
|
|
return (int) $DB->get_field_sql(
|
|
"SELECT COUNT(id)
|
|
FROM {hvp}
|
|
WHERE " . $DB->sql_compare_text('filtered') . " = ''");
|
|
}
|
|
|
|
/**
|
|
* Implements getNumContent().
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getNumContent($libraryid) {
|
|
global $DB;
|
|
|
|
return (int) $DB->get_field_sql(
|
|
"SELECT COUNT(id) FROM {hvp} WHERE main_library_id = ?",
|
|
array($libraryid));
|
|
}
|
|
|
|
/**
|
|
* Implements isContentSlugAvailable
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function isContentSlugAvailable($slug) {
|
|
global $DB;
|
|
|
|
return !$DB->get_field_sql("SELECT slug FROM {hvp} WHERE slug = ?", array($slug));
|
|
}
|
|
|
|
/**
|
|
* Implements saveCachedAssets
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function saveCachedAssets($key, $libraries) {
|
|
global $DB;
|
|
|
|
foreach ($libraries as $library) {
|
|
$cachedasset = (object) array(
|
|
'library_id' => $library['id'],
|
|
'hash' => $key
|
|
);
|
|
$DB->insert_record('hvp_libraries_cachedassets', $cachedasset);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements deleteCachedAssets
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function deleteCachedAssets($libraryid) {
|
|
global $DB;
|
|
|
|
// Get all the keys so we can remove the files.
|
|
$results = $DB->get_records_sql(
|
|
'SELECT hash
|
|
FROM {hvp_libraries_cachedassets}
|
|
WHERE library_id = ?',
|
|
array($libraryid));
|
|
|
|
// Remove all invalid keys.
|
|
$hashes = array();
|
|
foreach ($results as $key) {
|
|
$hashes[] = $key->hash;
|
|
$DB->delete_records('hvp_libraries_cachedassets', array('hash' => $key->hash));
|
|
}
|
|
|
|
return $hashes;
|
|
}
|
|
|
|
/**
|
|
* Implements getLibraryStats
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getLibraryStats($type) {
|
|
global $DB;
|
|
$count = array();
|
|
|
|
// Get the counts for the given type of event.
|
|
$records = $DB->get_records_sql(
|
|
"SELECT id,
|
|
library_name AS name,
|
|
library_version AS version,
|
|
num
|
|
FROM {hvp_counters}
|
|
WHERE type = ?",
|
|
array($type));
|
|
|
|
// Extract num from records.
|
|
foreach ($records as $library) {
|
|
$count[$library->name . ' ' . $library->version] = $library->num;
|
|
}
|
|
|
|
return $count;
|
|
}
|
|
|
|
/**
|
|
* Implements getNumAuthors
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function getNumAuthors() {
|
|
global $DB;
|
|
|
|
// Get number of unique courses using H5P.
|
|
return intval($DB->get_field_sql(
|
|
"SELECT COUNT(DISTINCT course)
|
|
FROM {hvp}"
|
|
));
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function afterExportCreated($content, $filename) {
|
|
}
|
|
|
|
/**
|
|
* Implements hasPermission
|
|
* @method hasPermission
|
|
* @param \H5PPermission $permission
|
|
* @param int $cmid context module id
|
|
* @return boolean
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function hasPermission($permission, $cmid = null) {
|
|
switch ($permission) {
|
|
case \H5PPermission::DOWNLOAD_H5P:
|
|
$cmcontext = \context_module::instance($cmid);
|
|
return has_capability('mod/hvp:getexport', $cmcontext);
|
|
case \H5PPermission::CREATE_RESTRICTED:
|
|
return has_capability('mod/hvp:userestrictedlibraries', $this->getajaxcoursecontext());
|
|
case \H5PPermission::UPDATE_LIBRARIES:
|
|
$context = \context_system::instance();
|
|
return has_capability('mod/hvp:updatelibraries', $context);
|
|
case \H5PPermission::INSTALL_RECOMMENDED:
|
|
return has_capability('mod/hvp:installrecommendedh5plibraries', $this->getajaxcoursecontext());
|
|
case \H5PPermission::EMBED_H5P:
|
|
$cmcontext = \context_module::instance($cmid);
|
|
return has_capability('mod/hvp:getembedcode', $cmcontext);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Gets course context in AJAX
|
|
*
|
|
* @return bool|\context|\context_course
|
|
*/
|
|
private function getajaxcoursecontext() {
|
|
$context = \context::instance_by_id(required_param('contextId', PARAM_RAW));
|
|
if ($context->contextlevel === CONTEXT_COURSE) {
|
|
return $context;
|
|
}
|
|
|
|
return $context->get_course_context();
|
|
}
|
|
|
|
/**
|
|
* Replaces existing content type cache with the one passed in
|
|
*
|
|
* @param object $contenttypecache Json with an array called 'libraries'
|
|
* containing the new content type cache that should replace the old one.
|
|
*/
|
|
// @codingStandardsIgnoreLine
|
|
public function replaceContentTypeCache($contenttypecache) {
|
|
global $DB;
|
|
|
|
// Replace existing cache.
|
|
$DB->delete_records('hvp_libraries_hub_cache');
|
|
foreach ($contenttypecache->contentTypes as $ct) {
|
|
$DB->insert_record('hvp_libraries_hub_cache', (object) array(
|
|
'machine_name' => $ct->id,
|
|
'major_version' => $ct->version->major,
|
|
'minor_version' => $ct->version->minor,
|
|
'patch_version' => $ct->version->patch,
|
|
'h5p_major_version' => $ct->coreApiVersionNeeded->major,
|
|
'h5p_minor_version' => $ct->coreApiVersionNeeded->minor,
|
|
'title' => $ct->title,
|
|
'summary' => $ct->summary,
|
|
'description' => $ct->description,
|
|
'icon' => $ct->icon,
|
|
'created_at' => (new \DateTime($ct->createdAt))->getTimestamp(),
|
|
'updated_at' => (new \DateTime($ct->updatedAt))->getTimestamp(),
|
|
'is_recommended' => $ct->isRecommended === true ? 1 : 0,
|
|
'popularity' => $ct->popularity,
|
|
'screenshots' => json_encode($ct->screenshots),
|
|
'license' => json_encode(isset($ct->license) ? $ct->license : array()),
|
|
'example' => $ct->example,
|
|
'tutorial' => isset($ct->tutorial) ? $ct->tutorial : '',
|
|
'keywords' => json_encode(isset($ct->keywords) ? $ct->keywords : array()),
|
|
'categories' => json_encode(isset($ct->categories) ? $ct->categories : array()),
|
|
'owner' => $ct->owner
|
|
), false, true);
|
|
}
|
|
}
|
|
}
|