Browse Source

Support QR codes to speed up attendance recording, using local_qrlinks plugin or external web service

Fix URL to remove duplicae wwwroot
Merge QR code handling code
MOODLE_36_STABLE
Eoin Campbell 6 years ago
committed by Dan Marsden
parent
commit
d1deae934b
  1. 4
      add_form.php
  2. 83
      attendance.php
  3. 1
      db/install.xml
  4. 10
      db/upgrade.php
  5. 5
      lang/en/attendance.php
  6. 8
      locallib.php
  7. 31
      password.php
  8. 11
      password_ajax.php
  9. 3
      settings.php
  10. 4
      version.php

4
add_form.php

@ -209,6 +209,7 @@ class mod_attendance_add_form extends moodleform {
$mgroup[] = & $mform->createElement('text', 'studentpassword', get_string('studentpassword', 'attendance')); $mgroup[] = & $mform->createElement('text', 'studentpassword', get_string('studentpassword', 'attendance'));
$mgroup[] = & $mform->createElement('checkbox', 'randompassword', '', get_string('randompassword', 'attendance')); $mgroup[] = & $mform->createElement('checkbox', 'randompassword', '', get_string('randompassword', 'attendance'));
$mgroup[] = & $mform->createElement('checkbox', 'includeqrcode', '', get_string('includeqrcode', 'attendance'));
$mform->addGroup($mgroup, 'passwordgrp', get_string('passwordgrp', 'attendance'), array(' '), false); $mform->addGroup($mgroup, 'passwordgrp', get_string('passwordgrp', 'attendance'), array(' '), false);
$mform->setType('studentpassword', PARAM_TEXT); $mform->setType('studentpassword', PARAM_TEXT);
@ -231,6 +232,9 @@ class mod_attendance_add_form extends moodleform {
if (isset($pluginconfig->randompassword_default)) { if (isset($pluginconfig->randompassword_default)) {
$mform->setDefault('randompassword', $pluginconfig->randompassword_default); $mform->setDefault('randompassword', $pluginconfig->randompassword_default);
} }
if (isset($pluginconfig->includeqrcode_default)) {
$mform->setDefault('includeqrcode', $pluginconfig->includeqrcode_default);
}
if (isset($pluginconfig->automark_default)) { if (isset($pluginconfig->automark_default)) {
$mform->setDefault('automark', $pluginconfig->automark_default); $mform->setDefault('automark', $pluginconfig->automark_default);
} }

83
attendance.php

@ -30,6 +30,7 @@ $pageparams = new mod_attendance_sessions_page_params();
// Check that the required parameters are present. // Check that the required parameters are present.
$id = required_param('sessid', PARAM_INT); $id = required_param('sessid', PARAM_INT);
$password = optional_param('studentpassword', '', PARAM_TEXT);
$attforsession = $DB->get_record('attendance_sessions', array('id' => $id), '*', MUST_EXIST); $attforsession = $DB->get_record('attendance_sessions', array('id' => $id), '*', MUST_EXIST);
$attendance = $DB->get_record('attendance', array('id' => $attforsession->attendanceid), '*', MUST_EXIST); $attendance = $DB->get_record('attendance', array('id' => $attforsession->attendanceid), '*', MUST_EXIST);
@ -56,7 +57,7 @@ $pageparams->sessionid = $id;
$att = new mod_attendance_structure($attendance, $cm, $course, $PAGE->context, $pageparams); $att = new mod_attendance_structure($attendance, $cm, $course, $PAGE->context, $pageparams);
// Require that a session key is passed to this page. // Require that a session key is passed to this page.
require_sesskey(); // require_sesskey();
// Check to see if autoassignstatus is in use and no password required. // Check to see if autoassignstatus is in use and no password required.
if ($attforsession->autoassignstatus && empty($attforsession->studentpassword)) { if ($attforsession->autoassignstatus && empty($attforsession->studentpassword)) {
@ -82,26 +83,24 @@ if ($attforsession->autoassignstatus && empty($attforsession->studentpassword))
$mform = new mod_attendance_student_attendance_form(null, $mform = new mod_attendance_student_attendance_form(null,
array('course' => $course, 'cm' => $cm, 'modcontext' => $PAGE->context, 'session' => $attforsession, 'attendance' => $att)); array('course' => $course, 'cm' => $cm, 'modcontext' => $PAGE->context, 'session' => $attforsession, 'attendance' => $att));
$PAGE->set_url($att->url_sessions()); if ($password !== '') {
$fromform = $mform->get_data();
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. // Check if password required and if set correctly.
if (!empty($attforsession->studentpassword) && if (!empty($attforsession->studentpassword) &&
$attforsession->studentpassword !== $fromform->studentpassword) { $attforsession->studentpassword !== $password) {
$url = new moodle_url('/mod/attendance/attendance.php', array('sessid' => $id, 'sesskey' => sesskey())); $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); redirect($url, get_string('incorrectpassword', 'mod_attendance'), null, \core\output\notification::NOTIFY_ERROR);
} }
if ($attforsession->autoassignstatus) { // Set the password and session id in the form, because they are saved in the attendance log.
$fromform->status = attendance_session_get_highest_status($att, $attforsession); $fromform->studentpassword = $password;
if (empty($fromform->status)) { $fromform->sessid = $attforsession->id;
$url = new moodle_url('/mod/attendance/view.php', array('id' => $cm->id));
print_error('attendance_no_status', 'mod_attendance', $url); $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);
} }
if (!empty($fromform->status)) { if (!empty($fromform->status)) {
@ -115,18 +114,52 @@ if ($mform->is_cancelled()) {
print_error('attendance_already_submitted', 'mod_attendance', $url); print_error('attendance_already_submitted', 'mod_attendance', $url);
} }
} }
} else {
$PAGE->set_url($att->url_sessions());
// The form did not validate correctly so we will set it to display the data they submitted. if ($mform->is_cancelled()) {
$mform->set_data($fromform); // 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);
}
}
if (!empty($fromform->status)) {
$success = $att->take_from_student($fromform);
$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);
}
}
$PAGE->set_title($course->shortname. ": ".$att->name); // The form did not validate correctly so we will set it to display the data they submitted.
$PAGE->set_heading($course->fullname); $mform->set_data($fromform);
$PAGE->set_cacheable(true); }
$PAGE->navbar->add($att->name);
$output = $PAGE->get_renderer('mod_attendance'); $PAGE->set_title($course->shortname. ": ".$att->name);
echo $output->header(); $PAGE->set_heading($course->fullname);
$mform->display(); $PAGE->set_cacheable(true);
echo $output->footer(); $PAGE->navbar->add($att->name);
$output = $PAGE->get_renderer('mod_attendance');
echo $output->header();
$mform->display();
echo $output->footer();
}

