#48 Added task and settings responsible for emailing certificates

This commit is contained in:
Mark Nelson 2017-02-02 17:17:41 +08:00
parent 2b27f564b8
commit 72c3b278e3
19 changed files with 982 additions and 9 deletions

View file

@ -42,8 +42,8 @@ class backup_customcert_activity_structure_step extends backup_activity_structur
// The instance.
$customcert = new backup_nested_element('customcert', array('id'), array(
'templateid', 'name', 'intro', 'introformat', 'requiredtime', 'protection',
'timecreated', 'timemodified'));
'templateid', 'name', 'intro', 'introformat', 'requiredtime', 'emailstudents',
'emailteachers', 'emailothers', 'protection', 'timecreated', 'timemodified'));
// The template.
$template = new backup_nested_element('template', array('id'), array(
@ -64,7 +64,7 @@ class backup_customcert_activity_structure_step extends backup_activity_structur
// The issues.
$issues = new backup_nested_element('issues');
$issue = new backup_nested_element('issue', array('id'), array(
'customcertid', 'userid', 'timecreated', 'code'));
'customcertid', 'userid', 'timecreated', 'emailed', 'code'));
// Build the tree.
$customcert->add_child($issues);

View file

@ -165,14 +165,22 @@ class certificate {
* Get the time the user has spent in the course.
*
* @param int $courseid
* @param int $userid
* @return int the total time spent in seconds
*/
public static function get_course_time($courseid) {
public static function get_course_time($courseid, $userid = 0) {
global $CFG, $DB, $USER;
if (empty($userid)) {
$userid = $USER->id;
}
$logmanager = get_log_manager();
$readers = $logmanager->get_readers();
$enabledreaders = get_config('tool_log', 'enabled_stores');
if (empty($enabledreaders)) {
return 0;
}
$enabledreaders = explode(',', $enabledreaders);
// Go through all the readers until we find one that we can use.
@ -201,7 +209,7 @@ class certificate {
WHERE userid = :userid
AND $coursefield = :courseid
ORDER BY $timefield ASC";
$params = array('userid' => $USER->id, 'courseid' => $courseid);
$params = array('userid' => $userid, 'courseid' => $courseid);
$totaltime = 0;
if ($logs = $DB->get_recordset_sql($sql, $params)) {
foreach ($logs as $log) {

View file

@ -0,0 +1,46 @@
<?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/>.
/**
* Email certificate as html renderer.
*
* @package mod_customcert
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_customcert\output\email;
defined('MOODLE_INTERNAL') || die();
/**
* Email certificate as html renderer.
*
* @package mod_customcert
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class renderer extends \mod_customcert\output\renderer {
/**
* The template name for this renderer.
*
* @return string
*/
public function get_template_name() {
return 'email_certificate_html';
}
}

View file

@ -0,0 +1,46 @@
<?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/>.
/**
* Email certificate as text renderer.
*
* @package mod_customcert
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_customcert\output\email;
defined('MOODLE_INTERNAL') || die();
/**
* Email certificate as text renderer.
*
* @package mod_customcert
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class renderer_textemail extends \mod_customcert\output\renderer {
/**
* The template name for this renderer.
*
* @return string
*/
public function get_template_name() {
return 'email_certificate_text';
}
}

View file

@ -0,0 +1,108 @@
<?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/>.
/**
* Email certificate renderable.
*
* @package mod_customcert
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_customcert\output;
defined('MOODLE_INTERNAL') || die();
/**
* Email certificate renderable.
*
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class email_certificate implements \renderable, \templatable {
/**
* @var bool Are we emailing the student?
*/
public $isstudent;
/**
* @var string The name of the user who owns the certificate.
*/
public $userfullname;
/**
* @var string The course full name.
*/
public $coursefullname;
/**
* @var int The certificate name.
*/
public $certificatename;
/**
* @var int The course module id.
*/
public $cmid;
/**
* Constructor.
*
* @param bool $isstudent Are we emailing the student?
* @param string $userfullname The name of the user who owns the certificate.
* @param string $coursefullname The name of the course.
* @param string $certificatename The name of the certificate.
* @param string $cmid The course module id.
*/
public function __construct($isstudent, $userfullname, $coursefullname, $certificatename, $cmid) {
$this->isstudent = $isstudent;
$this->userfullname = $userfullname;
$this->coursefullname = $coursefullname;
$this->certificatename = $certificatename;
$this->cmid = $cmid;
}
/**
* Export this data so it can be used as the context for a mustache template.
*
* @param \renderer_base $renderer The render to be used for formatting the email
* @return \stdClass The data ready for use in a mustache template
*/
public function export_for_template(\renderer_base $renderer) {
$data = new \stdClass();
// Used for the body text.
$info = new \stdClass();
$info->userfullname = $this->userfullname;
$info->certificatename = $this->certificatename;
$info->coursefullname = $this->coursefullname;
if ($this->isstudent) {
$data->emailgreeting = get_string('emailstudentgreeting', 'customcert', $this->userfullname);
$data->emailbody = get_string('emailstudentbody', 'customcert', $info);
$data->emailcertificatelink = new \moodle_url('/mod/customcert/view.php', array('id' => $this->cmid));
$data->emailcertificatetext = get_string('emailstudentcertificatelinktext', 'customcert');
} else {
$data->emailgreeting = get_string('emailnonstudentgreeting', 'customcert');
$data->emailbody = get_string('emailnonstudentbody', 'customcert', $info);
$data->emailcertificatelink = new \moodle_url('/mod/customcert/report.php', array('id' => $this->cmid));
$data->emailcertificatetext = get_string('emailnonstudentcertificatelinktext', 'customcert');
}
return $data;
}
}

View file

@ -49,4 +49,15 @@ class renderer extends plugin_renderer_base {
$data = $page->export_for_template($this);
return parent::render_from_template('mod_customcert/verify_certificate_results', $data);
}
/**
* Formats the email used to send the certificate by the email_certificate_task.
*
* @param email_certificate $certificate The certificate to email
* @return string
*/
public function render_email_certificate(email_certificate $certificate) {
$data = $certificate->export_for_template($this);
return $this->render_from_template('mod_customcert/' . $this->get_template_name(), $data);
}
}

View file

@ -0,0 +1,222 @@
<?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/>.
/**
* A scheduled task for emailing certificates.
*
* @package mod_customcert
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_customcert\task;
defined('MOODLE_INTERNAL') || die();
/**
* A scheduled task for emailing certificates.
*
* @package mod_customcert
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class email_certificate_task extends \core\task\scheduled_task {
/**
* Get a descriptive name for this task (shown to admins).
*
* @return string
*/
public function get_name() {
return get_string('taskemailcertificate', 'customcert');
}
/**
* Execute.
*/
public function execute() {
global $DB, $PAGE;
// Get all the certificates that have requested someone get emailed.
$sql = "SELECT c.*, ct.id as templateid, ct.name as templatename, ct.contextid, co.id as courseid,
co.shortname as coursename
FROM {customcert} c
JOIN {customcert_templates} ct
ON c.templateid = ct.id
JOIN {course} co
ON c.course = co.id
WHERE (c.emailstudents = :emailstudents
OR c.emailteachers = :emailteachers
OR c.emailothers != '')";
if ($customcerts = $DB->get_records_sql($sql, array('emailstudents' => 1, 'emailteachers' => 1))) {
// The renderers used for sending emails.
$htmlrenderer = $PAGE->get_renderer('mod_customcert', 'email', 'htmlemail');
$textrenderer = $PAGE->get_renderer('mod_customcert', 'email', 'textemail');
foreach ($customcerts as $customcert) {
// Get the context.
$context = \context::instance_by_id($customcert->contextid);
// Get the person we are going to send this email on behalf of.
// Look through the teachers.
if ($teachers = get_users_by_capability($context, 'moodle/course:update', 'u.*', 'u.id ASC',
'', '', '', '', false, true)) {
$teachers = sort_by_roleassignment_authority($teachers, $context);
$userfrom = reset($teachers);
} else { // Ok, no teachers, use administrator name.
$userfrom = get_admin();
}
$coursename = format_string($customcert->coursename, true, array('context' => $context));
$certificatename = format_string($customcert->name, true, array('context' => $context));
// Used to create the email subject.
$info = new \stdClass;
$info->coursename = $coursename;
$info->certificatename = $certificatename;
// Get a list of issues that have not yet been emailed.
$userfields = get_all_user_name_fields(true, 'u');
$sql = "SELECT u.id, u.username, $userfields, u.email, ci.id as issueid
FROM {customcert_issues} ci
JOIN {user} u
ON ci.userid = u.id
WHERE ci.customcertid = :customcertid
AND emailed = :emailed";
$issuedusers = $DB->get_records_sql($sql, array('customcertid' => $customcert->id,
'emailed' => 0));
// Now, get a list of users who can access the certificate but have not yet.
$enrolledusers = get_enrolled_users(\context_course::instance($customcert->courseid), 'mod/customcert:view');
foreach ($enrolledusers as $enroluser) {
// Check if the user has already been issued.
if (in_array($enroluser->id, array_keys((array) $issuedusers))) {
continue;
}
// Now check if the certificate is not visible to the current user.
$cm = get_fast_modinfo($customcert->courseid, $enroluser->id)->instances['customcert'][$customcert->id];
if (!$cm->uservisible) {
continue;
}
// Don't want to email those with the capability to manage the certificate.
if (has_capability('mod/customcert:manage', $context, $enroluser->id)) {
continue;
}
// Check that they have passed the required time.
if (\mod_customcert\certificate::get_course_time($customcert->courseid, $enroluser->id) <
($customcert->requiredtime * 60)) {
continue;
}
// Ok, issue them the certificate.
$customcertissue = new \stdClass();
$customcertissue->customcertid = $customcert->id;
$customcertissue->userid = $enroluser->id;
$customcertissue->code = \mod_customcert\certificate::generate_code();
$customcertissue->emailed = 0;
$customcertissue->timecreated = time();
// Insert the record into the database.
$issueid = $DB->insert_record('customcert_issues', $customcertissue);
// Add them to the array so we email them.
$enroluser->issueid = $issueid;
$issuedusers[] = $enroluser;
}
// Now, email the people we need to.
if ($issuedusers) {
foreach ($issuedusers as $user) {
$userfullname = fullname($user);
// Create a directory to store the PDF we will be sending.
$tempdir = make_temp_directory('certificate/attachment');
if (!$tempdir) {
return false;
}
// Now, get the PDF.
$template = new \stdClass();
$template->id = $customcert->templateid;
$template->name = $customcert->templatename;
$template->contextid = $customcert->contextid;
$template = new \mod_customcert\template($template);
$filecontents = $template->generate_pdf(false, $user->id, true);
// Set the name of the file we are going to send.
$filename = $coursename . '_' . $certificatename;
$filename = \core_text::entities_to_utf8($filename);
$filename = strip_tags($filename);
$filename = rtrim($filename, '.');
$filename = str_replace('&', '_', $filename) . '.pdf';
// Create the file we will be sending.
$tempfile = $tempdir . '/' . md5(microtime() . $user->id) . '.pdf';
file_put_contents($tempfile, $filecontents);
if ($customcert->emailstudents) {
$renderable = new \mod_customcert\output\email_certificate(true, $userfullname, $coursename,
$certificatename, $customcert->contextid);
$subject = get_string('emailstudentsubject', 'customcert', $info);
$message = $textrenderer->render($renderable);
$messagehtml = $htmlrenderer->render($renderable);
email_to_user($user, fullname($userfrom), $subject, $message, $messagehtml, $tempfile, $filename);
}
if ($customcert->emailteachers) {
$renderable = new \mod_customcert\output\email_certificate(false, $userfullname, $coursename,
$certificatename, $customcert->contextid);
$subject = get_string('emailnonstudentsubject', 'customcert', $info);
$message = $textrenderer->render($renderable);
$messagehtml = $htmlrenderer->render($renderable);
foreach ($teachers as $teacher) {
email_to_user($teacher, fullname($userfrom), $subject, $message, $messagehtml, $tempfile,
$filename);
}
}
if (!empty($customcert->emailothers)) {
$others = explode(',', $customcert->emailothers);
foreach ($others as $email) {
$email = trim($email);
if (validate_email($email)) {
$renderable = new \mod_customcert\output\email_certificate(false, $userfullname, $coursename,
$certificatename, $customcert->contextid);
$subject = get_string('emailnonstudentsubject', 'customcert', $info);
$message = $textrenderer->render($renderable);
$messagehtml = $htmlrenderer->render($renderable);
$emailuser = new \stdClass();
$emailuser->id = -1;
$emailuser->email = $email;
email_to_user($emailuser, fullname($userfrom), $subject, $message, $messagehtml, $tempfile,
$filename);
}
}
}
// Set the field so that it is emailed.
$DB->set_field('customcert_issues', 'emailed', 1, array('id' => $user->issueid));
}
}
}
}
}
}

View file

@ -250,8 +250,10 @@ class template {
*
* @param bool $preview true if it is a preview, false otherwise
* @param int $userid the id of the user whose certificate we want to view
* @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) {
public function generate_pdf($preview = false, $userid = null, $return = false) {
global $CFG, $DB, $USER;
if (empty($userid)) {
@ -303,6 +305,9 @@ class template {
}
}
}
if ($return) {
return $pdf->Output('', 'S');
}
$pdf->Output($filename, 'D');
}
}

