Merge branch 'MDL-83895-main' of https://github.com/aanabit/moodle
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
issueNumber: MDL-83896
|
||||
notes:
|
||||
core_courseformat:
|
||||
- message: >-
|
||||
Added new core_courseformat\output\local\overview\overviewdialog output
|
||||
class to create dialog elements in the course overview page. Overview
|
||||
dialog will display a combination of title, description and a list
|
||||
of items (label: value).
|
||||
type: improved
|
||||
@@ -0,0 +1,124 @@
|
||||
<?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/>.
|
||||
|
||||
namespace core_courseformat\output\local\overview;
|
||||
|
||||
use core\output\local\dropdown\dialog;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class to render an overview dialog element.
|
||||
*
|
||||
* @package core_courseformat
|
||||
* @copyright 2025 Mikel Martín <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class overviewdialog extends dialog {
|
||||
|
||||
/** @var stdClass[] The list of the items. */
|
||||
protected array $items;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* The definition object could contain the following keys:
|
||||
* - classes: component CSS classes.
|
||||
* - buttonclasses: the button CSS classes.
|
||||
* - dialogwidth: the dropdown width.
|
||||
* - extras: extra HTML attributes (attribute => value).
|
||||
*
|
||||
* @param string $buttoncontent the button content
|
||||
* @param string $title the overview dialog content title
|
||||
* @param string $description the overview dialog content description
|
||||
* @param array $definition an optional array of the element definition
|
||||
*/
|
||||
public function __construct(
|
||||
string $buttoncontent,
|
||||
/** @var string The title of the overview dialog content. */
|
||||
protected string $title = '',
|
||||
/** @var string The title of the overview dialog content. */
|
||||
protected string $description = '',
|
||||
array $definition = []
|
||||
) {
|
||||
parent::__construct($buttoncontent, '', $definition);
|
||||
$this->items = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the items to be displayed in the overview dialog.
|
||||
*
|
||||
* @param string $label the label of the item
|
||||
* @param string $value the value of the item
|
||||
* @return overviewdialog
|
||||
*/
|
||||
public function add_item(string $label, string $value): self {
|
||||
$this->items[] = (object) [
|
||||
'label' => $label,
|
||||
'value' => $value,
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title of the overview dialog content.
|
||||
*
|
||||
* @param string $title the title to set
|
||||
* @return overviewdialog
|
||||
*/
|
||||
public function set_title(string $title): self {
|
||||
$this->title = $title;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the description of the overview dialog content.
|
||||
*
|
||||
* @param string $description the description to set
|
||||
* @return overviewdialog
|
||||
*/
|
||||
public function set_description(string $description): self {
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export this data so it can be used as the context for a mustache template.
|
||||
*
|
||||
* @param \renderer_base $output typically, the renderer that's calling this function
|
||||
* @return array data context for a mustache template
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output): array {
|
||||
$data = [
|
||||
...parent::export_for_template($output),
|
||||
'title' => $this->title,
|
||||
'items' => $this->items,
|
||||
'hasitems' => count($this->items),
|
||||
'description' => $this->description,
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the template to use for this templatable.
|
||||
*
|
||||
* @param \renderer_base $renderer The renderer requesting the template name
|
||||
* @return string the template name
|
||||
*/
|
||||
public function get_template_name(\renderer_base $renderer): string {
|
||||
return 'core_courseformat/local/overview/overviewdialog';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_courseformat/local/overview/overviewdialog
|
||||
|
||||
Shows an overview dialog.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"buttoncontent" : "Trigger button",
|
||||
"title": "Total Attempts",
|
||||
"description": "This shows the total attempts made by the user in the course.",
|
||||
"hasitems": true,
|
||||
"items": [
|
||||
{
|
||||
"label": "Allowed Attempts",
|
||||
"value": 3
|
||||
},
|
||||
{
|
||||
"label": "Average Attempts",
|
||||
"value": "Max reached"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
{{< core/local/dropdown/dialog }}
|
||||
{{$ dialogcontent }}
|
||||
<div class="px-3">
|
||||
{{#title}}
|
||||
<span class="fw-bold">{{title}}</span>
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
<div class="mt-2 mb-3">{{{description}}}</div>
|
||||
{{/description}}
|
||||
{{#hasitems}}
|
||||
<ul class="my-2">
|
||||
{{#items}}
|
||||
<li>
|
||||
{{#str}}
|
||||
labelvalue, core, {
|
||||
"label": {{#quote}}{{label}}{{/quote}},
|
||||
"value": {{#quote}}<span class="fw-bold">{{value}}</span>{{/quote}}
|
||||
}
|
||||
{{/str}}
|
||||
</li>
|
||||
{{/items}}
|
||||
</ul>
|
||||
{{/hasitems}}
|
||||
</div>
|
||||
{{/ dialogcontent }}
|
||||
{{/ core/local/dropdown/dialog }}
|
||||
@@ -117,7 +117,7 @@ final class overviewfactory_test extends \advanced_testcase {
|
||||
],
|
||||
'h5pactivity' => [
|
||||
'resourcetype' => 'h5pactivity',
|
||||
'expected' => resourceoverview::class,
|
||||
'expected' => \mod_h5pactivity\courseformat\overview::class,
|
||||
],
|
||||
'lesson' => [
|
||||
'resourcetype' => 'lesson',
|
||||
|
||||
@@ -72,7 +72,7 @@ final class missingoverviewnotice_test extends \advanced_testcase {
|
||||
'folder' => ['modname' => 'folder', 'expectempty' => false],
|
||||
'forum' => ['modname' => 'forum', 'expectempty' => false],
|
||||
'glossary' => ['modname' => 'glossary', 'expectempty' => true],
|
||||
'h5pactivity' => ['modname' => 'h5pactivity', 'expectempty' => false],
|
||||
'h5pactivity' => ['modname' => 'h5pactivity', 'expectempty' => true],
|
||||
'imscp' => ['modname' => 'imscp', 'expectempty' => false],
|
||||
'label' => ['modname' => 'label', 'expectempty' => false],
|
||||
'lesson' => ['modname' => 'lesson', 'expectempty' => false],
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
<?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/>.
|
||||
|
||||
namespace mod_h5pactivity\courseformat;
|
||||
|
||||
use cm_info;
|
||||
use core_courseformat\local\overview\overviewitem;
|
||||
use core\output\action_link;
|
||||
use core\output\local\properties\text_align;
|
||||
use core\output\local\properties\button;
|
||||
use core\url;
|
||||
use core_courseformat\output\local\overview\overviewdialog;
|
||||
use mod_h5pactivity\local\manager;
|
||||
|
||||
/**
|
||||
* H5P activity overview integration.
|
||||
*
|
||||
* @package mod_h5pactivity
|
||||
* @copyright 2025 Amaia Anabitarte <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class overview extends \core_courseformat\activityoverviewbase {
|
||||
|
||||
/** @var manager H5P activity manager. */
|
||||
private $manager;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param cm_info $cm the course module instance.
|
||||
* @param \core\output\renderer_helper $rendererhelper the renderer helper.
|
||||
* @param \core_string_manager $stringmanager the string manager.
|
||||
*/
|
||||
public function __construct(
|
||||
cm_info $cm,
|
||||
/** @var \core\output\renderer_helper $rendererhelper the renderer helper */
|
||||
protected readonly \core\output\renderer_helper $rendererhelper,
|
||||
/** @var \core_string_manager $stringmanager the string manager */
|
||||
protected readonly \core_string_manager $stringmanager,
|
||||
) {
|
||||
parent::__construct($cm);
|
||||
|
||||
$this->manager = manager::create_from_coursemodule($cm);
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function get_actions_overview(): ?overviewitem {
|
||||
|
||||
if (!$this->manager->can_view_all_attempts()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$viewresults = $this->stringmanager->get_string('viewresults', 'mod_h5pactivity');
|
||||
$content = new action_link(
|
||||
url: new url('/mod/h5pactivity/report.php', ['id' => $this->cm->id]),
|
||||
text: $viewresults,
|
||||
attributes: ['class' => button::SECONDARY_OUTLINE->classes()],
|
||||
);
|
||||
|
||||
return new overviewitem(
|
||||
name: $this->stringmanager->get_string('actions'),
|
||||
value: '',
|
||||
content: $content,
|
||||
textalign: text_align::CENTER,
|
||||
);
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function get_extra_overview_items(): array {
|
||||
global $USER;
|
||||
|
||||
if (!$this->manager->can_view_own_attempts() && $this->manager->can_view_all_attempts()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!$this->manager->can_view_all_attempts()) {
|
||||
return [
|
||||
'myattempts' => $this->get_extra_userattempts_overview($USER->id),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'h5ptype' => $this->get_extra_h5ptype_overview(),
|
||||
'attempted' => $this->get_extra_studentsattempted_overview(),
|
||||
'totalattempts' => $this->get_extra_totalattempts_overview(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attempts of the given user.
|
||||
*
|
||||
* @param int $userid The user to return the attempts from.
|
||||
* @return overviewitem The overview item.
|
||||
*/
|
||||
private function get_extra_userattempts_overview(int $userid): overviewitem {
|
||||
|
||||
$attempts = $this->manager->count_attempts($userid);
|
||||
return new overviewitem(
|
||||
name: $this->stringmanager->get_string('attempts', 'mod_h5pactivity'),
|
||||
value: $attempts,
|
||||
content: $attempts ?? '-',
|
||||
textalign: text_align::CENTER,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the students who attempted.
|
||||
*
|
||||
* @return overviewitem The overview item.
|
||||
*/
|
||||
private function get_extra_studentsattempted_overview(): overviewitem {
|
||||
|
||||
$attempts = $this->manager->count_users_attempts();
|
||||
$participants = get_users_by_capability($this->context, 'mod/h5pactivity:submit');
|
||||
$params = [
|
||||
'count' => count($attempts),
|
||||
'total' => count($participants),
|
||||
];
|
||||
return new overviewitem(
|
||||
name: $this->stringmanager->get_string('attempted', 'mod_h5pactivity'),
|
||||
value: count($attempts),
|
||||
content: $this->stringmanager->get_string('count_of_total', 'core', $params),
|
||||
textalign: text_align::CENTER,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "Total attempts" colum data.
|
||||
*
|
||||
* @return overviewitem The overview item.
|
||||
*/
|
||||
private function get_extra_totalattempts_overview(): overviewitem {
|
||||
$totalattempts = $this->manager->count_attempts();
|
||||
$totalusers = $this->manager->count_users_attempts();
|
||||
|
||||
$content = '-';
|
||||
if ($totalusers && count($totalusers) > 0 && $totalattempts) {
|
||||
$averageattempts = (int) round($totalattempts / count($totalusers));
|
||||
$content = new overviewdialog(
|
||||
buttoncontent: $totalattempts,
|
||||
title: $this->stringmanager->get_string('totalattempts', 'mod_h5pactivity'),
|
||||
definition: ['buttonclasses' => button::SECONDARY_OUTLINE->classes() . ' dropdown-toggle'],
|
||||
);
|
||||
$method = $this->manager::get_grading_methods()[$this->manager->get_instance()->grademethod];
|
||||
$content->add_item($this->stringmanager->get_string('gradingmethod', 'grading'), $method);
|
||||
$content->add_item($this->stringmanager->get_string('averageattempts', 'mod_h5pactivity'), $averageattempts);
|
||||
}
|
||||
|
||||
return new overviewitem(
|
||||
name: $this->stringmanager->get_string('totalattempts', 'mod_h5pactivity'),
|
||||
value: $totalattempts,
|
||||
content: $content,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the H5P content type.
|
||||
*
|
||||
* @return overviewitem The overview item.
|
||||
*/
|
||||
private function get_extra_h5ptype_overview(): overviewitem {
|
||||
$fs = get_file_storage();
|
||||
$files = $fs->get_area_files($this->context->id, 'mod_h5pactivity', 'package', 0, 'id', false);
|
||||
$file = reset($files);
|
||||
|
||||
$h5p = \core_h5p\api::get_content_from_pathnamehash($file->get_pathnamehash());
|
||||
|
||||
$unknonwoverview = new overviewitem(
|
||||
name: $this->stringmanager->get_string('contenttype', 'mod_h5pactivity'),
|
||||
value: $this->stringmanager->get_string('unknowntype', 'mod_h5pactivity'),
|
||||
content: $this->stringmanager->get_string('unknowntype', 'mod_h5pactivity'),
|
||||
);
|
||||
|
||||
if (empty($h5p)) {
|
||||
return $unknonwoverview;
|
||||
}
|
||||
|
||||
$h5plib = \core_h5p\api::get_library($h5p->mainlibraryid);
|
||||
|
||||
// If the content is not yet deployed we cannot show the content type.
|
||||
if (empty($h5plib)) {
|
||||
return $unknonwoverview;
|
||||
}
|
||||
|
||||
return new overviewitem(
|
||||
name: $this->stringmanager->get_string('contenttype', 'mod_h5pactivity'),
|
||||
value: $h5plib->title,
|
||||
content: $h5plib->title,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -25,62 +25,5 @@
|
||||
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'] = 'table generaltable mod_index';
|
||||
|
||||
$align = ['center', 'left'];
|
||||
if ($course->format == 'weeks' || $course->format == 'topics') {
|
||||
$table->head = [get_string('section'), 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();
|
||||
$courseid = required_param('id', PARAM_INT);
|
||||
\core_courseformat\activityoverviewbase::redirect_to_overview_page($courseid, 'h5pactivity');
|
||||
|
||||
@@ -37,6 +37,7 @@ $string['answer_text'] = 'Answer text';
|
||||
$string['answer_noanswer'] = 'None';
|
||||
$string['areapackage'] = 'Package file';
|
||||
$string['attempt'] = 'Attempt';
|
||||
$string['attempted'] = 'Students who attempted';
|
||||
$string['attempt_average'] = 'Attempts average scored';
|
||||
$string['attempt_answer'] = 'Attempt answer';
|
||||
$string['attempt_completion_no'] = 'This attempt is not marked as completed';
|
||||
@@ -53,10 +54,12 @@ $string['attempts'] = 'Attempts';
|
||||
$string['attempts_report_header_label'] = 'Attempts ({$a})';
|
||||
$string['attempts_report'] = 'Attempts report';
|
||||
$string['attempts_none'] = 'This user has no attempts to display.';
|
||||
$string['averageattempts'] = 'Average attempts per student';
|
||||
$string['choice'] = 'Choice';
|
||||
$string['completion'] = 'Completion';
|
||||
$string['contentbank'] = 'More information about the content bank';
|
||||
$string['contentbank_help'] = 'In the content bank you can create and store content using several authoring tools, including an integrated H5P creator.';
|
||||
$string['contenttype'] = 'H5P type';
|
||||
$string['correct_answer'] = 'Correct answer';
|
||||
$string['deleteallattempts'] = 'All H5P attempts';
|
||||
$string['displayexport'] = 'Allow download';
|
||||
@@ -140,12 +143,15 @@ $string['score_out_of'] = '{$a->rawscore} out of {$a->maxscore}';
|
||||
$string['search:activity'] = 'H5P - activity information';
|
||||
$string['startdate'] = 'Start date';
|
||||
$string['statement_received'] = 'xAPI statement received';
|
||||
$string['totalattempts'] = 'Total attempts';
|
||||
$string['totalscore'] = 'Total score';
|
||||
$string['trackingdisabled'] = 'Attempt tracking is not enabled for this activity.';
|
||||
$string['trackingdisabled_enable'] = 'Attempt tracking is not enabled for this activity. You can enable it in <a href="{$a}">Settings</a>.';
|
||||
$string['tracking_messages'] = 'Some H5P provide attempt tracking data for advanced reporting such as number of attempts, responses and grades. Note: Some H5P don\'t provide attempt tracking data. In such cases, the following settings will have no effect.';
|
||||
$string['true'] = 'True';
|
||||
$string['unknowntype'] = 'Unknown H5P type';
|
||||
$string['usecontentbank'] = 'Use the <a href="{$a}" target="_blank">content bank (opens in new window)</a> to manage your H5P files';
|
||||
$string['view'] = 'View';
|
||||
$string['viewattempts'] = 'View attempts ({$a})';
|
||||
$string['viewresults'] = 'View results';
|
||||
$string['view_report'] = 'View report';
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
@mod @mod_h5pactivity
|
||||
Feature: Testing overview integration in H5P activity
|
||||
In order to summarize the H5P activity
|
||||
As a user
|
||||
I need to be able to see the H5P activity overview
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
| student2 | Student | 2 | student2@example.com |
|
||||
| student3 | Student | 3 | student3@example.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category | enablecompletion |
|
||||
| Course 1 | C1 | 0 | 1 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
| student3 | C1 | student |
|
||||
And the following "activity" exists:
|
||||
| course | C1 |
|
||||
| activity | h5pactivity |
|
||||
| name | H5P activity |
|
||||
| intro | description |
|
||||
| packagefilepath | h5p/tests/fixtures/find-the-words.h5p |
|
||||
| idnumber | h5p |
|
||||
| completion | 1 |
|
||||
| enabletracking | 1 |
|
||||
| reviewmode | 1 |
|
||||
| grademethod | 2 |
|
||||
And the following "activity" exists:
|
||||
| course | C1 |
|
||||
| activity | h5pactivity |
|
||||
| name | Empty H5P activity |
|
||||
| intro | empty |
|
||||
| idnumber | empty |
|
||||
And the following "mod_h5pactivity > attempts" exist:
|
||||
| user | h5pactivity | attempt | interactiontype | rawscore | maxscore | duration | completion | success |
|
||||
# student1.
|
||||
| student1 | H5P activity | 1 | choice | 2 | 2 | 1 | 1 | 1 |
|
||||
| student1 | H5P activity | 1 | compound | 2 | 2 | 4 | 1 | 1 |
|
||||
| student1 | H5P activity | 2 | choice | 0 | 2 | 1 | 1 | 0 |
|
||||
| student1 | H5P activity | 2 | compound | 0 | 2 | 4 | 1 | 0 |
|
||||
| student1 | H5P activity | 3 | matching | 2 | 2 | 1 | 1 | 1 |
|
||||
| student1 | H5P activity | 3 | compound | 2 | 2 | 4 | 1 | 1 |
|
||||
| student1 | H5P activity | 4 | true-false | 2 | 2 | 1 | 1 | 1 |
|
||||
| student1 | H5P activity | 4 | compound | 2 | 2 | 4 | 1 | 1 |
|
||||
# student2.
|
||||
| student2 | H5P activity | 1 | compound | 0 | 2 | 1 | 1 | 0 |
|
||||
# We need to navigate to the activity to deploy the H5P file.
|
||||
And I am on the "H5P activity" "h5pactivity activity" page logged in as admin
|
||||
And I log out
|
||||
|
||||
Scenario: The H5P activity overview report should generate log events
|
||||
Given I am on the "Course 1" "course > activities > h5pactivity" page logged in as "teacher1"
|
||||
And I am on the "Course 1" "course" page logged in as "teacher1"
|
||||
And I navigate to "Reports" in current page administration
|
||||
And I click on "Logs" "link"
|
||||
When I click on "Get these logs" "button"
|
||||
Then I should see "Course activities overview page viewed"
|
||||
And I should see "viewed the instance list for the module 'h5pactivity'"
|
||||
|
||||
@javascript
|
||||
Scenario: Students can see relevant columns in the H5P activity overview
|
||||
Given I am on the "Course 1" "course > activities > h5pactivity" page logged in as student1
|
||||
# Check columns.
|
||||
When I should see "Completion status" in the "h5pactivity_overview_collapsible" "region"
|
||||
# Check column values.
|
||||
Then the following should exist in the "Table listing all H5P activities" table:
|
||||
| Name | Attempts | Grade |
|
||||
| H5P activity | 4 | 75.00 |
|
||||
| Empty H5P activity | 0 | - |
|
||||
|
||||
@javascript
|
||||
Scenario: Teachers can see relevant columns in the H5P activity overview
|
||||
Given I am on the "Course 1" "course > activities > h5pactivity" page logged in as teacher1
|
||||
# Check columns.
|
||||
And I should see "Total attempts" in the "h5pactivity_overview_collapsible" "region"
|
||||
# Check column values.
|
||||
And the following should exist in the "Table listing all H5P activities" table:
|
||||
| Name | H5P type | Students who attempted | Total attempts | Actions |
|
||||
| H5P activity | Find The Words | 2 of 3 | 5 | View results |
|
||||
| Empty H5P activity | Unknown H5P type | 0 of 3 | - | View results |
|
||||
# Check the Total attempts value.
|
||||
And I should see "-" in the "Empty H5P activity" "table_row"
|
||||
When I click on "5" "button" in the "H5P activity" "table_row"
|
||||
Then I should see "Grading method: Average grade"
|
||||
And I should see "Average attempts per student: 3"
|
||||
# Check the View results link.
|
||||
And I click on "View results" "link" in the "H5P activity" "table_row"
|
||||
And I should see "Attempts (5)"
|
||||
|
||||
Scenario: The H5P activity index redirect to the activities overview
|
||||
Given I log in as "admin"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I add the "Activities" block
|
||||
When I click on "H5P" "link" in the "Activities" "block"
|
||||
Then I should see "An overview of all activities in the course"
|
||||
And I should see "Name" in the "h5pactivity_overview_collapsible" "region"
|
||||
And I should see "H5P type" in the "h5pactivity_overview_collapsible" "region"
|
||||
And I should see "Actions" in the "h5pactivity_overview_collapsible" "region"
|
||||
@@ -0,0 +1,247 @@
|
||||
<?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/>.
|
||||
|
||||
namespace mod_h5pactivity\courseformat;
|
||||
|
||||
use core_courseformat\local\overview\overviewfactory;
|
||||
|
||||
/**
|
||||
* Tests for H5P activity overview
|
||||
*
|
||||
* @covers \mod_h5pactivity\courseformat\overview
|
||||
* @package mod_h5pactivity
|
||||
* @category test
|
||||
* @copyright 2025 Amaia Anabitarte <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class overview_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test get_actions_overview.
|
||||
*
|
||||
* @covers ::get_actions_overview
|
||||
*/
|
||||
public function test_get_actions_overview(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$activity = $this->getDataGenerator()->create_module(
|
||||
'h5pactivity',
|
||||
['course' => $course, 'enabletracking' => 1],
|
||||
);
|
||||
$cm = get_fast_modinfo($course)->get_cm($activity->cmid);
|
||||
|
||||
// Prepare users: 1 teacher, 2 students, 1 unenroled user.
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
|
||||
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
|
||||
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity');
|
||||
|
||||
// Students have no action column.
|
||||
$this->setUser($student);
|
||||
$this->assertNull(overviewfactory::create($cm)->get_actions_overview());
|
||||
|
||||
// Teachers have a 'View results' button.
|
||||
$this->setUser($teacher);
|
||||
$items = overviewfactory::create($cm)->get_actions_overview();
|
||||
$this->assertNotNull($items);
|
||||
$this->assertEquals(get_string('actions'), $items->get_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_extra_h5ptype_overview.
|
||||
*
|
||||
* @covers ::get_extra_h5ptype_overview
|
||||
* @dataProvider provider_test_get_extra_h5type_overview
|
||||
*
|
||||
* @param string $h5pfile
|
||||
* @param bool $iscorrect
|
||||
* @param string $expected
|
||||
* @return void
|
||||
*/
|
||||
public function test_get_extra_h5ptype_overview(
|
||||
string $h5pfile,
|
||||
bool $iscorrect,
|
||||
string $expected
|
||||
): void {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$params = [
|
||||
'course' => $course->id,
|
||||
'packagefilepath' => $CFG->dirroot.'/h5p/tests/fixtures/'.$h5pfile,
|
||||
'introformat' => 1,
|
||||
];
|
||||
$activity = $this->getDataGenerator()->create_module('h5pactivity', $params);
|
||||
// Add filename and contextid to make easier the asserts.
|
||||
$activity->filename = $h5pfile;
|
||||
$context = \context_module::instance($activity->cmid);
|
||||
$activity->contextid = $context->id;
|
||||
|
||||
// Create a fake deploy H5P file.
|
||||
|
||||
/** @var \core_h5p_generator $h5pgenerator */
|
||||
$h5pgenerator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
|
||||
|
||||
if (!$iscorrect) {
|
||||
$this->expectException(\TypeError::class);
|
||||
}
|
||||
$h5pgenerator->create_export_file($activity->filename, $context->id, 'mod_h5pactivity', 'package');
|
||||
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
|
||||
$this->setUser($teacher);
|
||||
|
||||
$cm = get_fast_modinfo($course)->get_cm($activity->cmid);
|
||||
$items = overviewfactory::create($cm)->get_extra_overview_items();
|
||||
|
||||
$this->assertEquals($expected, $items['h5ptype']->get_value());
|
||||
|
||||
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
|
||||
$this->setUser($student);
|
||||
|
||||
$cm = get_fast_modinfo($course)->get_cm($activity->cmid);
|
||||
$items = overviewfactory::create($cm)->get_extra_overview_items();
|
||||
|
||||
$this->assertArrayNotHasKey('h5ptype', $items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test h5p type overview extra.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function provider_test_get_extra_h5type_overview(): array {
|
||||
return [
|
||||
'Basic package' => [
|
||||
'h5pfile' => 'basic_essay.h5p',
|
||||
'iscorrect' => true,
|
||||
'expected' => 'Essay',
|
||||
],
|
||||
'No json file' => [
|
||||
'h5pfile' => 'no-json-file.h5p',
|
||||
'iscorrect' => false,
|
||||
'expected' => get_string('unknowntype', 'mod_h5pactivity'),
|
||||
],
|
||||
'Unzippable package' => [
|
||||
'h5pfile' => 'unzippable.h5p',
|
||||
'iscorrect' => false,
|
||||
'expected' => get_string('unknowntype', 'mod_h5pactivity'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_extra_overview_items.
|
||||
*
|
||||
* @covers ::get_extra_overview_items
|
||||
*/
|
||||
public function test_get_extra_attempts_overview(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$activity = $this->getDataGenerator()->create_module(
|
||||
'h5pactivity',
|
||||
['course' => $course, 'enabletracking' => 1],
|
||||
);
|
||||
$cm = get_fast_modinfo($course)->get_cm($activity->cmid);
|
||||
|
||||
// Prepare users: 1 teacher, 2 students, 1 unenroled user.
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
|
||||
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
|
||||
$other = $this->getDataGenerator()->create_and_enrol($course, 'student');
|
||||
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity');
|
||||
|
||||
// No attempts yet.
|
||||
$this->setUser($teacher);
|
||||
$items = overviewfactory::create($cm)->get_extra_overview_items();
|
||||
$this->assertEquals(0, $items['totalattempts']->get_value());
|
||||
|
||||
$this->setUser($student);
|
||||
$items = overviewfactory::create($cm)->get_extra_overview_items();
|
||||
$this->assertEquals(0, $items['myattempts']->get_value());
|
||||
|
||||
// Attempts done by other student.
|
||||
$params = ['cmid' => $cm->id, 'userid' => $other->id];
|
||||
$generator->create_content($activity, $params);
|
||||
$generator->create_content($activity, $params);
|
||||
|
||||
$this->setUser($teacher);
|
||||
$items = overviewfactory::create($cm)->get_extra_overview_items();
|
||||
$this->assertEquals(2, $items['totalattempts']->get_value());
|
||||
|
||||
$this->setUser($student);
|
||||
$items = overviewfactory::create($cm)->get_extra_overview_items();
|
||||
$this->assertEquals(0, $items['myattempts']->get_value());
|
||||
|
||||
// Attempts done by the student.
|
||||
$params = ['cmid' => $cm->id, 'userid' => $student->id];
|
||||
$generator->create_content($activity, $params);
|
||||
$generator->create_content($activity, $params);
|
||||
|
||||
$this->setUser($teacher);
|
||||
$items = overviewfactory::create($cm)->get_extra_overview_items();
|
||||
$this->assertEquals(4, $items['totalattempts']->get_value());
|
||||
|
||||
$this->setUser($student);
|
||||
$items = overviewfactory::create($cm)->get_extra_overview_items();
|
||||
$this->assertEquals(2, $items['myattempts']->get_value());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_extra_studentsattempted_overview.
|
||||
*
|
||||
* @covers ::get_extra_studentsattempted_overview
|
||||
*/
|
||||
public function test_get_extra_studentsattempted_overview(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$activity = $this->getDataGenerator()->create_module(
|
||||
'h5pactivity',
|
||||
['course' => $course, 'enabletracking' => 1],
|
||||
);
|
||||
$cm = get_fast_modinfo($course)->get_cm($activity->cmid);
|
||||
|
||||
// Prepare users: 1 teacher, 2 students, 1 unenroled user.
|
||||
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
|
||||
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
|
||||
$other = $this->getDataGenerator()->create_and_enrol($course, 'student');
|
||||
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity');
|
||||
|
||||
// No attempts yet.
|
||||
$this->setUser($teacher);
|
||||
$items = overviewfactory::create($cm)->get_extra_overview_items();
|
||||
$this->assertEquals(0, $items['attempted']->get_value());
|
||||
$this->assertEquals('<strong>0</strong> of 2', $items['attempted']->get_content());
|
||||
|
||||
// With attempts.
|
||||
$params = ['cmid' => $cm->id, 'userid' => $student->id];
|
||||
$generator->create_content($activity, $params);
|
||||
$generator->create_content($activity, $params);
|
||||
|
||||
$items = overviewfactory::create($cm)->get_extra_overview_items();
|
||||
$this->assertEquals(1, $items['attempted']->get_value());
|
||||
$this->assertEquals('<strong>1</strong> of 2', $items['attempted']->get_content());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user