diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..b076f35 --- /dev/null +++ b/README.txt @@ -0,0 +1,24 @@ +QUICK INSTALL +============= + +There are two installation methods that are available. Follow one of these, then log into your Moodle site as an administrator and visit the notifications page to complete the install. + +==================== MOST RECOMMENDED METHOD - Git ==================== + +If you do not have git installed, please see the below link. Please note, it is not necessary to set up the SSH Keys. This is only needed if you are going to create a repository of your own on github.com. + +Information on installing git - http://help.github.com/set-up-git-redirect/ + +Once you have git installed, simply visit the Moodle mod directory and clone git://github.com/markn86/moodle-mod_certificate.git, remember to rename the folder to certificate if you do not specify this in the clone command + +Eg. Linux command line would be as follow - + +git clone git://github.com/markn86/moodle-mod_certificate.git certificate + +Use git pull to update this repository periodically to ensure you have the latest version. + +==================== Download the certificate module. ==================== + +Visit https://github.com/markn86/moodle-mod_certificate and download the zip, uncompress this zip and extract the folder. The folder will have a name similar to markn86-moodle-mod_certificate-c9fbadb, you MUST rename this to certificate. Place this folder in your mod folder in your Moodle directory. + +nb. The reason this is not the recommended method is due to the fact you have to over-write the contents of this folder to apply any future updates to the certificate module. In the above method there is a simple command to update the files. diff --git a/adminsetting.class.php b/adminsetting.class.php new file mode 100644 index 0000000..43f22f6 --- /dev/null +++ b/adminsetting.class.php @@ -0,0 +1,47 @@ +. + +/** + * Creates an upload form on the settings page + * + * @package mod + * @subpackage certificate + * @copyright Michael Avelar + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->libdir.'/adminlib.php'); + +/** +* Class extends admin setting class to allow/process an uploaded file +**/ +class mod_certificate_admin_setting_upload extends admin_setting_configtext { + public function __construct($name, $visiblename, $description, $defaultsetting) { + parent::__construct($name, $visiblename, $description, $defaultsetting, PARAM_RAW, 50); + } + + function output_html($data, $query='') { + // Create a dummy var for this field + $this->config_write($this->name, ''); + + return format_admin_setting($this, $this->visiblename, + html_writer::link(new moodle_url('/mod/certificate/upload_image.php'), get_string('upload')), + $this->description, true, '', null, $query); + } +} + +?> \ No newline at end of file diff --git a/backup/moodle2/backup_certificate_activity_task.class.php b/backup/moodle2/backup_certificate_activity_task.class.php new file mode 100644 index 0000000..07b8173 --- /dev/null +++ b/backup/moodle2/backup_certificate_activity_task.class.php @@ -0,0 +1,68 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->dirroot . '/mod/certificate/backup/moodle2/backup_certificate_stepslib.php'); // Because it exists (must) +require_once($CFG->dirroot . '/mod/certificate/backup/moodle2/backup_certificate_settingslib.php'); // Because it exists (optional) + +/** + * certificate backup task that provides all the settings and steps to perform one + * complete backup of the activity + */ +class backup_certificate_activity_task extends backup_activity_task { + + /** + * Define (add) particular settings this activity can have + */ + protected function define_my_settings() { + // No particular settings for this activity + } + + /** + * Define (add) particular steps this activity can have + */ + protected function define_my_steps() { + // Certificate only has one structure step + $this->add_step(new backup_certificate_activity_structure_step('certificate_structure', 'certificate.xml')); + } + + /** + * Code the transformations to perform in the activity in + * order to get transportable (encoded) links + */ + static public function encode_content_links($content) { + global $CFG; + + $base = preg_quote($CFG->wwwroot,"/"); + + // Link to the list of certificates + $search="/(".$base."\/mod\/certificate\/index.php\?id\=)([0-9]+)/"; + $content= preg_replace($search, '$@CERTIFICATEINDEX*$2@$', $content); + + // Link to certificate view by moduleid + $search="/(".$base."\/mod\/certificate\/view.php\?id\=)([0-9]+)/"; + $content= preg_replace($search, '$@CERTIFICATEVIEWBYID*$2@$', $content); + + return $content; + } +} diff --git a/backup/moodle2/backup_certificate_settingslib.php b/backup/moodle2/backup_certificate_settingslib.php new file mode 100644 index 0000000..8846b6d --- /dev/null +++ b/backup/moodle2/backup_certificate_settingslib.php @@ -0,0 +1,27 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + // This activity has no particular settings but the inherited from the generic + // backup_activity_task so here there isn't any class definition, like the ones + // existing in /backup/moodle2/backup_settingslib.php (activities section) diff --git a/backup/moodle2/backup_certificate_stepslib.php b/backup/moodle2/backup_certificate_stepslib.php new file mode 100644 index 0000000..143f2e4 --- /dev/null +++ b/backup/moodle2/backup_certificate_stepslib.php @@ -0,0 +1,74 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Define all the backup steps that will be used by the backup_certificate_activity_task + */ + +/** + * Define the complete certificate structure for backup, with file and id annotations + */ +class backup_certificate_activity_structure_step extends backup_activity_structure_step { + + protected function define_structure() { + + // To know if we are including userinfo + $userinfo = $this->get_setting_value('userinfo'); + + // Define each element separated + $certificate = new backup_nested_element('certificate', array('id'), array( + 'name', 'intro', 'introformat', 'emailteachers', 'emailothers', + 'savecert', 'reportcert', 'delivery', 'certificatetype', 'orientation', + 'borderstyle', 'bordercolor', 'printwmark', 'printdate', 'datefmt', 'printnumber', + 'printgrade', 'gradefmt', 'printoutcome', 'printhours', 'printteacher', 'customtext', + 'printsignature', 'printseal', 'timecreated', 'timemodified')); + + $issues = new backup_nested_element('issues'); + + $issue = new backup_nested_element('issue', array('id'), array( + 'certificateid', 'userid', 'timecreated', 'code')); + + // Build the tree + $certificate->add_child($issues); + $issues->add_child($issue); + + // Define sources + $certificate->set_source_table('certificate', array('id' => backup::VAR_ACTIVITYID)); + + // All the rest of elements only happen if we are including user info + if ($userinfo) { + $issue->set_source_table('certificate_issues', array('certificateid' => backup::VAR_PARENTID)); + } + + // Annotate the user id's where required. + $issue->annotate_ids('user', 'userid'); + + // Define file annotations + $certificate->annotate_files('mod_certificate', 'intro', null); // This file area hasn't itemid + $issue->annotate_files('mod_certificate', 'issue', 'id'); + + // Return the root element (certificate), wrapped into standard activity structure + return $this->prepare_activity_structure($certificate); + } +} diff --git a/backup/moodle2/restore_certificate_activity_task.class.php b/backup/moodle2/restore_certificate_activity_task.class.php new file mode 100644 index 0000000..2f88c0a --- /dev/null +++ b/backup/moodle2/restore_certificate_activity_task.class.php @@ -0,0 +1,148 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/mod/certificate/backup/moodle2/restore_certificate_stepslib.php'); // Because it exists (must) + +/** + * certificate restore task that provides all the settings and steps to perform one + * complete restore of the activity + */ +class restore_certificate_activity_task extends restore_activity_task { + + /** + * Define (add) particular settings this activity can have + */ + protected function define_my_settings() { + // No particular settings for this activity + } + + /** + * Define (add) particular steps this activity can have + */ + protected function define_my_steps() { + // Certificate only has one structure step + $this->add_step(new restore_certificate_activity_structure_step('certificate_structure', 'certificate.xml')); + } + + /** + * Define the contents in the activity that must be + * processed by the link decoder + */ + static public function define_decode_contents() { + $contents = array(); + + $contents[] = new restore_decode_content('certificate', array('intro'), 'certificate'); + + return $contents; + } + + /** + * Define the decoding rules for links belonging + * to the activity to be executed by the link decoder + */ + static public function define_decode_rules() { + $rules = array(); + + $rules[] = new restore_decode_rule('CERTIFICATEVIEWBYID', '/mod/certificate/view.php?id=$1', 'course_module'); + $rules[] = new restore_decode_rule('CERTIFICATEINDEX', '/mod/certificate/index.php?id=$1', 'course'); + + return $rules; + + } + + /** + * Define the restore log rules that will be applied + * by the {@link restore_logs_processor} when restoring + * certificate logs. It must return one array + * of {@link restore_log_rule} objects + */ + static public function define_restore_log_rules() { + $rules = array(); + + $rules[] = new restore_log_rule('certificate', 'add', 'view.php?id={course_module}', '{certificate}'); + $rules[] = new restore_log_rule('certificate', 'update', 'view.php?id={course_module}', '{certificate}'); + $rules[] = new restore_log_rule('certificate', 'view', 'view.php?id={course_module}', '{certificate}'); + $rules[] = new restore_log_rule('certificate', 'received', 'report.php?a={certificate}', '{certificate}'); + $rules[] = new restore_log_rule('certificate', 'view report', 'report.php?id={certificate}', '{certificate}'); + + return $rules; + } + + /** + * Define the restore log rules that will be applied + * by the {@link restore_logs_processor} when restoring + * course logs. It must return one array + * of {@link restore_log_rule} objects + * + * Note this rules are applied when restoring course logs + * by the restore final task, but are defined here at + * activity level. All them are rules not linked to any module instance (cmid = 0) + */ + static public function define_restore_log_rules_for_course() { + $rules = array(); + + // Fix old wrong uses (missing extension) + $rules[] = new restore_log_rule('certificate', 'view all', 'index.php?id={course}', null); + + return $rules; + } + + /* + * This function is called after all the activities in the backup have been restored. + * This allows us to get the new course module ids, as they may have been restored + * after the certificate module, meaning no id was available at the time. + */ + public function after_restore() { + global $DB; + + // Get the new module + $sql = "SELECT c.* + FROM {certificate} c + INNER JOIN {course_modules} cm + ON c.id = cm.instance + WHERE cm.id = :cmid"; + if ($certificate = $DB->get_record_sql($sql, (array('cmid'=>$this->get_moduleid())))) { + // A flag to check if we need to update the database or not + $update = false; + if ($certificate->printdate > 2) { // If greater than 2, then it is a grade item value + if ($newitem = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'course_module', $certificate->printdate)) { + $update = true; + $certificate->printdate = $newitem->newitemid; + } + } + if ($certificate->printgrade > 2) { + if ($newitem = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'course_module', $certificate->printgrade)) { + $update = true; + $certificate->printgrade = $newitem->newitemid; + } + } + if ($update) { + // Update the certificate + $DB->update_record('certificate', $certificate); + } + } + } +} diff --git a/backup/moodle2/restore_certificate_stepslib.php b/backup/moodle2/restore_certificate_stepslib.php new file mode 100644 index 0000000..5cf3bdf --- /dev/null +++ b/backup/moodle2/restore_certificate_stepslib.php @@ -0,0 +1,81 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Define all the restore steps that will be used by the restore_certificate_activity_task + */ + +/** + * Structure step to restore one certificate activity + */ +class restore_certificate_activity_structure_step extends restore_activity_structure_step { + + protected function define_structure() { + + $paths = array(); + $userinfo = $this->get_setting_value('userinfo'); + + $paths[] = new restore_path_element('certificate', '/activity/certificate'); + + if ($userinfo) { + $paths[] = new restore_path_element('certificate_issue', '/activity/certificate/issues/issue'); + } + + // Return the paths wrapped into standard activity structure + return $this->prepare_activity_structure($paths); + } + + protected function process_certificate($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + $data->course = $this->get_courseid(); + $data->timecreated = $this->apply_date_offset($data->timecreated); + $data->timemodified = $this->apply_date_offset($data->timemodified); + + // insert the certificate record + $newitemid = $DB->insert_record('certificate', $data); + // immediately after inserting "activity" record, call this + $this->apply_activity_instance($newitemid); + } + + protected function process_certificate_issue($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + + $data->certificateid = $this->get_new_parentid('certificate'); + $data->timecreated = $this->apply_date_offset($data->timecreated); + + $newitemid = $DB->insert_record('certificate_issues', $data); + $this->set_mapping('certificate_issue', $oldid, $newitemid); + } + + protected function after_execute() { + // Add certificate related files, no need to match by itemname (just internally handled context) + $this->add_related_files('mod_certificate', 'issue', 'certificate_issue'); + } +} diff --git a/db/access.php b/db/access.php new file mode 100644 index 0000000..bc7b822 --- /dev/null +++ b/db/access.php @@ -0,0 +1,74 @@ +. + +/** + * Certificate module capability definition + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$capabilities = array( + + 'mod/certificate:addinstance' => array( + 'riskbitmask' => RISK_XSS, + 'captype' => 'write', + 'contextlevel' => CONTEXT_COURSE, + 'archetypes' => array( + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ), + 'clonepermissionsfrom' => 'moodle/course:manageactivities' + ), + + 'mod/certificate:view' => array( + + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'student' => CAP_ALLOW, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ) + ), + + 'mod/certificate:manage' => array( + + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ) + ), + + 'mod/certificate:printteacher' => array( + + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ) + ), + +); \ No newline at end of file diff --git a/db/install.xml b/db/install.xml new file mode 100644 index 0000000..224ce0f --- /dev/null +++ b/db/install.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/db/log.php b/db/log.php new file mode 100644 index 0000000..c32db45 --- /dev/null +++ b/db/log.php @@ -0,0 +1,34 @@ +. + +/** + * Definition of log events + * + * @package mod + * @subpackage lesson + * @copyright 2010 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$logs = array( + array('module'=>'certificate', 'action'=>'view', 'mtable'=>'certificate', 'field'=>'name'), + array('module'=>'certificate', 'action'=>'add', 'mtable'=>'certificate', 'field'=>'name'), + array('module'=>'certificate', 'action'=>'update', 'mtable'=>'certificate', 'field'=>'name'), + array('module'=>'certificate', 'action'=>'received', 'mtable'=>'certificate', 'field'=>'name'), +); \ No newline at end of file diff --git a/db/upgrade.php b/db/upgrade.php new file mode 100644 index 0000000..fb3e499 --- /dev/null +++ b/db/upgrade.php @@ -0,0 +1,488 @@ +. + +/** + * This file keeps track of upgrades to the certificate module + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +function xmldb_certificate_upgrade($oldversion=0) { + + global $CFG, $THEME, $DB; + $dbman = $DB->get_manager(); + + // ===== 1.9.0 or older upgrade line ======// + if ($oldversion < 2007061300) { + // Add new fields to certificate table + $table = new xmldb_table('certificate'); + $field = new xmldb_field('emailothers'); + $field->set_attributes(XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'emailteachers'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $table = new xmldb_table('certificate'); + $field = new xmldb_field('printhours'); + $field->set_attributes(XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'gradefmt'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $table = new xmldb_table('certificate'); + $field = new xmldb_field('lockgrade'); + $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'printhours'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $table = new xmldb_table('certificate'); + $field = new xmldb_field('requiredgrade'); + $field->set_attributes(XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'lockgrade'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Rename field save to savecert + $field = new xmldb_field('save'); + if ($dbman->field_exists($table, $field)) { + $field->set_attributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'emailothers'); + // Launch rename field savecert + $dbman->rename_field($table, $field, 'savecert'); + } else { + $field = new xmldb_field('savecert'); + $field->set_attributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'emailothers'); + + $dbman->add_field($table, $field); + } + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2007061300, 'certificate'); + } + + if ($oldversion < 2007061301) { + $table = new xmldb_table('certificate_linked_modules'); + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null); + $table->add_field('certificate_id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'id'); + $table->add_field('linkid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'certificate_id'); + $table->add_field('linkgrade', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'linkid'); + $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'linkgrade'); + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'), null, null); + $table->add_index('certificate_id', XMLDB_INDEX_NOTUNIQUE, array('certificate_id')); + $table->add_index('linkid', XMLDB_INDEX_NOTUNIQUE, array('linkid')); + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2007061301, 'certificate'); + } + + if ($oldversion < 2007061302) { + $table = new xmldb_table('certificate_linked_modules'); + $field = new xmldb_field('linkid'); + $field->set_attributes(XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'certificate_id'); + $dbman->change_field_unsigned($table, $field); + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2007061302, 'certificate'); + } + + if ($oldversion < 2007102800) { + // Add new fields to certificate table + $table = new xmldb_table('certificate'); + $field = new xmldb_field('reportcert'); + $field->set_attributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'savecert'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $table = new xmldb_table('certificate_issues'); + $field = new xmldb_field('reportgrade'); + $field->set_attributes(XMLDB_TYPE_CHAR, '10', null, null, null, null, 'certdate'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2007102800, 'certificate'); + } + + if ($oldversion < 2007102806) { + // Add new fields to certificate table + $table = new xmldb_table('certificate'); + $field = new xmldb_field('printoutcome'); + $field->set_attributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'gradefmt'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2007102806, 'certificate'); + } + + if ($oldversion < 2008080904) { + // Add new fields to certificate table if they dont already exist + $table = new xmldb_table('certificate'); + $field = new xmldb_field('intro'); + $field->set_attributes(XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'name'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2008080904, 'certificate'); + } + + //===== 2.0 or older upgrade line ======// + + // Note, fresh 1.9 installs add the version 2009080900, so they miss this when upgrading from 1.9 -> 2.0. + if ($oldversion < 2009062900) { + // Add new field to certificate table + $table = new xmldb_table('certificate'); + $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'intro'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $field = new xmldb_field('orientation', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, ' ', 'certificatetype'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $field = new xmldb_field('reissuecert', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'reportcert'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Set default orientation accordingly + $DB->set_field('certificate', 'orientation', 'P', array('certificatetype' => 'portrait')); + $DB->set_field('certificate', 'orientation', 'P', array('certificatetype' => 'letter_portrait')); + $DB->set_field('certificate', 'orientation', 'P', array('certificatetype' => 'unicode_portrait')); + $DB->set_field('certificate', 'orientation', 'L', array('certificatetype' => 'landscape')); + $DB->set_field('certificate', 'orientation', 'L', array('certificatetype' => 'letter_landscape')); + $DB->set_field('certificate', 'orientation', 'L', array('certificatetype' => 'unicode_landscape')); + + // Update all the certificate types + $DB->set_field('certificate', 'certificatetype', 'A4_non_embedded', array('certificatetype' => 'landscape')); + $DB->set_field('certificate', 'certificatetype', 'A4_non_embedded', array('certificatetype' => 'portrait')); + $DB->set_field('certificate', 'certificatetype', 'A4_embedded', array('certificatetype' => 'unicode_landscape')); + $DB->set_field('certificate', 'certificatetype', 'A4_embedded', array('certificatetype' => 'unicode_portrait')); + $DB->set_field('certificate', 'certificatetype', 'letter_non_embedded', array('certificatetype' => 'letter_landscape')); + $DB->set_field('certificate', 'certificatetype', 'letter_non_embedded', array('certificatetype' => 'letter_portrait')); + + // savepoint reached + upgrade_mod_savepoint(true, 2009062900, 'certificate'); + } + + if ($oldversion < 2011030105) { + + // Define field id to be added to certificate + $table = new xmldb_table('certificate'); + $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'intro'); + + // Conditionally launch add field id + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2011030105, 'certificate'); + } + + // The Moodle 2.0 CVS certificate version sets it to 2011110101, if the user performed an upgrade + // then this upgrade will take care of several issues, if it's a fresh install then nothing is done. + if ($oldversion < 2011110102) { + require_once($CFG->libdir.'/conditionlib.php'); + + $table = new xmldb_table('certificate'); + + // It is possible for these fields not to be added, ever, it is included in the upgrade + // process but fresh certificate 1.9 install from CVS MOODLE_19_STABLE set the Moodle version + // to 2009080900, which means it missed all the earlier code written for upgrading to 2.0. + $reissuefield = new xmldb_field('reissuecert', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'reportcert'); + $orientationfield = new xmldb_field('orientation', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, ' ', 'certificatetype'); + + // Have to check, may be added during earlier upgrade, or may be missing due to not being included in install.xml + if (!$dbman->field_exists($table, $reissuefield)) { + $dbman->add_field($table, $reissuefield); + } + + if (!$dbman->field_exists($table, $orientationfield)) { + $dbman->add_field($table, $orientationfield); + } + + // Fresh 2.0 installs won't have this table, but upgrades from 1.9 will + if ($dbman->table_exists('certificate_linked_modules')) { + // No longer need lock grade, or required grade, but first need to + // convert so that the restrictions are still in place for Moodle 2.0 + if ($certs = $DB->get_records('certificate')) { + foreach ($certs as $cert) { + if ($cert->lockgrade == 0) { + // Can skip this certificate, no course grade required + continue; + } + if (!$cm = get_coursemodule_from_instance('certificate', $cert->id)) { + // Not valid skip it + continue; + } + if (!$gradeitem = $DB->get_record('grade_items', array('courseid' => $cm->course, 'itemtype' => 'course'))) { + // Not valid skip it + continue; + } + $condition_info = new condition_info($cm, CONDITION_MISSING_EVERYTHING); + $condition_info->add_grade_condition($gradeitem->id, $cert->requiredgrade, '110'); + } + } + // Fresh installs won't have this table, but upgrades will + // Lock grade and required grade field are not needed anymore + if ($dbman->field_exists($table, 'lockgrade')) { + $field = new xmldb_field('lockgrade'); + $dbman->drop_field($table, $field); + } + if ($dbman->field_exists($table, 'requiredgrade')) { + $field = new xmldb_field('requiredgrade'); + $dbman->drop_field($table, $field); + } + // Now we need to loop through the restrictions in the certificate_linked_modules + // table and convert it into the new Moodle 2.0 restrictions + if ($certlinks = $DB->get_records('certificate_linked_modules')) { + foreach ($certlinks as $link) { + // If the link id is '-1' then the setting applies to the time spent in the course and is not + // related to a module, meaning we can skip it for this section + if ($link->linkid == '-1') { + continue; + } + // Get the course module + if (!$cm = get_coursemodule_from_instance('certificate', $link->certificate_id)) { + // Not valid skip it + continue; + } + // Get grade item for module specified - is there an API function for this ?? + $sql = "SELECT gi.id + FROM {course_modules} cm + INNER JOIN {modules} m + ON cm.module = m.id + INNER JOIN {grade_items} gi + ON m.name = gi.itemmodule + WHERE cm.id = :cmid + AND cm.course = :courseid + AND cm.instance = gi.iteminstance"; + if (!$gradeitem = $DB->get_record_sql($sql, array('cmid'=>$link->linkid, 'courseid'=>$cm->course))) { + // Not valid skip it + continue; + } + $condition_info = new condition_info($cm, CONDITION_MISSING_EVERYTHING); + $condition_info->add_grade_condition($gradeitem->id, $link->linkgrade, '110', true); + } + } + } + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2011110102, 'certificate'); + } + + // Note - the date has not changed as it has been set in the future, so I am incrementing + // last digits. Actual date - 15/09/11 + if ($oldversion < 2011110103) { + // New orientation field needs a value in order to view the cert, otherwise you get + // an issue with FPDF and invalid orientation. This should be done during the upgrade, + // but due to version number issues it is possible it was not executed, so do it now. + $DB->set_field('certificate', 'orientation', 'P', array('certificatetype' => 'portrait')); + $DB->set_field('certificate', 'orientation', 'P', array('certificatetype' => 'letter_portrait')); + $DB->set_field('certificate', 'orientation', 'P', array('certificatetype' => 'unicode_portrait')); + $DB->set_field('certificate', 'orientation', 'L', array('certificatetype' => 'landscape')); + $DB->set_field('certificate', 'orientation', 'L', array('certificatetype' => 'letter_landscape')); + $DB->set_field('certificate', 'orientation', 'L', array('certificatetype' => 'unicode_landscape')); + + // If the certificate type does not match any of the orientations in the above then set to 'L' + $sql = "UPDATE {certificate} + SET orientation = 'L' + WHERE orientation = ''"; + $DB->execute($sql); + + // Update all the certificate types + $DB->set_field('certificate', 'certificatetype', 'A4_non_embedded', array('certificatetype' => 'landscape')); + $DB->set_field('certificate', 'certificatetype', 'A4_non_embedded', array('certificatetype' => 'portrait')); + $DB->set_field('certificate', 'certificatetype', 'A4_embedded', array('certificatetype' => 'unicode_landscape')); + $DB->set_field('certificate', 'certificatetype', 'A4_embedded', array('certificatetype' => 'unicode_portrait')); + $DB->set_field('certificate', 'certificatetype', 'letter_non_embedded', array('certificatetype' => 'letter_landscape')); + $DB->set_field('certificate', 'certificatetype', 'letter_non_embedded', array('certificatetype' => 'letter_portrait')); + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2011110103, 'certificate'); + } + + if ($oldversion < 2012022001) { + // CONTRIB-3470 - certdate remaining 0 on issued certificates, need to update + $sql = "UPDATE {certificate_issues} + SET certdate = timecreated + WHERE certdate = 0"; + $DB->execute($sql); + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2012022001, 'certificate'); + } + + if ($oldversion < 2012060901) { + // Editing this table + $table = new xmldb_table('certificate'); + + // Get rid of the reissue cert column, this was a hack introduced later + // in 1.9 when the bug was brought up that grades were not refreshing + // since they were being stored in the issues table. + // The certificate will now always return the current grade, student name + // and course name. + $field = new xmldb_field('reissuecert'); + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + + // The poor certificate_issues table is going to have a lot of + // duplicates, we don't need that now, just keep the latest one + $sql = "SELECT MAX(id) id1, MAX(id) as id2 + FROM {certificate_issues} + GROUP BY certificateid, userid"; + if ($arrids = $DB->get_records_sql_menu($sql)) { + $idstokeep = implode(",", $arrids); + $sql = "DELETE + FROM {certificate_issues} + WHERE id NOT IN ($idstokeep)"; + $DB->execute($sql); + } + + // Going to be editing this table + $table = new xmldb_table('certificate_issues'); + + // Conditionally remove columns no longer needed + $field = new xmldb_field('studentname'); + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + $field = new xmldb_field('classname'); + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + $field = new xmldb_field('certdate'); + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + $field = new xmldb_field('reportgrade'); + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + $field = new xmldb_field('mailed'); + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2012060901, 'certificate'); + } + + if ($oldversion < 2012072501) { + // Add a column to store the required grade + $table = new xmldb_table('certificate'); + $requiredtimefield = new xmldb_field('requiredtime', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, + XMLDB_NOTNULL, null, '0', 'delivery'); + + if (!$dbman->field_exists($table, $requiredtimefield)) { + $dbman->add_field($table, $requiredtimefield); + } + + // If this table still exists, then the install was from a 1.9 version + if ($dbman->table_exists('certificate_linked_modules')) { + // Now we need to loop through the restrictions in the certificate_linked_modules + // table and check if there were any required time conditions + if ($certlinks = $DB->get_records('certificate_linked_modules')) { + foreach ($certlinks as $link) { + // If the link id is '-1' then the setting applies to the time spent in the course + if ($link->linkid == '-1') { + // Make sure the certificate exists + if ($certificate = $DB->get_record('certificate', array('id' => $link->certificate_id))) { + $certificate->requiredtime = $link->linkgrade; + $DB->update_record('certificate', $certificate); + } + } + } + } + // We can now get rid of this table + $table = new xmldb_table('certificate_linked_modules'); + $dbman->drop_table($table); + } + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2012072501, 'certificate'); + } + + if ($oldversion < 2012082401) { + $table = new xmldb_table('certificate'); + + // Change length of the fields that store images, so longer image names can be stored + $field = new xmldb_field('borderstyle', XMLDB_TYPE_CHAR, '255', XMLDB_UNSIGNED, XMLDB_NOTNULL, 0); + $dbman->change_field_precision($table, $field); + + $field = new xmldb_field('printwmark', XMLDB_TYPE_CHAR, '255', XMLDB_UNSIGNED, XMLDB_NOTNULL, 0); + $dbman->change_field_precision($table, $field); + + $field = new xmldb_field('printsignature', XMLDB_TYPE_CHAR, '255', XMLDB_UNSIGNED, XMLDB_NOTNULL, 0); + $dbman->change_field_precision($table, $field); + + $field = new xmldb_field('printseal', XMLDB_TYPE_CHAR, '255', XMLDB_UNSIGNED, XMLDB_NOTNULL, 0); + $dbman->change_field_precision($table, $field); + + // Change length of fields that are unnecessarily large + $field = new xmldb_field('printnumber', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, 0, 0); + $dbman->change_field_precision($table, $field); + + $field = new xmldb_field('printhours', XMLDB_TYPE_CHAR, '255', XMLDB_UNSIGNED, false, 0, 0); + $dbman->change_field_precision($table, $field); + + $field = new xmldb_field('emailteachers', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, 0, 0); + $dbman->change_field_precision($table, $field); + + $field = new xmldb_field('savecert', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, 0, 0); + $dbman->change_field_precision($table, $field); + + $field = new xmldb_field('reportcert', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, 0, 0); + $dbman->change_field_precision($table, $field); + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2012082401, 'certificate'); + } + + if ($oldversion < 2012090901) { + $table = new xmldb_table('certificate'); + + $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, 0, 0, 'printseal'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Set the time created to the time modified + $sql = "UPDATE {certificate} + SET timecreated = timemodified"; + $DB->execute($sql); + + // Certificate savepoint reached + upgrade_mod_savepoint(true, 2012090901, 'certificate'); + } + + return true; +} diff --git a/deprecatedlib.php b/deprecatedlib.php new file mode 100644 index 0000000..5f07fcd --- /dev/null +++ b/deprecatedlib.php @@ -0,0 +1,249 @@ +. + +/** + * Deprecated certificate functions. + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Prepare to be print the date -- defaults to time. + * + * @deprecated since certificate version 2012052501 + * @param stdClass $certificate + * @param stdClass $course + * @return string the date + */ +function certificate_generate_date($certificate, $course) { + debugging('certificate_generate_date is deprecated, please use certificate_get_date instead which will + return a date in a human readable format.', DEBUG_DEVELOPER); + + global $DB, $USER; + + // Set certificate date to current time, can be overwritten later + $date = time(); + + 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' => $USER->id, 'courseid' => $course->id))) { + if (!empty($timecompleted->timecompleted)) { + $date = $timecompleted->timecompleted; + } + } + } else if ($certificate->printdate > 2) { + if ($modinfo = certificate_get_mod_grade($course, $certificate->printdate, $USER->id)) { + $date = $modinfo->dategraded; + } + } + + return $date; +} + +/** + * Prepare to print the course grade. + * + * @deprecated since certificate version 2012052501 + * @param stdClass $course + * @return mixed + */ +function certificate_print_course_grade($course){ + debugging('certificate_print_course_grade is deprecated, please use certificate_get_grade instead. Ideally + you should be using certificate_get_grade in your certificate type which will either get the course + or module grade depending on your certificate settings.', DEBUG_DEVELOPER); + + global $USER, $DB; + + if ($course_item = grade_item::fetch_course_item($course->id)) { + $grade = new grade_grade(array('itemid'=>$course_item->id, 'userid'=>$USER->id)); + $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); + + return $coursegrade; + } + + return false; +} + +/** + * Prepare to print an activity grade. + * + * @deprecated since certificate version 2012052501 + * @param stdClass $course + * @param int $moduleid + * @return mixed + */ +function certificate_print_mod_grade($course, $moduleid){ + debugging('certificate_print_mod_grade is deprecated, please use certificate_get_mod_grade instead. Ideally + you should be using certificate_get_grade in your certificate type which will either get the course + or module grade depending on your certificate settings.', DEBUG_DEVELOPER); + + global $USER; + + return certificate_get_mod_grade($course, $moduleid, $USER->id); +} + + +/** +* Prepare to print an outcome. +* +* @deprecated since certificate version 2012052501 +* @param stdClass $course +* @param int $moduleid +* @return mixed +*/ +function certificate_print_outcome($course, $id) { + debugging('certificate_print_outcome is deprecated, please use certificate_get_outcome instead', DEBUG_DEVELOPER); + + return certificate_get_outcome($certificate, $course); +} + +/** + * Creates rectangles for line border for A4 size paper. + * + * @deprecated since certificate version 2012052501 + * @param stdClass $pdf + * @param stdClass $certificate + * @return null + */ +function draw_frame($pdf, $certificate) { + debugging('draw_frame is deprecated, please use certificate_draw_frame instead', DEBUG_DEVELOPER); + + certificate_draw_frame($pdf, $certificate); +} + +/** + * Creates rectangles for line border for letter size paper. + * + * @deprecated since certificate version 2012052501 + * @param stdClass $pdf + * @param stdClass $certificate + * @return null + */ +function draw_frame_letter($pdf, $certificate) { + debugging('draw_frame_letter is deprecated, please use certificate_draw_frame_letter instead', DEBUG_DEVELOPER); + + certificate_draw_frame_letter($pdf, $certificate); +} + +/** + * Prints border images from the borders folder in PNG or JPG formats. + * + * @deprecated since certificate version 2012052501 + * @param stdClass $pdf; + * @param stdClass $certificate + * @param int $x x position + * @param int $y y position + * @param int $w the width + * @param int $h the height + * @return null + */ +function print_border($pdf, $certificate, $x, $y, $w, $h) { + debugging('print_watermark is deprecated, please use certificate_print_image instead', DEBUG_DEVELOPER); + + certificate_print_image($pdf, $certificate, CERT_IMAGE_BORDER, $x, $y, $w, $h); +} + +/** + * Prints watermark images. + * + * @deprecated since certificate version 2012052501 + * @param stdClass $pdf; + * @param stdClass $certificate + * @param int $x x position + * @param int $y y position + * @param int $w the width + * @param int $h the height + * @return null + */ +function print_watermark($pdf, $certificate, $x, $y, $w, $h) { + debugging('print_watermark is deprecated, please use certificate_print_image instead', DEBUG_DEVELOPER); + + certificate_print_image($pdf, $certificate, CERT_IMAGE_WATERMARK, $x, $y, $w, $h); +} + +/** + * Prints signature images or a line. + * + * @deprecated since certificate version 2012052501 + * @param stdClass $pdf + * @param stdClass $certificate + * @param int $x x position + * @param int $y y position + * @param int $w the width + * @param int $h the height + * @return null + */ +function print_signature($pdf, $certificate, $x, $y, $w, $h) { + debugging('print_signature is deprecated, please use certificate_print_image instead', DEBUG_DEVELOPER); + + certificate_print_image($pdf, $certificate, CERT_IMAGE_SIGNATURE, $x, $y, $w, $h); +} + +/** + * Prints seal images. + * + * @deprecated since certificate version 2012052501 + * @param stdClass $pdf; + * @param stdClass $certificate + * @param int $x x position + * @param int $y y position + * @param int $w the width + * @param int $h the height + * @return null + */ +function print_seal($pdf, $certificate, $x, $y, $w, $h) { + debugging('print_seal is deprecated, please use certificate_print_image instead', DEBUG_DEVELOPER); + + certificate_print_image($pdf, $certificate, CERT_IMAGE_SEAL, $x, $y, $w, $h); +} + +/** + * Sends text to output given the following params. + * + * @deprecated since certificate version 2012052501 + * @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 + * @return null + */ +function cert_printtext($pdf, $x, $y, $align, $font, $style, $size, $text) { + static $hasbeenwarned = false; + + if (!$hasbeenwarned) { + debugging('cert_printtext is deprecated, please use certificate_print_text instead', DEBUG_DEVELOPER); + } + + $hasbeenwarned = true; + certificate_print_text($pdf, $x, $y, $align, $font, $style, $size, $text); +} + diff --git a/index.php b/index.php new file mode 100644 index 0000000..3581325 --- /dev/null +++ b/index.php @@ -0,0 +1,118 @@ +. + +/** + * This page lists all the instances of certificate in a particular course + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../../config.php'); +require_once('lib.php'); + +$id = required_param('id', PARAM_INT); // Course Module ID + +// Ensure that the course specified is valid +if (!$course = $DB->get_record('course', array('id'=> $id))) { + print_error('Course ID is incorrect'); +} + +// Requires a login +require_course_login($course); + +// Declare variables +$currentsection = ""; +$printsection = ""; +$timenow = time(); + +// Strings used multiple times +$strcertificates = get_string('modulenameplural', 'certificate'); +$strissued = get_string('issued', 'certificate'); +$strname = get_string("name"); +$strsectionname = get_string('sectionname', 'format_'.$course->format); + +// Print the header +$PAGE->set_pagelayout('incourse'); +$PAGE->set_url('/mod/certificate/index.php', array('id'=>$course->id)); +$PAGE->navbar->add($strcertificates); +$PAGE->set_title($strcertificates); +$PAGE->set_heading($course->fullname); + +// Add the page view to the Moodle log +add_to_log($course->id, 'certificate', 'view all', 'index.php?id='.$course->id, ''); + +// Get the certificates, if there are none display a notice +if (!$certificates = get_all_instances_in_course('certificate', $course)) { + echo $OUTPUT->header(); + notice(get_string('nocertificates', 'certificate'), "$CFG->wwwroot/course/view.php?id=$course->id"); + echo $OUTPUT->footer(); + exit(); +} + +$usesections = course_format_uses_sections($course->format); + +$table = new html_table(); + +if ($usesections) { + $table->head = array ($strsectionname, $strname, $strissued); +} else { + $table->head = array ($strname, $strissued); +} + +foreach ($certificates as $certificate) { + if (!$certificate->visible) { + // Show dimmed if the mod is hidden + $link = html_writer::tag('a', $certificate->name, array('class' => 'dimmed', + 'href' => $CFG->wwwroot . '/mod/certificate/view.php?id=' . $certificate->coursemodule)); + } else { + // Show normal if the mod is visible + $link = html_writer::tag('a', $certificate->name, array('class' => 'dimmed', + 'href' => $CFG->wwwroot . '/mod/certificate/view.php?id=' . $certificate->coursemodule)); + } + + $strsection = ''; + if ($certificate->section != $currentsection) { + if ($certificate->section) { + $strsection = get_section_name($course, $certificate->section); + } + if ($currentsection !== '') { + $table->data[] = 'hr'; + } + $currentsection = $certificate->section; + } + + // Get the latest certificate issue + if ($certrecord = $DB->get_record('certificate_issues', array('userid' => $USER->id, 'certificateid' => $certificate->id))) { + $issued = userdate($certrecord->timecreated); + } else { + $issued = get_string('notreceived', 'certificate'); + } + + if ($usesections) { + $table->data[] = array ($strsection, $link, $issued); + } else { + $table->data[] = array ($link, $issued); + } +} + +echo $OUTPUT->header(); +echo '
'; +echo html_writer::table($table); +echo $OUTPUT->footer(); \ No newline at end of file diff --git a/lang/en/certificate.php b/lang/en/certificate.php new file mode 100644 index 0000000..88e9d34 --- /dev/null +++ b/lang/en/certificate.php @@ -0,0 +1,204 @@ +. + +/** + * Language strings for the certificate module + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['addlinklabel'] = 'Add another linked activity option'; +$string['addlinktitle'] = 'Click to add another linked activity option'; +$string['areaintro'] = 'Certificate introduction'; +$string['awarded'] = 'Awarded'; +$string['awardedto'] = 'Awarded To'; +$string['back'] = 'Back'; +$string['border'] = 'Border'; +$string['borderblack'] = 'Black'; +$string['borderblue'] = 'Blue'; +$string['borderbrown'] = 'Brown'; +$string['bordercolor'] = 'Border Lines'; +$string['bordercolor_help'] = 'Since images can substantially increase the size of the pdf file, you may choose to print a border of lines instead of using a border image (be sure the Border Image option is set to No). The Border Lines option will print a nice border of three lines of varying widths in the chosen color.'; +$string['bordergreen'] = 'Green'; +$string['borderlines'] = 'Lines'; +$string['borderstyle'] = 'Border Image'; +$string['borderstyle_help'] = 'The Border Image option allows you to choose a border image from the certificate/pix/borders folder. Select the border image that you want around the certificate edges or select no border.'; +$string['certificate'] = 'Verification for certificate code:'; +$string['certificate:addinstance'] = 'Add a certificate instance'; +$string['certificate:manage'] = 'Manage a certificate instance'; +$string['certificate:printteacher'] = 'Be listed as a teacher on the certificate if the print teacher setting is on'; +$string['certificate:student'] = 'Retrieve a certificate'; +$string['certificate:view'] = 'View a certificate'; +$string['certificatename'] = 'Certificate Name'; +$string['certificatereport'] = 'Certificates Report'; +$string['certificatesfor'] = 'Certificates for'; +$string['certificatetype'] = 'Certificate Type'; +$string['certificatetype_help'] = 'This is where you determine the layout of the certificate. The certificate type folder includes four default certificates: +A4 Embedded prints on A4 size paper with embedded font. +A4 Non-Embedded prints on A4 size paper without embedded fonts. +Letter Embedded prints on letter size paper with embedded font. +Letter Non-Embedded prints on letter size paper without embedded fonts. + +The non-embedded types use the Helvetica and Times fonts. If you feel your users will not have these fonts on their computer, or if your language uses characters or symbols that are not accommodated by the Helvetica and Times fonts, then choose an embedded type. The embedded types use the Dejavusans and Dejavuserif fonts. This will make the pdf files rather large; thus it is not recommended to use an embedded type unless you must. + +New type folders can be added to the certificate/type folder. The name of the folder and any new language strings for the new type must be added to the certificate language file.'; +$string['certify'] = 'This is to certify that'; +$string['code'] = 'Code'; +$string['completiondate'] = 'Course Completion'; +$string['course'] = 'For'; +$string['coursegrade'] = 'Course Grade'; +$string['coursename'] = 'Course'; +$string['coursetimereq'] = 'Required minutes in course'; +$string['coursetimereq_help'] = 'Enter here the minimum amount of time, in minutes, that a student must be logged into the course before they will be able to receive the certificate.'; +$string['credithours'] = 'Credit Hours'; +$string['customtext'] = 'Custom Text'; +$string['customtext_help'] = 'If you want the certificate to print different names for the teacher than those who are assigned +the role of teacher, do not select Print Teacher or any signature image except for the line image. Enter the teacher names in this text box as you would like them to appear. By default, this text is placed in the lower left of the certificate. The following html tags are available: <br>, <p>, <b>, <i>, <u>, <img> (src and width (or height) are mandatory), <a> (href is mandatory), <font> (possible attributes are: color, (hex color code), face, (arial, times, courier, helvetica, symbol)).'; +$string['date'] = 'On'; +$string['datefmt'] = 'Date Format'; +$string['datefmt_help'] = 'Choose a date format to print the date on the certificate. Or, choose the last option to have the date printed in the format of the user\'s chosen language.'; +$string['datehelp'] = 'Date'; +$string['deletissuedcertificates'] = 'Delete issued certificates'; +$string['delivery'] = 'Delivery'; +$string['delivery_help'] = 'Choose here how you would like your students to get their certificate. +Open in Browser: Opens the certificate in a new browser window. +Force Download: Opens the browser file download window. +Email Certificate: Choosing this option sends the certificate to the student as an email attachment. +After a user receives their certificate, if they click on the certificate link from the course homepage, they will see the date they received their certificate and will be able to review their received certificate.'; +$string['designoptions'] = 'Design Options'; +$string['download'] = 'Force download'; +$string['emailcertificate'] = 'Email (Must also choose save!)'; +$string['emailothers'] = 'Email Others'; +$string['emailothers_help'] = 'Enter the email addresses here, separated by a comma, of those who should be alerted with an email whenever students receive a certificate.'; +$string['emailstudenttext'] = 'Attached is your certificate for {$a->course}.'; +$string['emailteachers'] = 'Email Teachers'; +$string['emailteachers_help'] = 'If enabled, then teachers are alerted with an email whenever students receive a certificate.'; +$string['emailteachermail'] = ' +{$a->student} has received their certificate: \'{$a->certificate}\' +for {$a->course}. + +You can review it here: + + {$a->url}'; +$string['emailteachermailhtml'] = ' +{$a->student} has received their certificate: \'{$a->certificate}\' +for {$a->course}. + +You can review it here: + + Certificate Report.'; +$string['entercode'] = 'Enter certificate code to verify:'; +$string['getcertificate'] = 'Get your certificate'; +$string['grade'] = 'Grade'; +$string['gradedate'] = 'Grade Date'; +$string['gradefmt'] = 'Grade Format'; +$string['gradefmt_help'] = 'There are three available formats if you choose to print a grade on the certificate: + +Percentage Grade: Prints the grade as a percentage. +Points Grade: Prints the point value of the grade. +Letter Grade: Prints the percentage grade as a letter.'; +$string['gradeletter'] = 'Letter Grade'; +$string['gradepercent'] = 'Percentage Grade'; +$string['gradepoints'] = 'Points Grade'; +$string['imagetype'] = 'Image Type'; +$string['incompletemessage'] = 'In order to download your certificate, you must first complete all required '.'activities. Please return to the course to complete your coursework.'; +$string['intro'] = 'Introduction'; +$string['issueoptions'] = 'Issue Options'; +$string['issued'] = 'Issued'; +$string['issueddate'] = 'Date Issued'; +$string['landscape'] = 'Landscape'; +$string['lastviewed'] = 'You last received this certificate on:'; +$string['letter'] = 'Letter'; +$string['lockingoptions'] = 'Locking Options'; +$string['modulename'] = 'Certificate'; +$string['modulenameplural'] = 'Certificates'; +$string['mycertificates'] = 'My Certificates'; +$string['nocertificates'] = 'There are no certificates'; +$string['nocertificatesissued'] = 'There are no certificates that have been issued'; +$string['nocertificatesreceived'] = 'has not received any course certificates.'; +$string['nofileselected'] = 'Must choose a file to upload!'; +$string['nogrades'] = 'No grades available'; +$string['notapplicable'] = 'N/A'; +$string['notfound'] = 'The certificate number could not be validated.'; +$string['notissued'] = 'Not Issued'; +$string['notissuedyet'] = 'Not issued yet'; +$string['notreceived'] = 'You have not received this certificate'; +$string['openbrowser'] = 'Open in new window'; +$string['opendownload'] = 'Click the button below to save your certificate to your computer.'; +$string['openemail'] = 'Click the button below and your certificate will be sent to you as an email attachment.'; +$string['openwindow'] = 'Click the button below to open your certificate in a new browser window.'; +$string['or'] = 'Or'; +$string['orientation'] = 'Orientation'; +$string['orientation_help'] = 'Choose whether you want your certificate orientation to be portrait or landscape.'; +$string['pluginadministration'] = 'Certificate administration'; +$string['pluginname'] = 'Certificate'; +$string['portrait'] = 'Portrait'; +$string['printdate'] = 'Print Date'; +$string['printdate_help'] = 'This is the date that will be printed, if a print date is selected. If the course completion date is selected but the student has not completed the course, the date received will be printed. You can also choose to print the date based on when an activity was graded. If a certificate is issued before that activity is graded, the date received will be printed.'; +$string['printerfriendly'] = 'Printer-friendly page'; +$string['printhours'] = 'Print Credit Hours'; +$string['printhours_help'] = 'Enter here the number of credit hours to be printed on the certificate.'; +$string['printgrade'] = 'Print Grade'; +$string['printgrade_help'] = 'You can choose any available course grade items from the gradebook to print the user\'s grade received for that item on the certificate. The grade items are listed in the order in which they appear in the gradebook. Choose the format of the grade below.'; +$string['printnumber'] = 'Print Code'; +$string['printnumber_help'] = 'A unique 10-digit code of random letters and numbers can be printed on the certificate. This number can then be verified by comparing it to the code number displayed in the certificates report.'; +$string['printoutcome'] = 'Print Outcome'; +$string['printoutcome_help'] = 'You can choose any course outcome to print the name of the outcome and the user\'s received outcome on the certificate. An example might be: Assignment Outcome: Proficient.'; +$string['printseal'] = 'Seal or Logo Image'; +$string['printseal_help'] = 'This option allows you to select a seal or logo to print on the certificate from the certificate/pix/seals folder. By default, this image is placed in the lower right corner of the certificate.'; +$string['printsignature'] = 'Signature Image'; +$string['printsignature_help'] = 'This option allows you to print a signature image from the certificate/pix/signatures folder. You can print a graphic representation of a signature, or print a line for a written signature. By default, this image is placed in the lower left of the certificate.'; +$string['printteacher'] = 'Print Teacher Name(s)'; +$string['printteacher_help'] = 'For printing the teacher name on the certificate, set the role of teacher at the module level. Do this if, for example, you have more than one teacher for the course or you have more than one certificate in the course and you want to print different teacher names on each certificate. Click to edit the certificate, then click on the Locally assigned roles tab. Then assign the role of Teacher (editing teacher) to the certificate (they do not HAVE to be a teacher in the course--you can assign that role to anyone). Those names will be printed on the certificate for teacher.'; +$string['printwmark'] = 'Watermark Image'; +$string['printwmark_help'] = 'A watermark file can be placed in the background of the certificate. A watermark is a faded graphic. A watermark could be a logo, seal, crest, wording, or whatever you want to use as a graphic background.'; +$string['receivedcerts'] = 'Received certificates'; +$string['receiveddate'] = 'Date Received'; +$string['removecert'] = 'Issued certificates removed'; +$string['report'] = 'Report'; +$string['reportcert'] = 'Report Certificates'; +$string['reportcert_help'] = 'If you choose yes here, then this certificate\'s date received, code number, and the course name will be shown on the user certificate reports. If you choose to print a grade on this certificate, then that grade will also be shown on the certificate report.'; +$string['requiredtimenotmet'] = 'You must spend at least a minimum of {$a->requiredtime} minutes in the course before you can access this certificate'; +$string['requiredtimenotvalid'] = 'The required time must be a valid number greater than 0'; +$string['reviewcertificate'] = 'Review your certificate'; +$string['savecert'] = 'Save Certificates'; +$string['savecert_help'] = 'If you choose this option, then a copy of each user\'s certificate pdf file is saved in the course files moddata folder for that certificate. A link to each user\'s saved certificate will be displayed in the certificate report.'; +$string['seal'] = 'Seal'; +$string['sigline'] = 'line'; +$string['signature'] = 'Signature'; +$string['statement'] = 'has completed the course'; +$string['summaryofattempts'] = 'Summary of Previously Received Certificates'; +$string['textoptions'] = 'Text Options'; +$string['title'] = 'CERTIFICATE of ACHIEVEMENT'; +$string['to'] = 'Awarded to'; +$string['typeA4_embedded'] = 'A4 Embedded'; +$string['typeA4_non_embedded'] = 'A4 Non-Embedded'; +$string['typeletter_embedded'] = 'Letter Embedded'; +$string['typeletter_non_embedded'] = 'Letter Non-Embedded'; +$string['unsupportedfiletype'] = 'File must be a jpeg or png file'; +$string['uploadimage'] = 'Upload image'; +$string['uploadimagedesc'] = 'This button will take you to a new screen where you will be able to upload images.'; +$string['userdateformat'] = 'User\'s Language Date Format'; +$string['validate'] = 'Verify'; +$string['verifycertificate'] = 'Verify Certificate'; +$string['viewcertificateviews'] = 'View {$a} issued certificates'; +$string['viewed'] = 'You received this certificate on:'; +$string['viewtranscript'] = 'View Certificates'; +$string['watermark'] = 'Watermark'; \ No newline at end of file diff --git a/lib.php b/lib.php new file mode 100644 index 0000000..da930b9 --- /dev/null +++ b/lib.php @@ -0,0 +1,1516 @@ +. + +/** + * Certificate module core interaction API + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +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); + +/** + * 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 $CFG, $DB; + + $componentstr = get_string('modulenameplural', 'certificate'); + $status = array(); + + if (!empty($data->reset_certificate)) { + $sql = "SELECT cert.id + FROM {certificate} cert + WHERE cert.course = :courseid"; + $DB->delete_records_select('certificate_issues', "certificateid IN ($sql)", array('courseid' => $data->courseid)); + $status[] = array('component' => $componentstr, 'item' => get_string('certificateremoved', '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 $page + * @return string the user complete information + */ +function certificate_user_complete($course, $user, $mod, $certificate) { + global $DB, $OUTPUT; + + 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); + certificate_print_user_files($certificate->id, $user->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; + } +} + +/** + * Function to be run periodically according to the moodle cron + * TODO:This needs to be done + */ +function certificate_cron () { + return true; +} + +/** + * 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, $DB; + + $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, $DB; + + 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->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 = ''; + $posthtml .= '

' . get_string('emailteachermailhtml', 'certificate', $info) . '

'; + $posthtml .= '
'; + + 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 + */ +function certificate_email_student($course, $certificate, $certrecord, $context) { + global $DB, $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)); + + // Remove full-stop at the end if it exists, to avoid "..pdf" being created and being filtered by clean_filename + $certname = rtrim($certificate->name, '.'); + $filename = clean_filename("$certname.pdf"); + + // Get hashed pathname + $fs = get_file_storage(); + + $component = 'mod_certificate'; + $filearea = 'issue'; + $filepath = '/'; + $files = $fs->get_area_files($context->id, $component, $filearea, $certrecord->id); + foreach ($files as $f) { + $filepathname = $f->get_contenthash(); + } + $attachment = 'filedir/'.certificate_path_from_hash($filepathname).'/'.$filepathname; + $attachname = $filename; + + return email_to_user($USER, $from, $subject, $message, $messagehtml, $attachment, $attachname); +} + +/** + * Retrieve certificate path from hash + * + * @param array $contenthash + * @return string the path + */ +function certificate_path_from_hash($contenthash) { + $l1 = $contenthash[0].$contenthash[1]; + $l2 = $contenthash[2].$contenthash[3]; + return "$l1/$l2"; +} + +/** + * 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'); + + if ($filearea === 'issue') { + $certrecord = (int)array_shift($args); + + if (!$certrecord = $DB->get_record('certificate_issues', array('id' => $certrecord))) { + return false; + } + + if ($USER->id != $certrecord->userid and !has_capability('mod/certificate:manage', $context)) { + return false; + } + + $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! + } +} + +/** + * 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 $DB, $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); + + // If the file exists, delete it and recreate it. This is to ensure that the + // latest certificate is saved on the server. For example, the student's grade + // may have been updated. This is a quick dirty hack. + if ($fs->file_exists($contextid, $component, $filearea, $certrecordid, $filepath, $filename)) { + $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 stdClass $context + * @return string return the user files + */ +function certificate_print_user_files($certificate, $userid, $context) { + global $CFG, $DB, $OUTPUT; + + $output = ''; + + $certrecord = $DB->get_record('certificate_issues', array('userid' => $userid, 'certificateid' => $certificate->id)); + $fs = get_file_storage(); + $browser = get_file_browser(); + + $component = 'mod_certificate'; + $filearea = 'issue'; + $files = $fs->get_area_files($context, $component, $filearea, $certrecord->id); + foreach ($files as $file) { + $filename = $file->get_filename(); + $mimetype = $file->get_mimetype(); + $link = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$context.'/mod_certificate/issue/'.$certrecord->id.'/'.$filename); + + $output = ''.$file->get_mimetype().' '. + ''.s($filename).''; + + } + $output .= '
'; + $output = '
'.$output.'
'; + + 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 $CFG, $DB; + + // get all users that can manage this certificate to exclude them from the report. + $context = context_module::instance($cm->id); + + $conditionssql = ''; + $conditionsparams = array(); + if ($certmanagers = array_keys(get_users_by_capability($context, 'mod/certificate:manage', 'u.id'))) { + list($sql, $params) = $DB->get_in_or_equal($certmanagers, SQL_PARAMS_NAMED, 'cert'); + $conditionssql .= "AND NOT u.id $sql \n"; + $conditionsparams += $params; + } + + + + $restricttogroup = false; + if ($groupmode) { + $currentgroup = groups_get_activity_group($cm); + if ($currentgroup) { + $restricttogroup = true; + $groupusers = array_keys(groups_get_members($currentgroup, 'u.*')); + if (empty($groupusers)) { + return array(); + } + } + } + + $restricttogrouping = false; + + // if groupmembersonly used, remove users who are not in any group + if (!empty($CFG->enablegroupings) and $cm->groupmembersonly) { + if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) { + $restricttogrouping = true; + } else { + return array(); + } + } + + if ($restricttogroup || $restricttogrouping) { + if ($restricttogroup) { + $allowedusers = $groupusers; + } else if ($restricttogroup && $restricttogrouping) { + $allowedusers = array_intersect($groupusers, $groupingusers); + } else { + $allowedusers = $groupingusers; + } + + list($sql, $params) = $DB->get_in_or_equal($allowedusers, SQL_PARAMS_NAMED, 'grp'); + $conditionssql .= "AND u.id $sql \n"; + $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); + + $users = $DB->get_records_sql("SELECT u.*, 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, $DB; + + 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, $USER; + + set_time_limit(0); + + $totaltime = 0; + $sql = "l.course = :courseid AND l.userid = :userid"; + if ($logs = get_logs($sql, array('courseid' => $courseid, 'userid' => $USER->id), 'l.time ASC', '', '', $totalcount)) { + 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->time; + $lasthit = $log->time; + $totaltime = 0; + } + $delay = $log->time - $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->time; + } else { + $totaltime += $delay; + } + // Now the actual log became the previous log for the next cycle + $lasthit = $log->time; + } + + 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, $DB; + + // 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; +} + +/** + * 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'); +} + +/** + * 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, $DB; + + 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)); + + if ($grade_item = grade_get_grades($course->id, 'mod', $module->name, $cm->instance, $userid)) { + $item = new grade_item(); + $itemproperties = reset($grade_item->items); + foreach ($itemproperties as $key => $value) { + $item->$key = $value; + } + $modinfo = new stdClass; + $modinfo->name = utf8_decode($DB->get_field($module->name, 'name', array('id' => $cm->instance))); + $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 %B %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 + * @return string the grade result + */ +function certificate_get_grade($certificate, $course, $userid = null) { + global $USER, $DB; + + if (empty($userid)) { + $userid = $USER->id; + } + + if ($certificate->printgrade > 0) { + if ($certificate->printgrade == 1) { + if ($course_item = grade_item::fetch_course_item($course->id)) { + // String used + $strcoursegrade = 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 = $strcoursegrade . ': ' . $coursegrade->percentage; + } else if ($certificate->gradefmt == 2) { + $grade = $strcoursegrade . ': ' . $coursegrade->points; + } else if ($certificate->gradefmt == 3) { + $grade = $strcoursegrade . ': ' . $coursegrade->letter; + } + + return $grade; + } + } else { // Print the mod grade + if ($modinfo = certificate_get_mod_grade($course, $certificate->printgrade, $userid)) { + // String used + $strgrade = get_string('grade', 'certificate'); + if ($certificate->gradefmt == 1) { + $grade = $modinfo->name . ' ' . $strgrade . ': ' . $modinfo->percentage; + } else if ($certificate->gradefmt == 2) { + $grade = $modinfo->name . ' ' . $strgrade . ': ' . $modinfo->points; + } else if ($certificate->gradefmt == 3) { + $grade = $modinfo->name . ' ' . $strgrade . ': ' . $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, $DB; + + 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 $course + * @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 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) { + global $CFG; + + 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'; + $path = "$CFG->dirroot/mod/certificate/pix/$type/$certificate->printsignature"; + $uploadpath = "$CFG->dataroot/mod/certificate/pix/$type/$certificate->printsignature"; + 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; + } + } +} + +/** + * Generates a 10-digit code of random letters and numbers. + * + * @return string + */ +function certificate_generate_code() { + global $DB; + + $uniquecodefound = false; + $code = random_string(10); + while (!$uniquecodefound) { + if (!$DB->record_exists('certificate_issues', array('code' => $code))) { + $uniquecodefound = true; + } else { + $code = 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)) { + if ($handle = opendir($path)) { + while (false !== ($file = readdir($handle))) { + if (strpos($file, '.png', 1) || strpos($file, '.jpg', 1) ) { + $i = strpos($file, '.'); + if ($i > 1) { + // Set the name + $options[$file] = substr($file, 0, $i); + } + } + } + closedir($handle); + } + } + + return $options; +} diff --git a/mod_form.php b/mod_form.php new file mode 100644 index 0000000..5d7c227 --- /dev/null +++ b/mod_form.php @@ -0,0 +1,186 @@ +. + +/** +* Instance add/edit form +* +* @package mod +* @subpackage certificate +* @copyright Mark Nelson +* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later +*/ + +if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page +} + +require_once ($CFG->dirroot.'/course/moodleform_mod.php'); +require_once($CFG->dirroot.'/mod/certificate/lib.php'); + +class mod_certificate_mod_form extends moodleform_mod { + + function definition() { + global $CFG; + + $mform =& $this->_form; + + $mform->addElement('header', 'general', get_string('general', 'form')); + + $mform->addElement('text', 'name', get_string('certificatename', 'certificate'), array('size'=>'64')); + if (!empty($CFG->formatstringstriptags)) { + $mform->setType('name', PARAM_TEXT); + } else { + $mform->setType('name', PARAM_CLEAN); + } + $mform->addRule('name', null, 'required', null, 'client'); + + $this->add_intro_editor(false, get_string('intro', 'certificate')); + + // Issue options + $mform->addElement('header', 'issueoptions', get_string('issueoptions', 'certificate')); + $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes')); + $mform->addElement('select', 'emailteachers', get_string('emailteachers', 'certificate'), $ynoptions); + $mform->setDefault('emailteachers', 0); + $mform->addHelpButton('emailteachers', 'emailteachers', 'certificate'); + + $mform->addElement('text', 'emailothers', get_string('emailothers', 'certificate'), array('size'=>'40', 'maxsize'=>'200')); + $mform->setType('emailothers', PARAM_TEXT); + $mform->addHelpButton('emailothers', 'emailothers', 'certificate'); + + $deliveryoptions = array( 0 => get_string('openbrowser', 'certificate'), 1 => get_string('download', 'certificate'), 2 => get_string('emailcertificate', 'certificate')); + $mform->addElement('select', 'delivery', get_string('delivery', 'certificate'), $deliveryoptions); + $mform->setDefault('delivery', 0); + $mform->addHelpButton('delivery', 'delivery', 'certificate'); + + $mform->addElement('select', 'savecert', get_string('savecert', 'certificate'), $ynoptions); + $mform->setDefault('savecert', 0); + $mform->addHelpButton('savecert', 'savecert', 'certificate'); + + $reportfile = "$CFG->dirroot/certificates/index.php"; + if (file_exists($reportfile)) { + $mform->addElement('select', 'reportcert', get_string('reportcert', 'certificate'), $ynoptions); + $mform->setDefault('reportcert', 0); + $mform->addHelpButton('reportcert', 'reportcert', 'certificate'); + } + + $mform->addElement('text', 'requiredtime', get_string('coursetimereq', 'certificate'), array('size'=>'3')); + $mform->setType('requiredtime', PARAM_INT); + $mform->addHelpButton('requiredtime', 'coursetimereq', 'certificate'); + + // Text Options + $mform->addElement('header', 'textoptions', get_string('textoptions', 'certificate')); + + $modules = certificate_get_mods(); + $dateoptions = certificate_get_date_options() + $modules; + $mform->addElement('select', 'printdate', get_string('printdate', 'certificate'), $dateoptions); + $mform->setDefault('printdate', 'N'); + $mform->addHelpButton('printdate', 'printdate', 'certificate'); + + $dateformatoptions = array( 1 => 'January 1, 2000', 2 => 'January 1st, 2000', 3 => '1 January 2000', + 4 => 'January 2000', 5 => get_string('userdateformat', 'certificate')); + $mform->addElement('select', 'datefmt', get_string('datefmt', 'certificate'), $dateformatoptions); + $mform->setDefault('datefmt', 0); + $mform->addHelpButton('datefmt', 'datefmt', 'certificate'); + + $mform->addElement('select', 'printnumber', get_string('printnumber', 'certificate'), $ynoptions); + $mform->setDefault('printnumber', 0); + $mform->addHelpButton('printnumber', 'printnumber', 'certificate'); + + $gradeoptions = certificate_get_grade_options() + certificate_get_grade_categories($this->current->course) + $modules; + $mform->addElement('select', 'printgrade', get_string('printgrade', 'certificate'),$gradeoptions); + $mform->setDefault('printgrade', 0); + $mform->addHelpButton('printgrade', 'printgrade', 'certificate'); + + $gradeformatoptions = array( 1 => get_string('gradepercent', 'certificate'), 2 => get_string('gradepoints', 'certificate'), + 3 => get_string('gradeletter', 'certificate')); + $mform->addElement('select', 'gradefmt', get_string('gradefmt', 'certificate'), $gradeformatoptions); + $mform->setDefault('gradefmt', 0); + $mform->addHelpButton('gradefmt', 'gradefmt', 'certificate'); + + $outcomeoptions = certificate_get_outcomes(); + $mform->addElement('select', 'printoutcome', get_string('printoutcome', 'certificate'),$outcomeoptions); + $mform->setDefault('printoutcome', 0); + $mform->addHelpButton('printoutcome', 'printoutcome', 'certificate'); + + $mform->addElement('text', 'printhours', get_string('printhours', 'certificate'), array('size'=>'5', 'maxlength' => '255')); + $mform->setType('printhours', PARAM_TEXT); + $mform->addHelpButton('printhours', 'printhours', 'certificate'); + + $mform->addElement('select', 'printteacher', get_string('printteacher', 'certificate'), $ynoptions); + $mform->setDefault('printteacher', 0); + $mform->addHelpButton('printteacher', 'printteacher', 'certificate'); + + $mform->addElement('textarea', 'customtext', get_string('customtext', 'certificate'), array('cols'=>'40', 'rows'=>'4', 'wrap'=>'virtual')); + $mform->setType('customtext', PARAM_RAW); + $mform->addHelpButton('customtext', 'customtext', 'certificate'); + + // Design Options + $mform->addElement('header', 'designoptions', get_string('designoptions', 'certificate')); + $mform->addElement('select', 'certificatetype', get_string('certificatetype', 'certificate'), certificate_types()); + $mform->setDefault('certificatetype', 'A4_non_embedded'); + $mform->addHelpButton('certificatetype', 'certificatetype', 'certificate'); + + $orientation = array( 'L' => get_string('landscape', 'certificate'), 'P' => get_string('portrait', 'certificate')); + $mform->addElement('select', 'orientation', get_string('orientation', 'certificate'), $orientation); + $mform->setDefault('orientation', 'landscape'); + $mform->addHelpButton('orientation', 'orientation', 'certificate'); + + $mform->addElement('select', 'borderstyle', get_string('borderstyle', 'certificate'), certificate_get_images(CERT_IMAGE_BORDER)); + $mform->setDefault('borderstyle', '0'); + $mform->addHelpButton('borderstyle', 'borderstyle', 'certificate'); + + $printframe = array( 0 => get_string('no'), 1 => get_string('borderblack', 'certificate'), 2 => get_string('borderbrown', 'certificate'), + 3 => get_string('borderblue', 'certificate'), 4 => get_string('bordergreen', 'certificate')); + $mform->addElement('select', 'bordercolor', get_string('bordercolor', 'certificate'), $printframe); + $mform->setDefault('bordercolor', '0'); + $mform->addHelpButton('bordercolor', 'bordercolor', 'certificate'); + + $mform->addElement('select', 'printwmark', get_string('printwmark', 'certificate'), certificate_get_images(CERT_IMAGE_WATERMARK)); + $mform->setDefault('printwmark', '0'); + $mform->addHelpButton('printwmark', 'printwmark', 'certificate'); + + $mform->addElement('select', 'printsignature', get_string('printsignature', 'certificate'), certificate_get_images(CERT_IMAGE_SIGNATURE)); + $mform->setDefault('printsignature', '0'); + $mform->addHelpButton('printsignature', 'printsignature', 'certificate'); + + $mform->addElement('select', 'printseal', get_string('printseal', 'certificate'), certificate_get_images(CERT_IMAGE_SEAL)); + $mform->setDefault('printseal', '0'); + $mform->addHelpButton('printseal', 'printseal', 'certificate'); + + $this->standard_coursemodule_elements(); + + $this->add_action_buttons(); + } + + /** + * Some basic validation + * + * @param $data + * @param $files + * @return array + */ + public function validation($data, $files) { + $errors = parent::validation($data, $files); + + // Check that the required time entered is valid + if ((!is_number($data['requiredtime']) || $data['requiredtime'] < 0)) { + $errors['requiredtime'] = get_string('requiredtimenotvalid', 'certificate'); + } + + return $errors; + } +} \ No newline at end of file diff --git a/pix/borders/Fancy1-black.jpg b/pix/borders/Fancy1-black.jpg new file mode 100644 index 0000000..5b9191f Binary files /dev/null and b/pix/borders/Fancy1-black.jpg differ diff --git a/pix/borders/Fancy1-blue.jpg b/pix/borders/Fancy1-blue.jpg new file mode 100644 index 0000000..23370a9 Binary files /dev/null and b/pix/borders/Fancy1-blue.jpg differ diff --git a/pix/borders/Fancy1-brown.jpg b/pix/borders/Fancy1-brown.jpg new file mode 100644 index 0000000..4bad403 Binary files /dev/null and b/pix/borders/Fancy1-brown.jpg differ diff --git a/pix/borders/Fancy1-green.jpg b/pix/borders/Fancy1-green.jpg new file mode 100644 index 0000000..79c4f7f Binary files /dev/null and b/pix/borders/Fancy1-green.jpg differ diff --git a/pix/borders/Fancy2-black.jpg b/pix/borders/Fancy2-black.jpg new file mode 100644 index 0000000..b85f182 Binary files /dev/null and b/pix/borders/Fancy2-black.jpg differ diff --git a/pix/borders/Fancy2-blue.jpg b/pix/borders/Fancy2-blue.jpg new file mode 100644 index 0000000..89f53f8 Binary files /dev/null and b/pix/borders/Fancy2-blue.jpg differ diff --git a/pix/borders/Fancy2-brown.jpg b/pix/borders/Fancy2-brown.jpg new file mode 100644 index 0000000..cf8e6c3 Binary files /dev/null and b/pix/borders/Fancy2-brown.jpg differ diff --git a/pix/borders/Fancy2-green.jpg b/pix/borders/Fancy2-green.jpg new file mode 100644 index 0000000..0ad1b52 Binary files /dev/null and b/pix/borders/Fancy2-green.jpg differ diff --git a/pix/icon.gif b/pix/icon.gif new file mode 100644 index 0000000..101ece6 Binary files /dev/null and b/pix/icon.gif differ diff --git a/pix/seals/Fancy.png b/pix/seals/Fancy.png new file mode 100644 index 0000000..a0e2819 Binary files /dev/null and b/pix/seals/Fancy.png differ diff --git a/pix/seals/Logo.png b/pix/seals/Logo.png new file mode 100644 index 0000000..3503d4d Binary files /dev/null and b/pix/seals/Logo.png differ diff --git a/pix/seals/Plain.png b/pix/seals/Plain.png new file mode 100644 index 0000000..3e9e2ce Binary files /dev/null and b/pix/seals/Plain.png differ diff --git a/pix/seals/Quality.png b/pix/seals/Quality.png new file mode 100644 index 0000000..8debb0e Binary files /dev/null and b/pix/seals/Quality.png differ diff --git a/pix/seals/Teamwork.png b/pix/seals/Teamwork.png new file mode 100644 index 0000000..6a90174 Binary files /dev/null and b/pix/seals/Teamwork.png differ diff --git a/pix/signatures/Line.png b/pix/signatures/Line.png new file mode 100644 index 0000000..53eda7b Binary files /dev/null and b/pix/signatures/Line.png differ diff --git a/pix/signatures/RVincent.png b/pix/signatures/RVincent.png new file mode 100644 index 0000000..af6678a Binary files /dev/null and b/pix/signatures/RVincent.png differ diff --git a/pix/watermarks/Crest.png b/pix/watermarks/Crest.png new file mode 100644 index 0000000..5f1f952 Binary files /dev/null and b/pix/watermarks/Crest.png differ diff --git a/pix/watermarks/Fleursdelis.png b/pix/watermarks/Fleursdelis.png new file mode 100644 index 0000000..7fb21b2 Binary files /dev/null and b/pix/watermarks/Fleursdelis.png differ diff --git a/report.php b/report.php new file mode 100644 index 0000000..553aca2 --- /dev/null +++ b/report.php @@ -0,0 +1,280 @@ +. + +/** + * Handles viewing the report + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../../config.php'); +require_once('lib.php'); + +$id = required_param('id', PARAM_INT); // Course module ID +$sort = optional_param('sort', '', PARAM_RAW); +$download = optional_param('download', '', PARAM_ALPHA); +$action = optional_param('action', '', PARAM_ALPHA); + +$page = optional_param('page', 0, PARAM_INT); +$perpage = optional_param('perpage', CERT_PER_PAGE, PARAM_INT); + +// Ensure the perpage variable does not exceed the max allowed if +// the user has not specified they wish to view all certificates. +if (CERT_PER_PAGE !== 0) { + if (($perpage > CERT_MAX_PER_PAGE) || ($perpage <= 0)) { + $perpage = CERT_MAX_PER_PAGE; + } +} else { + $perpage = '9999999'; +} + +$url = new moodle_url('/mod/certificate/report.php', array('id'=>$id, 'page' => $page, 'perpage' => $perpage)); +if ($download) { + $url->param('download', $download); +} +if ($action) { + $url->param('action', $action); +} +$PAGE->set_url($url); + +if (!$cm = get_coursemodule_from_id('certificate', $id)) { + print_error('Course Module ID was incorrect'); +} + +if (!$course = $DB->get_record('course', array('id'=> $cm->course))) { + print_error('Course is misconfigured'); +} + +if (!$certificate = $DB->get_record('certificate', array('id'=> $cm->instance))) { + print_error('Certificate ID was incorrect'); +} + +// Requires a course login +require_course_login($course->id, false, $cm); + +// Check capabilities +$context = context_module::instance($cm->id); +require_capability('mod/certificate:manage', $context); + +// Declare some variables +$strcertificates = get_string('modulenameplural', 'certificate'); +$strcertificate = get_string('modulename', 'certificate'); +$strto = get_string('awardedto', 'certificate'); +$strdate = get_string('receiveddate', 'certificate'); +$strgrade = get_string('grade','certificate'); +$strcode = get_string('code', 'certificate'); +$strreport= get_string('report', 'certificate'); + +if (!$download) { + $PAGE->navbar->add($strreport); + $PAGE->set_title(format_string($certificate->name).": $strreport"); + $PAGE->set_heading($course->fullname); + // Check to see if groups are being used in this choice + if ($groupmode = groups_get_activity_groupmode($cm)) { + groups_get_activity_group($cm, true); + } +} else { + $groupmode = groups_get_activity_groupmode($cm); + // Get all results when $page and $perpage are 0 + $page = $perpage = 0; +} + +add_to_log($course->id, 'certificate', 'view', "report.php?id=$cm->id", '$certificate->id', $cm->id); + +// Ensure there are issues to display, if not display notice +if (!$users = certificate_get_issues($certificate->id, $DB->sql_fullname(), $groupmode, $cm, $page, $perpage)) { + echo $OUTPUT->header(); + groups_print_activity_menu($cm, $CFG->wwwroot . '/mod/certificate/report.php?id='.$id); + notify(get_string('nocertificatesissued', 'certificate')); + echo $OUTPUT->footer($course); + exit(); +} + +if ($download == "ods") { + require_once("$CFG->libdir/odslib.class.php"); + + // Calculate file name + $filename = clean_filename("$course->shortname " . rtrim($certificate->name, '.') . '.ods'); + // Creating a workbook + $workbook = new MoodleODSWorkbook("-"); + // Send HTTP headers + $workbook->send($filename); + // Creating the first worksheet + $myxls = $workbook->add_worksheet($strreport); + + // Print names of all the fields + $myxls->write_string(0, 0, get_string("lastname")); + $myxls->write_string(0, 1, get_string("firstname")); + $myxls->write_string(0, 2, get_string("idnumber")); + $myxls->write_string(0, 3, get_string("group")); + $myxls->write_string(0, 4, $strdate); + $myxls->write_string(0, 5, $strgrade); + $myxls->write_string(0, 6, $strcode); + + // Generate the data for the body of the spreadsheet + $i = 0; + $row = 1; + if ($users) { + foreach ($users as $user) { + $myxls->write_string($row, 0, $user->lastname); + $myxls->write_string($row, 1, $user->firstname); + $studentid = (!empty($user->idnumber)) ? $user->idnumber : " "; + $myxls->write_string($row, 2, $studentid); + $ug2 = ''; + if ($usergrps = groups_get_all_groups($course->id, $user->id)) { + foreach ($usergrps as $ug) { + $ug2 = $ug2. $ug->name; + } + } + $myxls->write_string($row, 3, $ug2); + $myxls->write_string($row, 4, userdate($user->timecreated)); + $myxls->write_string($row, 5, certificate_get_grade($certificate, $course, $user->id)); + $myxls->write_string($row, 6, $user->code); + $row++; + } + $pos = 6; + } + // Close the workbook + $workbook->close(); + exit; +} + +if ($download == "xls") { + require_once("$CFG->libdir/excellib.class.php"); + + // Calculate file name + $filename = clean_filename("$course->shortname " . rtrim($certificate->name, '.') . '.xls'); + // Creating a workbook + $workbook = new MoodleExcelWorkbook("-"); + // Send HTTP headers + $workbook->send($filename); + // Creating the first worksheet + $myxls = $workbook->add_worksheet($strreport); + + // Print names of all the fields + $myxls->write_string(0, 0, get_string("lastname")); + $myxls->write_string(0, 1, get_string("firstname")); + $myxls->write_string(0, 2, get_string("idnumber")); + $myxls->write_string(0, 3, get_string("group")); + $myxls->write_string(0, 4, $strdate); + $myxls->write_string(0, 5, $strgrade); + $myxls->write_string(0, 6, $strcode); + + // Generate the data for the body of the spreadsheet + $i = 0; + $row = 1; + if ($users) { + foreach ($users as $user) { + $myxls->write_string($row, 0, $user->lastname); + $myxls->write_string($row, 1, $user->firstname); + $studentid = (!empty($user->idnumber)) ? $user->idnumber : " "; + $myxls->write_string($row,2,$studentid); + $ug2 = ''; + if ($usergrps = groups_get_all_groups($course->id, $user->id)) { + foreach ($usergrps as $ug) { + $ug2 = $ug2 . $ug->name; + } + } + $myxls->write_string($row, 3, $ug2); + $myxls->write_string($row, 4, userdate($user->timecreated)); + $myxls->write_string($row, 5, certificate_get_grade($certificate, $course, $user->id)); + $myxls->write_string($row, 6, $user->code); + $row++; + } + $pos = 6; + } + // Close the workbook + $workbook->close(); + exit; +} + +if ($download == "txt") { + $filename = clean_filename("$course->shortname " . rtrim($certificate->name, '.') . '.txt'); + + header("Content-Type: application/download\n"); + header("Content-Disposition: attachment; filename=\"$filename\""); + header("Expires: 0"); + header("Cache-Control: must-revalidate,post-check=0,pre-check=0"); + header("Pragma: public"); + + // Print names of all the fields + echo get_string("lastname"). "\t" .get_string("firstname") . "\t". get_string("idnumber") . "\t"; + echo get_string("group"). "\t"; + echo $strdate. "\t"; + echo $strgrade. "\t"; + echo $strcode. "\n"; + + // Generate the data for the body of the spreadsheet + $i=0; + $row=1; + if ($users) foreach ($users as $user) { + echo $user->lastname; + echo "\t" . $user->firstname; + $studentid = " "; + if (!empty($user->idnumber)) { + $studentid = $user->idnumber; + } + echo "\t" . $studentid . "\t"; + $ug2 = ''; + if ($usergrps = groups_get_all_groups($course->id, $user->id)) { + foreach ($usergrps as $ug) { + $ug2 = $ug2. $ug->name; + } + } + echo $ug2 . "\t"; + echo userdate($user->timecreated) . "\t"; + echo certificate_get_grade($certificate, $course, $user->id) . "\t"; + echo $user->code . "\n"; + $row++; + } + exit; +} + +$usercount = count(certificate_get_issues($certificate->id, $DB->sql_fullname(), $groupmode, $cm)); + +// Create the table for the users +$table = new html_table(); +$table->width = "95%"; +$table->tablealign = "center"; +$table->head = array($strto, $strdate, $strgrade, $strcode); +$table->align = array("left", "left", "center", "center"); +foreach ($users as $user) { + $name = $OUTPUT->user_picture($user) . fullname($user); + $date = userdate($user->timecreated) . certificate_print_user_files($certificate, $user->id, $context->id); + $code = $user->code; + $table->data[] = array ($name, $date, certificate_get_grade($certificate, $course, $user->id), $code); +} + +// Create table to store buttons +$tablebutton = new html_table(); +$tablebutton->attributes['class'] = 'downloadreport'; +$btndownloadods = $OUTPUT->single_button(new moodle_url("report.php", array('id'=>$cm->id, 'download'=>'ods')), get_string("downloadods")); +$btndownloadxls = $OUTPUT->single_button(new moodle_url("report.php", array('id'=>$cm->id, 'download'=>'xls')), get_string("downloadexcel")); +$btndownloadtxt = $OUTPUT->single_button(new moodle_url("report.php", array('id'=>$cm->id, 'download'=>'txt')), get_string("downloadtext")); +$tablebutton->data[] = array($btndownloadods, $btndownloadxls, $btndownloadtxt); + +echo $OUTPUT->header(); +groups_print_activity_menu($cm, $CFG->wwwroot . '/mod/certificate/report.php?id='.$id); +echo $OUTPUT->heading(get_string('modulenameplural', 'certificate')); +echo $OUTPUT->paging_bar($usercount, $page, $perpage, $url); +echo '
'; +echo html_writer::table($table); +echo html_writer::tag('div', html_writer::table($tablebutton), array('style' => 'margin:auto; width:50%')); +echo $OUTPUT->footer($course); diff --git a/review.php b/review.php new file mode 100644 index 0000000..69c6fbb --- /dev/null +++ b/review.php @@ -0,0 +1,100 @@ +. + +/** + * This page reviews a certificate + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../../config.php'); +require_once('lib.php'); +require_once("$CFG->libdir/pdflib.php"); + +// Retrieve any variables that are passed +$id = required_param('id', PARAM_INT); // Course Module ID +$action = optional_param('action', '', PARAM_ALPHA); + +if (!$cm = get_coursemodule_from_id('certificate', $id)) { + print_error('Course Module ID was incorrect'); +} + +if (!$course = $DB->get_record('course', array('id'=> $cm->course))) { + print_error('course is misconfigured'); +} + +if (!$certificate = $DB->get_record('certificate', array('id'=> $cm->instance))) { + print_error('course module is incorrect'); +} + +// Requires a course login +require_course_login($course->id, true, $cm); + +// Check the capabilities +$context = context_module::instance($cm->id); +require_capability('mod/certificate:view', $context); + +// Initialize $PAGE, compute blocks +$PAGE->set_url('/mod/certificate/review.php', array('id' => $cm->id)); +$PAGE->set_context($context); +$PAGE->set_cm($cm); +$PAGE->set_title(format_string($certificate->name)); +$PAGE->set_heading(format_string($course->fullname)); + +// Get previous cert record +if (!$certrecord = $DB->get_record('certificate_issues', array('userid' => $USER->id, 'certificateid' => $certificate->id))) { + notice(get_string('nocertificatesissued', 'certificate'), "$CFG->wwwroot/course/view.php?id=$course->id"); + die; +} + +// Load the specific certificatetype +require ("$CFG->dirroot/mod/certificate/type/$certificate->certificatetype/certificate.php"); + +if ($action) { + // Remove full-stop at the end if it exists, to avoid "..pdf" being created and being filtered by clean_filename + $certname = rtrim($certificate->name, '.'); + $filename = clean_filename("$certname.pdf"); + $pdf->Output($filename, 'I'); // open in browser + exit(); +} + +echo $OUTPUT->header(); + +if (has_capability('mod/certificate:manage', $context)) { + $numusers = count(certificate_get_issues($certificate->id, 'ci.timecreated ASC', '', $cm)); + $url = html_writer::tag('a', get_string('viewcertificateviews', 'certificate', $numusers), + array('href' => $CFG->wwwroot . '/mod/certificate/report.php?id=' . $cm->id)); + echo html_writer::tag('div', $url, array('class' => 'reportlink')); +} + +if (!empty($certificate->intro)) { + echo $OUTPUT->box(format_module_intro('certificate', $certificate, $cm->id), 'generalbox', 'intro'); +} + +echo html_writer::tag('p', get_string('viewed', 'certificate'). '
' . userdate($certrecord->timecreated), array('style' => 'text-align:center')); + +$link = new moodle_url('/mod/certificate/review.php?id='.$cm->id.'&action=get'); +$linkname = get_string('reviewcertificate', 'certificate'); +$button = new single_button($link, $linkname); +$button->add_action(new popup_action('click', $link, array('height' => 600, 'width' => 800))); + +echo html_writer::tag('div', $OUTPUT->render($button), array('style' => 'text-align:center')); + +echo $OUTPUT->footer($course); diff --git a/settings.php b/settings.php new file mode 100644 index 0000000..c5ca962 --- /dev/null +++ b/settings.php @@ -0,0 +1,34 @@ +. + +/** + * Provides some custom settings for the certificate module + * + * @package mod + * @subpackage certificate + * @copyright Michael Avelar + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->dirroot.'/mod/certificate/adminsetting.class.php'); + +$settings->add(new mod_certificate_admin_setting_upload('certificate/uploadimage', + get_string('uploadimage', 'certificate'), get_string('uploadimagedesc', 'certificate'), '')); + +?> \ No newline at end of file diff --git a/type/A4_embedded/certificate.php b/type/A4_embedded/certificate.php new file mode 100644 index 0000000..d95af58 --- /dev/null +++ b/type/A4_embedded/certificate.php @@ -0,0 +1,117 @@ +. + +/** + * A4_embedded certificate type + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); // It must be included from view.php +} + +$pdf = new PDF($certificate->orientation, 'mm', 'A4', true, 'UTF-8', false); + +$pdf->SetTitle($certificate->name); +$pdf->SetProtection(array('modify')); +$pdf->setPrintHeader(false); +$pdf->setPrintFooter(false); +$pdf->SetAutoPageBreak(false, 0); +$pdf->AddPage(); + +// Define variables +// Landscape +if ($certificate->orientation == 'L') { + $x = 10; + $y = 30; + $sealx = 230; + $sealy = 150; + $sigx = 47; + $sigy = 155; + $custx = 47; + $custy = 155; + $wmarkx = 40; + $wmarky = 31; + $wmarkw = 212; + $wmarkh = 148; + $brdrx = 0; + $brdry = 0; + $brdrw = 297; + $brdrh = 210; + $codey = 175; +} else { // Portrait + $x = 10; + $y = 40; + $sealx = 150; + $sealy = 220; + $sigx = 30; + $sigy = 230; + $custx = 30; + $custy = 230; + $wmarkx = 26; + $wmarky = 58; + $wmarkw = 158; + $wmarkh = 170; + $brdrx = 0; + $brdry = 0; + $brdrw = 210; + $brdrh = 297; + $codey = 250; +} + +// Add images and lines +certificate_print_image($pdf, $certificate, CERT_IMAGE_BORDER, $brdrx, $brdry, $brdrw, $brdrh); +certificate_draw_frame($pdf, $certificate); +// Set alpha to semi-transparency +$pdf->SetAlpha(0.2); +certificate_print_image($pdf, $certificate, CERT_IMAGE_WATERMARK, $wmarkx, $wmarky, $wmarkw, $wmarkh); +$pdf->SetAlpha(1); +certificate_print_image($pdf, $certificate, CERT_IMAGE_SEAL, $sealx, $sealy, '', ''); +certificate_print_image($pdf, $certificate, CERT_IMAGE_SIGNATURE, $sigx, $sigy, '', ''); + +// Add text +$pdf->SetTextColor(0, 0, 120); +certificate_print_text($pdf, $x, $y, 'C', 'freesans', '', 30, get_string('title', 'certificate')); +$pdf->SetTextColor(0, 0, 0); +certificate_print_text($pdf, $x, $y + 20, 'C', 'freeserif', '', 20, get_string('certify', 'certificate')); +certificate_print_text($pdf, $x, $y + 36, 'C', 'freesans', '', 30, fullname($USER)); +certificate_print_text($pdf, $x, $y + 55, 'C', 'freesans', '', 20, get_string('statement', 'certificate')); +certificate_print_text($pdf, $x, $y + 72, 'C', 'freesans', '', 20, $course->fullname); +certificate_print_text($pdf, $x, $y + 92, 'C', 'freesans', '', 14, certificate_get_date($certificate, $certrecord, $course)); +certificate_print_text($pdf, $x, $y + 102, 'C', 'freeserif', '', 10, certificate_get_grade($certificate, $course)); +certificate_print_text($pdf, $x, $y + 112, 'C', 'freeserif', '', 10, certificate_get_outcome($certificate, $course)); +if ($certificate->printhours) { + certificate_print_text($pdf, $x, $y + 122, 'C', 'freeserif', '', 10, get_string('credithours', 'certificate') . ': ' . $certificate->printhours); +} +certificate_print_text($pdf, $x, $codey, 'C', 'freeserif', '', 10, certificate_get_code($certificate, $certrecord)); +$i = 0; +if ($certificate->printteacher) { + $context = context_module::instance($cm->id); + if ($teachers = get_users_by_capability($context, 'mod/certificate:printteacher', '', $sort = 'u.lastname ASC', '', '', '', '', false)) { + foreach ($teachers as $teacher) { + $i++; + certificate_print_text($pdf, $sigx, $sigy + ($i * 4), 'L', 'freeserif', '', 12, fullname($teacher)); + } + } +} + +certificate_print_text($pdf, $custx, $custy, 'L', null, null, null, $certificate->customtext); +?> \ No newline at end of file diff --git a/type/A4_non_embedded/certificate.php b/type/A4_non_embedded/certificate.php new file mode 100644 index 0000000..7bdc7d4 --- /dev/null +++ b/type/A4_non_embedded/certificate.php @@ -0,0 +1,117 @@ +. + +/** + * A4_non_embedded certificate type + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); // It must be included from view.php +} + +$pdf = new PDF($certificate->orientation, 'mm', 'A4', true, 'UTF-8', false); + +$pdf->SetTitle($certificate->name); +$pdf->SetProtection(array('modify')); +$pdf->setPrintHeader(false); +$pdf->setPrintFooter(false); +$pdf->SetAutoPageBreak(false, 0); +$pdf->AddPage(); + +// Define variables +// Landscape +if ($certificate->orientation == 'L') { + $x = 10; + $y = 30; + $sealx = 230; + $sealy = 150; + $sigx = 47; + $sigy = 155; + $custx = 47; + $custy = 155; + $wmarkx = 40; + $wmarky = 31; + $wmarkw = 212; + $wmarkh = 148; + $brdrx = 0; + $brdry = 0; + $brdrw = 297; + $brdrh = 210; + $codey = 175; +} else { // Portrait + $x = 10; + $y = 40; + $sealx = 150; + $sealy = 220; + $sigx = 30; + $sigy = 230; + $custx = 30; + $custy = 230; + $wmarkx = 26; + $wmarky = 58; + $wmarkw = 158; + $wmarkh = 170; + $brdrx = 0; + $brdry = 0; + $brdrw = 210; + $brdrh = 297; + $codey = 250; +} + +// Add images and lines +certificate_print_image($pdf, $certificate, CERT_IMAGE_BORDER, $brdrx, $brdry, $brdrw, $brdrh); +certificate_draw_frame($pdf, $certificate); +// Set alpha to semi-transparency +$pdf->SetAlpha(0.2); +certificate_print_image($pdf, $certificate, CERT_IMAGE_WATERMARK, $wmarkx, $wmarky, $wmarkw, $wmarkh); +$pdf->SetAlpha(1); +certificate_print_image($pdf, $certificate, CERT_IMAGE_SEAL, $sealx, $sealy, '', ''); +certificate_print_image($pdf, $certificate, CERT_IMAGE_SIGNATURE, $sigx, $sigy, '', ''); + +// Add text +$pdf->SetTextColor(0, 0, 120); +certificate_print_text($pdf, $x, $y, 'C', 'Helvetica', '', 30, get_string('title', 'certificate')); +$pdf->SetTextColor(0, 0, 0); +certificate_print_text($pdf, $x, $y + 20, 'C', 'Times', '', 20, get_string('certify', 'certificate')); +certificate_print_text($pdf, $x, $y + 36, 'C', 'Helvetica', '', 30, fullname($USER)); +certificate_print_text($pdf, $x, $y + 55, 'C', 'Helvetica', '', 20, get_string('statement', 'certificate')); +certificate_print_text($pdf, $x, $y + 72, 'C', 'Helvetica', '', 20, $course->fullname); +certificate_print_text($pdf, $x, $y + 92, 'C', 'Helvetica', '', 14, certificate_get_date($certificate, $certrecord, $course)); +certificate_print_text($pdf, $x, $y + 102, 'C', 'Times', '', 10, certificate_get_grade($certificate, $course)); +certificate_print_text($pdf, $x, $y + 112, 'C', 'Times', '', 10, certificate_get_outcome($certificate, $course)); +if ($certificate->printhours) { + certificate_print_text($pdf, $x, $y + 122, 'C', 'Times', '', 10, get_string('credithours', 'certificate') . ': ' . $certificate->printhours); +} +certificate_print_text($pdf, $x, $codey, 'C', 'Times', '', 10, certificate_get_code($certificate, $certrecord)); +$i = 0; +if ($certificate->printteacher) { + $context = context_module::instance($cm->id); + if ($teachers = get_users_by_capability($context, 'mod/certificate:printteacher', '', $sort = 'u.lastname ASC', '', '', '', '', false)) { + foreach ($teachers as $teacher) { + $i++; + certificate_print_text($pdf, $sigx, $sigy + ($i * 4), 'L', 'Times', '', 12, fullname($teacher)); + } + } +} + +certificate_print_text($pdf, $custx, $custy, 'L', null, null, null, $certificate->customtext); +?> \ No newline at end of file diff --git a/type/letter_embedded/certificate.php b/type/letter_embedded/certificate.php new file mode 100644 index 0000000..c24b1a7 --- /dev/null +++ b/type/letter_embedded/certificate.php @@ -0,0 +1,117 @@ +. + +/** + * letter_embedded certificate type + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); // It must be included from view.php +} + +$pdf = new PDF($certificate->orientation, 'pt', 'Letter', true, 'UTF-8', false); + +$pdf->SetTitle($certificate->name); +$pdf->SetProtection(array('modify')); +$pdf->setPrintHeader(false); +$pdf->setPrintFooter(false); +$pdf->SetAutoPageBreak(false, 0); +$pdf->AddPage(); + +// Define variables +// Landscape +if ($certificate->orientation == 'L') { + $x = 28; + $y = 125; + $sealx = 590; + $sealy = 425; + $sigx = 130; + $sigy = 440; + $custx = 133; + $custy = 440; + $wmarkx = 100; + $wmarky = 90; + $wmarkw = 600; + $wmarkh = 420; + $brdrx = 0; + $brdry = 0; + $brdrw = 792; + $brdrh = 612; + $codey = 505; +} else { // Portrait + $x = 28; + $y = 170; + $sealx = 440; + $sealy = 590; + $sigx = 85; + $sigy = 580; + $custx = 88; + $custy = 580; + $wmarkx = 78; + $wmarky = 130; + $wmarkw = 450; + $wmarkh = 480; + $brdrx = 10; + $brdry = 10; + $brdrw = 594; + $brdrh = 771; + $codey = 660; +} + +// Add images and lines +certificate_print_image($pdf, $certificate, CERT_IMAGE_BORDER, $brdrx, $brdry, $brdrw, $brdrh); +certificate_draw_frame_letter($pdf, $certificate); +// Set alpha to semi-transparency +$pdf->SetAlpha(0.1); +certificate_print_image($pdf, $certificate, CERT_IMAGE_WATERMARK, $wmarkx, $wmarky, $wmarkw, $wmarkh); +$pdf->SetAlpha(1); +certificate_print_image($pdf, $certificate, CERT_IMAGE_SEAL, $sealx, $sealy, '', ''); +certificate_print_image($pdf, $certificate, CERT_IMAGE_SIGNATURE, $sigx, $sigy, '', ''); + +// Add text +$pdf->SetTextColor(0, 0, 120); +certificate_print_text($pdf, $x, $y, 'C', 'freesans', '', 30, get_string('title', 'certificate')); +$pdf->SetTextColor(0, 0, 0); +certificate_print_text($pdf, $x, $y + 55, 'C', 'freeserif', '', 20, get_string('certify', 'certificate')); +certificate_print_text($pdf, $x, $y + 105, 'C', 'freeserif', '', 30, fullname($USER)); +certificate_print_text($pdf, $x, $y + 155, 'C', 'freeserif', '', 20, get_string('statement', 'certificate')); +certificate_print_text($pdf, $x, $y + 205, 'C', 'freeserif', '', 20, $course->fullname); +certificate_print_text($pdf, $x, $y + 255, 'C', 'freeserif', '', 14, certificate_get_date($certificate, $certrecord, $course)); +certificate_print_text($pdf, $x, $y + 283, 'C', 'freeserif', '', 10, certificate_get_grade($certificate, $course)); +certificate_print_text($pdf, $x, $y + 311, 'C', 'freeserif', '', 10, certificate_get_outcome($certificate, $course)); +if ($certificate->printhours) { + certificate_print_text($pdf, $x, $y + 339, 'C', 'freeserif', '', 10, get_string('credithours', 'certificate') . ': ' . $certificate->printhours); +} +certificate_print_text($pdf, $x, $codey, 'C', 'freeserif', '', 10, certificate_get_code($certificate, $certrecord)); +$i = 0; +if ($certificate->printteacher) { + $context = context_module::instance($cm->id); + if ($teachers = get_users_by_capability($context, 'mod/certificate:printteacher', '', $sort = 'u.lastname ASC', '', '', '', '', false)) { + foreach ($teachers as $teacher) { + $i++; + certificate_print_text($pdf, $sigx, $sigy + ($i * 12), 'L', 'freeserif', '', 12, fullname($teacher)); + } + } +} + +certificate_print_text($pdf, $custx, $custy, 'L', null, null, null, $certificate->customtext); +?> \ No newline at end of file diff --git a/type/letter_non_embedded/certificate.php b/type/letter_non_embedded/certificate.php new file mode 100644 index 0000000..33b9635 --- /dev/null +++ b/type/letter_non_embedded/certificate.php @@ -0,0 +1,117 @@ +. + +/** + * letter_non_embedded certificate type + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); // It must be included from view.php +} + +$pdf = new PDF($certificate->orientation, 'pt', 'Letter', true, 'UTF-8', false); + +$pdf->SetTitle($certificate->name); +$pdf->SetProtection(array('modify')); +$pdf->setPrintHeader(false); +$pdf->setPrintFooter(false); +$pdf->SetAutoPageBreak(false, 0); +$pdf->AddPage(); + +// Define variables +// Landscape +if ($certificate->orientation == 'L') { + $x = 28; + $y = 125; + $sealx = 590; + $sealy = 425; + $sigx = 130; + $sigy = 440; + $custx = 133; + $custy = 440; + $wmarkx = 100; + $wmarky = 90; + $wmarkw = 600; + $wmarkh = 420; + $brdrx = 0; + $brdry = 0; + $brdrw = 792; + $brdrh = 612; + $codey = 505; +} else { // Portrait + $x = 28; + $y = 170; + $sealx = 440; + $sealy = 590; + $sigx = 85; + $sigy = 580; + $custx = 88; + $custy = 580; + $wmarkx = 78; + $wmarky = 130; + $wmarkw = 450; + $wmarkh = 480; + $brdrx = 10; + $brdry = 10; + $brdrw = 594; + $brdrh = 771; + $codey = 660; +} + +// Add images and lines +certificate_print_image($pdf, $certificate, CERT_IMAGE_BORDER, $brdrx, $brdry, $brdrw, $brdrh); +certificate_draw_frame_letter($pdf, $certificate); +// Set alpha to semi-transparency +$pdf->SetAlpha(0.1); +certificate_print_image($pdf, $certificate, CERT_IMAGE_WATERMARK, $wmarkx, $wmarky, $wmarkw, $wmarkh); +$pdf->SetAlpha(1); +certificate_print_image($pdf, $certificate, CERT_IMAGE_SEAL, $sealx, $sealy, '', ''); +certificate_print_image($pdf, $certificate, CERT_IMAGE_SIGNATURE, $sigx, $sigy, '', ''); + +// Add text +$pdf->SetTextColor(0, 0, 120); +certificate_print_text($pdf, $x, $y, 'C', 'Helvetica', '', 30, get_string('title', 'certificate')); +$pdf->SetTextColor(0, 0, 0); +certificate_print_text($pdf, $x, $y + 55, 'C', 'Times', '', 20, get_string('certify', 'certificate')); +certificate_print_text($pdf, $x, $y + 105, 'C', 'Helvetica', '', 30, fullname($USER)); +certificate_print_text($pdf, $x, $y + 155, 'C', 'Helvetica', '', 20, get_string('statement', 'certificate')); +certificate_print_text($pdf, $x, $y + 205, 'C', 'Helvetica', '', 20, $course->fullname); +certificate_print_text($pdf, $x, $y + 255, 'C', 'Helvetica', '', 14, certificate_get_date($certificate, $certrecord, $course)); +certificate_print_text($pdf, $x, $y + 283, 'C', 'Times', '', 10, certificate_get_grade($certificate, $course)); +certificate_print_text($pdf, $x, $y + 311, 'C', 'Times', '', 10, certificate_get_outcome($certificate, $course)); +if ($certificate->printhours) { + certificate_print_text($pdf, $x, $y + 339, 'C', 'Times', '', 10, get_string('credithours', 'certificate') . ': ' . $certificate->printhours); +} +certificate_print_text($pdf, $x, $codey, 'C', 'Times', '', 10, certificate_get_code($certificate, $certrecord)); +$i = 0; +if ($certificate->printteacher) { + $context = context_module::instance($cm->id); + if ($teachers = get_users_by_capability($context, 'mod/certificate:printteacher', '', $sort = 'u.lastname ASC', '', '', '', '', false)) { + foreach ($teachers as $teacher) { + $i++; + certificate_print_text($pdf, $sigx, $sigy + ($i * 12), 'L', 'Times', '', 12, fullname($teacher)); + } + } +} + +certificate_print_text($pdf, $custx, $custy, 'L', null, null, null, $certificate->customtext); +?> \ No newline at end of file diff --git a/upload_image.php b/upload_image.php new file mode 100644 index 0000000..c9811b3 --- /dev/null +++ b/upload_image.php @@ -0,0 +1,66 @@ +. + +/** + * Handles uploading files + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require('../../config.php'); +require_once($CFG->dirroot.'/mod/certificate/lib.php'); +require_once($CFG->dirroot.'/mod/certificate/upload_image_form.php'); + +require_login(); + +$context = context_system::instance(); +require_capability('moodle/site:config', $context); + +$struploadimage = get_string('uploadimage', 'certificate'); + +$PAGE->set_url('/admin/settings.php', array('section' => 'modsettingcertificate')); +$PAGE->set_pagetype('admin-setting-modsettingcertificate'); +$PAGE->set_pagelayout('admin'); +$PAGE->set_context($context); +$PAGE->set_title($struploadimage); +$PAGE->set_heading($SITE->fullname); +$PAGE->navbar->add($struploadimage); + +$upload_form = new mod_certificate_upload_image_form(); + +if ($upload_form->is_cancelled()) { + redirect(new moodle_url('/admin/settings.php?section=modsettingcertificate')); +} else if ($data = $upload_form->get_data()) { + // Ensure the directory for storing is created + $uploaddir = "mod/certificate/pix/$data->imagetype"; + $filename = $upload_form->get_new_filename('certificateimage'); + make_upload_directory($uploaddir); + $destination = $CFG->dataroot . '/' . $uploaddir . '/' . $filename; + if (!$upload_form->save_file('certificateimage', $destination, true)) { + throw new coding_exception('File upload failed'); + } + + redirect(new moodle_url('/admin/settings.php?section=modsettingcertificate'), get_string('changessaved')); +} + +echo $OUTPUT->header(); +echo $upload_form->display(); +echo $OUTPUT->footer(); +?> diff --git a/upload_image_form.php b/upload_image_form.php new file mode 100644 index 0000000..e5977cd --- /dev/null +++ b/upload_image_form.php @@ -0,0 +1,84 @@ +. + +/** + * Handles uploading files + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page +} + +require_once($CFG->libdir.'/formslib.php'); +require_once($CFG->dirroot.'/mod/certificate/lib.php'); + +class mod_certificate_upload_image_form extends moodleform { + + function definition() { + global $CFG; + + $mform =& $this->_form; + + $imagetypes = array( + CERT_IMAGE_BORDER => get_string('border', 'certificate'), + CERT_IMAGE_WATERMARK => get_string('watermark', 'certificate'), + CERT_IMAGE_SIGNATURE => get_string('signature', 'certificate'), + CERT_IMAGE_SEAL => get_string('seal', 'certificate') + ); + + $mform->addElement('select', 'imagetype', get_string('imagetype', 'certificate'), $imagetypes); + + $mform->addElement('filepicker', 'certificateimage', ''); + $mform->addRule('certificateimage', null, 'required', null, 'client'); + + $this->add_action_buttons(); + } + + /** + * Some validation - Michael Avelar + */ + function validation($data, $files) { + $errors = parent::validation($data, $files); + + $supportedtypes = array('jpe' => 'image/jpeg', + 'jpeIE' => 'image/pjpeg', + 'jpeg' => 'image/jpeg', + 'jpegIE' => 'image/pjpeg', + 'jpg' => 'image/jpeg', + 'jpgIE' => 'image/pjpeg', + 'png' => 'image/png', + 'pngIE' => 'image/x-png'); + + $files = $this->get_draft_files('certificateimage'); + if ($files) { + foreach ($files as $file) { + if (!in_array($file->get_mimetype(), $supportedtypes)) { + $errors['certificateimage'] = get_string('unsupportedfiletype', 'certificate'); + } + } + } else { + $errors['certificateimage'] = get_string('nofileselected', 'certificate'); + } + + return $errors; + } +} \ No newline at end of file diff --git a/version.php b/version.php new file mode 100644 index 0000000..2caf2fd --- /dev/null +++ b/version.php @@ -0,0 +1,33 @@ +. + +/** + * Code fragment to define the version of the certificate module + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late + */ + +$module->version = 2013102300; // The current module version (Date: YYYYMMDDXX) +$module->requires = 2012120300; // Requires this Moodle version +$module->cron = 0; // Period for cron to check this module (secs) +$module->component = 'mod_certificate'; + +$module->maturity = MATURITY_STABLE; +$module->release = "Stable"; // User-friendly version number diff --git a/view.php b/view.php new file mode 100644 index 0000000..e251af1 --- /dev/null +++ b/view.php @@ -0,0 +1,154 @@ +. + +/** + * Handles viewing a certificate + * + * @package mod + * @subpackage certificate + * @copyright Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once("../../config.php"); +require_once("$CFG->dirroot/mod/certificate/deprecatedlib.php"); +require_once("$CFG->dirroot/mod/certificate/lib.php"); +require_once("$CFG->libdir/pdflib.php"); + +$id = required_param('id', PARAM_INT); // Course Module ID +$action = optional_param('action', '', PARAM_ALPHA); +$edit = optional_param('edit', -1, PARAM_BOOL); + +if (!$cm = get_coursemodule_from_id('certificate', $id)) { + print_error('Course Module ID was incorrect'); +} +if (!$course = $DB->get_record('course', array('id'=> $cm->course))) { + print_error('course is misconfigured'); +} +if (!$certificate = $DB->get_record('certificate', array('id'=> $cm->instance))) { + print_error('course module is incorrect'); +} + +require_login($course->id, false, $cm); +$context = context_module::instance($cm->id); +require_capability('mod/certificate:view', $context); + +// log update +add_to_log($course->id, 'certificate', 'view', "view.php?id=$cm->id", $certificate->id, $cm->id); +$completion=new completion_info($course); +$completion->set_module_viewed($cm); + +// Initialize $PAGE, compute blocks +$PAGE->set_url('/mod/certificate/view.php', array('id' => $cm->id)); +$PAGE->set_context($context); +$PAGE->set_cm($cm); +$PAGE->set_title(format_string($certificate->name)); +$PAGE->set_heading(format_string($course->fullname)); + +// Set the context +$context = context_module::instance($cm->id); + +if (($edit != -1) and $PAGE->user_allowed_editing()) { + $USER->editing = $edit; +} + +// Add block editing button +if ($PAGE->user_allowed_editing()) { + $editvalue = $PAGE->user_is_editing() ? 'off' : 'on'; + $strsubmit = $PAGE->user_is_editing() ? get_string('blockseditoff') : get_string('blocksediton'); + $url = new moodle_url($CFG->wwwroot . '/mod/certificate/view.php', array('id' => $cm->id, 'edit' => $editvalue)); + $PAGE->set_button($OUTPUT->single_button($url, $strsubmit)); +} + +// Check if the user can view the certificate +if ($certificate->requiredtime && !has_capability('mod/certificate:manage', $context)) { + if (certificate_get_course_time($course->id) < ($certificate->requiredtime * 60)) { + $a = new stdClass; + $a->requiredtime = $certificate->requiredtime; + notice(get_string('requiredtimenotmet', 'certificate', $a), "$CFG->wwwroot/course/view.php?id=$course->id"); + die; + } +} + +// Create new certificate record, or return existing record +$certrecord = certificate_get_issue($course, $USER, $certificate, $cm); + +make_cache_directory('tcpdf'); + +// Load the specific certificate type. +require("$CFG->dirroot/mod/certificate/type/$certificate->certificatetype/certificate.php"); + +if (empty($action)) { // Not displaying PDF + echo $OUTPUT->header(); + + /// find out current groups mode + groups_print_activity_menu($cm, $CFG->wwwroot . '/mod/certificate/view.php?id=' . $cm->id); + $currentgroup = groups_get_activity_group($cm); + $groupmode = groups_get_activity_groupmode($cm); + + if (has_capability('mod/certificate:manage', $context)) { + $numusers = count(certificate_get_issues($certificate->id, 'ci.timecreated ASC', $groupmode, $cm)); + $url = html_writer::tag('a', get_string('viewcertificateviews', 'certificate', $numusers), + array('href' => $CFG->wwwroot . '/mod/certificate/report.php?id=' . $cm->id)); + echo html_writer::tag('div', $url, array('class' => 'reportlink')); + } + + if (!empty($certificate->intro)) { + echo $OUTPUT->box(format_module_intro('certificate', $certificate, $cm->id), 'generalbox', 'intro'); + } + + if ($attempts = certificate_get_attempts($certificate->id)) { + echo certificate_print_attempts($course, $certificate, $attempts); + } + if ($certificate->delivery == 0) { + $str = get_string('openwindow', 'certificate'); + } elseif ($certificate->delivery == 1) { + $str = get_string('opendownload', 'certificate'); + } elseif ($certificate->delivery == 2) { + $str = get_string('openemail', 'certificate'); + } + echo html_writer::tag('p', $str, array('style' => 'text-align:center')); + $linkname = get_string('getcertificate', 'certificate'); + // Add to log, only if we are reissuing + add_to_log($course->id, 'certificate', 'view', "view.php?id=$cm->id", $certificate->id, $cm->id); + + $link = new moodle_url('/mod/certificate/view.php?id='.$cm->id.'&action=get'); + $button = new single_button($link, $linkname); + $button->add_action(new popup_action('click', $link, 'view'.$cm->id, array('height' => 600, 'width' => 800))); + + echo html_writer::tag('div', $OUTPUT->render($button), array('style' => 'text-align:center')); + echo $OUTPUT->footer($course); + exit; +} else { // Output to pdf + // Remove full-stop at the end if it exists, to avoid "..pdf" being created and being filtered by clean_filename + $certname = rtrim($certificate->name, '.'); + $filename = clean_filename("$certname.pdf"); + if ($certificate->savecert == 1) { + // PDF contents are now in $file_contents as a string + $file_contents = $pdf->Output('', 'S'); + certificate_save_pdf($file_contents, $certrecord->id, $filename, $context->id); + } + if ($certificate->delivery == 0) { + $pdf->Output($filename, 'I'); // open in browser + } elseif ($certificate->delivery == 1) { + $pdf->Output($filename, 'D'); // force download when create + } elseif ($certificate->delivery == 2) { + certificate_email_student($course, $certificate, $certrecord, $context); + $pdf->Output($filename, 'I'); // open in browser + $pdf->Output('', 'S'); // send + } +}