Browse Source

Feature: add auto-marking by linked activity comletion.

40-behatfixes
Antony Videtta 4 years ago
committed by Dan Marsden
parent
commit
38771055ec
  1. 2
      backup/moodle2/backup_attendance_stepslib.php
  2. 9
      classes/form/addsession.php
  3. 8
      classes/form/updatesession.php
  4. 39
      classes/task/auto_mark.php
  5. 1
      db/install.xml
  6. 15
      db/upgrade.php
  7. 1
      externallib.php
  8. 2
      lang/en/attendance.php
  9. 49
      locallib.php
  10. 3
      renderhelpers.php

2
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', 'groupid', 'sessdate', 'duration', 'lasttaken', 'lasttakenby', 'timemodified',
'description', 'descriptionformat', 'studentscanmark', 'studentpassword', 'autoassignstatus', 'description', 'descriptionformat', 'studentscanmark', 'studentpassword', 'autoassignstatus',
'subnet', 'automark', 'automarkcompleted', 'statusset', 'absenteereport', 'preventsharedip', 'subnet', 'automark', 'automarkcompleted', 'statusset', 'absenteereport', 'preventsharedip',
'preventsharediptime', 'caleventid', 'calendarevent', 'includeqrcode')); 'preventsharediptime', 'caleventid', 'calendarevent', 'includeqrcode', 'automarkcmid'));
// XML nodes declaration - user data. // XML nodes declaration - user data.
$logs = new backup_nested_element('logs'); $logs = new backup_nested_element('logs');

9
classes/form/addsession.php