View file

@ -13,6 +13,9 @@
<FIELD NAME="intro" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false"/>
<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="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"/>
<FIELD NAME="protection" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
@ -41,6 +44,7 @@
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="customcertid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="code" TYPE="char" LENGTH="40" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="emailed" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>

38
db/tasks.php Normal file
View file

@ -0,0 +1,38 @@
<?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/>.
/**
* Definition of customcert scheduled tasks.
*
* @package mod_customcert
* @category task
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$tasks = array(
array(
'classname' => 'mod_customcert\task\email_certificate_task',
'blocking' => 0,
'minute' => '*',
'hour' => '*',
'day' => '*',
'month' => '*',
'dayofweek' => '*'
)
);

View file

@ -45,5 +45,40 @@ function xmldb_customcert_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2016120503, 'customcert');
}
if ($oldversion < 2016120505) {
$table = new xmldb_table('customcert');
$field = new xmldb_field('emailstudents', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'requiredtime');
// Conditionally launch add field.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
$field = new xmldb_field('emailteachers', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'emailstudents');
// Conditionally launch add field.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
$field = new xmldb_field('emailothers', XMLDB_TYPE_TEXT, null, null, null, null, null, 'emailteachers');
// Conditionally launch add field.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
$table = new xmldb_table('customcert_issues');
$field = new xmldb_field('emailed', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'code');
// Conditionally launch add field.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Savepoint reached.
upgrade_mod_savepoint(true, 2016120505, 'customcert');
}
return true;
}

View file

@ -57,6 +57,20 @@ $string['elements_help'] = 'This is the list of elements that will be displayed
Please note: The elements are rendered in this order. The order can be changed by using the arrows next to each element.';
$string['elementwidth'] = 'Width';
$string['elementwidth_help'] = 'Specify the width of the element - \'0\' means that there is no width constraint.';
$string['emailnonstudentbody'] = 'Attached is the certificate \'{$a->certificatename}\' for \'{$a->userfullname}\' for the course \'{$a->coursefullname}\'.';
$string['emailnonstudentcertificatelinktext'] = 'View certificate report';
$string['emailnonstudentgreeting'] = 'Hi';
$string['emailnonstudentsubject'] = '{$a->coursename}: {$a->certificatename}';
$string['emailstudentbody'] = 'Attached is your certificate \'{$a->certificatename}\' for the course \'{$a->coursefullname}\'.';
$string['emailstudentcertificatelinktext'] = 'View certificate';
$string['emailstudentgreeting'] = 'Dear {$a}';
$string['emailstudentsubject'] = '{$a->coursename}: {$a->certificatename}';
$string['emailstudents'] = 'Email students';
$string['emailstudents_help'] = 'If set this will email the students a copy of the certificate when it becomes available.';
$string['emailteachers'] = 'Email teachers';
$string['emailteachers_help'] = 'If set this will email the teachers a copy of the certificate when it becomes available.';
$string['emailothers'] = 'Email others';
$string['emailothers_help'] = 'If set this will email the email addresses listed here (separated by a comma) with a copy of the certificate when it becomes available.';
$string['font'] = 'Font';
$string['font_help'] = 'The font used when generating this element.';
$string['fontcolour'] = 'Colour';
@ -127,6 +141,7 @@ $string['showposxy_desc'] = 'This will show the X and Y position when editing of
This isn\'t required if you plan on solely using the drag and drop interface for this purpose.';
$string['summaryofissue'] = 'Summary of issue';
$string['taskemailcertificate'] = 'Handles emailing certificates.';
$string['templatename'] = 'Template name';
$string['templatenameexists'] = 'That template name is currently in use, please choose another.';
$string['topcenter'] = 'Center';

View file

@ -57,6 +57,18 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->addElement('header', 'options', get_string('options', 'customcert'));
$mform->addElement('selectyesno', 'emailstudents', get_string('emailstudents', 'customcert'));
$mform->setType('emailstudents', 0);
$mform->addHelpButton('emailstudents', 'emailstudents', 'customcert');
$mform->addElement('selectyesno', 'emailteachers', get_string('emailteachers', 'customcert'));
$mform->setDefault('emailteachers', 0);
$mform->addHelpButton('emailteachers', 'emailteachers', 'customcert');
$mform->addElement('text', 'emailothers', get_string('emailothers', 'customcert'), array('size' => '40'));
$mform->setType('emailothers', PARAM_TEXT);
$mform->addHelpButton('emailothers', 'emailothers', 'customcert');
$mform->addElement('text', 'requiredtime', get_string('coursetimereq', 'customcert'), array('size' => '3'));
$mform->setType('requiredtime', PARAM_INT);
$mform->addHelpButton('requiredtime', 'coursetimereq', 'customcert');

View file

@ -0,0 +1,46 @@
{{!
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 mod_customcert/email_certificate_html
The certificate verification result
Classes required for JS:
* None
Data attibutes required for JS:
* All data attributes are required
Context variables required for this template:
* emailgreeting
* emailbody
* emailcertificatelink
* emailcertificatelinktext
Example context (json):
{
"emailgreeting": "Dear Angus MacGyver",
"emailbody": "Attached is your certificate 'The basics' for the course 'Survival as an '80s action hero'",
"emailcertificatelink": "http://yoursite.com/mod/customcert/view.php?id=4",
"emailcertificatelinktext": "Certificate report"
}
}}
{{{emailgreeting}}}
{{{emailbody}}}
<a href="{{emailcertificatelink}}">{{emailcertificatelinktext}}</a>.

View file

@ -0,0 +1,44 @@
{{!
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 mod_customcert/email_certificate_html
The certificate verification result
Classes required for JS:
* None
Data attibutes required for JS:
* All data attributes are required
Context variables required for this template:
* emailgreeting
* emailbody
* emailcertificatelink
* emailcertificatelinktext
Example context (json):
{
"emailgreeting": "Dear Angus MacGyver",
"emailbody": "Attached is your certificate 'The basics' for the course 'Survival as an '80s action hero'",
"emailcertificatelink": "http://yoursite.com/mod/customcert/view.php?id=4",
"emailcertificatelinktext": "Certificate report"
}
}}
{{{emailgreeting}}}
{{{emailbody}}}

View file

@ -0,0 +1,269 @@
<?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/>.
/**
* File contains the unit tests for the email certificate task.
*
* @package mod_customcert
* @category test
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
/**
* Unit tests for the email certificate task.
*
* @package mod_customcert
* @category test
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_customcert_task_email_certificate_task_testcase extends advanced_testcase {
/**
* Test set up.
*/
public function setUp() {
$this->resetAfterTest();
}
/**
* Tests the email certificate task for students.
*/
public function test_email_certificates_students() {
global $CFG, $DB;
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create some users.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user(array('firstname' => 'Teacher', 'lastname' => 'One'));
// Enrol two of them in the course as students.
$roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
$this->getDataGenerator()->enrol_user($user2->id, $course->id);
// Enrol one of the users as a teacher.
$this->getDataGenerator()->enrol_user($user3->id, $course->id, $roleids['editingteacher']);
// Create a custom certificate.
$customcert = $this->getDataGenerator()->create_module('customcert', array('course' => $course->id,
'emailstudents' => 1));
// Ok, now issue this to one user.
$customcertissue = new stdClass();
$customcertissue->customcertid = $customcert->id;
$customcertissue->userid = $user1->id;
$customcertissue->code = \mod_customcert\certificate::generate_code();
$customcertissue->timecreated = time();
$customcertissue->emailed = 0;
// Insert the record into the database.
$DB->insert_record('customcert_issues', $customcertissue);
// Confirm there is only one entry in this table.
$this->assertEquals(1, $DB->count_records('customcert_issues'));
// Run the task.
$sink = $this->redirectEmails();
$task = new \mod_customcert\task\email_certificate_task();
$task->execute();
$emails = $sink->get_messages();
// Get the issues from the issues table now.
$issues = $DB->get_records('customcert_issues');
$this->assertCount(2, $issues);
// Confirm that it was marked as emailed and was not issued to the teacher.
foreach ($issues as $issue) {
$this->assertEquals(1, $issue->emailed);
$this->assertNotEquals($user3->id, $issue->userid);
}
// Confirm that we sent out emails to the two users.
$this->assertCount(2, $emails);
$this->assertContains(fullname($user3), $emails[0]->header);
$this->assertEquals($CFG->noreplyaddress, $emails[0]->from);
$this->assertEquals($user1->email, $emails[0]->to);
$this->assertContains(fullname($user3), $emails[1]->header);
$this->assertEquals($CFG->noreplyaddress, $emails[1]->from);
$this->assertEquals($user2->email, $emails[1]->to);
}
/**
* Tests the email certificate task for teachers.
*/
public function test_email_certificates_teachers() {
global $CFG, $DB;
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create some users.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user(array('firstname' => 'Teacher', 'lastname' => 'One'));
// Enrol two of them in the course as students.
$roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
$this->getDataGenerator()->enrol_user($user2->id, $course->id);
// Enrol one of the users as a teacher.
$this->getDataGenerator()->enrol_user($user3->id, $course->id, $roleids['editingteacher']);
// Create a custom certificate.
$this->getDataGenerator()->create_module('customcert', array('course' => $course->id,
'emailteachers' => 1));
// Run the task.
$sink = $this->redirectEmails();
$task = new \mod_customcert\task\email_certificate_task();
$task->execute();
$emails = $sink->get_messages();
// Confirm that we only sent out 2 emails, both emails to the teacher for the two students.
$this->assertCount(2, $emails);
$this->assertContains(fullname($user3), utf8_encode($emails[0]->header));
$this->assertEquals($CFG->noreplyaddress, $emails[0]->from);
$this->assertEquals($user3->email, $emails[0]->to);
$this->assertContains(fullname($user3), utf8_encode($emails[1]->header));
$this->assertEquals($CFG->noreplyaddress, $emails[1]->from);
$this->assertEquals($user3->email, $emails[1]->to);
}
/**
* Tests the email certificate task for others.
*/
public function test_email_certificates_others() {
global $CFG;
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create some users.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
// Enrol two of them in the course as students.
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
$this->getDataGenerator()->enrol_user($user2->id, $course->id);
// Create a custom certificate.
$this->getDataGenerator()->create_module('customcert', array('course' => $course->id,
'emailothers' => 'testcustomcert@example.com, doo@dah'));
// Run the task.
$sink = $this->redirectEmails();
$task = new \mod_customcert\task\email_certificate_task();
$task->execute();
$emails = $sink->get_messages();
// Confirm that we only sent out 2 emails, both emails to the other address that was valid for the two students.
$this->assertCount(2, $emails);
$this->assertContains(fullname(get_admin()), utf8_encode($emails[0]->header));
$this->assertEquals($CFG->noreplyaddress, $emails[0]->from);
$this->assertEquals('testcustomcert@example.com', $emails[0]->to);
$this->assertContains(fullname(get_admin()), utf8_encode($emails[1]->header));
$this->assertEquals($CFG->noreplyaddress, $emails[1]->from);
$this->assertEquals('testcustomcert@example.com', $emails[1]->to);
}
/**
* Tests the email certificate task when the certificate is not visible.
*/
public function test_email_certificates_students_not_visible() {
global $DB;
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create a user.
$user1 = $this->getDataGenerator()->create_user();
// Enrol them in the course.
$roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
// Create a custom certificate.
$this->getDataGenerator()->create_module('customcert', array('course' => $course->id, 'emailstudents' => 1));
// Remove the permission for the user to view the certificate.
assign_capability('mod/customcert:view', CAP_PROHIBIT, $roleids['student'], \context_course::instance($course->id));
// Run the task.
$sink = $this->redirectEmails();
$task = new \mod_customcert\task\email_certificate_task();
$task->execute();
$emails = $sink->get_messages();
// Confirm there are no issues as the user did not have permissions to view it.
$issues = $DB->get_records('customcert_issues');
$this->assertCount(0, $issues);
// Confirm no emails were sent.
$this->assertCount(0, $emails);
}
/**
* Tests the email certificate task when the student has not met the required time for the course.
*/
public function test_email_certificates_students_havent_met_required_time() {
global $DB;
// Set the standard log to on.
set_config('enabled_stores', 'logstore_standard', 'tool_log');
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create a user.
$user1 = $this->getDataGenerator()->create_user();
// Enrol them in the course.
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
// Create a custom certificate.
$this->getDataGenerator()->create_module('customcert', array('course' => $course->id, 'emailstudents' => 1,
'requiredtime' => '60'));
// Run the task.
$sink = $this->redirectEmails();
$task = new \mod_customcert\task\email_certificate_task();
$task->execute();
$emails = $sink->get_messages();
// Confirm there are no issues as the user did not meet the required time.
$issues = $DB->get_records('customcert_issues');
$this->assertCount(0, $issues);
// Confirm no emails were sent.
$this->assertCount(0, $emails);
}
}

