Browse Source

Make update from student's 'allsessions' attendance report work.

nwp90-nwp90-allsessionsreport
Nick Phillips 6 years ago
committed by Dan Marsden
parent
commit
04a4a8f1e1
  1. 50
      locallib.php
  2. 141
      renderables.php
  3. 156
      renderer.php
  4. 24
      view.php

50
locallib.php

@ -115,7 +115,7 @@ function attendance_get_setname($attid, $statusset, $includevalues = true) {
* @param stdClass $pageparams * @param stdClass $pageparams
* @return array * @return array
*/ */
function get_user_sessions_log_full($userid, $pageparams) { function attendance_get_user_sessions_log_full($userid, $pageparams) {
global $DB; global $DB;
// All taken sessions (including previous groups). // All taken sessions (including previous groups).
@ -364,6 +364,54 @@ function attendance_update_users_grade($attendance, $userids=array()) {
return grade_update('mod/attendance', $course->id, 'mod', 'attendance', $attendance->id, 0, $grades); return grade_update('mod/attendance', $course->id, 'mod', 'attendance', $attendance->id, 0, $grades);
} }
/**
* Update grades for specified users for specified attendance
*
* @param integer $attendanceid - the id of the attendance to update
* @param integer $grade - the value of the 'grade' property of the specified attendance
* @param array $userids - the userids of the users to be updated
*/
function attendance_update_users_grades_by_id($attendanceid, $grade, $userids) {
global $DB;
if (empty($grade)) {
return false;
}
list($course, $cm) = get_course_and_cm_from_instance($attendanceid, 'attendance');
$summary = new mod_attendance_summary($attendanceid, $userids);
if (empty($userids)) {
$context = context_module::instance($cm->id);
$userids = array_keys(get_enrolled_users($context, 'mod/attendance:canbelisted', 0, 'u.id'));
}
if ($grade < 0) {
$dbparams = array('id' => -($grade));
$scale = $DB->get_record('scale', $dbparams);
$scalearray = explode(',', $scale->scale);
$attendancegrade = count($scalearray);
} else {
$attendancegrade = $grade;
}
$grades = array();
foreach ($userids as $userid) {
$grades[$userid] = new stdClass();
$grades[$userid]->userid = $userid;
if ($summary->has_taken_sessions($userid)) {
$usersummary = $summary->get_taken_sessions_summary_for($userid);
$grades[$userid]->rawgrade = $usersummary->takensessionspercentage * $attendancegrade;
} else {
$grades[$userid]->rawgrade = null;
}
}
return grade_update('mod/attendance', $course->id, 'mod', 'attendance', $attendanceid, 0, $grades);
}
/** /**
* Add an attendance status variable * Add an attendance status variable
* *

141
renderables.php

@ -516,7 +516,7 @@ class attendance_user_data implements renderable {
$this->filtercontrols = new attendance_filter_controls($att); $this->filtercontrols = new attendance_filter_controls($att);
} }
$this->sessionslog = get_user_sessions_log_full($userid, $this->pageparams); $this->sessionslog = attendance_get_user_sessions_log_full($userid, $this->pageparams);
foreach ($this->sessionslog as $sessid => $sess) { foreach ($this->sessionslog as $sessid => $sess) {
$this->sessionslog[$sessid]->cmid = $this->coursesatts[$sess->attendanceid]->cmid; $this->sessionslog[$sessid]->cmid = $this->coursesatts[$sess->attendanceid]->cmid;
@ -546,12 +546,145 @@ class attendance_user_data implements renderable {
} }
/** /**
* url helper. * Url function
* @param array $params
* @param array $excludeparams
* @return moodle_url * @return moodle_url
*/ */
public function url() { public function url($params=array(), $excludeparams=array()) {
return new moodle_url($this->urlpath, $this->urlparams); $params = array_merge($this->urlparams, $params);
foreach ($excludeparams as $paramkey) {
unset($params[$paramkey]);
}
return new moodle_url($this->urlpath, $params);
}
/**
* Take multiple sessions attendance from form data.
*
* @param stdClass $formdata
*/
public function take_sessions_from_form_data($formdata) {
global $DB, $USER;
// TODO: WARNING - $formdata is unclean - comes from direct $_POST - ideally needs a rewrite but we do some cleaning below.
// This whole function could do with a nice clean up.
// XXX - replace this, see below
//$statuses = implode(',', array_keys( (array)$this->get_statuses() ));
$now = time();
$sesslog = array();
$formdata = (array)$formdata;
$dbstudlogs = array();
$updatedsessions = array();
$sessionatt = array();
foreach ($formdata as $key => $value) {
// Look at Remarks field because the user options may not be passed if empty.
if (substr($key, 0, 7) == 'remarks') {
$formlog = array();
$parts = explode('sess', substr($key, 7));
$stid = $parts[0];
if (!(is_numeric($stid))) { // Sanity check on $stid.
print_error('nonnumericid', 'attendance');
}
$sessid = $parts[1];
if (!(is_numeric($sessid))) { // Sanity check on $sessid.
print_error('nonnumericid', 'attendance');
}
$dbsession = $this->sessionslog[$sessid];
$context = context_module::instance($dbsession->cmid);
if (!has_capability('mod/attendance:takeattendances', $context)) {
// How do we tell user about this?
error_log("User without capability tried to take attendance for context, cmid:", $dbsession->cmid);
continue;
}
$formkey = 'user'.$stid.'sess'.$sessid;
$attid = $dbsession->attendanceid;
$statusset = array_filter($this->statuses[$attid], function($x) use($dbsession) { return $x->setnumber === $dbsession->statusset; });
$sessionatt[$sessid] = $attid;
$formlog = new stdClass();
if (array_key_exists($formkey, $formdata) && is_numeric($formdata[$formkey])) {
$formlog->statusid = $formdata[$formkey];
}
$formlog->studentid = $stid; // We check is_numeric on this above.
$formlog->statusset = implode(',', array_keys($statusset));
$formlog->remarks = $value;
$formlog->sessionid = $sessid;
$formlog->timetaken = $now;
$formlog->takenby = $USER->id;
if (!array_key_exists($stid, $sesslog)) {
$sesslog[$stid] = array();
}
$sesslog[$stid][$sessid] = $formlog;
}
}
$updateatts = array();
foreach ($sesslog as $stid => $userlog) {
$dbstudlog = $DB->get_records('attendance_log', array('studentid' => $stid), '', 'sessionid,statusid,remarks,id,statusset');
foreach($userlog as $log) {
if (array_key_exists($log->sessionid, $dbstudlog)) {
$attid = $sessionatt[$log->sessionid];
// Check if anything important has changed before updating record.
// Don't update timetaken/takenby records if nothing has changed.
if ($dbstudlog[$log->sessionid]->remarks != $log->remarks ||
$dbstudlog[$log->sessionid]->statusid != $log->statusid ||
$dbstudlog[$log->sessionid]->statusset != $log->statusset) {
$log->id = $dbstudlog[$log->sessionid]->id;
$DB->update_record('attendance_log', $log);
$updatedsessions[$log->sessionid] = $log->sessionid;
if (!array_key_exists($attid, $updateatts)) {
$updateatts[$attid] = array();
}
array_push($updateatts[$attid], $log->studentid);
}
} else {
$DB->insert_record('attendance_log', $log, false);
$updatedsessions[$log->sessionid] = $log->sessionid;
if (!array_key_exists($attid, $updateatts)) {
$updateatts[$attid] = array();
}
array_push($updateatts[$attid], $log->studentid);
}
}
}
foreach ($updatedsessions as $sessionid) {
$session = $this->sessionslog[$sessionid];
$session->lasttaken = $now;
$session->lasttakenby = $USER->id;
$DB->update_record('attendance_sessions', $session);
}
if (!empty($updateatts)) {
$attendancegrade = $DB->get_records_list('attendance', 'id', array_keys($updateatts), '', 'id, grade');
foreach($updateatts as $attid => $updateusers) {
if ($attendancegrade[$attid] != 0) {
attendance_update_users_grades_by_id($attid, $grade, $updateusers);
}
}
}
// Create url for link in log screen.
$params = $this->pageparams->get_significant_params();
// XXX - TODO
// Waiting for event for viewing user report(s) before creating derived event for editing.
/* $event = \mod_attendance\event\attendance_taken::create(array( */
/* 'objectid' => $this->id, */
/* 'context' => $this->context, */
/* 'other' => $params)); */
/* $event->add_record_snapshot('course_modules', $this->cm); */
/* $event->add_record_snapshot('attendance_sessions', $session); */
/* $event->trigger(); */
} }
} }
/** /**

156
renderer.php

@ -1000,6 +1000,71 @@ class mod_attendance_renderer extends plugin_renderer_base {
return $celldata; return $celldata;
} }
/**
* Construct take session controls.
*
* @param attendance_take_data $takedata
* @param stdClass $user
* @return array
*/
private function construct_take_session_controls(attendance_take_data $takedata, $user) {
$celldata = array();
if ($user->enrolmentend and $user->enrolmentend < $takedata->sessioninfo->sessdate) {
$celldata['text'] = get_string('enrolmentend', 'attendance', userdate($user->enrolmentend, '%d.%m.%Y'));
$celldata['colspan'] = count($takedata->statuses) + 1;
$celldata['class'] = 'userwithoutenrol';
} else if (!$user->enrolmentend and $user->enrolmentstatus == ENROL_USER_SUSPENDED) {
// No enrolmentend and ENROL_USER_SUSPENDED.
$celldata['text'] = get_string('enrolmentsuspended', 'attendance');
$celldata['colspan'] = count($takedata->statuses) + 1;
$celldata['class'] = 'userwithoutenrol';
} else {
if ($takedata->updatemode and !array_key_exists($user->id, $takedata->sessionlog)) {
$celldata['class'] = 'userwithoutdata';
}
$celldata['text'] = array();
foreach ($takedata->statuses as $st) {
$params = array(
'type' => 'radio',
'name' => 'user'.$user->id.'sess'.$takedata->sessioninfo->id,
'class' => 'st'.$st->id,
'value' => $st->id);
if (array_key_exists($user->id, $takedata->sessionlog) and $st->id == $takedata->sessionlog[$user->id]->statusid) {
$params['checked'] = '';
}
$input = html_writer::empty_tag('input', $params);
if ($takedata->pageparams->viewmode == mod_attendance_take_page_params::SORTED_GRID) {
$input = html_writer::tag('nobr', $input . $st->acronym);
}
$celldata['text'][] = $input;
}
$params = array(
'type' => 'text',
'name' => 'remarks'.$user->id.'sess'.$takedata->sessioninfo->id,
'maxlength' => 255);
if (array_key_exists($user->id, $takedata->sessionlog)) {
$params['value'] = $takedata->sessionlog[$user->id]->remarks;
}
$input = html_writer::empty_tag('input', $params);
if ($takedata->pageparams->viewmode == mod_attendance_take_page_params::SORTED_GRID) {
$input = html_writer::empty_tag('br').$input;
}
$celldata['text'][] = $input;
if ($user->enrolmentstart > $takedata->sessioninfo->sessdate + $takedata->sessioninfo->duration) {
$celldata['warning'] = get_string('enrolmentstart', 'attendance',
userdate($user->enrolmentstart, '%H:%M %d.%m.%Y'));
$celldata['class'] = 'userwithoutenrol';
}
}
return $celldata;
}
/** /**
* Render header. * Render header.
* *
@ -1453,15 +1518,6 @@ class mod_attendance_renderer extends plugin_renderer_base {
$summarywidth++; $summarywidth++;
} }
/* if (has_capability('mod/attendance:takeattendances', $context)) { */
/* $table->head[] = get_string('action'); */
/* $table->align[] = ''; */
/* $table->colclasses[] = 'actioncol'; */
/* $table->size[] = ''; */
/* $colcount++; */
/* $summarywidth++; */
/* } */
$statusmaxpoints = array(); $statusmaxpoints = array();
foreach ($userdata->statuses as $attid => $attstatuses) { foreach ($userdata->statuses as $attid => $attstatuses) {
$statusmaxpoints[$attid] = attendance_get_statusset_maxpoints($attstatuses); $statusmaxpoints[$attid] = attendance_get_statusset_maxpoints($attstatuses);
@ -1863,7 +1919,61 @@ class mod_attendance_renderer extends plugin_renderer_base {
} }
if (!empty($USER->editing)) { if (!empty($USER->editing)) {
// TODO: add ability to edit attendance here $context = context_module::instance($sess->cmid);
if (has_capability('mod/attendance:takeattendances', $context)) {
// TODO: add ability to edit attendance here
$celltext = '';
// takedata needs:
// sessioninfo->sessdate
// sessioninfo->duration
// statuses
// updatemode
// sessionlog[userid]->statusid
// sessionlog[userid]->remarks
// pageparams->viewmode == mod_attendance_take_page_params::SORTED_GRID
// and urlparams to be able to use url method later.
//
// user needs:
// enrolmentstart
// enrolmentend
// enrolmentstatus
// id
$nastyhack = new ReflectionClass('attendance_take_data');
$takedata = $nastyhack->newInstanceWithoutConstructor();
$takedata->sessioninfo = $sess;
$takedata->statuses = array_filter($userdata->statuses[$sess->attendanceid], function($x) use ($sess) {
return ($x->setnumber == $sess->statusset);
});
$takedata->updatemode = true;
$takedata->sessionlog = array($userdata->user->id => $sess);
$takedata->pageparams = new stdClass();
$takedata->pageparams->viewmode = mod_attendance_take_page_params::SORTED_GRID;
$ucdata = $this->construct_take_session_controls($takedata, $userdata->user);
$celltext = join($ucdata['text']);
if (array_key_exists('warning', $ucdata)) {
$celltext .= html_writer::empty_tag('br');
$celltext .= $ucdata['warning'];
}
if (array_key_exists('class', $ucdata)) {
$row->attributes['class'] = $ucdata['class'];
}
$cell = new html_table_cell($celltext);
$cell->colspan = 2;
$row->cells[] = $cell;
}
else {
if (!empty($sess->statusid)) {
$status = $userdata->statuses[$sess->attendanceid][$sess->statusid];
$row->cells[] = $status->description;
$row->cells[] = $sess->remarks;
}
}
} else { } else {
if (!empty($sess->statusid)) { if (!empty($sess->statusid)) {
$status = $userdata->statuses[$sess->attendanceid][$sess->statusid]; $status = $userdata->statuses[$sess->attendanceid][$sess->statusid];
@ -1904,7 +2014,31 @@ class mod_attendance_renderer extends plugin_renderer_base {
} }
} }
$allsessions->detail = html_writer::table($table); if (!empty($USER->editing)) {
$row = new html_table_row();
$params = array(
'type' => 'submit',
'class' => 'btn btn-primary',
'value' => get_string('save', 'attendance'));
$cell = new html_table_cell(html_writer::tag('center', html_writer::empty_tag('input', $params)));
$cell->colspan = $colcount + (($groupby == 'activity')? 2 : 1);
$row->cells[] = $cell;
$table->data[] = $row;
}
$logtext = html_writer::table($table);
if (!empty($USER->editing)) {
$formtext = html_writer::start_div('no-overflow');
$formtext .= $logtext;
$formtext .= html_writer::input_hidden_params($userdata->url(array('sesskey' => sesskey())));
$formtext .= html_writer::end_div();
// could use userdata->urlpath if not private or userdata->url_path() if existed, but '' turns
// out to DTRT.
$logtext = html_writer::tag('form', $formtext, array('method' => 'post', 'action' => '',
'id' => 'attendancetakeform'));
}
$allsessions->detail = $logtext;
return $allsessions; return $allsessions;
} }

