first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+232
View File
@@ -0,0 +1,232 @@
<?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\external;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_multiple_structure;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
use mod_h5pactivity\local\manager;
use mod_h5pactivity\local\attempt;
use mod_h5pactivity\local\report\attempts as report_attempts;
use context_module;
use stdClass;
/**
* This is the external method for getting the information needed to present an attempts report.
*
* @package mod_h5pactivity
* @since Moodle 3.9
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class get_attempts extends external_api {
/**
* Webservice parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters(
[
'h5pactivityid' => new external_value(PARAM_INT, 'h5p activity instance id'),
'userids' => new external_multiple_structure(
new external_value(PARAM_INT, 'The user ids to get attempts (null means only current user)', VALUE_DEFAULT),
'User ids', VALUE_DEFAULT, []
),
]
);
}
/**
* Return user attempts information in a h5p activity.
*
* @throws moodle_exception if the user cannot see the report
* @param int $h5pactivityid The h5p activity id
* @param int[]|null $userids The user ids (if no provided $USER will be used)
* @return stdClass report data
*/
public static function execute(int $h5pactivityid, ?array $userids = []): stdClass {
global $USER;
$params = external_api::validate_parameters(self::execute_parameters(), [
'h5pactivityid' => $h5pactivityid,
'userids' => $userids,
]);
$h5pactivityid = $params['h5pactivityid'];
$userids = $params['userids'];
if (empty($userids)) {
$userids = [$USER->id];
}
$warnings = [];
// Request and permission validation.
list ($course, $cm) = get_course_and_cm_from_instance($h5pactivityid, 'h5pactivity');
$context = context_module::instance($cm->id);
self::validate_context($context);
$manager = manager::create_from_coursemodule($cm);
$instance = $manager->get_instance();
$usersattempts = [];
foreach ($userids as $userid) {
$report = $manager->get_report($userid);
if ($report && $report instanceof report_attempts) {
$usersattempts[] = self::export_user_attempts($report, $userid);
} else {
$warnings[] = [
'item' => 'user',
'itemid' => $userid,
'warningcode' => '1',
'message' => "Cannot access user attempts",
];
}
}
$result = (object)[
'activityid' => $instance->id,
'usersattempts' => $usersattempts,
'warnings' => $warnings,
];
return $result;
}
/**
* Export attempts data for a specific user.
*
* @param report_attempts $report the report attempts object
* @param int $userid the user id
* @return stdClass
*/
public static function export_user_attempts(report_attempts $report, int $userid): stdClass {
$scored = $report->get_scored();
$attempts = $report->get_attempts();
$result = (object)[
'userid' => $userid,
'attempts' => [],
];
foreach ($attempts as $attempt) {
$result->attempts[] = self::export_attempt($attempt);
}
if (!empty($scored)) {
$result->scored = (object)[
'title' => $scored->title,
'grademethod' => $scored->grademethod,
'attempts' => [self::export_attempt($scored->attempt)],
];
}
return $result;
}
/**
* Return a data object from an attempt.
*
* @param attempt $attempt the attempt object
* @return stdClass a WS compatible version of the attempt
*/
private static function export_attempt(attempt $attempt): stdClass {
$result = (object)[
'id' => $attempt->get_id(),
'h5pactivityid' => $attempt->get_h5pactivityid(),
'userid' => $attempt->get_userid(),
'timecreated' => $attempt->get_timecreated(),
'timemodified' => $attempt->get_timemodified(),
'attempt' => $attempt->get_attempt(),
'rawscore' => $attempt->get_rawscore(),
'maxscore' => $attempt->get_maxscore(),
'duration' => $attempt->get_duration(),
'scaled' => $attempt->get_scaled(),
];
if ($attempt->get_completion() !== null) {
$result->completion = $attempt->get_completion();
}
if ($attempt->get_success() !== null) {
$result->success = $attempt->get_success();
}
return $result;
}
/**
* Describes the get_h5pactivity_access_information return value.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([
'activityid' => new external_value(PARAM_INT, 'Activity course module ID'),
'usersattempts' => new external_multiple_structure(
self::get_user_attempts_returns(), 'The complete users attempts list'
),
'warnings' => new external_warnings(),
], 'Activity attempts data');
}
/**
* Describes the get_h5pactivity_access_information return value.
*
* @return external_single_structure
*/
public static function get_user_attempts_returns(): external_single_structure {
$structure = [
'userid' => new external_value(PARAM_INT, 'The user id'),
'attempts' => new external_multiple_structure(self::get_attempt_returns(), 'The complete attempts list'),
'scored' => new external_single_structure([
'title' => new external_value(PARAM_NOTAGS, 'Scored attempts title'),
'grademethod' => new external_value(PARAM_NOTAGS, 'Scored attempts title'),
'attempts' => new external_multiple_structure(self::get_attempt_returns(), 'List of the grading attempts'),
], 'Attempts used to grade the activity', VALUE_OPTIONAL),
];
return new external_single_structure($structure);
}
/**
* Return the external structure of an attempt.
*
* @return external_single_structure
*/
private static function get_attempt_returns(): external_single_structure {
$result = new external_single_structure([
'id' => new external_value(PARAM_INT, 'ID of the context'),
'h5pactivityid' => new external_value(PARAM_INT, 'ID of the H5P activity'),
'userid' => new external_value(PARAM_INT, 'ID of the user'),
'timecreated' => new external_value(PARAM_INT, 'Attempt creation'),
'timemodified' => new external_value(PARAM_INT, 'Attempt modified'),
'attempt' => new external_value(PARAM_INT, 'Attempt number'),
'rawscore' => new external_value(PARAM_INT, 'Attempt score value'),
'maxscore' => new external_value(PARAM_INT, 'Attempt max score'),
'duration' => new external_value(PARAM_INT, 'Attempt duration in seconds'),
'completion' => new external_value(PARAM_INT, 'Attempt completion', VALUE_OPTIONAL),
'success' => new external_value(PARAM_INT, 'Attempt success', VALUE_OPTIONAL),
'scaled' => new external_value(PARAM_FLOAT, 'Attempt scaled'),
]);
return $result;
}
}
@@ -0,0 +1,138 @@
<?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\external;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_multiple_structure;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
use context_module;
use core_h5p\factory;
/**
* This is the external method for returning a list of h5p activities.
*
* @copyright 2020 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class get_h5pactivities_by_courses extends external_api {
/**
* Parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters (
[
'courseids' => new external_multiple_structure(
new external_value(PARAM_INT, 'Course id'), 'Array of course ids', VALUE_DEFAULT, []
),
]
);
}
/**
* Returns a list of h5p activities in a provided list of courses.
* If no list is provided all h5p activities that the user can view will be returned.
*
* @param array $courseids course ids
* @return array of h5p activities and warnings
* @since Moodle 3.9
*/
public static function execute(array $courseids): array {
global $PAGE;
$warnings = [];
$returnedh5pactivities = [];
$params = external_api::validate_parameters(self::execute_parameters(), [
'courseids' => $courseids
]);
$mycourses = [];
if (empty($params['courseids'])) {
$mycourses = enrol_get_my_courses();
$params['courseids'] = array_keys($mycourses);
}
// Ensure there are courseids to loop through.
if (!empty($params['courseids'])) {
$factory = new factory();
list($courses, $warnings) = \core_external\util::validate_courses($params['courseids'], $mycourses);
$output = $PAGE->get_renderer('core');
// Get the h5p activities in this course, this function checks users visibility permissions.
// We can avoid then additional validate_context calls.
$h5pactivities = get_all_instances_in_courses('h5pactivity', $courses);
foreach ($h5pactivities as $h5pactivity) {
$context = context_module::instance($h5pactivity->coursemodule);
// Remove fields that are not from the h5p activity (added by get_all_instances_in_courses).
unset($h5pactivity->coursemodule, $h5pactivity->context,
$h5pactivity->visible, $h5pactivity->section,
$h5pactivity->groupmode, $h5pactivity->groupingid);
$exporter = new h5pactivity_summary_exporter($h5pactivity,
['context' => $context, 'factory' => $factory]);
$summary = $exporter->export($output);
$returnedh5pactivities[] = $summary;
}
}
$h5pglobalsettings = [
'enablesavestate' => get_config('mod_h5pactivity', 'enablesavestate'),
];
if (!empty($h5pglobalsettings['enablesavestate'])) {
$h5pglobalsettings['savestatefreq'] = get_config('mod_h5pactivity', 'savestatefreq');
}
$result = [
'h5pactivities' => $returnedh5pactivities,
'h5pglobalsettings' => $h5pglobalsettings,
'warnings' => $warnings
];
return $result;
}
/**
* Describes the get_h5pactivities_by_courses return value.
*
* @return external_single_structure
* @since Moodle 3.9
*/
public static function execute_returns() {
return new external_single_structure(
[
'h5pactivities' => new external_multiple_structure(
h5pactivity_summary_exporter::get_read_structure()
),
'h5pglobalsettings' => new external_single_structure(
[
'enablesavestate' => new external_value(PARAM_BOOL, 'Whether saving state is enabled.'),
'savestatefreq' => new external_value(PARAM_INT, 'How often (in seconds) state is saved.', VALUE_OPTIONAL),
],
'H5P global settings',
VALUE_OPTIONAL,
),
'warnings' => new external_warnings(),
]
);
}
}
@@ -0,0 +1,109 @@
<?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\external;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
use context_module;
use mod_h5pactivity\local\manager;
/**
* This is the external method for getting access information for a h5p activity.
*
* @copyright 2020 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class get_h5pactivity_access_information extends external_api {
/**
* Parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters(
[
'h5pactivityid' => new external_value(PARAM_INT, 'h5p activity instance id')
]
);
}
/**
* Return access information for a given h5p activity.
*
* @param int $h5pactivityid The h5p activity id.
* @return array of warnings and the access information
* @since Moodle 3.9
* @throws moodle_exception
*/
public static function execute(int $h5pactivityid): array {
global $DB;
$params = external_api::validate_parameters(self::execute_parameters(), [
'h5pactivityid' => $h5pactivityid
]);
// Request and permission validation.
$h5pactivity = $DB->get_record('h5pactivity', ['id' => $params['h5pactivityid']], '*', MUST_EXIST);
list($course, $cm) = get_course_and_cm_from_instance($h5pactivity, 'h5pactivity');
$context = context_module::instance($cm->id);
self::validate_context($context);
$result = [];
// Return all the available capabilities.
$manager = manager::create_from_coursemodule($cm);
$capabilities = load_capability_def('mod_h5pactivity');
foreach ($capabilities as $capname => $capdata) {
$field = 'can' . str_replace('mod/h5pactivity:', '', $capname);
// For mod/h5pactivity:submit we need to check if tracking is enabled in the h5pactivity for the current user.
if ($field == 'cansubmit') {
$result[$field] = $manager->is_tracking_enabled() && $manager->can_submit();
} else {
$result[$field] = has_capability($capname, $context);
}
}
$result['warnings'] = [];
return $result;
}
/**
* Describes the get_h5pactivity_access_information return value.
*
* @return external_single_structure
* @since Moodle 3.9
*/
public static function execute_returns() {
$structure = [
'warnings' => new external_warnings()
];
$capabilities = load_capability_def('mod_h5pactivity');
foreach ($capabilities as $capname => $capdata) {
$field = 'can' . str_replace('mod/h5pactivity:', '', $capname);
$structure[$field] = new external_value(PARAM_BOOL, 'Whether the user has the capability ' . $capname . ' allowed.',
VALUE_OPTIONAL);
}
return new external_single_structure($structure);
}
}
+293
View File
@@ -0,0 +1,293 @@
<?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\external;
use mod_h5pactivity\local\manager;
use mod_h5pactivity\local\report\results as report_results;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_multiple_structure;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
use context_module;
use stdClass;
/**
* This is the external method for getting the information needed to present a results report.
*
* @package mod_h5pactivity
* @since Moodle 3.9
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class get_results extends external_api {
/**
* Webservice parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters(
[
'h5pactivityid' => new external_value(PARAM_INT, 'h5p activity instance id'),
'attemptids' => new external_multiple_structure(
new external_value(PARAM_INT, 'The attempt id'),
'Attempt ids', VALUE_DEFAULT, []
),
]
);
}
/**
* Return user attempts results information in a h5p activity.
*
* In case an empty array of attempt ids is passed, the method will load all
* activity attempts from the current user.
*
* @throws moodle_exception if the user cannot see the report
* @param int $h5pactivityid The h5p activity id
* @param int[] $attemptids The attempt ids
* @return stdClass report data
*/
public static function execute(int $h5pactivityid, array $attemptids = []): stdClass {
global $USER;
$params = external_api::validate_parameters(self::execute_parameters(), [
'h5pactivityid' => $h5pactivityid,
'attemptids' => $attemptids,
]);
$h5pactivityid = $params['h5pactivityid'];
$attemptids = $params['attemptids'];
$warnings = [];
// Request and permission validation.
list ($course, $cm) = get_course_and_cm_from_instance($h5pactivityid, 'h5pactivity');
$context = context_module::instance($cm->id);
self::validate_context($context);
$manager = manager::create_from_coursemodule($cm);
if (empty($attemptids)) {
$attemptids = [];
foreach ($manager->get_user_attempts($USER->id) as $attempt) {
$attemptids[] = $attempt->get_id();
}
}
$attempts = [];
foreach ($attemptids as $attemptid) {
$report = $manager->get_report(null, $attemptid);
if ($report && $report instanceof report_results) {
$attempts[] = self::export_attempt($report);
} else {
$warnings[] = [
'item' => 'h5pactivity_attempts',
'itemid' => $attemptid,
'warningcode' => '1',
'message' => "Cannot access attempt",
];
}
}
$result = (object)[
'activityid' => $h5pactivityid,
'attempts' => $attempts,
'warnings' => $warnings,
];
return $result;
}
/**
* Return a data object from an attempt.
*
* @param report_results $report the attempt data
* @return stdClass a WS compatible version of the attempt
*/
private static function export_attempt(report_results $report): stdClass {
$data = $report->export_data_for_external();
$attemptdata = $data->attempt;
$attempt = (object)[
'id' => $attemptdata->id,
'h5pactivityid' => $attemptdata->h5pactivityid,
'userid' => $attemptdata->userid,
'timecreated' => $attemptdata->timecreated,
'timemodified' => $attemptdata->timemodified,
'attempt' => $attemptdata->attempt,
'rawscore' => $attemptdata->rawscore,
'maxscore' => $attemptdata->maxscore,
'duration' => (empty($attemptdata->durationvalue)) ? 0 : $attemptdata->durationvalue,
'scaled' => (empty($attemptdata->scaled)) ? 0 : $attemptdata->scaled,
'results' => [],
];
if (isset($attemptdata->completion) && $attemptdata->completion !== null) {
$attempt->completion = $attemptdata->completion;
}
if (isset($attemptdata->success) && $attemptdata->success !== null) {
$attempt->success = $attemptdata->success;
}
foreach ($data->results as $result) {
$attempt->results[] = self::export_result($result);
}
return $attempt;
}
/**
* Return a data object from a result.
*
* @param stdClass $data the result data
* @return stdClass a WS compatible version of the result
*/
private static function export_result(stdClass $data): stdClass {
$result = (object)[
'id' => $data->id,
'attemptid' => $data->attemptid,
'subcontent' => $data->subcontent,
'timecreated' => $data->timecreated,
'interactiontype' => $data->interactiontype,
'description' => $data->description,
'rawscore' => $data->rawscore,
'maxscore' => $data->maxscore,
'duration' => $data->duration,
'optionslabel' => $data->optionslabel ?? get_string('choice', 'mod_h5pactivity'),
'correctlabel' => $data->correctlabel ?? get_string('correct_answer', 'mod_h5pactivity'),
'answerlabel' => $data->answerlabel ?? get_string('attempt_answer', 'mod_h5pactivity'),
'track' => $data->track ?? false,
];
if (isset($data->completion) && $data->completion !== null) {
$result->completion = $data->completion;
}
if (isset($data->success) && $data->success !== null) {
$result->success = $data->success;
}
if (isset($data->options)) {
$result->options = $data->options;
}
if (isset($data->content)) {
$result->content = $data->content;
}
return $result;
}
/**
* Describes the get_h5pactivity_access_information return value.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([
'activityid' => new external_value(PARAM_INT, 'Activity course module ID'),
'attempts' => new external_multiple_structure(
self::get_attempt_returns(), 'The complete attempts list'
),
'warnings' => new external_warnings(),
], 'Activity attempts results data');
}
/**
* Return the external structure of an attempt
* @return external_single_structure
*/
private static function get_attempt_returns(): external_single_structure {
$result = new external_single_structure([
'id' => new external_value(PARAM_INT, 'ID of the context'),
'h5pactivityid' => new external_value(PARAM_INT, 'ID of the H5P activity'),
'userid' => new external_value(PARAM_INT, 'ID of the user'),
'timecreated' => new external_value(PARAM_INT, 'Attempt creation'),
'timemodified' => new external_value(PARAM_INT, 'Attempt modified'),
'attempt' => new external_value(PARAM_INT, 'Attempt number'),
'rawscore' => new external_value(PARAM_INT, 'Attempt score value'),
'maxscore' => new external_value(PARAM_INT, 'Attempt max score'),
'duration' => new external_value(PARAM_INT, 'Attempt duration in seconds'),
'completion' => new external_value(PARAM_INT, 'Attempt completion', VALUE_OPTIONAL),
'success' => new external_value(PARAM_INT, 'Attempt success', VALUE_OPTIONAL),
'scaled' => new external_value(PARAM_FLOAT, 'Attempt scaled'),
'results' => new external_multiple_structure(
self::get_result_returns(),
'The results of the attempt', VALUE_OPTIONAL
),
], 'The attempt general information');
return $result;
}
/**
* Return the external structure of a result
* @return external_single_structure
*/
private static function get_result_returns(): external_single_structure {
$result = new external_single_structure([
'id' => new external_value(PARAM_INT, 'ID of the context'),
'attemptid' => new external_value(PARAM_INT, 'ID of the H5P attempt'),
'subcontent' => new external_value(PARAM_NOTAGS, 'Subcontent identifier'),
'timecreated' => new external_value(PARAM_INT, 'Result creation'),
'interactiontype' => new external_value(PARAM_NOTAGS, 'Interaction type'),
'description' => new external_value(PARAM_RAW, 'Result description'),
'content' => new external_value(PARAM_RAW, 'Result extra content', VALUE_OPTIONAL),
'rawscore' => new external_value(PARAM_INT, 'Result score value'),
'maxscore' => new external_value(PARAM_INT, 'Result max score'),
'duration' => new external_value(PARAM_INT, 'Result duration in seconds', VALUE_OPTIONAL, 0),
'completion' => new external_value(PARAM_INT, 'Result completion', VALUE_OPTIONAL),
'success' => new external_value(PARAM_INT, 'Result success', VALUE_OPTIONAL),
'optionslabel' => new external_value(PARAM_NOTAGS, 'Label used for result options', VALUE_OPTIONAL),
'correctlabel' => new external_value(PARAM_NOTAGS, 'Label used for correct answers', VALUE_OPTIONAL),
'answerlabel' => new external_value(PARAM_NOTAGS, 'Label used for user answers', VALUE_OPTIONAL),
'track' => new external_value(PARAM_BOOL, 'If the result has valid track information', VALUE_OPTIONAL),
'options' => new external_multiple_structure(
new external_single_structure([
'description' => new external_value(PARAM_RAW, 'Option description', VALUE_OPTIONAL),
'id' => new external_value(PARAM_TEXT, 'Option string identifier', VALUE_OPTIONAL),
'correctanswer' => self::get_answer_returns('The option correct answer', VALUE_OPTIONAL),
'useranswer' => self::get_answer_returns('The option user answer', VALUE_OPTIONAL),
]),
'The statement options', VALUE_OPTIONAL
),
], 'A single result statement tracking information');
return $result;
}
/**
* Return the external structure of an answer or correctanswer
*
* @param string $description the return description
* @param int $required the return required value
* @return external_single_structure
*/
private static function get_answer_returns(string $description, int $required = VALUE_REQUIRED): external_single_structure {
$result = new external_single_structure([
'answer' => new external_value(PARAM_NOTAGS, 'Option text value', VALUE_OPTIONAL),
'correct' => new external_value(PARAM_BOOL, 'If has to be displayed as correct', VALUE_OPTIONAL),
'incorrect' => new external_value(PARAM_BOOL, 'If has to be displayed as incorrect', VALUE_OPTIONAL),
'text' => new external_value(PARAM_BOOL, 'If has to be displayed as simple text', VALUE_OPTIONAL),
'checked' => new external_value(PARAM_BOOL, 'If has to be displayed as a checked option', VALUE_OPTIONAL),
'unchecked' => new external_value(PARAM_BOOL, 'If has to be displayed as a unchecked option', VALUE_OPTIONAL),
'pass' => new external_value(PARAM_BOOL, 'If has to be displayed as passed', VALUE_OPTIONAL),
'fail' => new external_value(PARAM_BOOL, 'If has to be displayed as failed', VALUE_OPTIONAL),
], $description, $required);
return $result;
}
}
+302
View File
@@ -0,0 +1,302 @@
<?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\external;
use mod_h5pactivity\local\manager;
use mod_h5pactivity\local\attempt;
use mod_h5pactivity\local\report;
use mod_h5pactivity\local\report\attempts as report_attempts;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_multiple_structure;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
use moodle_exception;
use context_module;
use stdClass;
/**
* This is the external method to return the information needed to list all enrolled user attempts.
*
* @package mod_h5pactivity
* @since Moodle 3.11
* @copyright 2020 Ilya Tregubov <ilya@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class get_user_attempts extends external_api {
/**
* Webservice parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters(
[
'h5pactivityid' => new external_value(PARAM_INT, 'h5p activity instance id'),
'sortorder' => new external_value(PARAM_TEXT,
'sort by either user id, firstname or lastname (with optional asc/desc)', VALUE_DEFAULT, 'id ASC'),
'page' => new external_value(PARAM_INT, 'current page', VALUE_DEFAULT, -1),
'perpage' => new external_value(PARAM_INT, 'items per page', VALUE_DEFAULT, 0),
'firstinitial' => new external_value(PARAM_TEXT, 'Users whose first name ' .
'starts with $firstinitial', VALUE_DEFAULT, ''),
'lastinitial' => new external_value(PARAM_TEXT, 'Users whose last name ' .
'starts with $lastinitial', VALUE_DEFAULT, ''),
]
);
}
/**
* Return user attempts information in a h5p activity.
*
* @throws moodle_exception if the user cannot see the report
* @param int $h5pactivityid The h5p activity id
* @param int $sortorder The sort order
* @param int $page page number
* @param int $perpage items per page
* @param int $firstinitial Users whose first name starts with $firstinitial
* @param int $lastinitial Users whose last name starts with $lastinitial
* @return stdClass report data
*/
public static function execute(int $h5pactivityid, $sortorder = 'id ASC', ?int $page = 0,
?int $perpage = 0, $firstinitial = '', $lastinitial = ''): stdClass {
[
'h5pactivityid' => $h5pactivityid,
'sortorder' => $sortorder,
'page' => $page,
'perpage' => $perpage,
'firstinitial' => $firstinitial,
'lastinitial' => $lastinitial,
] = external_api::validate_parameters(self::execute_parameters(), [
'h5pactivityid' => $h5pactivityid,
'sortorder' => $sortorder,
'page' => $page,
'perpage' => $perpage,
'firstinitial' => $firstinitial,
'lastinitial' => $lastinitial,
]);
$warnings = [];
[$course, $cm] = get_course_and_cm_from_instance($h5pactivityid, 'h5pactivity');
$context = context_module::instance($cm->id);
self::validate_context($context);
$manager = manager::create_from_coursemodule($cm);
$instance = $manager->get_instance();
if (!$manager->can_view_all_attempts()) {
throw new moodle_exception('nopermissiontoviewattempts', 'error', '', null,
'h5pactivity:reviewattempts required view attempts of all enrolled users.');
}
// Ensure sortorder parameter is safe to use. Fallback to default value of the parameter itself.
$sortorderparts = explode(' ', $sortorder, 2);
$sortorder = get_safe_orderby([
'id' => 'u.id',
'firstname' => 'u.firstname',
'lastname' => 'u.lastname',
'default' => 'u.id',
], $sortorderparts[0], $sortorderparts[1] ?? '');
$users = self::get_active_users($manager, 'u.id, u.firstname, u.lastname',
$sortorder, $page * $perpage, $perpage);
$usersattempts = [];
foreach ($users as $user) {
if ($firstinitial) {
if (strpos($user->firstname, $firstinitial) === false) {
continue;
}
}
if ($lastinitial) {
if (strpos($user->lastname, $lastinitial) === false) {
continue;
}
}
$report = $manager->get_report($user->id);
if ($report && $report instanceof report_attempts) {
$usersattempts[] = self::export_user_attempts($report, $user->id);
} else {
$warnings[] = [
'item' => 'user',
'itemid' => $user->id,
'warningcode' => '1',
'message' => "Cannot access user attempts",
];
}
}
$result = (object)[
'activityid' => $instance->id,
'usersattempts' => $usersattempts,
'warnings' => $warnings,
];
return $result;
}
/**
* Generate the active users list
*
* @param manager $manager the h5pactivity manager
* @param string $userfields the user fields to get
* @param string $sortorder the SQL sortorder
* @param int $limitfrom SQL limit from
* @param int $limitnum SQL limit num
*/
private static function get_active_users(
manager $manager,
string $userfields = 'u.*',
string $sortorder = '',
int $limitfrom = 0,
int $limitnum = 0
): array {
global $DB;
$capjoin = $manager->get_active_users_join(true);
// Final SQL.
$sql = "SELECT DISTINCT {$userfields}
FROM {user} u {$capjoin->joins}
WHERE {$capjoin->wheres}
{$sortorder}";
return $DB->get_records_sql($sql, $capjoin->params, $limitfrom, $limitnum);
}
/**
* Export attempts data for a specific user.
*
* @param report $report the report attempts object
* @param int $userid the user id
* @return stdClass
*/
private static function export_user_attempts(report $report, int $userid): stdClass {
$scored = $report->get_scored();
$attempts = $report->get_attempts();
$result = (object)[
'userid' => $userid,
'attempts' => [],
];
foreach ($attempts as $attempt) {
$result->attempts[] = self::export_attempt($attempt);
}
if (!empty($scored)) {
$result->scored = (object)[
'title' => $scored->title,
'grademethod' => $scored->grademethod,
'attempts' => [self::export_attempt($scored->attempt)],
];
}
return $result;
}
/**
* Return a data object from an attempt.
*
* @param attempt $attempt the attempt object
* @return stdClass a WS compatible version of the attempt
*/
private static function export_attempt(attempt $attempt): stdClass {
$result = (object)[
'id' => $attempt->get_id(),
'h5pactivityid' => $attempt->get_h5pactivityid(),
'userid' => $attempt->get_userid(),
'timecreated' => $attempt->get_timecreated(),
'timemodified' => $attempt->get_timemodified(),
'attempt' => $attempt->get_attempt(),
'rawscore' => $attempt->get_rawscore(),
'maxscore' => $attempt->get_maxscore(),
'duration' => $attempt->get_duration(),
'scaled' => $attempt->get_scaled(),
];
if ($attempt->get_completion() !== null) {
$result->completion = $attempt->get_completion();
}
if ($attempt->get_success() !== null) {
$result->success = $attempt->get_success();
}
return $result;
}
/**
* Describes the get_h5pactivity_access_information return value.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([
'activityid' => new external_value(PARAM_INT, 'Activity course module ID'),
'usersattempts' => new external_multiple_structure(
self::get_user_attempts_returns(), 'The complete users attempts list'
),
'warnings' => new external_warnings(),
], 'Activity attempts data');
}
/**
* Describes the get_h5pactivity_access_information return value.
*
* @return external_single_structure
*/
private static function get_user_attempts_returns(): external_single_structure {
$structure = [
'userid' => new external_value(PARAM_INT, 'The user id'),
'attempts' => new external_multiple_structure(self::get_user_attempt_returns(), 'The complete attempts list'),
'scored' => new external_single_structure([
'title' => new external_value(PARAM_NOTAGS, 'Scored attempts title'),
'grademethod' => new external_value(PARAM_NOTAGS, 'Grading method'),
'attempts' => new external_multiple_structure(self::get_user_attempt_returns(), 'List of the grading attempts'),
], 'Attempts used to grade the activity', VALUE_OPTIONAL),
];
return new external_single_structure($structure);
}
/**
* Return the external structure of an attempt.
*
* @return external_single_structure
*/
private static function get_user_attempt_returns(): external_single_structure {
$result = new external_single_structure([
'id' => new external_value(PARAM_INT, 'ID of the context'),
'h5pactivityid' => new external_value(PARAM_INT, 'ID of the H5P activity'),
'userid' => new external_value(PARAM_INT, 'ID of the user'),
'timecreated' => new external_value(PARAM_INT, 'Attempt creation'),
'timemodified' => new external_value(PARAM_INT, 'Attempt modified'),
'attempt' => new external_value(PARAM_INT, 'Attempt number'),
'rawscore' => new external_value(PARAM_INT, 'Attempt score value'),
'maxscore' => new external_value(PARAM_INT, 'Attempt max score'),
'duration' => new external_value(PARAM_INT, 'Attempt duration in seconds'),
'completion' => new external_value(PARAM_INT, 'Attempt completion', VALUE_OPTIONAL),
'success' => new external_value(PARAM_INT, 'Attempt success', VALUE_OPTIONAL),
'scaled' => new external_value(PARAM_FLOAT, 'Attempt scaled'),
]);
return $result;
}
}
@@ -0,0 +1,244 @@
<?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/>.
/**
* Class for exporting h5p activity data.
*
* @package mod_h5pactivity
* @since Moodle 3.9
* @copyright 2020 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_h5pactivity\external;
use core\external\exporter;
use renderer_base;
use core_external\util as external_util;
use core_external\external_files;
use core_h5p\api;
/**
* Class for exporting h5p activity data.
*
* @copyright 2020 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class h5pactivity_summary_exporter extends exporter {
/**
* Properties definition.
*
* @return array
*/
protected static function define_properties() {
return [
'id' => [
'type' => PARAM_INT,
'description' => 'The primary key of the record.',
],
'course' => [
'type' => PARAM_INT,
'description' => 'Course id this h5p activity is part of.',
],
'name' => [
'type' => PARAM_TEXT,
'description' => 'The name of the activity module instance.',
],
'timecreated' => [
'type' => PARAM_INT,
'description' => 'Timestamp of when the instance was added to the course.',
'optional' => true,
],
'timemodified' => [
'type' => PARAM_INT,
'description' => 'Timestamp of when the instance was last modified.',
'optional' => true,
],
'intro' => [
'default' => '',
'type' => PARAM_RAW,
'description' => 'H5P activity description.',
'null' => NULL_ALLOWED,
],
'introformat' => [
'choices' => [FORMAT_HTML, FORMAT_MOODLE, FORMAT_PLAIN, FORMAT_MARKDOWN],
'type' => PARAM_INT,
'default' => FORMAT_MOODLE,
'description' => 'The format of the intro field.',
],
'grade' => [
'type' => PARAM_INT,
'default' => 0,
'description' => 'The maximum grade for submission.',
'optional' => true,
],
'displayoptions' => [
'type' => PARAM_INT,
'default' => 0,
'description' => 'H5P Button display options.',
],
'enabletracking' => [
'type' => PARAM_INT,
'default' => 1,
'description' => 'Enable xAPI tracking.',
],
'grademethod' => [
'type' => PARAM_INT,
'default' => 1,
'description' => 'Which H5P attempt is used for grading.',
],
'contenthash' => [
'type' => PARAM_ALPHANUM,
'description' => 'Sha1 hash of file content.',
'optional' => true,
],
];
}
/**
* Related objects definition.
*
* @return array
*/
protected static function define_related() {
return [
'context' => 'context',
'factory' => 'core_h5p\\factory'
];
}
/**
* Other properties definition.
*
* @return array
*/
protected static function define_other_properties() {
return [
'coursemodule' => [
'type' => PARAM_INT
],
'context' => [
'type' => PARAM_INT
],
'introfiles' => [
'type' => external_files::get_properties_for_exporter(),
'multiple' => true
],
'package' => [
'type' => external_files::get_properties_for_exporter(),
'multiple' => true
],
'deployedfile' => [
'optional' => true,
'description' => 'H5P file deployed.',
'type' => [
'filename' => array(
'type' => PARAM_FILE,
'description' => 'File name.',
'optional' => true,
'null' => NULL_NOT_ALLOWED,
),
'filepath' => array(
'type' => PARAM_PATH,
'description' => 'File path.',
'optional' => true,
'null' => NULL_NOT_ALLOWED,
),
'filesize' => array(
'type' => PARAM_INT,
'description' => 'File size.',
'optional' => true,
'null' => NULL_NOT_ALLOWED,
),
'fileurl' => array(
'type' => PARAM_URL,
'description' => 'Downloadable file url.',
'optional' => true,
'null' => NULL_NOT_ALLOWED,
),
'timemodified' => array(
'type' => PARAM_INT,
'description' => 'Time modified.',
'optional' => true,
'null' => NULL_NOT_ALLOWED,
),
'mimetype' => array(
'type' => PARAM_RAW,
'description' => 'File mime type.',
'optional' => true,
'null' => NULL_NOT_ALLOWED,
)
]
],
];
}
/**
* Assign values to the defined other properties.
*
* @param renderer_base $output The output renderer object.
* @return array
*/
protected function get_other_values(renderer_base $output) {
$context = $this->related['context'];
$factory = $this->related['factory'];
$values = [
'coursemodule' => $context->instanceid,
'context' => $context->id,
];
$values['introfiles'] = external_util::get_area_files($context->id, 'mod_h5pactivity', 'intro', false, false);
$values['package'] = external_util::get_area_files($context->id, 'mod_h5pactivity', 'package', false, true);
// Only if this H5P activity has been deployed, return the exported file.
$fileh5p = api::get_export_info_from_context_id($context->id, $factory, 'mod_h5pactivity', 'package');
if ($fileh5p) {
$values['deployedfile'] = $fileh5p;
}
return $values;
}
/**
* Get the formatting parameters for the intro.
*
* @return array with the formatting parameters
*/
protected function get_format_parameters_for_intro() {
return [
'component' => 'mod_h5pactivity',
'filearea' => 'intro',
'options' => ['noclean' => true],
];
}
/**
* Get the formatting parameters for the package.
*
* @return array with the formatting parameters
*/
protected function get_format_parameters_for_package() {
return [
'component' => 'mod_h5pactivity',
'filearea' => 'package',
'itemid' => 0,
'options' => ['noclean' => true],
];
}
}
+122
View File
@@ -0,0 +1,122 @@
<?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\external;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
use mod_h5pactivity\local\manager;
use mod_h5pactivity\event\report_viewed;
use context_module;
use stdClass;
/**
* This is the external method for logging that the h5pactivity was viewed.
*
* @package mod_h5pactivity
* @copyright 2021 Ilya Tregubov <ilya@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.11
*/
class log_report_viewed extends external_api {
/**
* Webservice parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters(
[
'h5pactivityid' => new external_value(PARAM_INT, 'h5p activity instance id'),
'userid' => new external_value(
PARAM_INT,
'The user id to log attempt (null means only current user)',
VALUE_DEFAULT
),
'attemptid' => new external_value(PARAM_INT, 'The attempt id', VALUE_DEFAULT),
]
);
}
/**
* Logs that the h5pactivity was viewed.
*
* @throws moodle_exception if the user cannot see the report
* @param int $h5pactivityid The h5p activity id
* @param int|null $userid The user id
* @param int|null $attemptid The attempt id
* @return array of warnings and status result
*/
public static function execute(int $h5pactivityid, int $userid = null, int $attemptid = null): stdClass {
$params = external_api::validate_parameters(self::execute_parameters(), [
'h5pactivityid' => $h5pactivityid,
'userid' => $userid,
'attemptid' => $attemptid,
]);
$h5pactivityid = $params['h5pactivityid'];
$userid = $params['userid'];
$attemptid = $params['attemptid'];
// Request and permission validation.
list ($course, $cm) = get_course_and_cm_from_instance($h5pactivityid, 'h5pactivity');
$context = context_module::instance($cm->id);
self::validate_context($context);
$manager = manager::create_from_coursemodule($cm);
$instance = $manager->get_instance();
// Trigger event.
$other = [
'instanceid' => $instance->id,
'userid' => $userid,
'attemptid' => $attemptid,
];
$event = report_viewed::create([
'objectid' => $instance->id,
'context' => $context,
'other' => $other,
]);
$event->trigger();
$result = (object)[
'status' => true,
'warnings' => [],
];
return $result;
}
/**
* Describes the report_viewed return value.
*
* @return external_single_structure
* @since Moodle 3.11
*/
public static function execute_returns() {
return new external_single_structure(
[
'status' => new external_value(PARAM_BOOL, 'status: true if success'),
'warnings' => new external_warnings()
]
);
}
}
+94
View File
@@ -0,0 +1,94 @@
<?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\external;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
use context_module;
use mod_h5pactivity\local\manager;
/**
* This is the external method for triggering the course module viewed event.
*
* @package mod_h5pactivity
* @since Moodle 3.9
* @copyright 2020 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class view_h5pactivity extends external_api {
/**
* Parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters(
[
'h5pactivityid' => new external_value(PARAM_INT, 'H5P activity instance id')
]
);
}
/**
* Trigger the course module viewed event and update the module completion status.
*
* @param int $h5pactivityid The h5p activity id.
* @return array of warnings and the access information
* @since Moodle 3.9
* @throws moodle_exception
*/
public static function execute(int $h5pactivityid): array {
$params = external_api::validate_parameters(self::execute_parameters(), [
'h5pactivityid' => $h5pactivityid
]);
$warnings = [];
// Request and permission validation.
list($course, $cm) = get_course_and_cm_from_instance($params['h5pactivityid'], 'h5pactivity');
$context = context_module::instance($cm->id);
self::validate_context($context);
$manager = manager::create_from_coursemodule($cm);
$manager->set_module_viewed($course);
$result = array(
'status' => true,
'warnings' => $warnings,
);
return $result;
}
/**
* Describes the view_h5pactivity return value.
*
* @return external_single_structure
* @since Moodle 3.9
*/
public static function execute_returns() {
return new external_single_structure(
[
'status' => new external_value(PARAM_BOOL, 'status: true if success'),
'warnings' => new external_warnings()
]
);
}
}