Compare commits

...

24 commits

Author SHA1 Message Date
Mark Nelson
1f63287e5f Bump version 2021-06-13 14:12:46 +08:00
Mark Nelson
bcba998a97 Use 'cron_setup_user' when sending emails (#414) 2021-06-13 14:06:21 +08:00
Mark Nelson
768fb4f84e Set proper context when sending emails (#402) 2021-06-13 13:42:52 +08:00
hieuvu
0955f09c65 Add actions title to elements table (#425) 2021-06-08 17:49:51 +08:00
Mark Nelson
b4c54be04c Removed .travis.yml file 2021-05-27 20:14:47 +08:00
Mark Nelson
c946a6adf1 Fix failing GHA 2021-05-27 19:51:31 +08:00
Mark Nelson
1ca6063d4b Fix Moodle branch in GH actions (#407) 2021-05-27 19:32:20 +08:00
Marina Glancy
c355d7799c Add github actions (#407) 2021-05-27 19:28:13 +08:00
Mark Nelson
bef0be1b67 Fix Moodle Code Checker complaints 2021-05-27 18:53:33 +08:00
Mark Nelson
d940ca6508 Update CHANGES.md 2021-04-16 14:42:23 +08:00
Mikhail Golenkov
c3602b11b3 Fix the issue with displaying PDF when debugging is ON (#420) 2021-04-16 14:37:51 +08:00
Mark Nelson
f6d875d147 Removed mention of github actions in CHANGES.md
We are not adding them for 3.8.
2021-04-05 20:14:26 +08:00
Mark Nelson
2a923bd8de Add type hinting to get_course_time() 2021-04-05 20:12:07 +08:00
Mark Nelson
e14e923fec Use instance of moodle_url() in the function notice() 2021-04-05 20:09:30 +08:00
Mark Nelson
e202e8ff43 Fix get_course_time() allowing users to view certificate early (#403) 2021-04-05 20:02:12 +08:00
Mark Nelson
42b0a43d0a Remove github actions for 3.8 2021-04-05 17:17:51 +08:00
Mark Nelson
3efd75e00a Updated CHANGES.md 2021-04-05 17:03:14 +08:00
Mark Nelson
ed565c0a11 Add ability to choose how to deliver the certificate (#401) 2021-04-05 17:02:50 +08:00
Mark Nelson
aac32e1c19 Updated CHANGES.md 2021-04-03 11:29:19 +08:00
Mark Nelson
e88682769c Add ability to show description on course page (#406) 2021-04-03 10:37:39 +08:00
Mark Nelson
02fa6819de Set for version 3.8 (#407) 2021-04-03 10:16:35 +08:00
Marina Glancy
2a5c9f6a3d Add github actions (#407) 2021-04-03 10:14:56 +08:00
Toni Förster
be637b11ce Allow managers to download certificates (#412)
Currently, it is not possible for editing teachers
and managers to download certificates for users because
we only check for $canreceive.
2021-04-02 20:53:50 +08:00
Mark Nelson
11659e39a0 Fix PHPDocs for the method get_course_field_value() 2020-11-27 20:23:35 +08:00
22 changed files with 230 additions and 98 deletions

121
.github/workflows/moodle-ci.yml vendored Normal file
View file

@ -0,0 +1,121 @@
name: Moodle Plugin CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-18.04
services:
postgres:
image: postgres:9.6
env:
POSTGRES_USER: 'postgres'
POSTGRES_HOST_AUTH_METHOD: 'trust'
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3
mariadb:
image: mariadb:10
env:
MYSQL_USER: 'root'
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3
strategy:
fail-fast: false
matrix:
include:
- php: '7.2'
moodle-branch: 'MOODLE_38_STABLE'
database: pgsql
- php: '7.2'
moodle-branch: 'MOODLE_38_STABLE'
database: mariadb
- php: '7.1'
moodle-branch: 'MOODLE_38_STABLE'
database: pgsql
- php: '7.1'
moodle-branch: 'MOODLE_38_STABLE'
database: mariadb
steps:
- name: Check out repository code
uses: actions/checkout@v2
with:
path: plugin
- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
- name: Initialise moodle-plugin-ci
run: |
composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3
echo $(cd ci/bin; pwd) >> $GITHUB_PATH
echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH
sudo locale-gen en_AU.UTF-8
echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV
- name: Install moodle-plugin-ci
run: moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1
env:
DB: ${{ matrix.database }}
MOODLE_BRANCH: ${{ matrix.moodle-branch }}
MUSTACHE_IGNORE_NAMES: 'mobile_*.mustache'
- name: PHP Lint
if: ${{ always() }}
run: moodle-plugin-ci phplint
- name: PHP Copy/Paste Detector
continue-on-error: true # This step will show errors but will not fail
if: ${{ always() }}
run: moodle-plugin-ci phpcpd
- name: PHP Mess Detector
continue-on-error: true # This step will show errors but will not fail
if: ${{ always() }}
run: moodle-plugin-ci phpmd
- name: Moodle Code Checker
if: ${{ always() }}
run: moodle-plugin-ci codechecker --max-warnings 0
- name: Moodle PHPDoc Checker
if: ${{ always() }}
run: moodle-plugin-ci phpdoc
- name: Validating
if: ${{ always() }}
run: moodle-plugin-ci validate
- name: Check upgrade savepoints
if: ${{ always() }}
run: moodle-plugin-ci savepoints
- name: Mustache Lint
if: ${{ always() }}
run: moodle-plugin-ci mustache
- name: Grunt
continue-on-error: true # This step will show errors but will not fail
if: ${{ always() }}
run: moodle-plugin-ci grunt --max-lint-warnings 0
- name: PHPUnit tests
if: ${{ always() }}
run: |
moodle-plugin-ci phpunit
cd moodle
vendor/bin/phpunit --fail-on-risky --disallow-test-output -v admin/tool/dataprivacy/tests/metadata_registry_test.php
vendor/bin/phpunit --fail-on-risky --disallow-test-output -v lib/tests/externallib_test.php
vendor/bin/phpunit --fail-on-risky --disallow-test-output -v privacy/tests/provider_test.php
- name: Behat features
if: ${{ always() }}
run: moodle-plugin-ci behat --profile chrome

View file

@ -1,52 +0,0 @@
language: php
# For javascript behat tests we need sudo
sudo: true
dist: trusty
cache:
directories:
- $HOME/.composer/cache
- $HOME/.npm
php:
- 7.1
- 7.2
addons:
firefox: 47.0.1
postgresql: 9.4
apt:
packages:
- openjdk-8-jre-headless
env:
global:
- MOODLE_BRANCH=MOODLE_38_STABLE
- IGNORE_NAMES=mobile_*.mustache # Mobile mustache has specific syntax, ignore their templates
matrix:
- DB=pgsql
- DB=mysqli
before_install:
- phpenv config-rm xdebug.ini
- nvm install 14.0
- nvm use 14.0
- cd ../..
- composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3
- export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH"
install:
- moodle-plugin-ci install
script:
- moodle-plugin-ci phplint
# - moodle-plugin-ci phpcpd # subplugins often have similar code and cause "duplicated code" errors
# - moodle-plugin-ci phpmd # too much noise from this check, maybe, some day...
- moodle-plugin-ci codechecker
- moodle-plugin-ci validate
- moodle-plugin-ci savepoints
- moodle-plugin-ci mustache
- moodle-plugin-ci grunt -t stylelint:css -t js
- moodle-plugin-ci phpunit
- moodle-plugin-ci behat

View file

@ -4,6 +4,19 @@ 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.
## [3.8.6] - 2021-06-13
### Added
- The ability to show the description on the course page (#406).
- The ability to choose how to deliver the certificate (#401).
### Fixed
- Managers are now able to download their students' certificates (#412).
- Users being able to view the certificate before the required time set (#403).
- Fixed the issue with displaying PDF when debugging is ON (#420).
- Using incorrect context when sending emails (#402).
- Use `cron_setup_user` when sending emails (#414).
## [3.8.5] - 2020-11-26
### Added

View file

@ -56,7 +56,7 @@ class backup_customcert_activity_task extends backup_activity_task {
* @param string $content
* @return mixed|string
*/
static public function encode_content_links($content) {
public static function encode_content_links($content) {
global $CFG;
$base = preg_quote($CFG->wwwroot, "/");

View file

@ -53,7 +53,7 @@ class restore_customcert_activity_task extends restore_activity_task {
/**
* Define the contents in the activity that must be processed by the link decoder.
*/
static public function define_decode_contents() {
public static function define_decode_contents() {
$contents = array();
$contents[] = new restore_decode_content('customcert', array('intro'), 'customcert');
@ -64,7 +64,7 @@ class restore_customcert_activity_task extends restore_activity_task {
/**
* Define the decoding rules for links belonging to the activity to be executed by the link decoder.
*/
static public function define_decode_rules() {
public static function define_decode_rules() {
$rules = array();
$rules[] = new restore_decode_rule('CUSTOMCERTVIEWBYID', '/mod/customcert/view.php?id=$1', 'course_module');
@ -75,12 +75,12 @@ class restore_customcert_activity_task extends restore_activity_task {
}
/**
* Define the restore log rules that will be applied by the {@link restore_logs_processor} when restoring
* customcert logs. It must return one array of {@link restore_log_rule} objects.
* Define the restore log rules that will be applied by the {@see restore_logs_processor} when restoring
* customcert logs. It must return one array of {@see restore_log_rule} objects.
*
* @return array the restore log rules
*/
static public function define_restore_log_rules() {
public static function define_restore_log_rules() {
$rules = array();
$rules[] = new restore_log_rule('customcert', 'add', 'view.php?id={course_module}', '{customcert}');

View file

@ -37,6 +37,16 @@ defined('MOODLE_INTERNAL') || die();
*/
class certificate {
/**
* Send the file inline to the browser.
*/
const DELIVERY_OPTION_INLINE = 'I';
/**
* Send to the browser and force a file download
*/
const DELIVERY_OPTION_DOWNLOAD = 'D';
/**
* @var string the print protection variable
*/
@ -165,7 +175,7 @@ class certificate {
* @param int $userid
* @return int the total time spent in seconds
*/
public static function get_course_time($courseid, $userid = 0) {
public static function get_course_time(int $courseid, int $userid = 0): int {
global $CFG, $DB, $USER;
if (empty($userid)) {
@ -217,7 +227,7 @@ class certificate {
$totaltime = 0;
}
$delay = $log->$timefield - $lasthit;
if ($delay > ($CFG->sessiontimeout * 60)) {
if ($delay > $CFG->sessiontimeout) {
// The difference between the last log and the current log is more than
// the timeout Register session value so that we have found a session!
$login = $log->$timefield;

View file

@ -247,7 +247,7 @@ class edit_form extends \moodleform {
// Create a table to display these elements.
$table = new \html_table();
$table->attributes = array('class' => 'generaltable elementstable');
$table->head = array(get_string('name', 'customcert'), get_string('type', 'customcert'), '');
$table->head = array(get_string('name', 'customcert'), get_string('type', 'customcert'), get_string('actions'));
$table->align = array('left', 'left', 'left');
// Loop through and add the elements to the table.
foreach ($elements as $element) {

View file

@ -377,7 +377,7 @@ abstract class element {
* @param bool $preview true if it is a preview, false otherwise
* @param \stdClass $user the user we are rendering this for
*/
public abstract function render($pdf, $preview, $user);
abstract public function render($pdf, $preview, $user);
/**
* Render the element in html.
@ -389,7 +389,7 @@ abstract class element {
*
* @return string the html
*/
public abstract function render_html();
abstract public function render_html();
/**
* Handles deleting any data this element may have introduced.

View file

@ -43,10 +43,20 @@ class course_module_viewed extends \core\event\course_module_viewed {
parent::init();
}
/**
* {@inheritdoc}
*
* @return string[]
*/
public static function get_objectid_mapping() {
return array('db' => 'customcert', 'restore' => 'customcert');
}
/**
* {@inheritdoc}
*
* @return bool
*/
public static function get_other_mapping() {
// No need to map.
return false;

View file

@ -84,6 +84,9 @@ class email_certificate_task extends \core\task\scheduled_task {
// Get the context.
$context = \context::instance_by_id($customcert->contextid);
// Set the $PAGE context - this ensure settings, such as language, are kept and don't default to the site settings.
$PAGE->set_context($context);
// Get the person we are going to send this email on behalf of.
$userfrom = \core_user::get_noreply_user();
@ -176,6 +179,9 @@ class email_certificate_task extends \core\task\scheduled_task {
// Now, email the people we need to.
foreach ($issuedusers as $user) {
// Set up the user.
cron_setup_user($user);
$userfullname = fullname($user);
$info->userfullname = $userfullname;

View file

@ -253,7 +253,7 @@ class template {
* @param bool $return Do we want to return the contents of the PDF?
* @return string|void Can return the PDF in string format if specified.
*/
public function generate_pdf($preview = false, $userid = null, $return = false) {
public function generate_pdf(bool $preview = false, int $userid = null, bool $return = false) {
global $CFG, $DB, $USER;
if (empty($userid)) {
@ -269,12 +269,18 @@ class template {
// Create the pdf object.
$pdf = new \pdf();
$customcert = $DB->get_record('customcert', ['templateid' => $this->id]);
// If the template belongs to a certificate then we need to check what permissions we set for it.
if ($protection = $DB->get_field('customcert', 'protection', array('templateid' => $this->id))) {
if (!empty($protection)) {
$protection = explode(', ', $protection);
if (!empty($customcert->protection)) {
$protection = explode(', ', $customcert->protection);
$pdf->SetProtection($protection);
}
if (empty($customcert->deliveryoption)) {
$deliveryoption = certificate::DELIVERY_OPTION_INLINE;
} else {
$deliveryoption = $customcert->deliveryoption;
}
$pdf->setPrintHeader(false);
@ -320,7 +326,7 @@ class template {
return $pdf->Output('', 'S');
}
$pdf->Output($filename, 'I');
$pdf->Output($filename, $deliveryoption);
}
}

View file

@ -14,6 +14,7 @@
<FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="requiredtime" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="verifyany" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="deliveryoption" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="emailstudents" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="emailteachers" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="emailothers" TYPE="text" NOTNULL="false" SEQUENCE="false"/>

View file

@ -166,5 +166,17 @@ function xmldb_customcert_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2019111803, 'customcert');
}
if ($oldversion < 2019111806) {
$table = new xmldb_table('customcert');
$field = new xmldb_field('deliveryoption', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'verifyany');
// Conditionally launch add field.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
upgrade_mod_savepoint(true, 2019111806, 'customcert');
}
return true;
}

View file

@ -123,7 +123,7 @@ class element extends \mod_customcert\element {
/**
* Helper function that returns the field value in a human-readable format.
*
* @param \stdClass $user the user we are rendering this for
* @param \stdClass $course the course we are rendering this for
* @param bool $preview Is this a preview?
* @return string
*/

View file

@ -57,6 +57,9 @@ $string['deleteissueconfirm'] = 'Are you sure you want to delete this certificat
$string['deleteissuedcertificates'] = 'Delete issued certificates';
$string['deletepageconfirm'] = 'Are you sure you want to delete this certificate page?';
$string['deletetemplateconfirm'] = 'Are you sure you want to delete this certificate template?';
$string['deliveryoptiondownload'] = 'Send to the browser and force a file download';
$string['deliveryoptioninline'] = 'Send the file inline to the browser';
$string['deliveryoptions'] = 'Delivery options';
$string['description'] = 'Description';
$string['duplicate'] = 'Duplicate';
$string['duplicateconfirm'] = 'Duplicate confirmation';

View file

@ -264,6 +264,8 @@ function customcert_supports($feature) {
return true;
case FEATURE_MOD_INTRO:
return true;
case FEATURE_SHOW_DESCRIPTION:
return true;
case FEATURE_COMPLETION_TRACKS_VIEWS:
return true;
case FEATURE_BACKUP_MOODLE2:

View file

@ -22,6 +22,8 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use mod_customcert\certificate;
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
require_once($CFG->dirroot.'/course/moodleform_mod.php');
@ -55,14 +57,20 @@ class mod_customcert_mod_form extends moodleform_mod {
$this->standard_intro_elements(get_string('description', 'customcert'));
$optionsheader = $mform->createElement('header', 'options', get_string('options', 'customcert'));
$mform->addElement('header', 'options', get_string('options', 'customcert'));
$deliveryoptions = [
certificate::DELIVERY_OPTION_INLINE => get_string('deliveryoptioninline', 'customcert'),
certificate::DELIVERY_OPTION_DOWNLOAD => get_string('deliveryoptiondownload', 'customcert')
];
$mform->addElement('select', 'deliveryoption', get_string('deliveryoptions', 'customcert'), $deliveryoptions);
$mform->setDefault('deliveryoption', certificate::DELIVERY_OPTION_INLINE);
if (has_capability('mod/customcert:manageemailstudents', $this->get_context())) {
$mform->addElement('selectyesno', 'emailstudents', get_string('emailstudents', 'customcert'));
$mform->setDefault('emailstudents', get_config('customcert', 'emailstudents'));
$mform->addHelpButton('emailstudents', 'emailstudents', 'customcert');
$mform->setType('emailstudents', PARAM_INT);
$firstoption = 'emailstudents';
}
if (has_capability('mod/customcert:manageemailteachers', $this->get_context())) {
@ -70,7 +78,6 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->setDefault('emailteachers', get_config('customcert', 'emailteachers'));
$mform->addHelpButton('emailteachers', 'emailteachers', 'customcert');
$mform->setType('emailteachers', PARAM_INT);
$firstoption = empty($firstoption) ? 'emailteachers' : $firstoption;
}
if (has_capability('mod/customcert:manageemailothers', $this->get_context())) {
@ -78,7 +85,6 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->addHelpButton('emailothers', 'emailothers', 'customcert');
$mform->setDefault('emailothers', get_config('customcert', 'emailothers'));
$mform->setType('emailothers', PARAM_TEXT);
$firstoption = empty($firstoption) ? 'emailothers' : $firstoption;
}
if (has_capability('mod/customcert:manageverifyany', $this->get_context())) {
@ -86,7 +92,6 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->addHelpButton('verifyany', 'verifycertificateanyone', 'customcert');
$mform->setDefault('verifyany', get_config('customcert', 'verifyany'));
$mform->setType('verifyany', PARAM_INT);
$firstoption = empty($firstoption) ? 'verifyany' : $firstoption;
}
if (has_capability('mod/customcert:managerequiredtime', $this->get_context())) {
@ -94,7 +99,6 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->addHelpButton('requiredtime', 'coursetimereq', 'customcert');
$mform->setDefault('requiredtime', get_config('customcert', 'requiredtime'));
$mform->setType('requiredtime', PARAM_INT);
$firstoption = empty($firstoption) ? 'requiredtime' : $firstoption;
}
if (has_capability('mod/customcert:manageprotection', $this->get_context())) {
@ -106,11 +110,6 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->setType('protection_print', PARAM_BOOL);
$mform->setType('protection_modify', PARAM_BOOL);
$mform->setType('protection_copy', PARAM_BOOL);
$firstoption = empty($firstoption) ? 'protection_print' : $firstoption;
}
if (!empty($firstoption)) {
$mform->insertElementBefore($optionsheader, $firstoption);
}
$this->standard_coursemodule_elements();
@ -227,13 +226,13 @@ class mod_customcert_mod_form extends moodleform_mod {
$protection = explode(', ', $protection);
if (in_array(\mod_customcert\certificate::PROTECTION_PRINT, $protection)) {
if (in_array(certificate::PROTECTION_PRINT, $protection)) {
$data->protection_print = 1;
}
if (in_array(\mod_customcert\certificate::PROTECTION_MODIFY, $protection)) {
if (in_array(certificate::PROTECTION_MODIFY, $protection)) {
$data->protection_modify = 1;
}
if (in_array(\mod_customcert\certificate::PROTECTION_COPY, $protection)) {
if (in_array(certificate::PROTECTION_COPY, $protection)) {
$data->protection_copy = 1;
}

View file

@ -49,9 +49,15 @@ $user = \core_user::get_user($userid, '*', MUST_EXIST);
// If we are viewing certificates that are not for the currently logged in user then do a capability check.
if (($userid != $USER->id) && !has_capability('mod/customcert:viewallcertificates', context_system::instance())) {
print_error('You are not allowed to view these certificates');
throw new moodle_exception('You are not allowed to view these certificates');
}
$PAGE->set_url($pageurl);
$PAGE->set_context(context_user::instance($userid));
$PAGE->set_title(get_string('mycertificates', 'customcert'));
$PAGE->set_pagelayout('standard');
$PAGE->navigation->extend_for_user($user);
// Check if we requested to download a certificate.
if ($downloadcert) {
$template = $DB->get_record('customcert_templates', array('id' => $customcert->templateid), '*', MUST_EXIST);
@ -68,12 +74,6 @@ if ($table->is_downloading()) {
exit();
}
$PAGE->set_url($pageurl);
$PAGE->set_context(context_user::instance($userid));
$PAGE->set_title(get_string('mycertificates', 'customcert'));
$PAGE->set_pagelayout('standard');
$PAGE->navigation->extend_for_user($user);
// Additional page setup.
$PAGE->navbar->add(get_string('profile'), new moodle_url('/user/profile.php', array('id' => $userid)));
$PAGE->navbar->add(get_string('mycertificates', 'customcert'));

View file

@ -40,7 +40,7 @@ class behat_mod_customcert extends behat_base {
/**
* Adds an element to the specified page of a template.
*
* @codingStandardsIgnoreLine
* phpcs:ignore
* @Given /^I add the element "(?P<element_name>(?:[^"]|\\")*)" to page "(?P<page_number>\d+)" of the "(?P<template_name>(?:[^"]|\\")*)" certificate template$/
* @param string $elementname
* @param int $pagenum

View file

@ -55,7 +55,7 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
// Create a custom certificate with no elements.
$this->getDataGenerator()->create_module('customcert', ['course' => $course->id, 'emailstudents' => 1]);
// Enrol the user as a student
// Enrol the user as a student.
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
// Run the task.

View file

@ -24,10 +24,10 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2019111805; // The current module version (Date: YYYYMMDDXX).
$plugin->version = 2019111807; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2019111800; // Requires this Moodle version (3.8).
$plugin->cron = 0; // Period for cron to check this module (secs).
$plugin->component = 'mod_customcert';
$plugin->maturity = MATURITY_STABLE;
$plugin->release = "3.8.5"; // User-friendly version number.
$plugin->release = "3.8.6"; // User-friendly version number.

View file

@ -56,7 +56,8 @@ if ($customcert->requiredtime && !$canmanage) {
if (\mod_customcert\certificate::get_course_time($course->id) < ($customcert->requiredtime * 60)) {
$a = new stdClass;
$a->requiredtime = $customcert->requiredtime;
notice(get_string('requiredtimenotmet', 'customcert', $a), "$CFG->wwwroot/course/view.php?id=$course->id");
$url = new moodle_url('/course/view.php', ['id' => $course->id]);
notice(get_string('requiredtimenotmet', 'customcert', $a), $url);
die;
}
}
@ -158,7 +159,7 @@ if (!$downloadown && !$downloadissue) {
}
echo $OUTPUT->footer($course);
exit();
} else if ($canreceive) { // Output to pdf.
} else if ($canreceive || $canmanage) { // Output to pdf.
// Set the userid value of who we are downloading the certificate for.
$userid = $USER->id;
if ($downloadown) {