Merge branch 'MDL-67707-master' of git://github.com/ferranrecio/moodle

This commit is contained in:
Sara Arjona
2020-03-17 09:03:12 +01:00
35 changed files with 2319 additions and 19 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ require("../config.php");
require_once("lib.php");
$sectionreturn = optional_param('sr', null, PARAM_INT);
$add = optional_param('add', '', PARAM_ALPHA);
$add = optional_param('add', '', PARAM_ALPHANUM);
$type = optional_param('type', '', PARAM_ALPHA);
$indent = optional_param('indent', 0, PARAM_INT);
$update = optional_param('update', 0, PARAM_INT);
+1 -1
View File
@@ -31,7 +31,7 @@ require_once($CFG->libdir.'/completionlib.php');
require_once($CFG->libdir.'/plagiarismlib.php');
require_once($CFG->dirroot . '/course/modlib.php');
$add = optional_param('add', '', PARAM_ALPHA); // module name
$add = optional_param('add', '', PARAM_ALPHANUM); // Module name.
$update = optional_param('update', 0, PARAM_INT);
$return = optional_param('return', 0, PARAM_BOOL); //return to course/view.php if false or mod/modname/view.php if true
$type = optional_param('type', '', PARAM_ALPHANUM); //TODO: hopefully will be removed in 2.0
+1 -1
View File
@@ -942,7 +942,7 @@ abstract class moodleform_mod extends moodleform {
$mform->setType('instance', PARAM_INT);
$mform->addElement('hidden', 'add', 0);
$mform->setType('add', PARAM_ALPHA);
$mform->setType('add', PARAM_ALPHANUM);
$mform->addElement('hidden', 'update', 0);
$mform->setType('update', PARAM_INT);
+1
View File
@@ -4,6 +4,7 @@ information provided here is intended especially for developers.
=== 3.9 ===
* The function get_module_metadata is now deprecated. Please use \core_course\local\service\content_item_service instead.
* Activity module names are now PARAM_ALPHANUM instead of PARAM_ALPHA so integers can be used in activity module names
=== 3.8 ===
@@ -65,7 +65,7 @@ Feature: Render H5P content using filters
And I add a "File" to section "1"
And I set the following fields to these values:
| Name | ipsumFile |
And I upload "filter/displayh5p/tests/fixtures/ipsums.h5p" file to "Select files" filemanager
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "Select files" filemanager
And I press "Save and return to course"
And I follow "PageName1"
And I navigate to "Edit settings" in current page administration
@@ -102,7 +102,7 @@ Feature: Render H5P content using filters
And I add a "File" to section "1"
And I set the following fields to these values:
| Name | ipsumFile |
And I upload "filter/displayh5p/tests/fixtures/ipsums.h5p" file to "Select files" filemanager
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "Select files" filemanager
And I press "Save and return to course"
And I follow "PageName1"
And I navigate to "Edit settings" in current page administration
@@ -127,7 +127,7 @@ Feature: Render H5P content using filters
And I add a "File" to section "1"
And I set the following fields to these values:
| Name | ipsumFileTeacher |
And I upload "filter/displayh5p/tests/fixtures/ipsums.h5p" file to "Select files" filemanager
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "Select files" filemanager
And I press "Save and return to course"
And I follow "PageName1"
And I navigate to "Edit settings" in current page administration
@@ -151,7 +151,7 @@ Feature: Render H5P content using filters
And I add a "File" to section "1"
And I set the following fields to these values:
| Name | ipsumFile |
And I upload "filter/displayh5p/tests/fixtures/ipsums.h5p" file to "Select files" filemanager
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "Select files" filemanager
And I press "Save and return to course"
And I follow "PageName2"
And I navigate to "Edit settings" in current page administration
+20
View File
@@ -107,6 +107,26 @@ class helper {
return $core->getStorableDisplayOptions($disableoptions, 0);
}
/**
* Convert the int representation of display options into stdClass
*
* @param core $core The \core_h5p\core object
* @param int $displayint integer value representing display options
*
* @return int The representation of display options as int
*/
public static function decode_display_options(core $core, int $displayint = null): \stdClass {
$config = new \stdClass();
if ($displayint === null) {
$displayint = self::get_display_options($core, $config);
}
$displayarray = $core->getDisplayOptionsForEdit($displayint);
$config->export = $displayarray[core::DISPLAY_OPTION_DOWNLOAD] ?? 0;
$config->embed = $displayarray[core::DISPLAY_OPTION_EMBED] ?? 0;
$config->copyright = $displayarray[core::DISPLAY_OPTION_COPYRIGHT] ?? 0;
return $config;
}
/**
* Checks if the author of the .h5p file is "trustable". If the file hasn't been uploaded by a user with the
* required capability, the content won't be deployed.
+34 -2
View File
@@ -123,6 +123,38 @@ class player {
}
}
/**
* Get the encoded URL for embeding this H5P content.
*
* @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
*
* @return string The embedable code to display a H5P file.
*/
public static function display(string $url, \stdClass $config, bool $preventredirect = true): string {
global $OUTPUT;
$params = [
'url' => $url,
'preventredirect' => $preventredirect,
];
$optparams = ['frame', 'export', 'embed', 'copyright'];
foreach ($optparams as $optparam) {
if (!empty($config->$optparam)) {
$params[$optparam] = $config->$optparam;
}
}
$fileurl = new \moodle_url('/h5p/embed.php', $params);
$template = new \stdClass();
$template->embedurl = $fileurl->out(false);
$result = $OUTPUT->render_from_template('core_h5p/h5pembed', $template);
$result .= self::get_resize_code();
return $result;
}
/**
* Get the error messages stored in our H5P framework.
*
@@ -167,7 +199,7 @@ class player {
'exportUrl' => ($exporturl instanceof \moodle_url) ? $exporturl->out(false) : '',
'embedCode' => $this->get_embed_code($this->url->out(),
$displayoptions[ core::DISPLAY_OPTION_EMBED ]),
'resizeCode' => $this->get_resize_code(),
'resizeCode' => self::get_resize_code(),
'title' => $this->content['slug'],
'displayOptions' => $displayoptions,
'url' => self::get_embed_url($this->url->out())->out(),
@@ -715,7 +747,7 @@ class player {
*
* @return string The HTML code with the resize script.
*/
private function get_resize_code(): string {
private static function get_resize_code(): string {
global $OUTPUT;
$template = new \stdClass();
+4 -2
View File
@@ -28,5 +28,7 @@
}
}}
<iframe src="{{embedurl}}" width=":w" height=":h" allowfullscreen="allowfullscreen"></iframe>
<iframe src="{{embedurl}}" name="h5player" width=":w" height=":h"
allowfullscreen="allowfullscreen" class="h5p-player w-100 border-0"
style="min-height: 230px;">
</iframe>
+11 -4
View File
@@ -41,14 +41,14 @@ class helper_testcase extends \advanced_testcase {
/**
* Test the behaviour of get_display_options().
*
* @dataProvider get_display_options_provider
* @dataProvider display_options_provider
* @param bool $frame Whether the frame should be displayed or not
* @param bool $export Whether the export action button should be displayed or not
* @param bool $embed Whether the embed action button should be displayed or not
* @param bool $copyright Whether the copyright action button should be displayed or not
* @param int $expected The expectation with the displayoptions value
*/
public function test_get_display_options(bool $frame, bool $export, bool $embed, bool $copyright, int $expected): void {
public function test_display_options(bool $frame, bool $export, bool $embed, bool $copyright, int $expected): void {
$this->setRunTestInSeparateProcess(true);
$this->resetAfterTest();
@@ -60,9 +60,16 @@ class helper_testcase extends \advanced_testcase {
'embed' => $embed,
'copyright' => $copyright,
];
$displayoptions = helper::get_display_options($core, $config);
// Test getting display options.
$displayoptions = helper::get_display_options($core, $config);
$this->assertEquals($expected, $displayoptions);
// Test decoding display options.
$decoded = helper::decode_display_options($core, $expected);
$this->assertEquals($decoded->export, $config->export);
$this->assertEquals($decoded->embed, $config->embed);
$this->assertEquals($decoded->copyright, $config->copyright);
}
/**
@@ -70,7 +77,7 @@ class helper_testcase extends \advanced_testcase {
*
* @return array
*/
public function get_display_options_provider(): array {
public function display_options_provider(): array {
return [
'All display options disabled' => [
false,
+1 -1
View File
@@ -1914,7 +1914,7 @@ class core_plugin_manager {
'mod' => array(
'assign', 'assignment', 'book', 'chat', 'choice', 'data', 'feedback', 'folder',
'forum', 'glossary', 'imscp', 'label', 'lesson', 'lti', 'page',
'forum', 'glossary', 'h5pactivity', 'imscp', 'label', 'lesson', 'lti', 'page',
'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop'
),
@@ -40,7 +40,7 @@ Feature: Add h5ps to Atto
Scenario: Insert an h5p file
Given I log in as "admin"
And I follow "Manage private files..."
And I upload "lib/editor/atto/tests/fixtures/guess-the-answer.h5p" file to "Files" filemanager
And I upload "h5p/tests/fixtures/guess-the-answer.h5p" file to "Files" filemanager
And I click on "Save changes" "button"
And I am on "Course 1" course homepage
And I follow "PageName1"
@@ -145,7 +145,7 @@ Feature: Add h5ps to Atto
Scenario: Enable/disable H5P options
Given I log in as "admin"
And I follow "Manage private files..."
And I upload "lib/editor/atto/tests/fixtures/guess-the-answer.h5p" file to "Files" filemanager
And I upload "h5p/tests/fixtures/guess-the-answer.h5p" file to "Files" filemanager
And I click on "Save changes" "button"
And I am on "Course 1" course homepage
And I follow "PageName1"
@@ -209,7 +209,7 @@ Feature: Add h5ps to Atto
| student1 | C1 | student |
And I log in as "admin"
And I follow "Manage private files..."
And I upload "lib/editor/atto/tests/fixtures/guess-the-answer.h5p" file to "Files" filemanager
And I upload "h5p/tests/fixtures/guess-the-answer.h5p" file to "Files" filemanager
And I click on "Save changes" "button"
And I am on "Course 1" course homepage
And I follow "PageName1"
@@ -0,0 +1,70 @@
<?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/>.
/**
* The task that provides all the steps to perform a complete backup is defined here.
*
* @package mod_h5pactivity
* @category backup
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot.'/mod/h5pactivity/backup/moodle2/backup_h5pactivity_stepslib.php');
/**
* The class provides all the settings and steps to perform one complete backup of mod_h5pactivity.
*/
class backup_h5pactivity_activity_task extends backup_activity_task {
/**
* Defines particular settings for the plugin.
*/
protected function define_my_settings() {
return;
}
/**
* Defines particular steps for the backup process.
*/
protected function define_my_steps() {
$this->add_step(new backup_h5pactivity_activity_structure_step('h5pactivity_structure', 'h5pactivity.xml'));
}
/**
* Codes the transformations to perform in the activity in order to get transportable (encoded) links.
*
* @param string $content content to encode.
* @return string encoded string
*/
static public function encode_content_links($content) {
global $CFG;
$base = preg_quote($CFG->wwwroot, "/");
// Link to the list of choices.
$search = "/(".$base."\/mod\/h5pactivity\/index.php\?id\=)([0-9]+)/";
$content = preg_replace($search, '$@H5PACTIVITYINDEX*$2@$', $content);
// Link to choice view by moduleid.
$search = "/(".$base."\/mod\/h5pactivity\/view.php\?id\=)([0-9]+)/";
$content = preg_replace($search, '$@H5PACTIVITYVIEWBYID*$2@$', $content);
return $content;
}
}
@@ -0,0 +1,58 @@
<?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/>.
/**
* Backup steps for mod_h5pactivity are defined here.
*
* @package mod_h5pactivity
* @category backup
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Define the complete structure for backup, with file and id annotations.
*/
class backup_h5pactivity_activity_structure_step extends backup_activity_structure_step {
/**
* Defines the structure of the resulting xml file.
*
* @return backup_nested_element The structure wrapped by the common 'activity' element.
*/
protected function define_structure() {
$userinfo = $this->get_setting_value('userinfo');
// Replace with the attributes and final elements that the element will handle.
$attributes = ['id'];
$finalelements = ['name', 'timecreated', 'timemodified', 'intro',
'introformat', 'grade', 'displayoptions'];
$root = new backup_nested_element('h5pactivity', $attributes, $finalelements);
// Define the source tables for the elements.
$root->set_source_table('h5pactivity', ['id' => backup::VAR_ACTIVITYID]);
// Define id annotations.
// Define file annotations.
$root->annotate_files('mod_h5pactivity', 'intro', null); // This file area hasn't itemid.
$root->annotate_files('mod_h5pactivity', 'package', null); // This file area hasn't itemid.
return $this->prepare_activity_structure($root);
}
}
@@ -0,0 +1,93 @@
<?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/>.
/**
* The task that provides a complete restore of mod_h5pactivity is defined here.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot.'/mod/h5pactivity/backup/moodle2/restore_h5pactivity_stepslib.php');
/**
* Restore task for mod_h5pactivity.
*/
class restore_h5pactivity_activity_task extends restore_activity_task {
/**
* Defines particular settings that this activity can have.
*/
protected function define_my_settings(): void {
return;
}
/**
* Defines particular steps that this activity can have.
*
* @return base_step.
*/
protected function define_my_steps(): void {
$this->add_step(new restore_h5pactivity_activity_structure_step('h5pactivity_structure', 'h5pactivity.xml'));
}
/**
* Defines the contents in the activity that must be processed by the link decoder.
*
* @return array.
*/
static public function define_decode_contents(): array {
$contents = [];
// Define the contents.
$contents[] = new restore_decode_content('h5pactivity', ['intro'], 'h5pactivity');
return $contents;
}
/**
* Defines the decoding rules for links belonging to the activity to be executed by the link decoder.
*
* @return restore_decode_rule[].
*/
static public function define_decode_rules(): array {
$rules = [];
$rules[] = new restore_decode_rule('H5PACTIVITYVIEWBYID', '/mod/h5pactivity/view.php?id=$1', 'course_module');
$rules[] = new restore_decode_rule('H5PACTIVITYINDEX', '/mod/h5pactivity/index.php?id=$1', 'course');
return $rules;
}
/**
* Defines the restore log rules that will be applied by the
* {@link restore_logs_processor} when restoring mod_h5pactivity logs. It
* must return one array of {@link restore_log_rule} objects.
*
* @return restore_log_rule[].
*/
static public function define_restore_log_rules(): array {
$rules = [];
// Define the rules.
$rules[] = new restore_log_rule('h5pactivity', 'view all', 'index.php?id={course}', null);
return $rules;
}
}
@@ -0,0 +1,67 @@
<?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/>.
/**
* All the steps to restore mod_h5pactivity are defined here.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Defines the structure step to restore one mod_h5pactivity activity.
*/
class restore_h5pactivity_activity_structure_step extends restore_activity_structure_step {
/**
* Defines the structure to be restored.
*
* @return restore_path_element[].
*/
protected function define_structure(): array {
$paths = [];
$userinfo = $this->get_setting_value('userinfo');
$paths[] = new restore_path_element('h5pactivity', '/activity/h5pactivity');
return $this->prepare_activity_structure($paths);
}
/**
* Processes the elt restore data.
*
* @param array $data Parsed element data.
*/
protected function process_h5pactivity(array $data): void {
global $DB;
$data = (object) $data;
$data->course = $this->get_courseid();
// Insert the record.
$newitemid = $DB->insert_record('h5pactivity', $data);
// Immediately after inserting "activity" record, call this.
$this->apply_activity_instance($newitemid);
}
/**
* Defines post-execution actions.
*/
protected function after_execute(): void {
// Add related files, no need to match by itemname (just internally handled context).
$this->add_related_files('mod_h5pactivity', 'intro', null);
$this->add_related_files('mod_h5pactivity', 'package', null);
}
}
@@ -0,0 +1,37 @@
<?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/>.
/**
* Plugin event classes are defined here.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_h5pactivity\event;
defined('MOODLE_INTERNAL') || die();
/**
* The course_module_instance_list_viewed event class.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed {
}
@@ -0,0 +1,59 @@
<?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/>.
/**
* Plugin event classes are defined here.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_h5pactivity\event;
defined('MOODLE_INTERNAL') || die();
/**
* The course_module_viewed event class.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_module_viewed extends \core\event\course_module_viewed {
/**
* Init method.
*
* @return void
*/
protected function init(): void {
$this->data['objecttable'] = 'h5pactivity';
$this->data['crud'] = 'r';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
}
/**
* This is used when restoring course logs where it is required that we
* map the objectid to it's new value in the new course.
*
* @return array
*/
public static function get_objectid_mapping() {
return ['db' => 'h5pactivity', 'restore' => 'h5pactivity'];
}
}
@@ -0,0 +1,46 @@
<?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/>.
/**
* Defines {@link \mod_h5pactivity\privacy\provider} class.
*
* @package mod_h5pactivity
* @category privacy
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_h5pactivity\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy API implementation for the H5P activity plugin.
*
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() : string {
return 'privacy:metadata';
}
}
+51
View File
@@ -0,0 +1,51 @@
<?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/>.
/**
* Plugin capabilities are defined here.
*
* @package mod_h5pactivity
* @category access
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = [
'mod/h5pactivity:view' => [
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => [
'guest' => CAP_ALLOW,
'student' => CAP_ALLOW,
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
],
],
'mod/h5pactivity:addinstance' => [
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => [
'manager' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
],
'clonepermissionsfrom' => 'moodle/course:manageactivities',
],
];
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/h5pactivity/db" VERSION="20200227" COMMENT="XMLDB file for Moodle mod_h5pactivity"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="h5pactivity" COMMENT="Stores the h5pactivity activity module instances.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the course this activity is part of."/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Timestamp of when the instance was added to the course."/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Timestamp of when the instance was last modified."/>
<FIELD NAME="intro" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Activity description."/>
<FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the intro field."/>
<FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="displayoptions" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="H5P Button display options"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="fk_course" TYPE="foreign" FIELDS="course" REFTABLE="course" REFFIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
+42
View File
@@ -0,0 +1,42 @@
<?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/>.
/**
* Redirect the user to the appropiate submission related page.
*
* @package mod_h5pactivity
* @category grade
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require(__DIR__.'/../../config.php');
// Course module ID.
$id = required_param('id', PARAM_INT);
// Item number may be != 0 for activities that allow more than one grade per user.
$itemnumber = optional_param('itemnumber', 0, PARAM_INT);
// Graded user ID (optional).
$userid = optional_param('userid', 0, PARAM_INT);
require_login();
// TODO: in the near future this file will redirect to a specific user H5P attempts page.
// In the simplest case just redirect to the view page.
redirect('view.php?id='.$id);
+89
View File
@@ -0,0 +1,89 @@
<?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/>.
/**
* Display information about all the mod_h5pactivity modules in the requested course.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require(__DIR__.'/../../config.php');
require_once(__DIR__.'/lib.php');
$id = required_param('id', PARAM_INT);
$course = $DB->get_record('course', ['id' => $id], '*', MUST_EXIST);
require_course_login($course);
$coursecontext = context_course::instance($course->id);
$event = \mod_h5pactivity\event\course_module_instance_list_viewed::create(['context' => $coursecontext]);
$event->add_record_snapshot('course', $course);
$event->trigger();
$PAGE->set_url('/mod/h5pactivity/index.php', ['id' => $id]);
$PAGE->set_title(format_string($course->fullname));
$PAGE->set_heading(format_string($course->fullname));
$PAGE->set_context($coursecontext);
echo $OUTPUT->header();
$modulenameplural = get_string('modulenameplural', 'mod_h5pactivity');
echo $OUTPUT->heading($modulenameplural);
$h5pactivities = get_all_instances_in_course('h5pactivity', $course);
if (empty($h5pactivities)) {
notice(get_string('thereareno', 'moodle'), new moodle_url('/course/view.php', ['id' => $course->id]));
exit;
}
$table = new html_table();
$table->attributes['class'] = 'generaltable mod_index';
$align = ['center', 'left'];
if ($course->format == 'weeks') {
$table->head = [get_string('week'), get_string('name')];
$table->align = ['center', 'left'];
} else if ($course->format == 'topics') {
$table->head = [get_string('topic'), get_string('name')];
$table->align = ['center', 'left'];
} else {
$table->head = [get_string('name')];
$table->align = ['left'];
}
foreach ($h5pactivities as $h5pactivity) {
$attributes = [];
if (!$h5pactivity->visible) {
$attributes['class'] = 'dimmed';
}
$link = html_writer::link(
new moodle_url('/mod/h5pactivity/view.php', ['id' => $h5pactivity->coursemodule]),
format_string($h5pactivity->name, true),
$attributes);
if ($course->format == 'weeks' or $course->format == 'topics') {
$table->data[] = [$h5pactivity->section, $link];
} else {
$table->data[] = [$link];
}
}
echo html_writer::table($table);
echo $OUTPUT->footer();
+47
View File
@@ -0,0 +1,47 @@
<?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/>.
/**
* Plugin strings are defined here.
*
* @package mod_h5pactivity
* @category string
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$string['areapackage'] = 'Package file';
$string['displayexport'] = 'Allow download';
$string['displayembed'] = 'Embed button';
$string['displaycopyright'] = 'Copyright button';
$string['h5pactivity:addinstance'] = 'Add a new H5P';
$string['h5pactivity:view'] = 'View H5P';
$string['h5pactivityfieldset'] = 'H5P Settings';
$string['h5pactivityname'] = 'H5P';
$string['h5pactivitysettings'] = 'Settings';
$string['h5pdisplay'] = 'H5P options';
$string['modulename'] = 'H5P activity';
$string['modulename_help'] = 'Use this module to use a H5P compatible content as a course activity.';
$string['modulename_link'] = 'mod/h5pactivity/view';
$string['modulenameplural'] = 'H5P activities';
$string['package'] = 'Package file';
$string['package_help'] = 'The package file is a h5pfile containing H5P dynamic content.';
$string['page-mod-h5pactivity-x'] = 'Any H5P module page';
$string['pluginadministration'] = 'H5P administration';
$string['pluginname'] = 'H5P activity';
$string['privacy:metadata'] = 'The H5P activity plugin does not store any personal data.';
+408
View File
@@ -0,0 +1,408 @@
<?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/>.
/**
* Library of interface functions and constants.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Checks if H5P activity supports a specific feature.
*
* @uses FEATURE_GROUPS
* @uses FEATURE_GROUPINGS
* @uses FEATURE_MOD_INTRO
* @uses FEATURE_SHOW_DESCRIPTION
* @uses FEATURE_COMPLETION_TRACKS_VIEWS
* @uses FEATURE_COMPLETION_HAS_RULES
* @uses FEATURE_MODEDIT_DEFAULT_COMPLETION
* @uses FEATURE_GRADE_HAS_GRADE
* @uses FEATURE_GRADE_OUTCOMES
* @uses FEATURE_BACKUP_MOODLE2
* @param string $feature FEATURE_xx constant for requested feature
* @return mixed True if module supports feature, false if not, null if doesn't know
*/
function h5pactivity_supports(string $feature): ?bool {
switch($feature) {
case FEATURE_GROUPS:
return true;
case FEATURE_GROUPINGS:
return true;
case FEATURE_MOD_INTRO:
return true;
case FEATURE_SHOW_DESCRIPTION:
return true;
case FEATURE_COMPLETION_TRACKS_VIEWS:
return true;
case FEATURE_MODEDIT_DEFAULT_COMPLETION:
return true;
case FEATURE_GRADE_HAS_GRADE:
return true;
case FEATURE_GRADE_OUTCOMES:
return true;
case FEATURE_BACKUP_MOODLE2:
return true;
default:
return null;
}
}
/**
* Saves a new instance of the mod_h5pactivity into the database.
*
* Given an object containing all the necessary data, (defined by the form
* in mod_form.php) this function will create a new instance and return the id
* number of the instance.
*
* @param stdClass $data An object from the form.
* @param mod_h5pactivity_mod_form $mform The form.
* @return int The id of the newly inserted record.
*/
function h5pactivity_add_instance(stdClass $data, mod_h5pactivity_mod_form $mform = null): int {
global $DB;
$data->timecreated = time();
$cmid = $data->coursemodule;
$data->id = $DB->insert_record('h5pactivity', $data);
// We need to use context now, so we need to make sure all needed info is already in db.
$DB->set_field('course_modules', 'instance', $data->id, ['id' => $cmid]);
h5pactivity_set_mainfile($data);
// Extra fields required in grade related functions.
$data->cmid = $data->coursemodule;
h5pactivity_grade_item_update($data);
return $data->id;
}
/**
* Updates an instance of the mod_h5pactivity in the database.
*
* Given an object containing all the necessary data (defined in mod_form.php),
* this function will update an existing instance with new data.
*
* @param stdClass $data An object from the form in mod_form.php.
* @param mod_h5pactivity_mod_form $mform The form.
* @return bool True if successful, false otherwise.
*/
function h5pactivity_update_instance(stdClass $data, mod_h5pactivity_mod_form $mform = null): bool {
global $DB;
$data->timemodified = time();
$data->id = $data->instance;
h5pactivity_set_mainfile($data);
// Extra fields required in grade related functions.
$data->cmid = $data->coursemodule;
h5pactivity_grade_item_update($data);
h5pactivity_update_grades($data);
return $DB->update_record('h5pactivity', $data);
}
/**
* Removes an instance of the mod_h5pactivity from the database.
*
* @param int $id Id of the module instance.
* @return bool True if successful, false on failure.
*/
function h5pactivity_delete_instance(int $id): bool {
global $DB;
$activity = $DB->get_record('h5pactivity', ['id' => $id]);
if (!$activity) {
return false;
}
$DB->delete_records('h5pactivity', ['id' => $id]);
h5pactivity_grade_item_delete($activity);
return true;
}
/**
* Checks if scale is being used by any instance of mod_h5pactivity.
*
* This is used to find out if scale used anywhere.
*
* @param int $scaleid ID of the scale.
* @return bool True if the scale is used by any mod_h5pactivity instance.
*/
function h5pactivity_scale_used_anywhere(int $scaleid): bool {
global $DB;
if ($scaleid and $DB->record_exists('h5pactivity', ['grade' => -$scaleid])) {
return true;
} else {
return false;
}
}
/**
* Creates or updates grade item for the given mod_h5pactivity instance.
*
* Needed by {@link grade_update_mod_grades()}.
*
* @param stdClass $moduleinstance Instance object with extra cmidnumber and modname property.
* @param mixed $grades optional array/object of grade(s); 'reset' means reset grades in gradebook
* @return int int 0 if ok, error code otherwise
*/
function h5pactivity_grade_item_update(stdClass $moduleinstance, $grades=null): int {
global $CFG;
require_once($CFG->libdir.'/gradelib.php');
$item = [];
$item['itemname'] = clean_param($moduleinstance->name, PARAM_NOTAGS);
$item['gradetype'] = GRADE_TYPE_VALUE;
if (isset($moduleinstance->cmidnumber)) {
$item['idnumber'] = $moduleinstance->cmidnumber;
}
if ($moduleinstance->grade > 0) {
$item['gradetype'] = GRADE_TYPE_VALUE;
$item['grademax'] = $moduleinstance->grade;
$item['grademin'] = 0;
} else if ($moduleinstance->grade < 0) {
$item['gradetype'] = GRADE_TYPE_SCALE;
$item['scaleid'] = -$moduleinstance->grade;
} else {
$item['gradetype'] = GRADE_TYPE_NONE;
}
if ($grades === 'reset') {
$params['reset'] = true;
$grades = null;
}
return grade_update('mod/h5pactivity', $moduleinstance->course, 'mod',
'h5pactivity', $moduleinstance->id, 0, null, $item);
}
/**
* Delete grade item for given mod_h5pactivity instance.
*
* @param stdClass $moduleinstance Instance object.
* @return int Returns GRADE_UPDATE_OK, GRADE_UPDATE_FAILED, GRADE_UPDATE_MULTIPLE or GRADE_UPDATE_ITEM_LOCKED
*/
function h5pactivity_grade_item_delete(stdClass $moduleinstance): ?int {
global $CFG;
require_once($CFG->libdir.'/gradelib.php');
return grade_update('mod/h5pactivity', $moduleinstance->course, 'mod', 'h5pactivity',
$moduleinstance->id, 0, null, ['deleted' => 1]);
}
/**
* Update mod_h5pactivity grades in the gradebook.
*
* Needed by {@link grade_update_mod_grades()}.
*
* @param stdClass $moduleinstance Instance object with extra cmidnumber and modname property.
* @param int $userid Update grade of specific user only, 0 means all participants.
*/
function h5pactivity_update_grades(stdClass $moduleinstance, int $userid = 0): void {
global $CFG;
require_once($CFG->libdir.'/gradelib.php');
// Populate array of grade objects indexed by userid.
$grades = [];
grade_update('mod/h5pactivity', $moduleinstance->course, 'mod',
'h5pactivity', $moduleinstance->id, 0, $grades);
}
/**
* This function is used by the reset_course_userdata function in moodlelib.
* This function will remove all assignment submissions and feedbacks in the database
* and clean up any related data.
*
* @param stdClass $data the data submitted from the reset course.
* @return array
*/
function h5pactivity_reset_userdata($data) {
global $CFG, $DB;
// TODO: When attempts are created this function will remove them.
return [];
}
/**
* Removes all grades from gradebook
*
* @param int $courseid Coude ID
* @param string $type optional type (default '')
*/
function h5pactivity_reset_gradebook(int $courseid, string $type=''): void {
global $DB;
$sql = "SELECT a.*, cm.idnumber as cmidnumber, a.course as courseid
FROM {h5pactivity} a, {course_modules} cm, {modules} m
WHERE m.name='h5pactivity' AND m.id=cm.module AND cm.instance=s.id AND s.course=?";
if ($activities = $DB->get_records_sql($sql, [$courseid])) {
foreach ($activities as $activity) {
h5pactivity_grade_item_update($activity, true);
}
}
}
/**
* Return a list of page types
*
* @param string $pagetype current page type
* @param stdClass $parentcontext Block's parent context
* @param stdClass $currentcontext Current context of block
* @return array array of page types and it's names
*/
function h5pactivity_page_type_list(string $pagetype, stdClass $parentcontext, stdClass $currentcontext): array {
$modulepagetype = [
'mod-h5pactivity-*' => get_string('page-mod-h5pactivity-x', 'h5pactivity'),
];
return $modulepagetype;
}
/**
* Check if the module has any update that affects the current user since a given time.
*
* @param cm_info $cm course module data
* @param int $from the time to check updates from
* @param array $filter if we need to check only specific updates
* @return stdClass an object with the different type of areas indicating if they were updated or not
*/
function h5pactivity_check_updates_since(cm_info $cm, int $from, array $filter = []): stdClass {
$updates = course_check_module_updates_since($cm, $from, ['package'], $filter);
return $updates;
}
/**
* Returns the lists of all browsable file areas within the given module context.
*
* The file area 'intro' for the activity introduction field is added automatically
* by {@link file_browser::get_file_info_context_module()}.
*
* @param stdClass $course course object
* @param stdClass $cm course module object
* @param stdClass $context context object
* @return string[] array of pair file area => human file area name
*/
function h5pactivity_get_file_areas(stdClass $course, stdClass $cm, stdClass $context): array {
$areas = [];
$areas['package'] = get_string('areapackage', 'mod_h5pactivity');
return $areas;
}
/**
* File browsing support for data module.
*
* @param file_browser $browser
* @param array $areas
* @param stdClass $course
* @param stdClass $cm
* @param context $context
* @param string $filearea
* @param int $itemid
* @param string $filepath
* @param string $filename
* @return file_info_stored|null file_info_stored instance or null if not found
*/
function h5pactivity_get_file_info(file_browser $browser, array $areas, stdClass $course,
stdClass $cm, context $context, string $filearea, int $itemid,
string $filepath, string $filename): ?file_info_stored {
global $CFG;
if (!has_capability('moodle/course:managefiles', $context)) {
return null;
}
$fs = get_file_storage();
if ($filearea === 'package') {
$filepath = is_null($filepath) ? '/' : $filepath;
$filename = is_null($filename) ? '.' : $filename;
$urlbase = $CFG->wwwroot.'/pluginfile.php';
if (!$storedfile = $fs->get_file($context->id, 'mod_h5pactivity', 'package', 0, $filepath, $filename)) {
if ($filepath === '/' and $filename === '.') {
$storedfile = new virtual_root_file($context->id, 'mod_h5pactivity', 'package', 0);
} else {
// Not found.
return null;
}
}
return new file_info_stored($browser, $context, $storedfile, $urlbase, $areas[$filearea], false, true, false, false);
}
return null;
}
/**
* Serves the files from the mod_h5pactivity file areas.
*
* @param mixed $course course or id of the course
* @param mixed $cm course module or id of the course module
* @param context $context
* @param string $filearea
* @param array $args
* @param bool $forcedownload
* @param array $options additional options affecting the file serving
* @return bool false if file not found, does not return if found - just send the file
*/
function h5pactivity_pluginfile($course, $cm, context $context,
string $filearea, array $args, bool $forcedownload, array $options = []): bool {
if ($context->contextlevel != CONTEXT_MODULE) {
return false;
}
require_login($course, true, $cm);
$fullpath = '';
if ($filearea === 'package') {
$revision = (int)array_shift($args); // Prevents caching problems - ignored here.
$relativepath = implode('/', $args);
$fullpath = "/$context->id/mod_h5pactivity/package/0/$relativepath";
}
if (empty($fullpath)) {
return false;
}
$fs = get_file_storage();
$file = $fs->get_file_by_hash(sha1($fullpath));
if (empty($file)) {
return false;
}
send_stored_file($file, $lifetime, 0, false, $options);
}
/**
* Saves draft files as the activity package.
*
* @param stdClass $data an object from the form
*/
function h5pactivity_set_mainfile(stdClass $data): void {
$fs = get_file_storage();
$cmid = $data->coursemodule;
$context = context_module::instance($cmid);
if (!empty($data->packagefile)) {
$fs = get_file_storage();
$fs->delete_area_files($context->id, 'mod_h5pactivity', 'package');
file_save_draft_area_files($data->packagefile, $context->id, 'mod_h5pactivity', 'package',
0, ['subdirs' => 0, 'maxfiles' => 1]);
}
}
+182
View File
@@ -0,0 +1,182 @@
<?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/>.
/**
* The main mod_h5pactivity configuration form.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot.'/course/moodleform_mod.php');
/**
* Module instance settings form.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_h5pactivity_mod_form extends moodleform_mod {
/**
* Defines forms elements
*/
public function definition(): void {
global $CFG;
$mform = $this->_form;
// Adding the "general" fieldset, where all the common settings are shown.
$mform->addElement('header', 'general', get_string('general', 'form'));
// Adding the standard "name" field.
$mform->addElement('text', 'name', get_string('name'), ['size' => '64']);
if (!empty($CFG->formatstringstriptags)) {
$mform->setType('name', PARAM_TEXT);
} else {
$mform->setType('name', PARAM_CLEANHTML);
}
$mform->addRule('name', null, 'required', null, 'client');
$mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
$this->standard_intro_elements();
// Adding the rest of mod_h5pactivity settings, spreading all them into this fieldset.
$options = [];
$options['accepted_types'] = ['.h5p'];
$options['maxbytes'] = 0;
$options['maxfiles'] = 1;
$options['subdirs'] = 0;
$mform->addElement('filemanager', 'packagefile', get_string('package', 'mod_h5pactivity'), null, $options);
$mform->addHelpButton('packagefile', 'package', 'mod_h5pactivity');
// H5P displaying options.
$factory = new \core_h5p\factory();
$core = $factory->get_core();
$displayoptions = (array) \core_h5p\helper::decode_display_options($core);
$mform->addElement('header', 'h5pdisplay', get_string('h5pdisplay', 'mod_h5pactivity'));
foreach ($displayoptions as $key => $value) {
$name = get_string('display'.$key, 'mod_h5pactivity');
$fieldname = "displayopt[$key]";
$mform->addElement('checkbox', $fieldname, $name);
$mform->setType($fieldname, PARAM_BOOL);
}
// Add standard grading elements.
$this->standard_grading_coursemodule_elements();
// Add standard elements.
$this->standard_coursemodule_elements();
// Add standard buttons.
$this->add_action_buttons();
}
/**
* Enforce validation rules here
*
* @param array $data array of ("fieldname"=>value) of submitted data
* @param array $files array of uploaded files "element_name"=>tmp_file_path
* @return array
**/
public function validation($data, $files) {
global $USER;
$errors = parent::validation($data, $files);
if (empty($data['packagefile'])) {
$errors['packagefile'] = get_string('required');
} else {
$draftitemid = file_get_submitted_draft_itemid('packagefile');
file_prepare_draft_area($draftitemid, $this->context->id, 'mod_h5pactivity', 'packagefilecheck', null,
['subdirs' => 0, 'maxfiles' => 1]);
// Get file from users draft area.
$usercontext = context_user::instance($USER->id);
$fs = get_file_storage();
$files = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id', false);
if (count($files) < 1) {
$errors['packagefile'] = get_string('required');
return $errors;
}
$file = reset($files);
if (!$file->is_external_file() && !empty($data['updatefreq'])) {
// Make sure updatefreq is not set if using normal local file.
$errors['updatefreq'] = get_string('updatefreq_error', 'mod_h5pactivity');
}
}
return $errors;
}
/**
* Enforce defaults here.
*
* @param array $defaultvalues Form defaults
* @return void
**/
public function data_preprocessing(&$defaultvalues) {
// H5P file.
$draftitemid = file_get_submitted_draft_itemid('packagefile');
file_prepare_draft_area($draftitemid, $this->context->id, 'mod_h5pactivity',
'package', 0, ['subdirs' => 0, 'maxfiles' => 1]);
$defaultvalues['packagefile'] = $draftitemid;
// H5P display options.
$factory = new \core_h5p\factory();
$core = $factory->get_core();
if (isset($defaultvalues['displayoptions'])) {
$currentdisplay = $defaultvalues['displayoptions'];
$displayoptions = (array) \core_h5p\helper::decode_display_options($core, $currentdisplay);
} else {
$displayoptions = (array) \core_h5p\helper::decode_display_options($core);
}
foreach ($displayoptions as $key => $value) {
$fieldname = "displayopt[$key]";
$defaultvalues[$fieldname] = $value;
}
}
/**
* Allows modules to modify the data returned by form get_data().
* This method is also called in the bulk activity completion form.
*
* Only available on moodleform_mod.
*
* @param stdClass $data passed by reference
*/
public function data_postprocessing($data) {
parent::data_postprocessing($data);
$factory = new \core_h5p\factory();
$core = $factory->get_core();
if (isset($data->displayopt)) {
$config = (object) $data->displayopt;
} else {
$config = \core_h5p\helper::decode_display_options($core);
}
$data->displayoptions = \core_h5p\helper::get_display_options($core, $config);
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

+431
View File
@@ -0,0 +1,431 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
id="svg969"
version="1.1"
overflow="visible"
preserveAspectRatio="xMinYMid meet"
viewBox="-0.1 -2 24 24"
height="24"
width="24">
<metadata
id="metadata975">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs973">
<linearGradient
gradientTransform="translate(-0.2)"
y2="8.8710003"
x2="11.5"
y1="2"
x1="11.5"
gradientUnits="userSpaceOnUse"
id="i">
<stop
id="stop1538"
stop-color="#D0813A"
offset="0" />
<stop
id="stop1540"
stop-color="#AF551D"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="translate(-0.2)"
y2="10.935"
x2="11.499"
y1="1"
x1="11.499"
gradientUnits="userSpaceOnUse"
id="h">
<stop
id="stop1531"
stop-color="#D58738"
offset="0" />
<stop
id="stop1533"
stop-color="#AB551F"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="translate(-0.2)"
y2="13.001"
x2="11.499"
x1="11.499"
gradientUnits="userSpaceOnUse"
id="g">
<stop
id="stop1524"
stop-color="#8D470D"
offset="0" />
<stop
id="stop1526"
stop-color="#7C3D09"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="translate(-0.2)"
y2="5"
x2="11.999"
y1="2"
x1="11.999"
gradientUnits="userSpaceOnUse"
id="f-0">
<stop
id="stop1517"
stop-color="#FFC30F"
offset="0" />
<stop
id="stop1519"
stop-color="#F5AE0D"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="translate(-0.2)"
y2="6"
x2="11.999"
y1="1"
x1="11.999"
gradientUnits="userSpaceOnUse"
id="e-9">
<stop
id="stop1510"
stop-color="#FFEBA8"
offset="0" />
<stop
id="stop1512"
stop-color="#F8BE27"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="translate(-0.2)"
y2="7"
x2="11.999"
x1="11.999"
gradientUnits="userSpaceOnUse"
id="d-3">
<stop
id="stop1503"
stop-color="#F0A829"
offset="0" />
<stop
id="stop1505"
stop-color="#C7671A"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="translate(-0.2)"
y2="18"
x2="11.999"
y1="2"
x1="11.999"
gradientUnits="userSpaceOnUse"
id="c-6">
<stop
id="stop1496"
stop-color="#FFC30F"
offset="0" />
<stop
id="stop1498"
stop-color="#F5AE0D"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="translate(-0.2)"
y2="19"
x2="11.999"
y1="1"
x1="11.999"
gradientUnits="userSpaceOnUse"
id="b-0">
<stop
id="stop1489"
stop-color="#FFEBA8"
offset="0" />
<stop
id="stop1491"
stop-color="#F8BE27"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="translate(-0.2)"
y2="20"
x2="11.999"
x1="11.999"
gradientUnits="userSpaceOnUse"
id="a-6">
<stop
id="stop1482"
stop-color="#F0A829"
offset="0" />
<stop
id="stop1484"
stop-color="#C7671A"
offset="1" />
</linearGradient>
<linearGradient
y2="18"
x2="11.966"
y1="6.9569998"
x1="11.966"
gradientUnits="userSpaceOnUse"
id="f-9"
gradientTransform="translate(-2.1,-7)">
<stop
id="stop960-2"
stop-color="#95BFF8"
offset="0" />
<stop
id="stop962-0"
stop-color="#84ADEF"
offset=".557" />
<stop
id="stop964-2"
stop-color="#7CA4EB"
offset="1" />
</linearGradient>
<linearGradient
y2="18"
x2="11.966"
y1="6.957"
x1="11.966"
gradientUnits="userSpaceOnUse"
id="linearGradient2278"
xlink:href="#f" />
<linearGradient
y2="18"
x2="11.966"
y1="6.957"
x1="11.966"
gradientUnits="userSpaceOnUse"
id="linearGradient2280"
xlink:href="#f" />
<linearGradient
y2="19"
x2="11.967"
y1="5.954"
x1="11.967"
gradientUnits="userSpaceOnUse"
id="e-2"
gradientTransform="translate(-1,-6)">
<stop
id="stop953-2"
stop-color="#BBE0F7"
offset="0" />
<stop
id="stop955-8"
stop-color="#82B4FB"
offset="1" />
</linearGradient>
<linearGradient
y2="19"
x2="11.967"
y1="5.954"
x1="11.967"
gradientUnits="userSpaceOnUse"
id="linearGradient2321"
xlink:href="#e" />
<linearGradient
y2="19"
x2="11.967"
y1="5.954"
x1="11.967"
gradientUnits="userSpaceOnUse"
id="linearGradient2323"
xlink:href="#e" />
<linearGradient
y2="20"
x2="11.935"
x1="11.935"
gradientUnits="userSpaceOnUse"
id="a-7"
gradientTransform="translate(-1.9)">
<stop
id="stop923-3"
stop-color="#76A1F0"
offset="0" />
<stop
id="stop925-6"
stop-color="#6B90D5"
offset="1" />
</linearGradient>
<linearGradient
y2="20"
x2="11.935"
x1="11.935"
gradientUnits="userSpaceOnUse"
id="linearGradient2348"
xlink:href="#a" />
<linearGradient
y2="20"
x2="11.935"
x1="11.935"
gradientUnits="userSpaceOnUse"
id="linearGradient2350"
xlink:href="#a" />
</defs>
<linearGradient
y2="20"
x2="11.935"
x1="11.935"
gradientUnits="userSpaceOnUse"
id="a">
<stop
id="stop923"
stop-color="#76A1F0"
offset="0" />
<stop
id="stop925"
stop-color="#6B90D5"
offset="1" />
</linearGradient>
<path
id="path1487"
d="m 0.8,-5e-7 h 22 V 20 h -22 z"
style="opacity:1;vector-effect:none;fill:url(#linearGradient2348);fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
id="path1494"
d="m 1.8,0.9999995 h 20 V 19 h -20 z"
style="opacity:1;vector-effect:none;fill:url(#linearGradient2323);fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
id="path1501"
d="m 2.8,1.9999995 h 18 V 18 h -18 z"
style="opacity:1;vector-effect:none;fill:url(#linearGradient2278);fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
id="path1508"
d="m -0.2,-5e-7 h 24 v 7 h -24 z"
style="opacity:1;vector-effect:none;fill:url(#linearGradient2350);fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
id="path1515"
d="m 0.8,0.9999995 h 22 v 5 h -22 z"
style="opacity:1;vector-effect:none;fill:url(#linearGradient2321);fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
id="path1522"
d="m 1.8,1.9999995 h 20 v 3 h -20 z"
style="opacity:1;vector-effect:none;fill:url(#linearGradient2280);fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<linearGradient
y2="19"
x2="11.935"
y1=".989"
x1="11.935"
gradientUnits="userSpaceOnUse"
id="b">
<stop
id="stop930"
stop-color="#BBE0F7"
offset="0" />
<stop
id="stop932"
stop-color="#82B4FB"
offset="1" />
</linearGradient>
<linearGradient
y2="18"
x2="11.935"
y1="1.992"
x1="11.935"
gradientUnits="userSpaceOnUse"
id="c">
<stop
id="stop937"
stop-color="#95BFF8"
offset="0" />
<stop
id="stop939"
stop-color="#84ADEF"
offset=".557" />
<stop
id="stop941"
stop-color="#7CA4EB"
offset="1" />
</linearGradient>
<linearGradient
y2="20"
x2="11.936"
y1="5"
x1="11.936"
gradientUnits="userSpaceOnUse"
id="d">
<stop
id="stop946"
stop-color="#76A1F0"
offset="0" />
<stop
id="stop948"
stop-color="#6B90D5"
offset="1" />
</linearGradient>
<linearGradient
y2="19"
x2="11.967"
y1="5.954"
x1="11.967"
gradientUnits="userSpaceOnUse"
id="e">
<stop
id="stop953"
stop-color="#BBE0F7"
offset="0" />
<stop
id="stop955"
stop-color="#82B4FB"
offset="1" />
</linearGradient>
<linearGradient
y2="18"
x2="11.966"
y1="6.957"
x1="11.966"
gradientUnits="userSpaceOnUse"
id="f">
<stop
id="stop960"
stop-color="#95BFF8"
offset="0" />
<stop
id="stop962"
stop-color="#84ADEF"
offset=".557" />
<stop
id="stop964"
stop-color="#7CA4EB"
offset="1" />
</linearGradient>
<style
id="style2"
type="text/css">
.st0{fill:none;}
.st1{fill:#8DB7E2;}
.st2{fill:#FFFFFF;}
.st3{opacity:0.2;}
.st4{fill:#2574A9;}
.st5{fill:#2376C1;}
</style>
<g
id="g848"
transform="matrix(0.05279347,0,0,0.05279347,2.6957661,8.5728055)"
style="fill:#ffffff;fill-opacity:1">
<path
id="path844"
d="M 325.7,14.7 C 317.6,6.9 305.3,3 289,3 H 245.5 234 v 31 h -66 l -5.4,22.2 c 4.5,-2.1 10.9,-4.2 15.3,-5.3 4.4,-1.1 8.8,-0.9 13.1,-0.9 14.6,0 26.5,4.5 35.6,13.3 9.1,8.8 13.6,20 13.6,33.4 0,9.4 -2.3,18.5 -7,27.2 -4.7,8.7 -11.3,15.4 -19.9,20 -3.1,1.6 -6.5,3.1 -10.2,4.1 H 245.5 259 V 95 h 25 c 18.2,0 31.7,-4.2 40.6,-12.5 8.9,-8.3 13.3,-19.9 13.3,-34.6 0,-14.3 -4.1,-25.4 -12.2,-33.2 z m -37,45.9 c -3.5,3 -9.6,4.4 -18.3,4.4 H 259 V 33 h 13.2 c 8.4,0 14.2,1.5 17.2,4.7 3.1,3.2 4.6,6.9 4.6,11.5 0,4.7 -1.8,8.4 -5.3,11.4 z"
style="fill:#ffffff;fill-opacity:1" />
<path
id="path846"
d="m 176.5,76.3 c -7.9,0 -14.7,4.6 -18,11.2 L 119,81.9 136.8,3 H 113.2 101 V 65 H 51 V 3 H 7 V 148 H 51 V 95 h 50 v 53 h 12.2 42 c -6.7,-2 -12.5,-4.6 -17.2,-8.1 -4.8,-3.6 -8.7,-7.7 -11.7,-12.3 -3,-4.6 -5.3,-9.7 -7.3,-16.5 l 39.6,-5.7 c 3.3,6.6 10.1,11.1 17.9,11.1 11.1,0 20.1,-9 20.1,-20.1 0,-11.1 -9.1,-20.1 -20.1,-20.1 z"
style="fill:#ffffff;fill-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1,126 @@
@mod @mod_h5pactivity @core_h5p @_file_upload @_switch_iframe
Feature: Add H5P activity
In order to let students access a H5P package
As a teacher
I need to add H5P activity to a course
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/h5p:updatelibraries | Allow | editingteacher | System | |
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
@javascript
Scenario: Add a h5pactivity activity to a course
When I add a "H5P activity" to section "1"
And I set the following fields to these values:
| Name | Awesome H5P package |
| Description | Description |
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "Package file" filemanager
And I click on "Save and display" "button"
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should see "Lorum ipsum"
And I should not see "Reuse"
And I should not see "Rights of use"
And I should not see "Embed"
And I switch to the main frame
@javascript
Scenario: Add a h5pactivity activity with download
When I add a "H5P activity" to section "1"
And I set the following fields to these values:
| Name | Awesome H5P package |
| Description | Description |
| Allow download | 1 |
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "Package file" filemanager
And I click on "Save and display" "button"
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should see "Reuse"
And I should not see "Rights of use"
And I should not see "Embed"
And I switch to the main frame
@javascript
Scenario: Add a h5pactivity activity with embed
When I add a "H5P activity" to section "1"
And I set the following fields to these values:
| Name | Awesome H5P package |
| Description | Description |
| Embed button | 1 |
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "Package file" filemanager
And I click on "Save and display" "button"
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should not see "Reuse"
And I should not see "Rights of use"
And I should see "Embed"
And I switch to the main frame
@javascript
Scenario: Add a h5pactivity activity with copyright
When I add a "H5P activity" to section "1"
And I set the following fields to these values:
| Name | Awesome H5P package |
| Description | Description |
| Copyright button | 1 |
And I upload "h5p/tests/fixtures/guess-the-answer.h5p" file to "Package file" filemanager
And I click on "Save and display" "button"
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should not see "Reuse"
And I should see "Rights of use"
And I should not see "Embed"
And I switch to the main frame
@javascript
Scenario: Add a h5pactivity activity with copyright in a content without copyright
When I add a "H5P activity" to section "1"
And I set the following fields to these values:
| Name | Awesome H5P package |
| Description | Description |
| Copyright button | 1 |
And I upload "h5p/tests/fixtures/ipsums.h5p" file to "Package file" filemanager
And I click on "Save and display" "button"
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should not see "Reuse"
And I should not see "Rights of use"
And I should not see "Embed"
And I switch to the main frame
@javascript
Scenario: Add a h5pactivity activity to a course with all display options enabled
When I add a "H5P activity" to section "1"
And I set the following fields to these values:
| Name | Awesome H5P package |
| Description | Description |
| Allow download | 1 |
| Embed button | 1 |
| Copyright button | 1 |
And I upload "h5p/tests/fixtures/guess-the-answer.h5p" file to "Package file" filemanager
And I click on "Save and display" "button"
And I wait until the page is ready
Then I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
And I should see "Reuse"
And I should see "Rights of use"
And I should see "Embed"
And I switch to the main frame
+107
View File
@@ -0,0 +1,107 @@
<?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/>.
/**
* Events test.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* H5P activity events test cases.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_h5pactivity_events_testcase extends advanced_testcase {
/**
* Setup is called before calling test case.
*/
public function setUp() {
// Must be a non-guest user to create h5pactivities.
$this->setAdminUser();
}
/**
* Test course_module_instance_list_viewed event.
*/
public function test_course_module_instance_list_viewed() {
// There is no proper API to call to trigger this event, so what we are
// doing here is simply making sure that the events returns the right information.
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$params = [
'context' => context_course::instance($course->id)
];
$event = \mod_h5pactivity\event\course_module_instance_list_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_h5pactivity\event\course_module_instance_list_viewed', $event);
$this->assertEquals(context_course::instance($course->id), $event->get_context());
$expected = [$course->id, 'h5pactivity', 'view all', 'index.php?id='.$course->id, ''];
$this->assertEventLegacyLogData($expected, $event);
$this->assertEventContextNotUsed($event);
}
/**
* Test course_module_viewed event.
*/
public function test_course_module_viewed() {
// There is no proper API to call to trigger this event, so what we are
// doing here is simply making sure that the events returns the right information.
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course->id]);
$params = [
'context' => context_module::instance($activity->cmid),
'objectid' => $activity->id
];
$event = \mod_h5pactivity\event\course_module_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_h5pactivity\event\course_module_viewed', $event);
$this->assertEquals(context_module::instance($activity->cmid), $event->get_context());
$this->assertEquals($activity->id, $event->objectid);
$expected = [$course->id, 'h5pactivity', 'view', 'view.php?id=' . $activity->cmid, $activity->id, $activity->cmid];
$this->assertEventLegacyLogData($expected, $event);
$this->assertEventContextNotUsed($event);
}
}
+91
View File
@@ -0,0 +1,91 @@
<?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/>.
/**
* Data generator.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* h5pactivity module data generator class.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_h5pactivity_generator extends testing_module_generator {
/**
* Creates new h5pactivity module instance. By default it contains a short
* text file.
*
* @param array|stdClass $record data for module being generated. Requires 'course' key
* (an id or the full object). Also can have any fields from add module form.
* @param null|array $options general options for course module. Since 2.6 it is
* possible to omit this argument by merging options into $record
* @return stdClass record from module-defined table with additional field
* cmid (corresponding id in course_modules table)
*/
public function create_instance($record = null, array $options = null) {
global $CFG, $USER;
// Ensure the record can be modified without affecting calling code.
$record = (object)(array)$record;
// Fill in optional values if not specified.
if (!isset($record->packagefilepath)) {
$record->packagefilepath = $CFG->dirroot.'/h5p/tests/fixtures/h5ptest.zip';
}
if (!isset($record->grade)) {
$record->grade = 100;
}
if (!isset($record->displayoptions)) {
$factory = new \core_h5p\factory();
$core = $factory->get_core();
$config = \core_h5p\helper::decode_display_options($core);
$record->displayoptions = \core_h5p\helper::get_display_options($core, $config);
}
// The 'packagefile' value corresponds to the draft file area ID. If not specified, create from packagefilepath.
if (empty($record->packagefile)) {
if (!isloggedin() || isguestuser()) {
throw new coding_exception('Scorm generator requires a current user');
}
if (!file_exists($record->packagefilepath)) {
throw new coding_exception("File {$record->packagefilepath} does not exist");
}
$usercontext = context_user::instance($USER->id);
// Pick a random context id for specified user.
$record->packagefile = file_get_unused_draft_itemid();
// Add actual file there.
$filerecord = ['component' => 'user', 'filearea' => 'draft',
'contextid' => $usercontext->id, 'itemid' => $record->packagefile,
'filename' => basename($record->packagefilepath), 'filepath' => '/'];
$fs = get_file_storage();
$fs->create_file_from_pathname($filerecord, $record->packagefilepath);
}
// Do work to actually add the instance.
return parent::create_instance($record, (array)$options);
}
}
+106
View File
@@ -0,0 +1,106 @@
<?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_h5pactivity generator tests
*
* @package mod_h5pactivity
* @category test
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Genarator tests class for mod_h5pactivity.
*
* @package mod_h5pactivity
* @category test
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_h5pactivity_generator_testcase extends advanced_testcase {
/**
* Test on H5P activity creation.
*/
public function test_create_instance() {
global $DB, $CFG, $USER;
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
// Create one activity.
$this->assertFalse($DB->record_exists('h5pactivity', ['course' => $course->id]));
$activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]);
$records = $DB->get_records('h5pactivity', ['course' => $course->id], 'id');
$this->assertEquals(15, $activity->displayoptions);
$this->assertEquals(1, count($records));
$this->assertTrue(array_key_exists($activity->id, $records));
// Create a second one with different name and dusplay options.
$params = ['course' => $course->id, 'name' => 'Another h5pactivity', 'displayoptions' => 6];
$activity = $this->getDataGenerator()->create_module('h5pactivity', $params);
$records = $DB->get_records('h5pactivity', ['course' => $course->id], 'id');
$this->assertEquals(6, $activity->displayoptions);
$this->assertEquals(2, count($records));
$this->assertEquals('Another h5pactivity', $records[$activity->id]->name);
// Examples of specifying the package file (do not validate anything, just check for exceptions).
// 1. As path to the file in filesystem.
$params = [
'course' => $course->id,
'packagefilepath' => $CFG->dirroot.'/h5p/tests/fixtures/filltheblanks.h5p'
];
$activity = $this->getDataGenerator()->create_module('h5pactivity', $params);
// 2. As file draft area id.
$fs = get_file_storage();
$params = [
'course' => $course->id,
'packagefile' => file_get_unused_draft_itemid()
];
$usercontext = context_user::instance($USER->id);
$filerecord = ['component' => 'user', 'filearea' => 'draft',
'contextid' => $usercontext->id, 'itemid' => $params['packagefile'],
'filename' => 'singlescobasic.zip', 'filepath' => '/'];
$filepath = $CFG->dirroot.'/h5p/tests/fixtures/filltheblanks.h5p';
$fs->create_file_from_pathname($filerecord, $filepath);
$activity = $this->getDataGenerator()->create_module('h5pactivity', $params);
}
/**
* Test that a new H5P activity cannot be generated without a valid file
* other user.
*/
public function test_create_file_exception() {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
// Testing generator exceptions.
$params = [
'course' => $course->id,
'packagefilepath' => $CFG->dirroot.'/h5p/tests/fixtures/wrong_file_.xxx'
];
$this->expectException(coding_exception::class);
$activity = $this->getDataGenerator()->create_module('h5pactivity', $params);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?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/>.
/**
* Plugin version and other meta-data are defined here.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'mod_h5pactivity';
$plugin->version = 2020022501;
$plugin->requires = 2020013000;
+74
View File
@@ -0,0 +1,74 @@
<?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/>.
/**
* Prints an instance of mod_h5pactivity.
*
* @package mod_h5pactivity
* @copyright 2020 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require(__DIR__.'/../../config.php');
require_once(__DIR__.'/lib.php');
require_once($CFG->libdir.'/completionlib.php');
$id = required_param('id', PARAM_INT);
list ($course, $cm) = get_course_and_cm_from_cmid($id, 'h5pactivity');
require_login($course, true, $cm);
$moduleinstance = $DB->get_record('h5pactivity', ['id' => $cm->instance], '*', MUST_EXIST);
$context = context_module::instance($cm->id);
$event = \mod_h5pactivity\event\course_module_viewed::create([
'objectid' => $moduleinstance->id,
'context' => $context
]);
$event->add_record_snapshot('course', $course);
$event->add_record_snapshot('h5pactivity', $moduleinstance);
$event->trigger();
// Completion.
$completion = new completion_info($course);
$completion->set_module_viewed($cm);
// Convert display options to a valid object.
$factory = new \core_h5p\factory();
$core = $factory->get_core();
$config = \core_h5p\helper::decode_display_options($core, $moduleinstance->displayoptions);
// Instantiate player.
$fs = get_file_storage();
$files = $fs->get_area_files($context->id, 'mod_h5pactivity', 'package', 0, 'id', false);
$file = reset($files);
$fileurl = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
$file->get_filearea(), $file->get_itemid(), $file->get_filepath(),
$file->get_filename(), false);
$PAGE->set_url('/mod/h5pactivity/view.php', ['id' => $cm->id]);
$PAGE->set_title(format_string($moduleinstance->name));
$PAGE->set_heading(format_string($course->fullname));
$PAGE->set_context($context);
echo $OUTPUT->header();
// TODO: add component to enable xAPI traking.
echo \core_h5p\player::display($fileurl, $config, true);
echo $OUTPUT->footer();