mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
MDL-67788 core_h5p: add tracking to player
This commit is contained in:
parent
df0e58adb1
commit
8685c313e0
@ -27,6 +27,7 @@ namespace core_h5p;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core_h5p\local\library\autoloader;
|
||||
use core_xapi\local\statement\item_activity;
|
||||
|
||||
/**
|
||||
* H5P player class, for displaying any local H5P content.
|
||||
@ -67,6 +68,11 @@ class player {
|
||||
*/
|
||||
private $content;
|
||||
|
||||
/**
|
||||
* @var string optional component name to send xAPI statements.
|
||||
*/
|
||||
private $component;
|
||||
|
||||
/**
|
||||
* @var string Type of embed object, div or iframe.
|
||||
*/
|
||||
@ -98,8 +104,9 @@ class player {
|
||||
* @param string $url Local URL of the H5P file to display.
|
||||
* @param stdClass $config Configuration for H5P buttons.
|
||||
* @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions
|
||||
* @param string $component optional moodle component to sent xAPI tracking
|
||||
*/
|
||||
public function __construct(string $url, \stdClass $config, bool $preventredirect = true) {
|
||||
public function __construct(string $url, \stdClass $config, bool $preventredirect = true, string $component = '') {
|
||||
if (empty($url)) {
|
||||
throw new \moodle_exception('h5pinvalidurl', 'core_h5p');
|
||||
}
|
||||
@ -110,6 +117,8 @@ class player {
|
||||
|
||||
$this->messages = new \stdClass();
|
||||
|
||||
$this->component = $component;
|
||||
|
||||
// Create \core_h5p\core instance.
|
||||
$this->core = $this->factory->get_core();
|
||||
|
||||
@ -129,14 +138,17 @@ class player {
|
||||
* @param string $url Local URL of the H5P file to display.
|
||||
* @param stdClass $config Configuration for H5P buttons.
|
||||
* @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions
|
||||
* @param string $component optional moodle component to sent xAPI tracking
|
||||
*
|
||||
* @return string The embedable code to display a H5P file.
|
||||
*/
|
||||
public static function display(string $url, \stdClass $config, bool $preventredirect = true): string {
|
||||
public static function display(string $url, \stdClass $config, bool $preventredirect = true,
|
||||
string $component = ''): string {
|
||||
global $OUTPUT;
|
||||
$params = [
|
||||
'url' => $url,
|
||||
'preventredirect' => $preventredirect,
|
||||
'component' => $component,
|
||||
];
|
||||
|
||||
$optparams = ['frame', 'export', 'embed', 'copyright'];
|
||||
@ -193,6 +205,7 @@ class player {
|
||||
$contenturl = \moodle_url::make_pluginfile_url($systemcontext->id, \core_h5p\file_storage::COMPONENT,
|
||||
\core_h5p\file_storage::CONTENT_FILEAREA, $this->h5pid, null, null);
|
||||
$exporturl = $this->get_export_settings($displayoptions[ core::DISPLAY_OPTION_DOWNLOAD ]);
|
||||
$xapiobject = item_activity::create_from_id($this->context->id);
|
||||
$contentsettings = [
|
||||
'library' => core::libraryToString($this->content['library']),
|
||||
'fullScreen' => $this->content['library']['fullscreen'],
|
||||
@ -202,7 +215,7 @@ class player {
|
||||
'resizeCode' => self::get_resize_code(),
|
||||
'title' => $this->content['slug'],
|
||||
'displayOptions' => $displayoptions,
|
||||
'url' => self::get_embed_url($this->url->out())->out(),
|
||||
'url' => $xapiobject->get_data()->id,
|
||||
'contentUrl' => $contenturl->out(),
|
||||
'metadata' => $this->content['metadata'],
|
||||
'contentUserData' => [0 => ['state' => '{}']]
|
||||
@ -698,7 +711,7 @@ class player {
|
||||
* @return array The settings.
|
||||
*/
|
||||
private function get_core_settings(): array {
|
||||
global $CFG;
|
||||
global $CFG, $USER;
|
||||
|
||||
$basepath = $CFG->wwwroot . '/';
|
||||
$systemcontext = \context_system::instance();
|
||||
@ -717,7 +730,7 @@ class player {
|
||||
'saveFreq' => false,
|
||||
'siteUrl' => $CFG->wwwroot,
|
||||
'l10n' => array('H5P' => $this->core->getLocalization()),
|
||||
'user' => [],
|
||||
'user' => ['name' => $USER->username, 'mail' => $USER->email],
|
||||
'hubIsEnabled' => false,
|
||||
'reportingIsEnabled' => false,
|
||||
'crossorigin' => null,
|
||||
@ -725,6 +738,7 @@ class player {
|
||||
'pluginCacheBuster' => $this->get_cache_buster(),
|
||||
'libraryUrl' => autoloader::get_h5p_core_library_url('js'),
|
||||
'moodleLibraryPaths' => $this->core->get_dependency_roots($this->h5pid),
|
||||
'moodleComponent' => $this->component,
|
||||
);
|
||||
|
||||
return $settings;
|
||||
|
@ -36,9 +36,11 @@ $config->copyright = optional_param('copyright', 0, PARAM_INT);
|
||||
|
||||
$preventredirect = optional_param('preventredirect', true, PARAM_BOOL);
|
||||
|
||||
$component = optional_param('component', '', PARAM_COMPONENT);
|
||||
|
||||
$PAGE->set_url(new \moodle_url('/h5p/embed.php', array('url' => $url)));
|
||||
try {
|
||||
$h5pplayer = new \core_h5p\player($url, $config, $preventredirect);
|
||||
$h5pplayer = new \core_h5p\player($url, $config, $preventredirect, $component);
|
||||
$messages = $h5pplayer->get_messages();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
@ -92,4 +94,4 @@ if (empty($messages->error) && empty($messages->exception)) {
|
||||
echo $OUTPUT->render_from_template('core_h5p/h5perror', $messages);
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
echo $OUTPUT->footer();
|
||||
|
@ -71,6 +71,27 @@ H5PEmbedCommunicator = (function() {
|
||||
// Parent origin can be anything.
|
||||
window.parent.postMessage(data, '*');
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a xAPI statement to LMS.
|
||||
*
|
||||
* @param {string} component
|
||||
* @param {Object} statements
|
||||
*/
|
||||
self.post = function(component, statements) {
|
||||
require(['core/ajax'], function(ajax) {
|
||||
var data = {
|
||||
component: component,
|
||||
requestjson: JSON.stringify(statements)
|
||||
};
|
||||
ajax.call([
|
||||
{
|
||||
methodname: 'core_xapi_statement_post',
|
||||
args: data
|
||||
}
|
||||
]);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return (window.postMessage && window.addEventListener ? new Communicator() : undefined);
|
||||
@ -150,6 +171,38 @@ document.onreadystatechange = function() {
|
||||
}, 0);
|
||||
});
|
||||
|
||||
// Get emitted xAPI data.
|
||||
H5P.externalDispatcher.on('xAPI', function(event) {
|
||||
var moodlecomponent = H5P.getMoodleComponent();
|
||||
if (moodlecomponent == undefined) {
|
||||
return;
|
||||
}
|
||||
// Skip malformed events.
|
||||
var hasStatement = event && event.data && event.data.statement;
|
||||
if (!hasStatement) {
|
||||
return;
|
||||
}
|
||||
|
||||
var statement = event.data.statement;
|
||||
var validVerb = statement.verb && statement.verb.id;
|
||||
if (!validVerb) {
|
||||
return;
|
||||
}
|
||||
|
||||
var isCompleted = statement.verb.id === 'http://adlnet.gov/expapi/verbs/answered'
|
||||
|| statement.verb.id === 'http://adlnet.gov/expapi/verbs/completed';
|
||||
|
||||
var isChild = statement.context && statement.context.contextActivities &&
|
||||
statement.context.contextActivities.parent &&
|
||||
statement.context.contextActivities.parent[0] &&
|
||||
statement.context.contextActivities.parent[0].id;
|
||||
|
||||
if (isCompleted && !isChild) {
|
||||
var statements = H5P.getXAPIStatements(this.contentId, statement);
|
||||
H5PEmbedCommunicator.post(moodlecomponent, statements);
|
||||
}
|
||||
});
|
||||
|
||||
// Trigger initial resize for instance.
|
||||
H5P.trigger(instance, 'resize');
|
||||
};
|
||||
|
@ -7,3 +7,43 @@ H5P.getLibraryPath = function (library) {
|
||||
}
|
||||
return H5P._getLibraryPath(library);
|
||||
};
|
||||
H5P.findInstanceFromId = function (contentId) {
|
||||
if (!contentId) {
|
||||
return H5P.instances[0];
|
||||
}
|
||||
if (H5P.instances !== undefined) {
|
||||
for (var i = 0; i < H5P.instances.length; i++) {
|
||||
if (H5P.instances[i].contentId === contentId) {
|
||||
return H5P.instances[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
H5P.getXAPIStatements = function (contentId, statement) {
|
||||
var statements = [];
|
||||
var instance = H5P.findInstanceFromId(contentId);
|
||||
if (!instance){
|
||||
return statements;
|
||||
}
|
||||
if (instance.getXAPIData == undefined) {
|
||||
var xAPIData = {
|
||||
statement: statement
|
||||
};
|
||||
} else {
|
||||
var xAPIData = instance.getXAPIData();
|
||||
}
|
||||
if (xAPIData.statement != undefined) {
|
||||
statements.push(xAPIData.statement);
|
||||
}
|
||||
if (xAPIData.children != undefined) {
|
||||
statements = statements.concat(xAPIData.children.map(a => a.statement));
|
||||
}
|
||||
return statements;
|
||||
};
|
||||
H5P.getMoodleComponent = function () {
|
||||
if (H5PIntegration.moodleComponent) {
|
||||
return H5PIntegration.moodleComponent;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user