Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
96 changes: 96 additions & 0 deletions classes/external.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
]);
}
}
8 changes: 8 additions & 0 deletions db/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
],
];
2 changes: 2 additions & 0 deletions lang/en/customcert.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down