@ -46,7 +46,7 @@ class addsession extends moodleform {
*/ */
public function definition() { public function definition() {
global $CFG, $USER; global $CFG, $USER, $DB;
$mform =& $this->_form; $mform =& $this->_form;
$course = $this->_customdata['course']; $course = $this->_customdata['course'];
@ -215,6 +215,12 @@ class addsession extends moodleform {
$mform->addHelpButton('automark', 'automark', 'attendance'); $mform->addHelpButton('automark', 'automark', 'attendance');
$mform->setDefault('automark', $this->_customdata['att']->automark); $mform->setDefault('automark', $this->_customdata['att']->automark);
$automarkcmoptions = attendance_get_coursemodulenames($course->id);
$mform->addElement('select', 'automarkcmid', get_string('selectactivity', 'attendance'), $automarkcmoptions);
$mform->setType('automarkcmid', PARAM_INT);
$mform->hideif('automarkcmid', 'automark', 'neq', '3');
if (!empty($studentscanmark)) { if (!empty($studentscanmark)) {
$mgroup = array(); $mgroup = array();
@ -240,6 +246,7 @@ class addsession extends moodleform {
$mform->addElement('checkbox', 'autoassignstatus', '', get_string('autoassignstatus', 'attendance')); $mform->addElement('checkbox', 'autoassignstatus', '', get_string('autoassignstatus', 'attendance'));
$mform->addHelpButton('autoassignstatus', 'autoassignstatus', 'attendance'); $mform->addHelpButton('autoassignstatus', 'autoassignstatus', 'attendance');
$mform->hideif('autoassignstatus', 'studentscanmark', 'notchecked'); $mform->hideif('autoassignstatus', 'studentscanmark', 'notchecked');
if (isset($pluginconfig->autoassignstatus)) { if (isset($pluginconfig->autoassignstatus)) {
$mform->setDefault('autoassignstatus', $pluginconfig->autoassignstatus); $mform->setDefault('autoassignstatus', $pluginconfig->autoassignstatus);
} }

8
classes/form/updatesession.php

@ -41,7 +41,7 @@ class updatesession extends \moodleform {
*/ */
public function definition() { public function definition() {
global $DB; global $DB, $COURSE;
$mform =& $this->_form; $mform =& $this->_form;
$modcontext = $this->_customdata['modcontext']; $modcontext = $this->_customdata['modcontext'];
@ -148,6 +148,12 @@ class updatesession extends \moodleform {
$mform->setType('automark', PARAM_INT); $mform->setType('automark', PARAM_INT);
$mform->addHelpButton('automark', 'automark', 'attendance'); $mform->addHelpButton('automark', 'automark', 'attendance');
$automarkcmoptions2 = attendance_get_coursemodulenames($COURSE->id);
$mform->addElement('select', 'automarkcmid', get_string('selectactivity', 'attendance'), $automarkcmoptions2);
$mform->setType('automarkcmid', PARAM_INT);
$mform->hideif('automarkcmid', 'automark', 'neq', '3');
if (!empty($studentscanmark)) { if (!empty($studentscanmark)) {
$mform->addElement('text', 'studentpassword', get_string('studentpassword', 'attendance')); $mform->addElement('text', 'studentpassword', get_string('studentpassword', 'attendance'));
$mform->setType('studentpassword', PARAM_TEXT); $mform->setType('studentpassword', PARAM_TEXT);

39
classes/task/auto_mark.php

@ -34,6 +34,7 @@ require_once($CFG->dirroot . '/mod/attendance/locallib.php');
* @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
*/ */
class auto_mark extends \core\task\scheduled_task { class auto_mark extends \core\task\scheduled_task {
/** /**
* Returns localised general event name. * Returns localised general event name.
* *
@ -76,10 +77,12 @@ class auto_mark extends \core\task\scheduled_task {
$setunmarked = $DB->get_field('attendance_statuses', 'id', $setunmarked = $DB->get_field('attendance_statuses', 'id',
array('attendanceid' => $session->attendanceid, 'setnumber' => $session->statusset, array('attendanceid' => $session->attendanceid, 'setnumber' => $session->statusset,
'setunmarked' => 1, 'deleted' => 0)); 'setunmarked' => 1, 'deleted' => 0));
if (empty($setunmarked)) { if (empty($setunmarked)) {
mtrace("No unmarked status configured for session id: ".$session->id); mtrace("No unmarked status configured for session id: ".$session->id);
continue; continue;
} }
if (empty($cacheatt[$session->attendanceid])) { if (empty($cacheatt[$session->attendanceid])) {
$cacheatt[$session->attendanceid] = $DB->get_record('attendance', array('id' => $session->attendanceid)); $cacheatt[$session->attendanceid] = $DB->get_record('attendance', array('id' => $session->attendanceid));
} }
@ -102,6 +105,9 @@ class auto_mark extends \core\task\scheduled_task {
} }
$pageparams->sessionid = $session->id; $pageparams->sessionid = $session->id;
$att = new \mod_attendance_structure($cacheatt[$session->attendanceid],
$cachecm[$session->attendanceid], $cachecourse[$courseid], $context, $pageparams);
if ($session->automark == 1) { if ($session->automark == 1) {
$userfirstacess = array(); $userfirstacess = array();
// If set to do full automarking, get all users that have accessed course during session open. // If set to do full automarking, get all users that have accessed course during session open.
@ -136,12 +142,39 @@ class auto_mark extends \core\task\scheduled_task {
} }
} }
$logusers->close(); $logusers->close();
} else if ($session->automark == 3) {
$completedusers = array();
$newlog = new \stdClass();
$newlog->timetaken = $now;
$newlog->takenby = 0;
$newlog->sessionid = $session->id;
$newlog->remarks = get_string('autorecorded', 'attendance');
$newlog->statusset = implode(',', array_keys( (array)$att->get_statuses()));
// Get users who have completed the course in this session.
$completedusers[] = $DB->get_record('course_modules_completion', array(
'coursemoduleid' => $session->automarkcmid,
'completionstate' => 1
));
if (!empty($completedusers)) {
// Get automark status the users and update the attendance log.
foreach ($completedusers as $completionuser) {
$newlog->statusid = $att->get_automark_status($completionuser->timemodified, $session->id);
if (!empty($newlog->statusid)) {
$newlog->studentid = $completionuser->userid;
$DB->insert_record('attendance_log', $newlog);
}
}
}
} }
// Get all unmarked students. // Get all unmarked students.
$att = new \mod_attendance_structure($cacheatt[$session->attendanceid],
$cachecm[$session->attendanceid], $cachecourse[$courseid], $context, $pageparams);
$users = $att->get_users($session->groupid, 0); $users = $att->get_users($session->groupid, 0);
$existinglog = $DB->get_recordset('attendance_log', array('sessionid' => $session->id)); $existinglog = $DB->get_recordset('attendance_log', array('sessionid' => $session->id));

1
db/install.xml

@ -52,6 +52,7 @@
<FIELD NAME="includeqrcode" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Include a QR code image when displaying the password"/> <FIELD NAME="includeqrcode" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Include a QR code image when displaying the password"/>
<FIELD NAME="rotateqrcode" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="rotateqrcode" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="rotateqrcodesecret" TYPE="char" LENGTH="10" NOTNULL="false" SEQUENCE="false"/> <FIELD NAME="rotateqrcodesecret" TYPE="char" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="automarkcmid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</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"/>

15
db/upgrade.php

@ -650,5 +650,20 @@ function xmldb_attendance_upgrade($oldversion=0) {
upgrade_mod_savepoint(true, 2021050700, 'attendance'); upgrade_mod_savepoint(true, 2021050700, 'attendance');
} }
if ($oldversion < 2021060700) {
// Changing precision of field statusset on table attendance_log to (1333).
$table = new xmldb_table('attendance_sessions');
$field = new xmldb_field('automarkcmid', XMLDB_TYPE_CHAR, '10', null, null, null, null, 'rotateqrcodesecret');
// Launch change of precision for field statusset.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Attendance savepoint reached.
upgrade_mod_savepoint(true, 2021060700, 'attendance');
}
return $result; return $result;
} }

1
externallib.php

@ -255,6 +255,7 @@ class mod_attendance_external extends external_api {
$sess->subnet = $attendance->subnet; $sess->subnet = $attendance->subnet;
$sess->statusset = 0; $sess->statusset = 0;
$sess->groupid = $groupid; $sess->groupid = $groupid;
$sess->automarkcmid = 0;
$sessionid = $attendance->add_session($sess); $sessionid = $attendance->add_session($sess);
return array('sessionid' => $sessionid); return array('sessionid' => $sessionid);

2
lang/en/attendance.php

@ -76,11 +76,13 @@ $string['attrecords'] = 'Attendances records';
$string['autoassignstatus'] = 'Automatically select highest status available'; $string['autoassignstatus'] = 'Automatically select highest status available';
$string['autoassignstatus_help'] = 'If this is selected, students will automatically be assigned the highest available grade.'; $string['autoassignstatus_help'] = 'If this is selected, students will automatically be assigned the highest available grade.';
$string['automark'] = 'Automatic marking'; $string['automark'] = 'Automatic marking';
$string['selectactivity'] = 'Select activity';
$string['automark_help'] = 'Allows marking to be completed automatically. $string['automark_help'] = 'Allows marking to be completed automatically.
If "Yes" students will be automatically marked depending on their first access to the course. If "Yes" students will be automatically marked depending on their first access to the course.
If "Set unmarked at end of session" any students who have not marked their attendance will be set to the unmarked status selected.'; If "Set unmarked at end of session" any students who have not marked their attendance will be set to the unmarked status selected.';
$string['automarkall'] = 'Yes'; $string['automarkall'] = 'Yes';
$string['automarkclose'] = 'Set unmarked at end of session'; $string['automarkclose'] = 'Set unmarked at end of session';
$string['onactivitycompletion'] = 'On activity completion';
$string['automarktask'] = 'Check for attendance sessions that require auto marking'; $string['automarktask'] = 'Check for attendance sessions that require auto marking';
$string['autorecorded'] = 'system auto recorded'; $string['autorecorded'] = 'system auto recorded';
$string['averageattendance'] = 'Average attendance'; $string['averageattendance'] = 'Average attendance';

49
locallib.php

@ -42,6 +42,8 @@ define('ATT_SORT_FIRSTNAME', 2);
define('ATTENDANCE_AUTOMARK_DISABLED', 0); define('ATTENDANCE_AUTOMARK_DISABLED', 0);
define('ATTENDANCE_AUTOMARK_ALL', 1); define('ATTENDANCE_AUTOMARK_ALL', 1);
define('ATTENDANCE_AUTOMARK_CLOSE', 2); define('ATTENDANCE_AUTOMARK_CLOSE', 2);
define('ATTENDANCE_AUTOMARK_ACTIVITYCOMPLETION', 3);
define('ATTENDANCE_SHAREDIP_DISABLED', 0); define('ATTENDANCE_SHAREDIP_DISABLED', 0);
define('ATTENDANCE_SHAREDIP_MINUTES', 1); define('ATTENDANCE_SHAREDIP_MINUTES', 1);
@ -788,6 +790,12 @@ function attendance_construct_sessions_data_for_add($formdata, mod_attendance_st
} }
$sess->automark = $formdata->automark; $sess->automark = $formdata->automark;
$sess->automarkcompleted = 0; $sess->automarkcompleted = 0;
if (!empty($formdata->automarkcmid)) {
$sess->automarkcmid = $formdata->automarkcmid;
} else {
$sess->automarkcmid = 0;
}
if (!empty($formdata->preventsharedip)) { if (!empty($formdata->preventsharedip)) {
$sess->preventsharedip = $formdata->preventsharedip; $sess->preventsharedip = $formdata->preventsharedip;
} }
@ -852,6 +860,13 @@ function attendance_construct_sessions_data_for_add($formdata, mod_attendance_st
$sess->studentpassword = ''; $sess->studentpassword = '';
$sess->automark = 0; $sess->automark = 0;
$sess->automarkcompleted = 0; $sess->automarkcompleted = 0;
if (!empty($formdata->automarkcmid)) {
$sess->automarkcmid = $formdata->automarkcmid;
} else {
$sess->automarkcmid = 0;
}
$sess->absenteereport = $absenteereport; $sess->absenteereport = $absenteereport;
$sess->includeqrcode = 0; $sess->includeqrcode = 0;
$sess->rotateqrcode = 0; $sess->rotateqrcode = 0;
@ -1150,15 +1165,49 @@ function attendance_session_get_highest_status(mod_attendance_structure $att, $a
* @return array * @return array
*/ */
function attendance_get_automarkoptions() { function attendance_get_automarkoptions() {
$options = array(); $options = array();
$options[ATTENDANCE_AUTOMARK_DISABLED] = get_string('noautomark', 'attendance'); $options[ATTENDANCE_AUTOMARK_DISABLED] = get_string('noautomark', 'attendance');
if (strpos(get_config('tool_log', 'enabled_stores'), 'logstore_standard') !== false) { if (strpos(get_config('tool_log', 'enabled_stores'), 'logstore_standard') !== false) {
$options[ATTENDANCE_AUTOMARK_ALL] = get_string('automarkall', 'attendance'); $options[ATTENDANCE_AUTOMARK_ALL] = get_string('automarkall', 'attendance');
} }
$options[ATTENDANCE_AUTOMARK_CLOSE] = get_string('automarkclose', 'attendance'); $options[ATTENDANCE_AUTOMARK_CLOSE] = get_string('automarkclose', 'attendance');
$options[ATTENDANCE_AUTOMARK_ACTIVITYCOMPLETION] = get_string('onactivitycompletion', 'attendance');
return $options; return $options;
} }
/**
* Get course module names associated to this course, if they're visible and complete.
* @param int $id - course id.
* @return array $automarkcmoptions - list of course module names associated to this course.
*/
function attendance_get_coursemodulenames($id) {
global $DB;
$automarkcmoptions = [];
$sql = "SELECT DISTINCT cm.id, cm.module, m.name
FROM {course_modules} cm
JOIN {modules} m ON m.id = cm.module
WHERE cm.course = :cmcourse
AND cm.visible = :cmvisible
AND cm.completion = :cmcompletion";
$coursemodulenames = $DB->get_records_sql($sql, array(
'cmcourse' => $id,
'cmvisible' => 1,
'cmcompletion' => 1
));
if ($coursemodulenames) {
foreach ($coursemodulenames as $coursemodulename) {
$automarkcmoptions[$coursemodulename->id] = format_string($coursemodulename->name);
}
}
return $automarkcmoptions;
}
/** /**
* Get available sharedip options. * Get available sharedip options.
* *

3
renderhelpers.php

@ -68,7 +68,8 @@ class user_sessions_cells_generator {
$this->construct_existing_status_cell($this->reportdata->statuses[$statusid]->acronym . $this->construct_existing_status_cell($this->reportdata->statuses[$statusid]->acronym .
" ({$points}/{$maxpoints})"); " ({$points}/{$maxpoints})");
} else { } else {
if (!empty($this->reportdata->allstatuses[$statusid] && isset($this->reportdata->allstatuses[$statusid]->acronym))) { if (!empty($this->reportdata->allstatuses[$statusid] &&
isset($this->reportdata->allstatuses[$statusid]->acronym))) {
$statusac = $this->reportdata->allstatuses[$statusid]->acronym; $statusac = $this->reportdata->allstatuses[$statusid]->acronym;
} else { } else {
$statusac = get_string('unknownstatus', 'mod_attendance', $statusid); $statusac = get_string('unknownstatus', 'mod_attendance', $statusid);

Loading…
Cancel
Save