. /** * Certificate module core interaction API * * @package mod_certificate * @copyright Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot.'/mod/certificate/locallib.php'); /** * Add certificate instance. * * @param stdClass $certificate * @return int new certificate instance id */ function certificate_add_instance($certificate) { global $DB; // Create the certificate. $certificate->timecreated = time(); $certificate->timemodified = $certificate->timecreated; return $DB->insert_record('certificate', $certificate); } /** * Update certificate instance. * * @param stdClass $certificate * @return bool true */ function certificate_update_instance($certificate) { global $DB; // Update the certificate. $certificate->timemodified = time(); $certificate->id = $certificate->instance; return $DB->update_record('certificate', $certificate); } /** * Given an ID of an instance of this module, * this function will permanently delete the instance * and any data that depends on it. * * @param int $id * @return bool true if successful */ function certificate_delete_instance($id) { global $DB; // Ensure the certificate exists if (!$certificate = $DB->get_record('certificate', array('id' => $id))) { return false; } // Prepare file record object if (!$cm = get_coursemodule_from_instance('certificate', $id)) { return false; } $result = true; $DB->delete_records('certificate_issues', array('certificateid' => $id)); if (!$DB->delete_records('certificate', array('id' => $id))) { $result = false; } // Delete any files associated with the certificate $context = context_module::instance($cm->id); $fs = get_file_storage(); $fs->delete_area_files($context->id); return $result; } /** * This function is used by the reset_course_userdata function in moodlelib. * This function will remove all posts from the specified certificate * and clean up any related data. * * Written by Jean-Michel Vedrine * * @param $data the data submitted from the reset course. * @return array status array */ function certificate_reset_userdata($data) { global $DB; $componentstr = get_string('modulenameplural', 'certificate'); $status = array(); if (!empty($data->reset_certificate)) { $sql = "SELECT cert.id FROM {certificate} cert WHERE cert.course = :courseid"; $params = array('courseid' => $data->courseid); $certificates = $DB->get_records_sql($sql, $params); $fs = get_file_storage(); if ($certificates) { foreach ($certificates as $certid => $unused) { if (!$cm = get_coursemodule_from_instance('certificate', $certid)) { continue; } $context = context_module::instance($cm->id); $fs->delete_area_files($context->id, 'mod_certificate', 'issue'); } } $DB->delete_records_select('certificate_issues', "certificateid IN ($sql)", $params); $status[] = array('component' => $componentstr, 'item' => get_string('removecert', 'certificate'), 'error' => false); } // Updating dates - shift may be negative too if ($data->timeshift) { shift_course_mod_dates('certificate', array('timeopen', 'timeclose'), $data->timeshift, $data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false); } return $status; } /** * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the certificate. * * Written by Jean-Michel Vedrine * * @param $mform form passed by reference */ function certificate_reset_course_form_definition(&$mform) { $mform->addElement('header', 'certificateheader', get_string('modulenameplural', 'certificate')); $mform->addElement('advcheckbox', 'reset_certificate', get_string('deletissuedcertificates', 'certificate')); } /** * Course reset form defaults. * * Written by Jean-Michel Vedrine * * @param stdClass $course * @return array */ function certificate_reset_course_form_defaults($course) { return array('reset_certificate' => 1); } /** * Returns information about received certificate. * Used for user activity reports. * * @param stdClass $course * @param stdClass $user * @param stdClass $mod * @param stdClass $certificate * @return stdClass the user outline object */ function certificate_user_outline($course, $user, $mod, $certificate) { global $DB; $result = new stdClass; if ($issue = $DB->get_record('certificate_issues', array('certificateid' => $certificate->id, 'userid' => $user->id))) { $result->info = get_string('issued', 'certificate'); $result->time = $issue->timecreated; } else { $result->info = get_string('notissued', 'certificate'); } return $result; } /** * Returns information about received certificate. * Used for user activity reports. * * @param stdClass $course * @param stdClass $user * @param stdClass $mod * @param stdClass $certificate * @return string the user complete information */ function certificate_user_complete($course, $user, $mod, $certificate) { global $DB, $OUTPUT, $CFG; require_once($CFG->dirroot.'/mod/certificate/locallib.php'); if ($issue = $DB->get_record('certificate_issues', array('certificateid' => $certificate->id, 'userid' => $user->id))) { echo $OUTPUT->box_start(); echo get_string('issued', 'certificate') . ": "; echo userdate($issue->timecreated); $cm = get_coursemodule_from_instance('certificate', $certificate->id, $course->id); certificate_print_user_files($certificate, $user->id, context_module::instance($cm->id)->id); echo '
'; echo $OUTPUT->box_end(); } else { print_string('notissuedyet', 'certificate'); } } /** * Must return an array of user records (all data) who are participants * for a given instance of certificate. * * @param int $certificateid * @return stdClass list of participants */ function certificate_get_participants($certificateid) { global $DB; $sql = "SELECT DISTINCT u.id, u.id FROM {user} u, {certificate_issues} a WHERE a.certificateid = :certificateid AND u.id = a.userid"; return $DB->get_records_sql($sql, array('certificateid' => $certificateid)); } /** * @uses FEATURE_GROUPS * @uses FEATURE_GROUPINGS * @uses FEATURE_GROUPMEMBERSONLY * @uses FEATURE_MOD_INTRO * @uses FEATURE_COMPLETION_TRACKS_VIEWS * @uses FEATURE_GRADE_HAS_GRADE * @uses FEATURE_GRADE_OUTCOMES * @param string $feature FEATURE_xx constant for requested feature * @return mixed True if module supports feature, null if doesn't know */ function certificate_supports($feature) { switch ($feature) { case FEATURE_GROUPS: return true; case FEATURE_GROUPINGS: return true; case FEATURE_GROUPMEMBERSONLY: return true; case FEATURE_MOD_INTRO: return true; case FEATURE_COMPLETION_TRACKS_VIEWS: return true; case FEATURE_BACKUP_MOODLE2: return true; default: return null; } } /** * Serves certificate issues and other files. * * @param stdClass $course * @param stdClass $cm * @param stdClass $context * @param string $filearea * @param array $args * @param bool $forcedownload * @return bool|nothing false if file not found, does not return anything if found - just send the file */ function certificate_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { global $CFG, $DB, $USER; if ($context->contextlevel != CONTEXT_MODULE) { return false; } if (!$certificate = $DB->get_record('certificate', array('id' => $cm->instance))) { return false; } require_login($course, false, $cm); require_once($CFG->libdir.'/filelib.php'); $certrecord = (int)array_shift($args); if (!$certrecord = $DB->get_record('certificate_issues', array('id' => $certrecord))) { return false; } $canmanagecertificate = has_capability('mod/certificate:manage', $context); if ($USER->id != $certrecord->userid and !$canmanagecertificate) { return false; } if ($filearea === 'issue') { $relativepath = implode('/', $args); $fullpath = "/{$context->id}/mod_certificate/issue/$certrecord->id/$relativepath"; $fs = get_file_storage(); if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { return false; } send_stored_file($file, 0, 0, true); // download MUST be forced - security! } else if ($filearea === 'onthefly') { require_once($CFG->dirroot.'/mod/certificate/locallib.php'); require_once("$CFG->libdir/pdflib.php"); if (!$certificate = $DB->get_record('certificate', array('id' => $certrecord->certificateid))) { return false; } if ($certificate->requiredtime && !$canmanagecertificate) { if (certificate_get_course_time($course->id) < ($certificate->requiredtime * 60)) { return false; } } // Load the specific certificate type. It will fill the $pdf var. require("$CFG->dirroot/mod/certificate/type/$certificate->certificatetype/certificate.php"); $filename = certificate_get_certificate_filename($certificate, $cm, $course) . '.pdf'; $filecontents = $pdf->Output('', 'S'); send_file($filecontents, $filename, 0, 0, true, true, 'application/pdf'); } } /** * Used for course participation report (in case certificate is added). * * @return array */ function certificate_get_view_actions() { return array('view', 'view all', 'view report'); } /** * Used for course participation report (in case certificate is added). * * @return array */ function certificate_get_post_actions() { return array('received'); } // TODO mover para outro local, usado também em certificado function certificate_obtemCampoCustomizadoCurso($idCurso, $nomeCampo) { global $DB; $sql = " SELECT d.value, f.configdata::json->>'options' as options FROM mdl_course c JOIN mdl_context ctx ON c.id = ? AND ctx.contextlevel = 50 AND ctx.instanceid = c.id JOIN mdl_customfield_field f ON f.shortname = ? JOIN mdl_customfield_data d ON d.fieldid = f.id AND d.contextid = ctx.id "; $valueArray = $DB->get_record_sql($sql, [$idCurso, $nomeCampo]); if($valueArray) { $value = $valueArray->value; $options = $valueArray->options; if($options == null) { return $value; } else { $optionsArray = preg_split("/\s*\n\s*/", trim($options)); return $optionsArray[$value-1]; } } else { return ''; } } /** * Function to be run periodically according to the moodle cron * TODO:This needs to be done */ function certificate_cron () { global $DB; // $sql = "select distinct cm.id as cmid, c.*, ce.id as certificateid, ce.name as certificatename // from {certificate} ce // inner join {course} c on c.id = ce.course // inner join {course_modules} cm on cm.course = c.id and cm.instance = ce.id // where c.visible = 1 // order by c.id"; $sql = "select distinct cm.id as cmid, c.*, ce.id as certificateid, ce.name as certificatename from {certificate} ce inner join {course} c on c.id = ce.course inner join {course_modules} cm on cm.course = c.id and cm.instance = ce.id and cm.module = ? where c.visible = 1 order by c.id"; echo "\n\nGenerate certificates for user that has completed the course-------------------------\n"; $certmodule = $DB->get_record('modules', array('name' => 'certificate')); $courses = $DB->get_records_sql($sql, array($certmodule->id)); $sql = "select u.* from {course_completions} cc inner join {user} u on u.id = cc.userid where cc.course = ? and cc.timecompleted > 0 and cc.userid not in (select ci.userid from {certificate_issues} ci where ci.certificateid = ?) order by u.firstname"; foreach ($courses as $course) { echo " Processing course {$course->fullname}, certificate: {$course->certificatename}...\n"; $students = $DB->get_records_sql($sql, array($course->id, $course->certificateid)); $total = count($students); if ($total > 0) { echo " {$total} students without certificate found, generating certificates for them...\n"; $certificate = $DB->get_record('certificate', array('id' => $course->certificateid)); $cm = get_coursemodule_from_id('certificate', $course->cmid); foreach ($students as $student) { if (!$certificate->requiredtime or (certificate_get_course_time($course->id) >= ($certificate->requiredtime * 60))) { echo " generating issue certificate for {$student->firstname} {$student->lastname}..."; $certrecord = certificate_get_issue($course, $student, $certificate, $cm); $context = context_course::instance($course->id); $event = \mod_certificate\event\certificate_created::create(array( 'objectid' => $certrecord->id, 'context' => $context, 'other' => $certrecord) ); $event->trigger(); echo " Done! Certificate {$certrecord->code} generated!\n"; } else { echo " {$student->firstname} {$student->lastname} has not required course time. Skiped!\n"; } } } else { echo " No students without certificate found! Course skipped.\n"; } } return true; }