24
view.php

@ -62,14 +62,6 @@ if (!$pageparams->studentid) {
} }
} }
$PAGE->set_url($att->url_view($pageparams->get_significant_params()));
$PAGE->set_title($course->shortname. ": ".$att->name);
$PAGE->set_heading($course->fullname);
$PAGE->set_cacheable(true);
$PAGE->navbar->add(get_string('attendancereport', 'attendance'));
$output = $PAGE->get_renderer('mod_attendance');
if (isset($pageparams->studentid) && $USER->id != $pageparams->studentid) { if (isset($pageparams->studentid) && $USER->id != $pageparams->studentid) {
// Only users with proper permissions should be able to see any user's individual report. // Only users with proper permissions should be able to see any user's individual report.
require_capability('mod/attendance:viewreports', $context); require_capability('mod/attendance:viewreports', $context);
@ -79,6 +71,9 @@ if (isset($pageparams->studentid) && $USER->id != $pageparams->studentid) {
$userid = $USER->id; $userid = $USER->id;
} }
$url = $att->url_view($pageparams->get_significant_params());
$PAGE->set_url($url);
$userdata = new attendance_user_data($att, $userid); $userdata = new attendance_user_data($att, $userid);
// Create url for link in log screen. // Create url for link in log screen.
@ -105,6 +100,19 @@ $event->trigger();
$header = new mod_attendance_header($att); $header = new mod_attendance_header($att);
if (($formdata = data_submitted()) && confirm_sesskey()) {
$userdata->take_sessions_from_form_data($formdata);
redirect($url, get_string('attendancesuccess', 'attendance'));
}
$PAGE->set_title($course->shortname. ": ".$att->name);
$PAGE->set_heading($course->fullname);
$PAGE->set_cacheable(true);
$PAGE->navbar->add(get_string('attendancereport', 'attendance'));
$output = $PAGE->get_renderer('mod_attendance');
echo $output->header(); echo $output->header();
echo $output->render($header); echo $output->render($header);

Loading…
Cancel
Save