1
db/install.xml

@ -49,6 +49,7 @@
<FIELD NAME="preventsharediptime" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/> <FIELD NAME="preventsharediptime" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="caleventid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="caleventid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="calendarevent" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/> <FIELD NAME="calendarevent" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
<FIELD NAME="includeqrcode" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Include a QR code image when displaying the password"/>
</FIELDS> </FIELDS>
<KEYS> <KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for attendance_sessions"/> <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for attendance_sessions"/>

10
db/upgrade.php

@ -525,5 +525,15 @@ function xmldb_attendance_upgrade($oldversion=0) {
upgrade_mod_savepoint(true, 2018072700, 'attendance'); upgrade_mod_savepoint(true, 2018072700, 'attendance');
} }
if ($oldversion < 2018082106) {
$table = new xmldb_table('attendance_sessions');
$field = new xmldb_field('includeqrcode', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED,
XMLDB_NOTNULL, null, '0', 'calendarevent');
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
upgrade_mod_savepoint(true, 2018082106, 'attendance');
}
return $result; return $result;
} }

5
lang/en/attendance.php

@ -239,6 +239,7 @@ $string['importsessions'] = 'Import Sessions';
$string['identifyby'] = 'Identify student by'; $string['identifyby'] = 'Identify student by';
$string['includeall'] = 'Select all sessions'; $string['includeall'] = 'Select all sessions';
$string['includenottaken'] = 'Include not taken sessions'; $string['includenottaken'] = 'Include not taken sessions';
$string['includeqrcode'] = 'Include QR code';
$string['includeremarks'] = 'Include remarks'; $string['includeremarks'] = 'Include remarks';
$string['incorrectpassword'] = 'You have entered an incorrect password and your attendance has not been recorded, please enter the correct password.'; $string['incorrectpassword'] = 'You have entered an incorrect password and your attendance has not been recorded, please enter the correct password.';
$string['indetail'] = 'In detail...'; $string['indetail'] = 'In detail...';
@ -341,6 +342,9 @@ $string['preventsharediptime_help'] = 'Allow an IP address to be re-used for tak
$string['preventsharederror'] = 'Self-marking has been disabled for a session because this device appears to have been used to record attendance for another student.'; $string['preventsharederror'] = 'Self-marking has been disabled for a session because this device appears to have been used to record attendance for another student.';
$string['priorto'] = 'The session date is prior to the course start date ({$a}) so that the new sessions scheduled before this date will be hidden (not accessible). You can change the course start date at any time (see course settings) in order to have access to earlier sessions.<br><br>Please change the session date or just click the "Add session" button again to confirm?'; $string['priorto'] = 'The session date is prior to the course start date ({$a}) so that the new sessions scheduled before this date will be hidden (not accessible). You can change the course start date at any time (see course settings) in order to have access to earlier sessions.<br><br>Please change the session date or just click the "Add session" button again to confirm?';
$string['processingfile'] = 'Processing file'; $string['processingfile'] = 'Processing file';
$string['qrcode'] = 'QR Code';
$string['qrcodemissing'] = 'QR Code not available. Please ask your administrator to install the <a href="https://moodle.org/plugins/local_qrlinks">QR Links</a> plugin.';
$string['qrcodewarning'] = 'Local QR code generator not available. Using web-based 3rd-party service <a href="https://goqr.me/">goQR.me</a> instead.';
$string['randompassword'] = 'Random password'; $string['randompassword'] = 'Random password';
$string['remark'] = 'Remark for: {$a}'; $string['remark'] = 'Remark for: {$a}';
$string['remarks'] = 'Remarks'; $string['remarks'] = 'Remarks';
@ -434,6 +438,7 @@ $string['setunmarked_help'] = 'If enabled in the session, set this status if a s
$string['showdefaults'] = 'Show defaults'; $string['showdefaults'] = 'Show defaults';
$string['showduration'] = 'Show duration'; $string['showduration'] = 'Show duration';
$string['showextrauserdetails'] = 'Show extra user details'; $string['showextrauserdetails'] = 'Show extra user details';
$string['showqrcode'] = 'Show QR Code';
$string['showsessiondetails'] = 'Show session details'; $string['showsessiondetails'] = 'Show session details';
$string['showsessiondescriptiononreport'] = 'Show session description in report'; $string['showsessiondescriptiononreport'] = 'Show session description in report';
$string['showsessiondescriptiononreport_desc'] = 'Show the session description in the attendance report listing.'; $string['showsessiondescriptiononreport_desc'] = 'Show the session description in the attendance report listing.';