64
tests/generator/lib.php Normal file
View file

@ -0,0 +1,64 @@
<?php
// This file is part of the customcert module for 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/>.
/**
* Contains the class responsible for data generation during unit tests
*
* @package mod_customcert
* @category test
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* The class responsible for data generation during unit tests
*
* @package mod_customcert
* @category test
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_customcert_generator extends testing_module_generator {
/**
* Creates an instance of the custom certificate.
*
* @param array|stdClass|null $record
* @param array|null $options.
* @return stdClass.
*/
public function create_instance($record = null, array $options = null) {
$record = (object)(array)$record;
$defaultsettings = array(
'requiredtime' => 0,
'emailstudents' => 0,
'emailteachers' => 0,
'emailothers' => '',
'protection' => ''
);
foreach ($defaultsettings as $name => $value) {
if (!isset($record->{$name})) {
$record->{$name} = $value;
}
}
return parent::create_instance($record, (array)$options);
}
}

View file

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

View file

@ -118,7 +118,7 @@ if (empty($action)) {
echo $downloadbutton;
echo $OUTPUT->footer($course);
exit;
} else { // Output to pdf
} else { // Output to pdf.
// Create new customcert issue record if one does not already exist.
if (!$DB->record_exists('customcert_issues', array('userid' => $USER->id, 'customcertid' => $customcert->id))) {
$customcertissue = new stdClass();