|
|
|
<?php
|
|
|
|
|
|
|
|
// This file is part of the Certificate 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/>.
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Certificate module internal API,
|
|
|
|
* this is in separate file to reduce memory use on non-certificate pages.
|
|
|
|
*
|
|
|
|
* @package mod_certificate
|
|
|
|
* @copyright Mark Nelson <markn@moodle.com>
|
|
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
|
*/
|
|
|
|
|
|
|
|
defined('MOODLE_INTERNAL') || die();
|
|
|
|
|
|
|
|
require_once($CFG->dirroot.'/mod/certificate/lib.php');
|
|
|
|
require_once($CFG->dirroot.'/course/lib.php');
|
|
|
|
require_once($CFG->dirroot.'/grade/lib.php');
|
|
|
|
require_once($CFG->dirroot.'/grade/querylib.php');
|
|
|
|
|
|
|
|
/** The border image folder */
|
|
|
|
define('CERT_IMAGE_BORDER', 'borders');
|
|
|
|
/** The watermark image folder */
|
|
|
|
define('CERT_IMAGE_WATERMARK', 'watermarks');
|
|
|
|
/** The signature image folder */
|
|
|
|
define('CERT_IMAGE_SIGNATURE', 'signatures');
|
|
|
|
/** The seal image folder */
|
|
|
|
define('CERT_IMAGE_SEAL', 'seals');
|
|
|
|
|
|
|
|
/** Set CERT_PER_PAGE to 0 if you wish to display all certificates on the report page */
|
|
|
|
define('CERT_PER_PAGE', 30);
|
|
|
|
|
|
|
|
define('CERT_MAX_PER_PAGE', 200);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a list of teachers by group
|
|
|
|
* for sending email alerts to teachers
|
|
|
|
*
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $user
|
|
|
|
* @param stdClass $course
|
|
|
|
* @param stdClass $cm
|
|
|
|
* @return array the teacher array
|
|
|
|
*/
|
|
|
|
function certificate_get_teachers($certificate, $user, $course, $cm) {
|
|
|
|
global $USER;
|
|
|
|
|
|
|
|
$context = context_module::instance($cm->id);
|
|
|
|
$potteachers = get_users_by_capability($context, 'mod/certificate:manage',
|
|
|
|
'', '', '', '', '', '', false, false);
|
|
|
|
if (empty($potteachers)) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
$teachers = array();
|
|
|
|
if (groups_get_activity_groupmode($cm, $course) == SEPARATEGROUPS) { // Separate groups are being used
|
|
|
|
if ($groups = groups_get_all_groups($course->id, $user->id)) { // Try to find all groups
|
|
|
|
foreach ($groups as $group) {
|
|
|
|
foreach ($potteachers as $t) {
|
|
|
|
if ($t->id == $user->id) {
|
|
|
|
continue; // do not send self
|
|
|
|
}
|
|
|
|
if (groups_is_member($group->id, $t->id)) {
|
|
|
|
$teachers[$t->id] = $t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// user not in group, try to find teachers without group
|
|
|
|
foreach ($potteachers as $t) {
|
|
|
|
if ($t->id == $USER->id) {
|
|
|
|
continue; // do not send self
|
|
|
|
}
|
|
|
|
if (!groups_get_all_groups($course->id, $t->id)) { //ugly hack
|
|
|
|
$teachers[$t->id] = $t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach ($potteachers as $t) {
|
|
|
|
if ($t->id == $USER->id) {
|
|
|
|
continue; // do not send self
|
|
|
|
}
|
|
|
|
$teachers[$t->id] = $t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $teachers;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Alerts teachers by email of received certificates. First checks
|
|
|
|
* whether the option to email teachers is set for this certificate.
|
|
|
|
*
|
|
|
|
* @param stdClass $course
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $certrecord
|
|
|
|
* @param stdClass $cm course module
|
|
|
|
*/
|
|
|
|
function certificate_email_teachers($course, $certificate, $certrecord, $cm) {
|
|
|
|
global $USER, $CFG, $DB;
|
|
|
|
|
|
|
|
if ($certificate->emailteachers == 0) { // No need to do anything
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$user = $DB->get_record('user', array('id' => $certrecord->userid));
|
|
|
|
|
|
|
|
if ($teachers = certificate_get_teachers($certificate, $user, $course, $cm)) {
|
|
|
|
$strawarded = get_string('awarded', 'certificate');
|
|
|
|
foreach ($teachers as $teacher) {
|
|
|
|
$info = new stdClass;
|
|
|
|
$info->student = fullname($USER);
|
|
|
|
$info->course = format_string($course->fullname,true);
|
|
|
|
$info->certificate = format_string($certificate->name,true);
|
|
|
|
$info->url = $CFG->wwwroot.'/mod/certificate/report.php?id='.$cm->id;
|
|
|
|
$from = $USER;
|
|
|
|
$postsubject = $strawarded . ': ' . $info->student . ' -> ' . $certificate->name;
|
|
|
|
$posttext = certificate_email_teachers_text($info);
|
|
|
|
$posthtml = ($teacher->mailformat == 1) ? certificate_email_teachers_html($info) : '';
|
|
|
|
|
|
|
|
@email_to_user($teacher, $from, $postsubject, $posttext, $posthtml); // If it fails, oh well, too bad.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Alerts others by email of received certificates. First checks
|
|
|
|
* whether the option to email others is set for this certificate.
|
|
|
|
* Uses the email_teachers info.
|
|
|
|
* Code suggested by Eloy Lafuente
|
|
|
|
*
|
|
|
|
* @param stdClass $course
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $certrecord
|
|
|
|
* @param stdClass $cm course module
|
|
|
|
*/
|
|
|
|
function certificate_email_others($course, $certificate, $certrecord, $cm) {
|
|
|
|
global $USER, $CFG;
|
|
|
|
|
|
|
|
if ($certificate->emailothers) {
|
|
|
|
$others = explode(',', $certificate->emailothers);
|
|
|
|
if ($others) {
|
|
|
|
$strawarded = get_string('awarded', 'certificate');
|
|
|
|
foreach ($others as $other) {
|
|
|
|
$other = trim($other);
|
|
|
|
if (validate_email($other)) {
|
|
|
|
$destination = new stdClass;
|
|
|
|
$destination->id = 1;
|
|
|
|
$destination->email = $other;
|
|
|
|
$info = new stdClass;
|
|
|
|
$info->student = fullname($USER);
|
|
|
|
$info->course = format_string($course->fullname, true);
|
|
|
|
$info->certificate = format_string($certificate->name, true);
|
|
|
|
$info->url = $CFG->wwwroot.'/mod/certificate/report.php?id='.$cm->id;
|
|
|
|
$from = $USER;
|
|
|
|
$postsubject = $strawarded . ': ' . $info->student . ' -> ' . $certificate->name;
|
|
|
|
$posttext = certificate_email_teachers_text($info);
|
|
|
|
$posthtml = certificate_email_teachers_html($info);
|
|
|
|
|
|
|
|
@email_to_user($destination, $from, $postsubject, $posttext, $posthtml); // If it fails, oh well, too bad.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates the text content for emails to teachers -- needs to be finished with cron
|
|
|
|
*
|
|
|
|
* @param $info object The info used by the 'emailteachermail' language string
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function certificate_email_teachers_text($info) {
|
|
|
|
$posttext = get_string('emailteachermail', 'certificate', $info) . "\n";
|
|
|
|
|
|
|
|
return $posttext;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates the html content for emails to teachers
|
|
|
|
*
|
|
|
|
* @param $info object The info used by the 'emailteachermailhtml' language string
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function certificate_email_teachers_html($info) {
|
|
|
|
$posthtml = '<font face="sans-serif">';
|
|
|
|
$posthtml .= '<p>' . get_string('emailteachermailhtml', 'certificate', $info) . '</p>';
|
|
|
|
$posthtml .= '</font>';
|
|
|
|
|
|
|
|
return $posthtml;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends the student their issued certificate from moddata as an email
|
|
|
|
* attachment.
|
|
|
|
*
|
|
|
|
* @param stdClass $course
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $certrecord
|
|
|
|
* @param stdClass $context
|
|
|
|
* @param string $filecontents the PDF file contents
|
|
|
|
* @param string $filename
|
|
|
|
* @return bool Returns true if mail was sent OK and false if there was an error.
|
|
|
|
*/
|
|
|
|
function certificate_email_student($course, $certificate, $certrecord, $context, $filecontents, $filename) {
|
|
|
|
global $USER;
|
|
|
|
|
|
|
|
// Get teachers
|
|
|
|
if ($users = get_users_by_capability($context, 'moodle/course:update', 'u.*', 'u.id ASC',
|
|
|
|
'', '', '', '', false, true)) {
|
|
|
|
$users = sort_by_roleassignment_authority($users, $context);
|
|
|
|
$teacher = array_shift($users);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we haven't found a teacher yet, look for a non-editing teacher in this course.
|
|
|
|
if (empty($teacher) && $users = get_users_by_capability($context, 'moodle/course:update', 'u.*', 'u.id ASC',
|
|
|
|
'', '', '', '', false, true)) {
|
|
|
|
$users = sort_by_roleassignment_authority($users, $context);
|
|
|
|
$teacher = array_shift($users);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ok, no teachers, use administrator name
|
|
|
|
if (empty($teacher)) {
|
|
|
|
$teacher = fullname(get_admin());
|
|
|
|
}
|
|
|
|
|
|
|
|
$info = new stdClass;
|
|
|
|
$info->username = fullname($USER);
|
|
|
|
$info->certificate = format_string($certificate->name, true);
|
|
|
|
$info->course = format_string($course->fullname, true);
|
|
|
|
$from = fullname($teacher);
|
|
|
|
$subject = $info->course . ': ' . $info->certificate;
|
|
|
|
$message = get_string('emailstudenttext', 'certificate', $info) . "\n";
|
|
|
|
|
|
|
|
// Make the HTML version more XHTML happy (&)
|
|
|
|
$messagehtml = text_to_html(get_string('emailstudenttext', 'certificate', $info));
|
|
|
|
|
|
|
|
$tempdir = make_temp_directory('certificate/attachment');
|
|
|
|
if (!$tempdir) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$tempfile = $tempdir.'/'.md5(sesskey().microtime().$USER->id.'.pdf');
|
|
|
|
$fp = fopen($tempfile, 'w+');
|
|
|
|
fputs($fp, $filecontents);
|
|
|
|
fclose($fp);
|
|
|
|
|
|
|
|
$prevabort = ignore_user_abort(true);
|
|
|
|
$result = email_to_user($USER, $from, $subject, $message, $messagehtml, $tempfile, $filename);
|
|
|
|
@unlink($tempfile);
|
|
|
|
ignore_user_abort($prevabort);
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function returns success or failure of file save
|
|
|
|
*
|
|
|
|
* @param string $pdf is the string contents of the pdf
|
|
|
|
* @param int $certrecordid the certificate issue record id
|
|
|
|
* @param string $filename pdf filename
|
|
|
|
* @param int $contextid context id
|
|
|
|
* @return bool return true if successful, false otherwise
|
|
|
|
*/
|
|
|
|
function certificate_save_pdf($pdf, $certrecordid, $filename, $contextid) {
|
|
|
|
global $USER;
|
|
|
|
|
|
|
|
if (empty($certrecordid)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (empty($pdf)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$fs = get_file_storage();
|
|
|
|
|
|
|
|
// Prepare file record object
|
|
|
|
$component = 'mod_certificate';
|
|
|
|
$filearea = 'issue';
|
|
|
|
$filepath = '/';
|
|
|
|
$fileinfo = array(
|
|
|
|
'contextid' => $contextid, // ID of context
|
|
|
|
'component' => $component, // usually = table name
|
|
|
|
'filearea' => $filearea, // usually = table name
|
|
|
|
'itemid' => $certrecordid, // usually = ID of row in table
|
|
|
|
'filepath' => $filepath, // any path beginning and ending in /
|
|
|
|
'filename' => $filename, // any filename
|
|
|
|
'mimetype' => 'application/pdf', // any filename
|
|
|
|
'userid' => $USER->id);
|
|
|
|
|
|
|
|
// We do not know the previous file name, better delete everything here,
|
|
|
|
// luckily there is supposed to be always only one certificate here.
|
|
|
|
$fs->delete_area_files($contextid, $component, $filearea, $certrecordid);
|
|
|
|
|
|
|
|
$fs->create_file_from_string($fileinfo, $pdf);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Produces a list of links to the issued certificates. Used for report.
|
|
|
|
*
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param int $userid
|
|
|
|
* @param int $contextid
|
|
|
|
* @return string return the user files
|
|
|
|
*/
|
|
|
|
function certificate_print_user_files($certificate, $userid, $contextid) {
|
|
|
|
global $CFG, $DB, $OUTPUT;
|
|
|
|
|
|
|
|
$output = '';
|
|
|
|
|
|
|
|
$certrecord = $DB->get_record('certificate_issues', array('userid' => $userid, 'certificateid' => $certificate->id));
|
|
|
|
$fs = get_file_storage();
|
|
|
|
|
|
|
|
$component = 'mod_certificate';
|
|
|
|
$filearea = 'issue';
|
|
|
|
$files = $fs->get_area_files($contextid, $component, $filearea, $certrecord->id);
|
|
|
|
foreach ($files as $file) {
|
|
|
|
$filename = $file->get_filename();
|
|
|
|
$link = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$contextid.'/mod_certificate/issue/'.$certrecord->id.'/'.$filename);
|
|
|
|
|
|
|
|
$output = '<img src="'.$OUTPUT->pix_url(file_mimetype_icon($file->get_mimetype())).'" height="16" width="16" alt="'.$file->get_mimetype().'" /> '.
|
|
|
|
'<a href="'.$link.'" >'.s($filename).'</a>';
|
|
|
|
|
|
|
|
}
|
|
|
|
$output .= '<br />';
|
|
|
|
$output = '<div class="files">'.$output.'</div>';
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Inserts preliminary user data when a certificate is viewed.
|
|
|
|
* Prevents form from issuing a certificate upon browser refresh.
|
|
|
|
*
|
|
|
|
* @param stdClass $course
|
|
|
|
* @param stdClass $user
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $cm
|
|
|
|
* @return stdClass the newly created certificate issue
|
|
|
|
*/
|
|
|
|
function certificate_get_issue($course, $user, $certificate, $cm) {
|
|
|
|
global $DB;
|
|
|
|
|
|
|
|
// Check if there is an issue already, should only ever be one
|
|
|
|
if ($certissue = $DB->get_record('certificate_issues', array('userid' => $user->id, 'certificateid' => $certificate->id))) {
|
|
|
|
return $certissue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create new certificate issue record
|
|
|
|
$certissue = new stdClass();
|
|
|
|
$certissue->certificateid = $certificate->id;
|
|
|
|
$certissue->userid = $user->id;
|
|
|
|
$certissue->code = certificate_generate_code();
|
|
|
|
$certissue->timecreated = time();
|
|
|
|
$certissue->id = $DB->insert_record('certificate_issues', $certissue);
|
|
|
|
|
|
|
|
// Email to the teachers and anyone else
|
|
|
|
certificate_email_teachers($course, $certificate, $certissue, $cm);
|
|
|
|
certificate_email_others($course, $certificate, $certissue, $cm);
|
|
|
|
|
|
|
|
return $certissue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a list of issued certificates - sorted for report.
|
|
|
|
*
|
|
|
|
* @param int $certificateid
|
|
|
|
* @param string $sort the sort order
|
|
|
|
* @param bool $groupmode are we in group mode ?
|
|
|
|
* @param stdClass $cm the course module
|
|
|
|
* @param int $page offset
|
|
|
|
* @param int $perpage total per page
|
|
|
|
* @return stdClass the users
|
|
|
|
*/
|
|
|
|
function certificate_get_issues($certificateid, $sort="ci.timecreated ASC", $groupmode, $cm, $page = 0, $perpage = 0) {
|
|
|
|
global $DB, $USER;
|
|
|
|
|
|
|
|
$context = context_module::instance($cm->id);
|
|
|
|
$conditionssql = '';
|
|
|
|
$conditionsparams = array();
|
|
|
|
|
|
|
|
// Get all users that can manage this certificate to exclude them from the report.
|
|
|
|
$certmanagers = array_keys(get_users_by_capability($context, 'mod/certificate:manage', 'u.id'));
|
|
|
|
$certmanagers = array_merge($certmanagers, array_keys(get_admins()));
|
|
|
|
list($sql, $params) = $DB->get_in_or_equal($certmanagers, SQL_PARAMS_NAMED, 'cert');
|
|
|
|
$conditionssql .= "AND NOT u.id $sql \n";
|
|
|
|
$conditionsparams += $params;
|
|
|
|
|
|
|
|
if ($groupmode) {
|
|
|
|
$canaccessallgroups = has_capability('moodle/site:accessallgroups', $context);
|
|
|
|
$currentgroup = groups_get_activity_group($cm);
|
|
|
|
|
|
|
|
// If we are viewing all participants and the user does not have access to all groups then return nothing.
|
|
|
|
if (!$currentgroup && !$canaccessallgroups) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($currentgroup) {
|
|
|
|
if (!$canaccessallgroups) {
|
|
|
|
// Guest users do not belong to any groups.
|
|
|
|
if (isguestuser()) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that the user belongs to the group we are viewing.
|
|
|
|
$usersgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid);
|
|
|
|
if ($usersgroups) {
|
|
|
|
if (!isset($usersgroups[$currentgroup])) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
} else { // They belong to no group, so return an empty array.
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$groupusers = array_keys(groups_get_members($currentgroup, 'u.*'));
|
|
|
|
if (empty($groupusers)) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
list($sql, $params) = $DB->get_in_or_equal($groupusers, SQL_PARAMS_NAMED, 'grp');
|
|
|
|
$conditionssql .= "AND u.id $sql ";
|
|
|
|
$conditionsparams += $params;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$page = (int) $page;
|
|
|
|
$perpage = (int) $perpage;
|
|
|
|
|
|
|
|
// Get all the users that have certificates issued, should only be one issue per user for a certificate
|
|
|
|
$allparams = $conditionsparams + array('certificateid' => $certificateid);
|
|
|
|
|
|
|
|
// The picture fields also include the name fields for the user.
|
|
|
|
$picturefields = user_picture::fields('u', get_extra_user_fields($context));
|
|
|
|
$users = $DB->get_records_sql("SELECT $picturefields, u.idnumber, ci.code, ci.timecreated
|
|
|
|
FROM {user} u
|
|
|
|
INNER JOIN {certificate_issues} ci
|
|
|
|
ON u.id = ci.userid
|
|
|
|
WHERE u.deleted = 0
|
|
|
|
AND ci.certificateid = :certificateid $conditionssql
|
|
|
|
ORDER BY {$sort}", $allparams, $page * $perpage, $perpage);
|
|
|
|
|
|
|
|
return $users;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a list of previously issued certificates--used for reissue.
|
|
|
|
*
|
|
|
|
* @param int $certificateid
|
|
|
|
* @return stdClass the attempts else false if none found
|
|
|
|
*/
|
|
|
|
function certificate_get_attempts($certificateid) {
|
|
|
|
global $DB, $USER;
|
|
|
|
|
|
|
|
$sql = "SELECT *
|
|
|
|
FROM {certificate_issues} i
|
|
|
|
WHERE certificateid = :certificateid
|
|
|
|
AND userid = :userid";
|
|
|
|
if ($issues = $DB->get_records_sql($sql, array('certificateid' => $certificateid, 'userid' => $USER->id))) {
|
|
|
|
return $issues;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prints a table of previously issued certificates--used for reissue.
|
|
|
|
*
|
|
|
|
* @param stdClass $course
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $attempts
|
|
|
|
* @return string the attempt table
|
|
|
|
*/
|
|
|
|
function certificate_print_attempts($course, $certificate, $attempts) {
|
|
|
|
global $OUTPUT;
|
|
|
|
|
|
|
|
echo $OUTPUT->heading(get_string('summaryofattempts', 'certificate'));
|
|
|
|
|
|
|
|
// Prepare table header
|
|
|
|
$table = new html_table();
|
|
|
|
$table->class = 'generaltable';
|
|
|
|
$table->head = array(get_string('issued', 'certificate'));
|
|
|
|
$table->align = array('left');
|
|
|
|
$table->attributes = array("style" => "width:20%; margin:auto");
|
|
|
|
$gradecolumn = $certificate->printgrade;
|
|
|
|
if ($gradecolumn) {
|
|
|
|
$table->head[] = get_string('grade');
|
|
|
|
$table->align[] = 'center';
|
|
|
|
$table->size[] = '';
|
|
|
|
}
|
|
|
|
// One row for each attempt
|
|
|
|
foreach ($attempts as $attempt) {
|
|
|
|
$row = array();
|
|
|
|
|
|
|
|
// prepare strings for time taken and date completed
|
|
|
|
$datecompleted = userdate($attempt->timecreated);
|
|
|
|
$row[] = $datecompleted;
|
|
|
|
|
|
|
|
if ($gradecolumn) {
|
|
|
|
$attemptgrade = certificate_get_grade($certificate, $course);
|
|
|
|
$row[] = $attemptgrade;
|
|
|
|
}
|
|
|
|
|
|
|
|
$table->data[$attempt->id] = $row;
|
|
|
|
}
|
|
|
|
|
|
|
|
echo html_writer::table($table);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the time the user has spent in the course
|
|
|
|
*
|
|
|
|
* @param int $courseid
|
|
|
|
* @return int the total time spent in seconds
|
|
|
|
*/
|
|
|
|
function certificate_get_course_time($courseid) {
|
|
|
|
global $CFG, $DB, $USER;
|
|
|
|
|
|
|
|
$logmanager = get_log_manager();
|
|
|
|
$readers = $logmanager->get_readers();
|
|
|
|
$enabledreaders = get_config('tool_log', 'enabled_stores');
|
|
|
|
$enabledreaders = explode(',', $enabledreaders);
|
|
|
|
|
|
|
|
// Go through all the readers until we find one that we can use.
|
|
|
|
foreach ($enabledreaders as $enabledreader) {
|
|
|
|
$reader = $readers[$enabledreader];
|
|
|
|
if ($reader instanceof \logstore_legacy\log\store) {
|
|
|
|
$logtable = 'log';
|
|
|
|
$coursefield = 'course';
|
|
|
|
$timefield = 'time';
|
|
|
|
break;
|
|
|
|
} else if ($reader instanceof \core\log\sql_internal_table_reader) {
|
|
|
|
$logtable = $reader->get_internal_log_table_name();
|
|
|
|
$coursefield = 'courseid';
|
|
|
|
$timefield = 'timecreated';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we didn't find a reader then return 0.
|
|
|
|
if (!isset($logtable)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
$sql = "SELECT id, $timefield
|
|
|
|
FROM {{$logtable}}
|
|
|
|
WHERE userid = :userid
|
|
|
|
AND $coursefield = :courseid
|
|
|
|
ORDER BY $timefield ASC";
|
|
|
|
$params = array('userid' => $USER->id, 'courseid' => $courseid);
|
|
|
|
|
|
|
|
$totaltime = 0;
|
|
|
|
if ($logs = $DB->get_recordset_sql($sql, $params)) {
|
|
|
|
foreach ($logs as $log) {
|
|
|
|
if (!isset($login)) {
|
|
|
|
// For the first time $login is not set so the first log is also the first login
|
|
|
|
$login = $log->$timefield;
|
|
|
|
$lasthit = $log->$timefield;
|
|
|
|
$totaltime = 0;
|
|
|
|
}
|
|
|
|
$delay = $log->$timefield - $lasthit;
|
|
|
|
if ($delay > ($CFG->sessiontimeout * 60)) {
|
|
|
|
// 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;
|
|
|
|
} else {
|
|
|
|
$totaltime += $delay;
|
|
|
|
}
|
|
|
|
// Now the actual log became the previous log for the next cycle
|
|
|
|
$lasthit = $log->$timefield;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $totaltime;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get all the modules
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function certificate_get_mods() {
|
|
|
|
global $COURSE, $DB;
|
|
|
|
|
|
|
|
$strtopic = get_string("topic");
|
|
|
|
$strweek = get_string("week");
|
|
|
|
$strsection = get_string("section");
|
|
|
|
|
|
|
|
// Collect modules data
|
|
|
|
$modinfo = get_fast_modinfo($COURSE);
|
|
|
|
$mods = $modinfo->get_cms();
|
|
|
|
|
|
|
|
$modules = array();
|
|
|
|
$sections = $modinfo->get_section_info_all();
|
|
|
|
for ($i = 0; $i <= count($sections) - 1; $i++) {
|
|
|
|
// should always be true
|
|
|
|
if (isset($sections[$i])) {
|
|
|
|
$section = $sections[$i];
|
|
|
|
if ($section->sequence) {
|
|
|
|
switch ($COURSE->format) {
|
|
|
|
case "topics":
|
|
|
|
$sectionlabel = $strtopic;
|
|
|
|
break;
|
|
|
|
case "weeks":
|
|
|
|
$sectionlabel = $strweek;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$sectionlabel = $strsection;
|
|
|
|
}
|
|
|
|
|
|
|
|
$sectionmods = explode(",", $section->sequence);
|
|
|
|
foreach ($sectionmods as $sectionmod) {
|
|
|
|
if (empty($mods[$sectionmod])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$mod = $mods[$sectionmod];
|
|
|
|
$instance = $DB->get_record($mod->modname, array('id' => $mod->instance));
|
|
|
|
if ($grade_items = grade_get_grade_items_for_activity($mod)) {
|
|
|
|
$mod_item = grade_get_grades($COURSE->id, 'mod', $mod->modname, $mod->instance);
|
|
|
|
$item = reset($mod_item->items);
|
|
|
|
if (isset($item->grademax)){
|
|
|
|
$modules[$mod->id] = $sectionlabel . ' ' . $section->section . ' : ' . $instance->name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $modules;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Search through all the modules for grade data for mod_form.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function certificate_get_grade_options() {
|
|
|
|
$gradeoptions['0'] = get_string('no');
|
|
|
|
$gradeoptions['1'] = get_string('coursegrade', 'certificate');
|
|
|
|
|
|
|
|
return $gradeoptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Search through all the modules for grade dates for mod_form.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function certificate_get_date_options() {
|
|
|
|
$dateoptions['0'] = get_string('no');
|
|
|
|
$dateoptions['1'] = get_string('issueddate', 'certificate');
|
|
|
|
$dateoptions['2'] = get_string('completiondate', 'certificate');
|
|
|
|
|
|
|
|
return $dateoptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetch all grade categories from the specified course.
|
|
|
|
*
|
|
|
|
* @param int $courseid the course id
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function certificate_get_grade_categories($courseid) {
|
|
|
|
$grade_category_options = array();
|
|
|
|
|
|
|
|
if ($grade_categories = grade_category::fetch_all(array('courseid' => $courseid))) {
|
|
|
|
foreach ($grade_categories as $grade_category) {
|
|
|
|
if (!$grade_category->is_course_category()) {
|
|
|
|
$grade_category_options[-$grade_category->id] = get_string('category') . ' : ' . $grade_category->get_name();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $grade_category_options;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the course outcomes for for mod_form print outcome.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function certificate_get_outcomes() {
|
|
|
|
global $COURSE;
|
|
|
|
|
|
|
|
// get all outcomes in course
|
|
|
|
$grade_seq = new grade_tree($COURSE->id, false, true, '', false);
|
|
|
|
if ($grade_items = $grade_seq->items) {
|
|
|
|
// list of item for menu
|
|
|
|
$printoutcome = array();
|
|
|
|
foreach ($grade_items as $grade_item) {
|
|
|
|
if (isset($grade_item->outcomeid)){
|
|
|
|
$itemmodule = $grade_item->itemmodule;
|
|
|
|
$printoutcome[$grade_item->id] = $itemmodule . ': ' . $grade_item->get_name();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isset($printoutcome)) {
|
|
|
|
$outcomeoptions['0'] = get_string('no');
|
|
|
|
foreach ($printoutcome as $key => $value) {
|
|
|
|
$outcomeoptions[$key] = $value;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$outcomeoptions['0'] = get_string('nooutcomes', 'certificate');
|
|
|
|
}
|
|
|
|
|
|
|
|
return $outcomeoptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get certificate types indexed and sorted by name for mod_form.
|
|
|
|
*
|
|
|
|
* @return array containing the certificate type
|
|
|
|
*/
|
|
|
|
function certificate_types() {
|
|
|
|
$types = array();
|
|
|
|
$names = get_list_of_plugins('mod/certificate/type');
|
|
|
|
$sm = get_string_manager();
|
|
|
|
foreach ($names as $name) {
|
|
|
|
if ($sm->string_exists('type'.$name, 'certificate')) {
|
|
|
|
$types[$name] = get_string('type'.$name, 'certificate');
|
|
|
|
} else {
|
|
|
|
$types[$name] = ucfirst($name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
asort($types);
|
|
|
|
return $types;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get images for mod_form.
|
|
|
|
*
|
|
|
|
* @param string $type the image type
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function certificate_get_images($type) {
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
switch($type) {
|
|
|
|
case CERT_IMAGE_BORDER :
|
|
|
|
$path = "$CFG->dirroot/mod/certificate/pix/borders";
|
|
|
|
$uploadpath = "$CFG->dataroot/mod/certificate/pix/borders";
|
|
|
|
break;
|
|
|
|
case CERT_IMAGE_SEAL :
|
|
|
|
$path = "$CFG->dirroot/mod/certificate/pix/seals";
|
|
|
|
$uploadpath = "$CFG->dataroot/mod/certificate/pix/seals";
|
|
|
|
break;
|
|
|
|
case CERT_IMAGE_SIGNATURE :
|
|
|
|
$path = "$CFG->dirroot/mod/certificate/pix/signatures";
|
|
|
|
$uploadpath = "$CFG->dataroot/mod/certificate/pix/signatures";
|
|
|
|
break;
|
|
|
|
case CERT_IMAGE_WATERMARK :
|
|
|
|
$path = "$CFG->dirroot/mod/certificate/pix/watermarks";
|
|
|
|
$uploadpath = "$CFG->dataroot/mod/certificate/pix/watermarks";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// If valid path
|
|
|
|
if (!empty($path)) {
|
|
|
|
$options = array();
|
|
|
|
$options += certificate_scan_image_dir($path);
|
|
|
|
$options += certificate_scan_image_dir($uploadpath);
|
|
|
|
|
|
|
|
// Sort images
|
|
|
|
ksort($options);
|
|
|
|
|
|
|
|
// Add the 'no' option to the top of the array
|
|
|
|
$options = array_merge(array('0' => get_string('no')), $options);
|
|
|
|
|
|
|
|
return $options;
|
|
|
|
} else {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prepare to print an activity grade.
|
|
|
|
*
|
|
|
|
* @param stdClass $course
|
|
|
|
* @param int $moduleid
|
|
|
|
* @param int $userid
|
|
|
|
* @return stdClass|bool return the mod object if it exists, false otherwise
|
|
|
|
*/
|
|
|
|
function certificate_get_mod_grade($course, $moduleid, $userid) {
|
|
|
|
global $DB;
|
|
|
|
|
|
|
|
$cm = $DB->get_record('course_modules', array('id' => $moduleid));
|
|
|
|
$module = $DB->get_record('modules', array('id' => $cm->module));
|
|
|
|
|
|
|
|
$grade_item = grade_get_grades($course->id, 'mod', $module->name, $cm->instance, $userid);
|
|
|
|
if (!empty($grade_item)) {
|
|
|
|
$item = new grade_item();
|
|
|
|
$itemproperties = reset($grade_item->items);
|
|
|
|
foreach ($itemproperties as $key => $value) {
|
|
|
|
$item->$key = $value;
|
|
|
|
}
|
|
|
|
$modinfo = new stdClass;
|
|
|
|
$modname = $DB->get_field($module->name, 'name', array('id' => $cm->instance));
|
|
|
|
$modinfo->name = format_string($modname, true, array('context' => context_module::instance($cm->id)));
|
|
|
|
$grade = $item->grades[$userid]->grade;
|
|
|
|
$item->gradetype = GRADE_TYPE_VALUE;
|
|
|
|
$item->courseid = $course->id;
|
|
|
|
|
|
|
|
$modinfo->points = grade_format_gradevalue($grade, $item, true, GRADE_DISPLAY_TYPE_REAL, $decimals = 2);
|
|
|
|
$modinfo->percentage = grade_format_gradevalue($grade, $item, true, GRADE_DISPLAY_TYPE_PERCENTAGE, $decimals = 2);
|
|
|
|
$modinfo->letter = grade_format_gradevalue($grade, $item, true, GRADE_DISPLAY_TYPE_LETTER, $decimals = 0);
|
|
|
|
|
|
|
|
if ($grade) {
|
|
|
|
$modinfo->dategraded = $item->grades[$userid]->dategraded;
|
|
|
|
} else {
|
|
|
|
$modinfo->dategraded = time();
|
|
|
|
}
|
|
|
|
return $modinfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the date to display for the certificate.
|
|
|
|
*
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $certrecord
|
|
|
|
* @param stdClass $course
|
|
|
|
* @param int $userid
|
|
|
|
* @return string the date
|
|
|
|
*/
|
|
|
|
function certificate_get_date($certificate, $certrecord, $course, $userid = null) {
|
|
|
|
global $DB, $USER;
|
|
|
|
|
|
|
|
if (empty($userid)) {
|
|
|
|
$userid = $USER->id;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set certificate date to current time, can be overwritten later
|
|
|
|
$date = $certrecord->timecreated;
|
|
|
|
|
|
|
|
if ($certificate->printdate == '2') {
|
|
|
|
// Get the enrolment end date
|
|
|
|
$sql = "SELECT MAX(c.timecompleted) as timecompleted
|
|
|
|
FROM {course_completions} c
|
|
|
|
WHERE c.userid = :userid
|
|
|
|
AND c.course = :courseid";
|
|
|
|
if ($timecompleted = $DB->get_record_sql($sql, array('userid' => $userid, 'courseid' => $course->id))) {
|
|
|
|
if (!empty($timecompleted->timecompleted)) {
|
|
|
|
$date = $timecompleted->timecompleted;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ($certificate->printdate > 2) {
|
|
|
|
if ($modinfo = certificate_get_mod_grade($course, $certificate->printdate, $userid)) {
|
|
|
|
$date = $modinfo->dategraded;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($certificate->printdate > 0) {
|
|
|
|
if ($certificate->datefmt == 1) {
|
|
|
|
$certificatedate = userdate($date, '%B %d, %Y');
|
|
|
|
} else if ($certificate->datefmt == 2) {
|
|
|
|
$suffix = certificate_get_ordinal_number_suffix(userdate($date, '%d'));
|
|
|
|
$certificatedate = userdate($date, '%B %d' . $suffix . ', %Y');
|
|
|
|
} else if ($certificate->datefmt == 3) {
|
|
|
|
$certificatedate = userdate($date, '%d de %B de %Y');
|
|
|
|
} else if ($certificate->datefmt == 4) {
|
|
|
|
$certificatedate = userdate($date, '%B %Y');
|
|
|
|
} else if ($certificate->datefmt == 5) {
|
|
|
|
$certificatedate = userdate($date, get_string('strftimedate', 'langconfig'));
|
|
|
|
}
|
|
|
|
|
|
|
|
return $certificatedate;
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper function to return the suffix of the day of
|
|
|
|
* the month, eg 'st' if it is the 1st of the month.
|
|
|
|
*
|
|
|
|
* @param int the day of the month
|
|
|
|
* @return string the suffix.
|
|
|
|
*/
|
|
|
|
function certificate_get_ordinal_number_suffix($day) {
|
|
|
|
if (!in_array(($day % 100), array(11, 12, 13))) {
|
|
|
|
switch ($day % 10) {
|
|
|
|
// Handle 1st, 2nd, 3rd
|
|
|
|
case 1: return 'st';
|
|
|
|
case 2: return 'nd';
|
|
|
|
case 3: return 'rd';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 'th';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the grade to display for the certificate.
|
|
|
|
*
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $course
|
|
|
|
* @param int $userid
|
|
|
|
* @param bool $valueonly if true return only the points, %age, or letter with no prefix
|
|
|
|
* @return string the grade result
|
|
|
|
*/
|
|
|
|
function certificate_get_grade($certificate, $course, $userid = null, $valueonly = false) {
|
|
|
|
global $USER;
|
|
|
|
|
|
|
|
if (empty($userid)) {
|
|
|
|
$userid = $USER->id;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($certificate->printgrade > 0) {
|
|
|
|
if ($certificate->printgrade == 1) {
|
|
|
|
if ($course_item = grade_item::fetch_course_item($course->id)) {
|
|
|
|
// Check we want to add a prefix to the grade.
|
|
|
|
$strprefix = '';
|
|
|
|
if (!$valueonly) {
|
|
|
|
$strprefix = get_string('coursegrade', 'certificate') . ': ';
|
|
|
|
}
|
|
|
|
|
|
|
|
$grade = new grade_grade(array('itemid' => $course_item->id, 'userid' => $userid));
|
|
|
|
$course_item->gradetype = GRADE_TYPE_VALUE;
|
|
|
|
$coursegrade = new stdClass;
|
|
|
|
$coursegrade->points = grade_format_gradevalue($grade->finalgrade, $course_item, true, GRADE_DISPLAY_TYPE_REAL, $decimals = 2);
|
|
|
|
$coursegrade->percentage = grade_format_gradevalue($grade->finalgrade, $course_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE, $decimals = 2);
|
|
|
|
$coursegrade->letter = grade_format_gradevalue($grade->finalgrade, $course_item, true, GRADE_DISPLAY_TYPE_LETTER, $decimals = 0);
|
|
|
|
|
|
|
|
if ($certificate->gradefmt == 1) {
|
|
|
|
$grade = $strprefix . $coursegrade->percentage;
|
|
|
|
} else if ($certificate->gradefmt == 2) {
|
|
|
|
$grade = $strprefix . $coursegrade->points;
|
|
|
|
} else if ($certificate->gradefmt == 3) {
|
|
|
|
$grade = $strprefix . $coursegrade->letter;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $grade;
|
|
|
|
}
|
|
|
|
} else { // Print the mod grade
|
|
|
|
if ($modinfo = certificate_get_mod_grade($course, $certificate->printgrade, $userid)) {
|
|
|
|
// Check we want to add a prefix to the grade.
|
|
|
|
$strprefix = '';
|
|
|
|
if (!$valueonly) {
|
|
|
|
$strprefix = $modinfo->name . ' ' . get_string('grade', 'certificate') . ': ';
|
|
|
|
}
|
|
|
|
if ($certificate->gradefmt == 1) {
|
|
|
|
$grade = $strprefix . $modinfo->percentage;
|
|
|
|
} else if ($certificate->gradefmt == 2) {
|
|
|
|
$grade = $strprefix . $modinfo->points;
|
|
|
|
} else if ($certificate->gradefmt == 3) {
|
|
|
|
$grade = $strprefix . $modinfo->letter;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $grade;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ($certificate->printgrade < 0) { // Must be a category id.
|
|
|
|
if ($category_item = grade_item::fetch(array('itemtype' => 'category', 'iteminstance' => -$certificate->printgrade))) {
|
|
|
|
$category_item->gradetype = GRADE_TYPE_VALUE;
|
|
|
|
|
|
|
|
$grade = new grade_grade(array('itemid' => $category_item->id, 'userid' => $userid));
|
|
|
|
|
|
|
|
$category_grade = new stdClass;
|
|
|
|
$category_grade->points = grade_format_gradevalue($grade->finalgrade, $category_item, true, GRADE_DISPLAY_TYPE_REAL, $decimals = 2);
|
|
|
|
$category_grade->percentage = grade_format_gradevalue($grade->finalgrade, $category_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE, $decimals = 2);
|
|
|
|
$category_grade->letter = grade_format_gradevalue($grade->finalgrade, $category_item, true, GRADE_DISPLAY_TYPE_LETTER, $decimals = 0);
|
|
|
|
|
|
|
|
if ($certificate->gradefmt == 1) {
|
|
|
|
$formattedgrade = $category_grade->percentage;
|
|
|
|
} else if ($certificate->gradefmt == 2) {
|
|
|
|
$formattedgrade = $category_grade->points;
|
|
|
|
} else if ($certificate->gradefmt == 3) {
|
|
|
|
$formattedgrade = $category_grade->letter;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $formattedgrade;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the outcome to display on the certificate
|
|
|
|
*
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $course
|
|
|
|
* @return string the outcome
|
|
|
|
*/
|
|
|
|
function certificate_get_outcome($certificate, $course) {
|
|
|
|
global $USER;
|
|
|
|
|
|
|
|
if ($certificate->printoutcome > 0) {
|
|
|
|
if ($grade_item = new grade_item(array('id' => $certificate->printoutcome))) {
|
|
|
|
$outcomeinfo = new stdClass;
|
|
|
|
$outcomeinfo->name = $grade_item->get_name();
|
|
|
|
$outcome = new grade_grade(array('itemid' => $grade_item->id, 'userid' => $USER->id));
|
|
|
|
$outcomeinfo->grade = grade_format_gradevalue($outcome->finalgrade, $grade_item, true, GRADE_DISPLAY_TYPE_REAL);
|
|
|
|
|
|
|
|
return $outcomeinfo->name . ': ' . $outcomeinfo->grade;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the code to display on the certificate.
|
|
|
|
*
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $certrecord
|
|
|
|
* @return string the code
|
|
|
|
*/
|
|
|
|
function certificate_get_code($certificate, $certrecord) {
|
|
|
|
if ($certificate->printnumber) {
|
|
|
|
return $certrecord->code;
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends text to output given the following params.
|
|
|
|
*
|
|
|
|
* @param stdClass $pdf
|
|
|
|
* @param int $x horizontal position
|
|
|
|
* @param int $y vertical position
|
|
|
|
* @param char $align L=left, C=center, R=right
|
|
|
|
* @param string $font any available font in font directory
|
|
|
|
* @param char $style ''=normal, B=bold, I=italic, U=underline
|
|
|
|
* @param int $size font size in points
|
|
|
|
* @param string $text the text to print
|
|
|
|
* @param int $width horizontal dimension of text block
|
|
|
|
*/
|
|
|
|
function certificate_print_text($pdf, $x, $y, $align, $font='freeserif', $style, $size = 10, $text, $width = 0) {
|
|
|
|
$pdf->setFont($font, $style, $size);
|
|
|
|
$pdf->SetXY($x, $y);
|
|
|
|
$pdf->writeHTMLCell($width, 0, '', '', $text, 0, 0, 0, true, $align);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates rectangles for line border for A4 size paper.
|
|
|
|
*
|
|
|
|
* @param stdClass $pdf
|
|
|
|
* @param stdClass $certificate
|
|
|
|
*/
|
|
|
|
function certificate_draw_frame($pdf, $certificate) {
|
|
|
|
if ($certificate->bordercolor > 0) {
|
|
|
|
if ($certificate->bordercolor == 1) {
|
|
|
|
$color = array(0, 0, 0); // black
|
|
|
|
}
|
|
|
|
if ($certificate->bordercolor == 2) {
|
|
|
|
$color = array(153, 102, 51); // brown
|
|
|
|
}
|
|
|
|
if ($certificate->bordercolor == 3) {
|
|
|
|
$color = array(0, 51, 204); // blue
|
|
|
|
}
|
|
|
|
if ($certificate->bordercolor == 4) {
|
|
|
|
$color = array(0, 180, 0); // green
|
|
|
|
}
|
|
|
|
switch ($certificate->orientation) {
|
|
|
|
case 'L':
|
|
|
|
// create outer line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 1.5, 'color' => $color));
|
|
|
|
$pdf->Rect(10, 10, 277, 190);
|
|
|
|
// create middle line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 0.2, 'color' => $color));
|
|
|
|
$pdf->Rect(13, 13, 271, 184);
|
|
|
|
// create inner line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 1.0, 'color' => $color));
|
|
|
|
$pdf->Rect(16, 16, 265, 178);
|
|
|
|
break;
|
|
|
|
case 'P':
|
|
|
|
// create outer line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 1.5, 'color' => $color));
|
|
|
|
$pdf->Rect(10, 10, 190, 277);
|
|
|
|
// create middle line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 0.2, 'color' => $color));
|
|
|
|
$pdf->Rect(13, 13, 184, 271);
|
|
|
|
// create inner line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 1.0, 'color' => $color));
|
|
|
|
$pdf->Rect(16, 16, 178, 265);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates rectangles for line border for letter size paper.
|
|
|
|
*
|
|
|
|
* @param stdClass $pdf
|
|
|
|
* @param stdClass $certificate
|
|
|
|
*/
|
|
|
|
function certificate_draw_frame_letter($pdf, $certificate) {
|
|
|
|
if ($certificate->bordercolor > 0) {
|
|
|
|
if ($certificate->bordercolor == 1) {
|
|
|
|
$color = array(0, 0, 0); //black
|
|
|
|
}
|
|
|
|
if ($certificate->bordercolor == 2) {
|
|
|
|
$color = array(153, 102, 51); //brown
|
|
|
|
}
|
|
|
|
if ($certificate->bordercolor == 3) {
|
|
|
|
$color = array(0, 51, 204); //blue
|
|
|
|
}
|
|
|
|
if ($certificate->bordercolor == 4) {
|
|
|
|
$color = array(0, 180, 0); //green
|
|
|
|
}
|
|
|
|
switch ($certificate->orientation) {
|
|
|
|
case 'L':
|
|
|
|
// create outer line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 4.25, 'color' => $color));
|
|
|
|
$pdf->Rect(28, 28, 736, 556);
|
|
|
|
// create middle line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 0.2, 'color' => $color));
|
|
|
|
$pdf->Rect(37, 37, 718, 538);
|
|
|
|
// create inner line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 2.8, 'color' => $color));
|
|
|
|
$pdf->Rect(46, 46, 700, 520);
|
|
|
|
break;
|
|
|
|
case 'P':
|
|
|
|
// create outer line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 1.5, 'color' => $color));
|
|
|
|
$pdf->Rect(25, 20, 561, 751);
|
|
|
|
// create middle line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 0.2, 'color' => $color));
|
|
|
|
$pdf->Rect(40, 35, 531, 721);
|
|
|
|
// create inner line border in selected color
|
|
|
|
$pdf->SetLineStyle(array('width' => 1.0, 'color' => $color));
|
|
|
|
$pdf->Rect(51, 46, 509, 699);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prints border images from the borders folder in PNG or JPG formats.
|
|
|
|
*
|
|
|
|
* @param stdClass $pdf
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param string $type the type of image
|
|
|
|
* @param int $x x position
|
|
|
|
* @param int $y y position
|
|
|
|
* @param int $w the width
|
|
|
|
* @param int $h the height
|
|
|
|
*/
|
|
|
|
function certificate_print_image($pdf, $certificate, $type, $x, $y, $w, $h, $cert_date = null) {
|
|
|
|
global $CFG, $DB;
|
|
|
|
|
|
|
|
switch($type) {
|
|
|
|
case CERT_IMAGE_BORDER :
|
|
|
|
$attr = 'borderstyle';
|
|
|
|
$path = "$CFG->dirroot/mod/certificate/pix/$type/$certificate->borderstyle";
|
|
|
|
$uploadpath = "$CFG->dataroot/mod/certificate/pix/$type/$certificate->borderstyle";
|
|
|
|
break;
|
|
|
|
case CERT_IMAGE_SEAL :
|
|
|
|
$attr = 'printseal';
|
|
|
|
$path = "$CFG->dirroot/mod/certificate/pix/$type/$certificate->printseal";
|
|
|
|
$uploadpath = "$CFG->dataroot/mod/certificate/pix/$type/$certificate->printseal";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CERT_IMAGE_SIGNATURE :
|
|
|
|
$attr = 'printsignature';
|
|
|
|
|
|
|
|
if($certificate->printsignature == 'automatica.jpeg' && ($cert_date != null)) {
|
|
|
|
$record = $DB->get_record_sql(
|
|
|
|
'SELECT nome_arquivo ' .
|
|
|
|
'FROM {ilb_assinaturas} ' .
|
|
|
|
'WHERE ? BETWEEN dat_ini_validade AND coalesce(dat_fim_validade, extract(epoch from current_timestamp))',
|
|
|
|
[$cert_date]
|
|
|
|
);
|
|
|
|
|
|
|
|
$arq_assinatura = $record->nome_arquivo;
|
|
|
|
}else {
|
|
|
|
$arq_assinatura = $certificate->printsignature;
|
|
|
|
}
|
|
|
|
$path = "$CFG->dirroot/mod/certificate/pix/$type/$arq_assinatura";
|
|
|
|
$uploadpath = "$CFG->dataroot/mod/certificate/pix/$type/$arq_assinatura";
|
|
|
|
|
|
|
|
break;
|
|
|
|
case CERT_IMAGE_WATERMARK :
|
|
|
|
$attr = 'printwmark';
|
|
|
|
$path = "$CFG->dirroot/mod/certificate/pix/$type/$certificate->printwmark";
|
|
|
|
$uploadpath = "$CFG->dataroot/mod/certificate/pix/$type/$certificate->printwmark";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Has to be valid
|
|
|
|
if (!empty($path)) {
|
|
|
|
switch ($certificate->$attr) {
|
|
|
|
case '0' :
|
|
|
|
case '' :
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
if (file_exists($path)) {
|
|
|
|
$pdf->Image($path, $x, $y, $w, $h);
|
|
|
|
}
|
|
|
|
if (file_exists($uploadpath)) {
|
|
|
|
$pdf->Image($uploadpath, $x, $y, $w, $h);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function custom_random_string($length=15) {
|
|
|
|
$pool = 'ABCDEFGHJKMNOPQRSTUVWXYZ';
|
|
|
|
$pool .= 'abcdefghjkmnopqrstuvwxyz';
|
|
|
|
$pool .= '0123456789';
|
|
|
|
$poollen = strlen($pool);
|
|
|
|
$string = '';
|
|
|
|
for($i=0; $i < $length; $i++) {
|
|
|
|
$string .= substr($pool, (mt_rand()%($poollen)), 1);
|
|
|
|
}
|
|
|
|
return $string;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a 10-digit code of random letters and numbers.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function certificate_generate_code() {
|
|
|
|
global $DB;
|
|
|
|
|
|
|
|
$uniquecodefound = false;
|
|
|
|
$code = custom_random_string(10);
|
|
|
|
while (!$uniquecodefound) {
|
|
|
|
if (!$DB->record_exists('certificate_issues', array('code' => $code))) {
|
|
|
|
$uniquecodefound = true;
|
|
|
|
} else {
|
|
|
|
$code = custom_random_string(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $code;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Scans directory for valid images
|
|
|
|
*
|
|
|
|
* @param string the path
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function certificate_scan_image_dir($path) {
|
|
|
|
// Array to store the images
|
|
|
|
$options = array();
|
|
|
|
|
|
|
|
// Start to scan directory
|
|
|
|
if (is_dir($path)) {
|
|
|
|
$iterator = new DirectoryIterator($path);
|
|
|
|
foreach ($iterator as $fileinfo) {
|
|
|
|
$filename = $fileinfo->getFilename();
|
|
|
|
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
|
|
|
if ($fileinfo->isFile() && in_array($extension, array('png', 'jpg', 'jpeg'))) {
|
|
|
|
$options[$filename] = pathinfo($filename, PATHINFO_FILENAME);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $options;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get normalised certificate file name without file extension.
|
|
|
|
*
|
|
|
|
* @param stdClass $certificate
|
|
|
|
* @param stdClass $cm
|
|
|
|
* @param stdClass $course
|
|
|
|
* @return string file name without extension
|
|
|
|
*/
|
|
|
|
function certificate_get_certificate_filename($certificate, $cm, $course) {
|
|
|
|
$coursecontext = context_course::instance($course->id);
|
|
|
|
$coursename = format_string($course->shortname, true, array('context' => $coursecontext));
|
|
|
|
|
|
|
|
$context = context_module::instance($cm->id);
|
|
|
|
$name = format_string($certificate->name, true, array('context' => $context));
|
|
|
|
|
|
|
|
$filename = $coursename . '_' . $name;
|
|
|
|
$filename = core_text::entities_to_utf8($filename);
|
|
|
|
$filename = strip_tags($filename);
|
|
|
|
$filename = rtrim($filename, '.');
|
|
|
|
|
|
|
|
// Ampersand is not a valid filename char, let's replace it with something else.
|
|
|
|
$filename = str_replace('&', '_', $filename);
|
|
|
|
|
|
|
|
$filename = clean_filename($filename);
|
|
|
|
|
|
|
|
if (empty($filename)) {
|
|
|
|
// This is weird, but we need some file name.
|
|
|
|
$filename = 'certificate';
|
|
|
|
}
|
|
|
|
|
|
|
|
return $filename;
|
|
|
|
}
|