From 67c63bfb1b4af571c783dd85c47db98ebb8156bc Mon Sep 17 00:00:00 2001 From: Dan Marsden Date: Wed, 12 Sep 2018 14:45:22 +1200 Subject: [PATCH] Improve QRcode support. --- add_form.php | 1 - attendance.php | 111 ++++++++++-------- backup/moodle2/backup_attendance_stepslib.php | 2 +- classes/import/sessions.php | 15 ++- classes/structure.php | 8 +- externallib.php | 3 +- lang/en/attendance.php | 3 +- password.php | 12 +- password_ajax.php | 4 +- settings.php | 6 + student_attendance_form.php | 2 + update_form.php | 5 +- 12 files changed, 103 insertions(+), 69 deletions(-) diff --git a/add_form.php b/add_form.php index 841a759..e96bfce 100644 --- a/add_form.php +++ b/add_form.php @@ -222,7 +222,6 @@ class mod_attendance_add_form extends moodleform { $mform->addElement('checkbox', 'autoassignstatus', '', get_string('autoassignstatus', 'attendance')); $mform->addHelpButton('autoassignstatus', 'autoassignstatus', 'attendance'); $mform->hideif('autoassignstatus', 'studentscanmark', 'notchecked'); - if (isset($pluginconfig->autoassignstatus)) { $mform->setDefault('autoassignstatus', $pluginconfig->autoassignstatus); } diff --git a/attendance.php b/attendance.php index 5698b0e..4aeb0c4 100644 --- a/attendance.php +++ b/attendance.php @@ -30,7 +30,7 @@ $pageparams = new mod_attendance_sessions_page_params(); // Check that the required parameters are present. $id = required_param('sessid', PARAM_INT); -$password = optional_param('studentpassword', '', PARAM_TEXT); +$qrpass = optional_param('qrpass', '', PARAM_TEXT); $attforsession = $DB->get_record('attendance_sessions', array('id' => $id), '*', MUST_EXIST); $attendance = $DB->get_record('attendance', array('id' => $attforsession->attendanceid), '*', MUST_EXIST); @@ -56,8 +56,14 @@ if (!empty($attforsession->subnet) && !address_in_subnet(getremoteaddr(), $attfo $pageparams->sessionid = $id; $att = new mod_attendance_structure($attendance, $cm, $course, $PAGE->context, $pageparams); -// Require that a session key is passed to this page. -// require_sesskey(); +if (empty($attforsession->includeqrcode)) { + $qrpass = ''; // Override qrpass if set, as it is not allowed. +} + +if (empty($qrpass)) { + // Sesskey is required on this page when QR code not in use. + require_sesskey(); +} // Check to see if autoassignstatus is in use and no password required. if ($attforsession->autoassignstatus && empty($attforsession->studentpassword)) { @@ -79,22 +85,20 @@ if ($attforsession->autoassignstatus && empty($attforsession->studentpassword)) } } -// Create the form. -$mform = new mod_attendance_student_attendance_form(null, - array('course' => $course, 'cm' => $cm, 'modcontext' => $PAGE->context, 'session' => $attforsession, 'attendance' => $att)); - -if ($password !== '') { - $fromform = $mform->get_data(); +// Check to see if autoassignstatus is in use and if qrcode is being used. +if (!empty($qrpass) && !empty($attforsession->autoassignstatus)) { + $fromform = new stdClass(); // Check if password required and if set correctly. if (!empty($attforsession->studentpassword) && - $attforsession->studentpassword !== $password) { + $attforsession->studentpassword !== $qrpass) { $url = new moodle_url('/mod/attendance/attendance.php', array('sessid' => $id, 'sesskey' => sesskey())); redirect($url, get_string('incorrectpassword', 'mod_attendance'), null, \core\output\notification::NOTIFY_ERROR); } + // Set the password and session id in the form, because they are saved in the attendance log. - $fromform->studentpassword = $password; + $fromform->studentpassword = $qrpass; $fromform->sessid = $attforsession->id; $fromform->status = attendance_session_get_highest_status($att, $attforsession); @@ -114,52 +118,57 @@ if ($password !== '') { print_error('attendance_already_submitted', 'mod_attendance', $url); } } -} else { - $PAGE->set_url($att->url_sessions()); +} - if ($mform->is_cancelled()) { - // The user cancelled the form, so redirect them to the view page. - $url = new moodle_url('/mod/attendance/view.php', array('id' => $cm->id)); - redirect($url); - } else if ($fromform = $mform->get_data()) { - // Check if password required and if set correctly. - if (!empty($attforsession->studentpassword) && - $attforsession->studentpassword !== $fromform->studentpassword) { - - $url = new moodle_url('/mod/attendance/attendance.php', array('sessid' => $id, 'sesskey' => sesskey())); - redirect($url, get_string('incorrectpassword', 'mod_attendance'), null, \core\output\notification::NOTIFY_ERROR); - } - if ($attforsession->autoassignstatus) { - $fromform->status = attendance_session_get_highest_status($att, $attforsession); - if (empty($fromform->status)) { - $url = new moodle_url('/mod/attendance/view.php', array('id' => $cm->id)); - print_error('attendance_no_status', 'mod_attendance', $url); - } - } +$PAGE->set_url($att->url_sessions()); + +// Create the form. +$mform = new mod_attendance_student_attendance_form(null, + array('course' => $course, 'cm' => $cm, 'modcontext' => $PAGE->context, 'session' => $attforsession, + 'attendance' => $att, 'password' => $qrpass)); - if (!empty($fromform->status)) { - $success = $att->take_from_student($fromform); +if ($mform->is_cancelled()) { + // The user cancelled the form, so redirect them to the view page. + $url = new moodle_url('/mod/attendance/view.php', array('id' => $cm->id)); + redirect($url); +} else if ($fromform = $mform->get_data()) { + // Check if password required and if set correctly. + if (!empty($attforsession->studentpassword) && + $attforsession->studentpassword !== $fromform->studentpassword) { + $url = new moodle_url('/mod/attendance/attendance.php', array('sessid' => $id, 'sesskey' => sesskey())); + redirect($url, get_string('incorrectpassword', 'mod_attendance'), null, \core\output\notification::NOTIFY_ERROR); + } + if ($attforsession->autoassignstatus) { + $fromform->status = attendance_session_get_highest_status($att, $attforsession); + if (empty($fromform->status)) { $url = new moodle_url('/mod/attendance/view.php', array('id' => $cm->id)); - if ($success) { - // Redirect back to the view page. - redirect($url, get_string('studentmarked', 'attendance')); - } else { - print_error('attendance_already_submitted', 'mod_attendance', $url); - } + print_error('attendance_no_status', 'mod_attendance', $url); } - - // The form did not validate correctly so we will set it to display the data they submitted. - $mform->set_data($fromform); } - $PAGE->set_title($course->shortname. ": ".$att->name); - $PAGE->set_heading($course->fullname); - $PAGE->set_cacheable(true); - $PAGE->navbar->add($att->name); + if (!empty($fromform->status)) { + $success = $att->take_from_student($fromform); - $output = $PAGE->get_renderer('mod_attendance'); - echo $output->header(); - $mform->display(); - echo $output->footer(); + $url = new moodle_url('/mod/attendance/view.php', array('id' => $cm->id)); + if ($success) { + // Redirect back to the view page. + redirect($url, get_string('studentmarked', 'attendance')); + } else { + print_error('attendance_already_submitted', 'mod_attendance', $url); + } + } + + // The form did not validate correctly so we will set it to display the data they submitted. + $mform->set_data($fromform); } + +$PAGE->set_title($course->shortname. ": ".$att->name); +$PAGE->set_heading($course->fullname); +$PAGE->set_cacheable(true); +$PAGE->navbar->add($att->name); + +$output = $PAGE->get_renderer('mod_attendance'); +echo $output->header(); +$mform->display(); +echo $output->footer(); diff --git a/backup/moodle2/backup_attendance_stepslib.php b/backup/moodle2/backup_attendance_stepslib.php index cdf21ab..51945ff 100644 --- a/backup/moodle2/backup_attendance_stepslib.php +++ b/backup/moodle2/backup_attendance_stepslib.php @@ -59,7 +59,7 @@ class backup_attendance_activity_structure_step extends backup_activity_structur 'groupid', 'sessdate', 'duration', 'lasttaken', 'lasttakenby', 'timemodified', 'description', 'descriptionformat', 'studentscanmark', 'studentpassword', 'autoassignstatus', 'subnet', 'automark', 'automarkcompleted', 'statusset', 'absenteereport', 'preventsharedip', - 'preventsharediptime', 'caleventid')); + 'preventsharediptime', 'caleventid', 'calendarevent', 'includeqrcode')); // XML nodes declaration - user data. $logs = new backup_nested_element('logs'); diff --git a/classes/import/sessions.php b/classes/import/sessions.php index 1e99a7a..f336a24 100644 --- a/classes/import/sessions.php +++ b/classes/import/sessions.php @@ -110,7 +110,8 @@ class sessions { get_string('absenteereport', 'attendance'), get_string('preventsharedip', 'attendance'), get_string('preventsharediptime', 'attendance'), - get_string('calendarevent', 'attendance') + get_string('calendarevent', 'attendance'), + get_string('includeqrcode', 'attendance'), ); } @@ -149,7 +150,8 @@ class sessions { 'absenteereport' => $data->header15, 'preventsharedip' => $data->header16, 'preventsharediptime' => $data->header17, - 'calendarevent' => $data->header18 + 'calendarevent' => $data->header18, + 'includeqrcode' => $data->header19 ); } else { return array( @@ -171,7 +173,8 @@ class sessions { 'absenteereport' => 15, 'preventsharedip' => 16, 'preventsharediptime' => 17, - 'calendarevent' => 18 + 'calendarevent' => 18, + 'includeqrcode' => 19 ); } } @@ -337,6 +340,12 @@ class sessions { $session->preventsharediptime = $this->get_column_data($row, $mapping['preventsharediptime']); } + if ($mapping['includeqrcode'] == -1) { + $session->includeqrcode = $pluginconfig->includeqrcode_default; + } else { + $session->includeqrcode = $this->get_column_data($row, $mapping['includeqrcode']); + } + $session->statusset = 0; $sessions[] = $session; diff --git a/classes/structure.php b/classes/structure.php index 0bda822..f1235e9 100644 --- a/classes/structure.php +++ b/classes/structure.php @@ -504,7 +504,9 @@ class mod_attendance_structure { if (!isset($sess->preventsharediptime)) { $sess->preventsharediptime = ''; } - + if (!isset($sess->includeqrcode)) { + $sess->includeqrcode = 0; + } $event->add_record_snapshot('attendance_sessions', $sess); $event->trigger(); } @@ -544,6 +546,7 @@ class mod_attendance_structure { $sess->automarkcompleted = 0; $sess->preventsharedip = 0; $sess->preventsharediptime = ''; + $sess->includeqrcode = 0; if (!empty(get_config('attendance', 'enablewarnings'))) { $sess->absenteereport = empty($formdata->absenteereport) ? 0 : 1; } @@ -570,6 +573,9 @@ class mod_attendance_structure { if (!empty($formdata->preventsharediptime)) { $sess->preventsharediptime = $formdata->preventsharediptime; } + if (!empty($formdata->includeqrcode)) { + $sess->includeqrcode = $formdata->includeqrcode; + } } diff --git a/externallib.php b/externallib.php index f302116..e5a3de5 100644 --- a/externallib.php +++ b/externallib.php @@ -72,7 +72,8 @@ class mod_wsattendance_external extends external_api { 'autoassignstatus' => new external_value(PARAM_INT, 'Automatically assign a status to students.'), 'preventsharedip' => new external_value(PARAM_INT, 'Prevent students from sharing IP addresses.'), 'preventsharediptime' => new external_value(PARAM_INT, 'Time delay before IP address is allowed again.'), - 'statusset' => new external_value(PARAM_INT, 'Session statusset.')); + 'statusset' => new external_value(PARAM_INT, 'Session statusset.'), + 'includeqrcode' => new external_value(PARAM_INT, 'Include QR code when displaying password')); return $session; } diff --git a/lang/en/attendance.php b/lang/en/attendance.php index 2dc081e..fe55484 100644 --- a/lang/en/attendance.php +++ b/lang/en/attendance.php @@ -344,7 +344,8 @@ $string['priorto'] = 'The session date is prior to the course start date ({$a}) $string['processingfile'] = 'Processing file'; $string['qrcode'] = 'QR Code'; $string['qrcodemissing'] = 'QR Code not available. Please ask your administrator to install the QR Links plugin.'; -$string['qrcodewarning'] = 'Local QR code generator not available. Using web-based 3rd-party service goQR.me instead.'; +$string['qrcodewarning'] = 'This QR code was generated using the 3rd-party service goQR.me.'; +$string['qrcodeadminwarning'] = 'Warning: QR codes for student self-marking will be generated using the external service goQR.me. Install the QR Links plugin to generate them locally.'; $string['randompassword'] = 'Random password'; $string['remark'] = 'Remark for: {$a}'; $string['remarks'] = 'Remarks'; diff --git a/password.php b/password.php index 2624b47..cc3de68 100644 --- a/password.php +++ b/password.php @@ -25,10 +25,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -use Endroid\QrCode\QrCode; require_once(dirname(__FILE__).'/../../config.php'); - $session = required_param('session', PARAM_INT); $session = $DB->get_record('attendance_sessions', array('id' => $session), '*', MUST_EXIST); @@ -51,16 +49,16 @@ $PAGE->set_title(get_string('password', 'attendance')); echo $OUTPUT->header(); echo html_writer::tag('h2', get_string('passwordgrp', 'attendance')); echo html_writer::span($session->studentpassword, 'student-password'); -echo html_writer::tag('h3', $plugininfos['qrlinks']); if (isset($session->includeqrcode) && $session->includeqrcode == 1) { - $qrcodeurl = $CFG->wwwroot . '/mod/attendance/attendance.php?studentpassword=' . $session->studentpassword . '&sessid=' . $session->id; + $qrcodeurl = $CFG->wwwroot . '/mod/attendance/attendance.php?qrpass=' . $session->studentpassword . '&sessid=' . $session->id; echo html_writer::tag('h3', get_string('qrcode', 'attendance')); // If the local_qrlinks plugin is installed, use it to create the QR code. $plugininfos = core_plugin_manager::instance()->get_plugins_of_type('local'); - if (isset($plugininfos['qrlinks'])) { - require_once(dirname(__FILE__).'/../../local/qrlinks/thirdparty/QrCode/src/QrCode.php'); + $qrlinklib = dirname(__FILE__).'/../../local/qrlinks/thirdparty/QrCode/src/QrCode.php'; + if (isset($plugininfos['qrlinks']) && file_exists($qrlinklib)) { + require_once($qrlinklib); $code = new QrCode($qrcodeurl); $code->setSize(500); echo html_writer::img('data:image/png;base64,' . base64_encode($code->get())); @@ -71,7 +69,7 @@ if (isset($session->includeqrcode) && $session->includeqrcode == 1) { if ($qrcode === false) { echo html_writer::tag('p', get_string('qrcodemissing', 'attendance')); } else { - echo html_writer::img('data:image/png;base64,' . base64_encode($qrcode)); + echo html_writer::img('data:image/png;base64,' . base64_encode($qrcode), get_string('qrcode', 'attendance')); echo html_writer::tag('p', get_string('qrcodewarning', 'attendance')); } } catch (Exception $e) { diff --git a/password_ajax.php b/password_ajax.php index d15c037..a0ecc47 100644 --- a/password_ajax.php +++ b/password_ajax.php @@ -47,8 +47,8 @@ $PAGE->set_context(context_system::instance()); $data->heading = get_string('passwordgrp', 'attendance'); if (isset($session->includeqrcode) && $session->includeqrcode == 1) { $studentattendancepage = '/mod/attendance/password.php?session=' . $session->id; - $data->text = html_writer::tag('p', html_writer::span($session->studentpassword, 'student-password') . - html_writer::empty_tag('br') . + $data->text = html_writer::tag('p', html_writer::span($session->studentpassword, 'student-password') . + html_writer::empty_tag('br') . html_writer::link($CFG->wwwroot . $studentattendancepage, get_string('showqrcode', 'attendance'))); } else { $data->text = html_writer::span($session->studentpassword, 'student-password'); diff --git a/settings.php b/settings.php index ca50f19..e170374 100644 --- a/settings.php +++ b/settings.php @@ -29,8 +29,14 @@ if ($ADMIN->fulltree) { require_once(dirname(__FILE__).'/locallib.php'); $tabmenu = attendance_print_settings_tabs(); + + if (empty($plugininfos['qrlinks'])) { + $tabmenu = '
'.get_string('qrcodeadminwarning', 'mod_attendance').'
'.$tabmenu; + } $settings->add(new admin_setting_heading('attendance_header', '', $tabmenu)); + $plugininfos = core_plugin_manager::instance()->get_plugins_of_type('local'); + // Paging options. $options = array( 0 => get_string('donotusepaging', 'attendance'), diff --git a/student_attendance_form.php b/student_attendance_form.php index 210ef74..2662470 100644 --- a/student_attendance_form.php +++ b/student_attendance_form.php @@ -44,6 +44,7 @@ class mod_attendance_student_attendance_form extends moodleform { $attforsession = $this->_customdata['session']; $attblock = $this->_customdata['attendance']; + $password = $this->_customdata['password']; $statuses = $attblock->get_statuses(); // Check if user has access to all statuses. @@ -81,6 +82,7 @@ class mod_attendance_student_attendance_form extends moodleform { $mform->addElement('text', 'studentpassword', get_string('password', 'attendance')); $mform->setType('studentpassword', PARAM_TEXT); $mform->addRule('studentpassword', get_string('passwordrequired', 'attendance'), 'required'); + $mform->setDefault('studentpassword', $password); } if (!$attforsession->autoassignstatus) { diff --git a/update_form.php b/update_form.php index c1d38ff..56a3a53 100644 --- a/update_form.php +++ b/update_form.php @@ -76,7 +76,8 @@ class mod_attendance_update_form extends moodleform { 'absenteereport' => $sess->absenteereport, 'automarkcompleted' => 0, 'preventsharedip' => $sess->preventsharedip, - 'preventsharediptime' => $sess->preventsharediptime + 'preventsharediptime' => $sess->preventsharediptime, + 'includeqrcode' => $sess->includeqrcode ); if ($sess->subnet == $attendancesubnet) { $data['usedefaultsubnet'] = 1; @@ -147,6 +148,8 @@ class mod_attendance_update_form extends moodleform { $mform->hideif('studentpassword', 'studentscanmark', 'notchecked'); $mform->hideif('studentpassword', 'automark', 'eq', ATTENDANCE_AUTOMARK_ALL); $mform->hideif('randompassword', 'automark', 'eq', ATTENDANCE_AUTOMARK_ALL); + $mform->addElement('checkbox', 'includeqrcode', '', get_string('includeqrcode', 'attendance')); + $mform->hideif('includeqrcode', 'studentscanmark', 'notchecked'); $mform->addElement('checkbox', 'autoassignstatus', '', get_string('autoassignstatus', 'attendance')); $mform->addHelpButton('autoassignstatus', 'autoassignstatus', 'attendance'); $mform->hideif('autoassignstatus', 'studentscanmark', 'notchecked');