8
locallib.php

@ -628,6 +628,7 @@ function attendance_construct_sessions_data_for_add($formdata, mod_attendance_st
$sess->timemodified = $now; $sess->timemodified = $now;
$sess->absenteereport = $absenteereport; $sess->absenteereport = $absenteereport;
$sess->studentpassword = ''; $sess->studentpassword = '';
$sess->includeqrcode = 0;
if (isset($formdata->studentscanmark)) { // Students will be able to mark their own attendance. if (isset($formdata->studentscanmark)) { // Students will be able to mark their own attendance.
$sess->studentscanmark = 1; $sess->studentscanmark = 1;
if (!empty($formdata->usedefaultsubnet)) { if (!empty($formdata->usedefaultsubnet)) {
@ -645,6 +646,9 @@ function attendance_construct_sessions_data_for_add($formdata, mod_attendance_st
} else if (!empty($formdata->studentpassword)) { } else if (!empty($formdata->studentpassword)) {
$sess->studentpassword = $formdata->studentpassword; $sess->studentpassword = $formdata->studentpassword;
} }
if (!empty($formdata->includeqrcode)) {
$sess->includeqrcode = $formdata->includeqrcode;
}
if (!empty($formdata->preventsharedip)) { if (!empty($formdata->preventsharedip)) {
$sess->preventsharedip = $formdata->preventsharedip; $sess->preventsharedip = $formdata->preventsharedip;
} }
@ -684,6 +688,7 @@ function attendance_construct_sessions_data_for_add($formdata, mod_attendance_st
$sess->automark = 0; $sess->automark = 0;
$sess->automarkcompleted = 0; $sess->automarkcompleted = 0;
$sess->absenteereport = $absenteereport; $sess->absenteereport = $absenteereport;
$sess->includeqrcode = 0;
if (isset($formdata->studentscanmark) && !empty($formdata->studentscanmark)) { if (isset($formdata->studentscanmark) && !empty($formdata->studentscanmark)) {
// Students will be able to mark their own attendance. // Students will be able to mark their own attendance.
@ -696,6 +701,9 @@ function attendance_construct_sessions_data_for_add($formdata, mod_attendance_st
} else if (!empty($formdata->studentpassword)) { } else if (!empty($formdata->studentpassword)) {
$sess->studentpassword = $formdata->studentpassword; $sess->studentpassword = $formdata->studentpassword;
} }
if (!empty($formdata->includeqrcode)) {
$sess->includeqrcode = $formdata->includeqrcode;
}
if (!empty($formdata->usedefaultsubnet)) { if (!empty($formdata->usedefaultsubnet)) {
$sess->subnet = $att->subnet; $sess->subnet = $att->subnet;
} else { } else {

31
password.php

@ -25,8 +25,10 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
use Endroid\QrCode\QrCode;
require_once(dirname(__FILE__).'/../../config.php'); require_once(dirname(__FILE__).'/../../config.php');
$session = required_param('session', PARAM_INT); $session = required_param('session', PARAM_INT);
$session = $DB->get_record('attendance_sessions', array('id' => $session), '*', MUST_EXIST); $session = $DB->get_record('attendance_sessions', array('id' => $session), '*', MUST_EXIST);
@ -47,5 +49,34 @@ $PAGE->set_context(context_system::instance());
$PAGE->set_title(get_string('password', 'attendance')); $PAGE->set_title(get_string('password', 'attendance'));
echo $OUTPUT->header(); echo $OUTPUT->header();
echo html_writer::tag('h2', get_string('passwordgrp', 'attendance'));
echo html_writer::span($session->studentpassword, 'student-password'); 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;
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');
$code = new QrCode($qrcodeurl);
$code->setSize(500);
echo html_writer::img('data:image/png;base64,' . base64_encode($code->get()));
} else {
// Otherwise try using an external API service to create the QR code instead.
try {
$qrcode = file_get_contents('https://api.qrserver.com/v1/create-qr-code/?size=500x500&data=' . urlencode($qrcodeurl));
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::tag('p', get_string('qrcodewarning', 'attendance'));
}
} catch (Exception $e) {
echo html_writer::tag('p', get_string('qrcodemissing', 'attendance'));
}
}
}
echo $OUTPUT->footer(); echo $OUTPUT->footer();

11
password_ajax.php

@ -44,7 +44,14 @@ $PAGE->set_pagelayout('popup');
$PAGE->set_context(context_system::instance()); $PAGE->set_context(context_system::instance());
$data->heading = ''; $data->heading = get_string('passwordgrp', 'attendance');
$data->text = html_writer::span($session->studentpassword, 'student-password'); 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') .
html_writer::link($CFG->wwwroot . $studentattendancepage, get_string('showqrcode', 'attendance')));
} else {
$data->text = html_writer::span($session->studentpassword, 'student-password');
}
echo json_encode($data); echo json_encode($data);

3
settings.php

@ -122,6 +122,9 @@ if ($ADMIN->fulltree) {
$settings->add(new admin_setting_configcheckbox('attendance/randompassword_default', $settings->add(new admin_setting_configcheckbox('attendance/randompassword_default',
get_string('randompassword', 'attendance'), '', 0)); get_string('randompassword', 'attendance'), '', 0));
$settings->add(new admin_setting_configcheckbox('attendance/includeqrcode_default',
get_string('includeqrcode', 'attendance'), '', 0));
$settings->add(new admin_setting_configcheckbox('attendance/autoassignstatus', $settings->add(new admin_setting_configcheckbox('attendance/autoassignstatus',
get_string('autoassignstatus', 'attendance'), '', 0)); get_string('autoassignstatus', 'attendance'), '', 0));

4
version.php

@ -23,9 +23,9 @@
*/ */
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
$plugin->version = 2018072701; $plugin->version = 2018082604;
$plugin->requires = 2018050800; // Requires 3.5. $plugin->requires = 2018050800; // Requires 3.5.
$plugin->release = '3.5.1'; $plugin->release = '3.5.2';
$plugin->maturity = MATURITY_ALPHA; $plugin->maturity = MATURITY_ALPHA;
$plugin->cron = 0; $plugin->cron = 0;
$plugin->component = 'mod_attendance'; $plugin->component = 'mod_attendance';

Loading…
Cancel
Save