diff --git a/CHANGES.md b/CHANGES.md index fca964c0..b8e4faae 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. Note - All hash comments refer to the issue number. Eg. #169 refers to https://github.com/mdjnelson/moodle-mod_customcert/issues/169. +## [Unreleased] + +### Added + +- Added web service function `mod_customcert_get_or_create_certificate` to get or create a certificate for the current user. + ## [5.0.0] - 2025-06-07 ### Fixed diff --git a/classes/external.php b/classes/external.php index cda511ed..5fe88a66 100644 --- a/classes/external.php +++ b/classes/external.php @@ -242,4 +242,100 @@ public static function delete_issue($certificateid, $issueid) { public static function delete_issue_returns() { return new external_value(PARAM_BOOL, 'True if successful, false otherwise'); } + + /** + * Returns the get_or_create_certificate parameters. + * + * @return external_function_parameters + */ + public static function get_or_create_certificate_parameters() { + return new external_function_parameters( + [ + 'cmid' => new external_value(PARAM_INT, 'The course module id'), + ] + ); + } + + /** + * Get or create a certificate for the current user. + * + * @param int $cmid The course module id + * @return array + */ + public static function get_or_create_certificate($cmid) { + global $DB, $USER, $CFG; + + $params = [ + 'cmid' => $cmid, + ]; + self::validate_parameters(self::get_or_create_certificate_parameters(), $params); + + // Get the course module, course, and customcert record. + $cm = $DB->get_record('course_modules', ['id' => $cmid]); + if (!$cm) { + throw new \moodle_exception('invalidcoursemodule', 'error'); + } + $course = $DB->get_record('course', ['id' => $cm->course]); + if (!$course) { + throw new \moodle_exception('invalidcourseid', 'error'); + } + $customcert = $DB->get_record('customcert', ['id' => $cm->instance]); + if (!$customcert) { + throw new \moodle_exception('invalidrecord', 'mod_customcert', '', ['id' => $cm->instance]); + } + + // Ensure the user is allowed to view this page. + self::validate_context(\context_module::instance($cm->id)); + require_capability('mod/customcert:view', \context_module::instance($cm->id)); + $canreceive = has_capability('mod/customcert:receiveissue', \context_module::instance($cm->id)); + + // Check if user can receive certificate. + if (!$canreceive) { + throw new \moodle_exception('nopermissiontogetcertificate', 'customcert'); + } + + // Check if the user can view the certificate based on time spent in course. + if ($customcert->requiredtime) { + if (\mod_customcert\certificate::get_course_time($course->id) < ($customcert->requiredtime * 60)) { + throw new \moodle_exception('requiredtimenotmet', 'customcert', '', $customcert->requiredtime); + } + } + + // Check if an issue already exists for this user and certificate. + $issue = $DB->get_record('customcert_issues', ['userid' => $USER->id, 'customcertid' => $customcert->id], '*', IGNORE_MISSING); + + // If no issue exists, create one. + if (!$issue) { + $issueid = \mod_customcert\certificate::issue_certificate($customcert->id, $USER->id); + $issue = $DB->get_record('customcert_issues', ['id' => $issueid], '*', IGNORE_MISSING); + if (!$issue) { + throw new \moodle_exception('no new issue', 'error'); + } + } + + // Generate the download URL. TODO: replace with wsfunction https://github.com/mdjnelson/moodle-mod_customcert/pull/681 + $downloadurl = $CFG->wwwroot . '/mod/customcert/view.php?id=' . $cm->id . '&downloadown=1'; + + // Return the issue data and download URL. + return [ + 'issueid' => $issue->id, + 'code' => $issue->code, + 'timecreated' => $issue->timecreated, + 'downloadurl' => $downloadurl, + ]; + } + + /** + * Returns the get_or_create_certificate result value. + * + * @return external_single_structure + */ + public static function get_or_create_certificate_returns() { + return new external_single_structure([ + 'issueid' => new external_value(PARAM_INT, 'issue id'), + 'code' => new external_value(PARAM_TEXT, 'certificate code'), + 'timecreated' => new external_value(PARAM_INT, 'time created'), + 'downloadurl' => new external_value(PARAM_URL, 'download URL'), + ]); + } } diff --git a/db/services.php b/db/services.php index 776bf9d1..a3c68bd0 100644 --- a/db/services.php +++ b/db/services.php @@ -50,4 +50,12 @@ 'type' => 'read', 'ajax' => true, ], + 'mod_customcert_get_or_create_certificate' => [ + 'classname' => 'mod_customcert\external', + 'methodname' => 'get_or_create_certificate', + 'classpath' => '', + 'description' => 'Get or create a certificate for the current user', + 'type' => 'write', + 'ajax' => true, + ], ]; diff --git a/lang/en/customcert.php b/lang/en/customcert.php index 70108186..90600b6a 100644 --- a/lang/en/customcert.php +++ b/lang/en/customcert.php @@ -176,6 +176,8 @@ $string['numbersuffix_st_as_in_first'] = 'st'; $string['options'] = 'Options'; $string['page'] = 'Page {$a}'; +$string['nopermissiontogetcertificate'] = 'You do not have permission to get this certificate'; +$string['requiredtimenotmet'] = 'You must spend at least a minimum of {$a} minutes in the course before you can access this certificate.'; $string['pluginadministration'] = 'Custom certificate administration'; $string['pluginname'] = 'Custom certificate'; $string['portrait'] = 'Portrait';