diff --git a/classes/view_page_params.php b/classes/view_page_params.php
index d1c04ac..fd5d696 100644
--- a/classes/view_page_params.php
+++ b/classes/view_page_params.php
@@ -46,6 +46,12 @@ class mod_attendance_view_page_params extends mod_attendance_page_with_filter_co
/** @var string */
public $mode;
+ /** @var string */
+ public $groupby;
+
+ /** @var string */
+ public $sesscourses;
+
/**
* mod_attendance_view_page_params constructor.
*/
@@ -67,6 +73,12 @@ class mod_attendance_view_page_params extends mod_attendance_page_with_filter_co
if ($this->mode != self::MODE_THIS_COURSE) {
$params['mode'] = $this->mode;
}
+ if ($this->groupby != 'course') {
+ $params['groupby'] = $this->groupby;
+ }
+ if ($this->sesscourses != 'current') {
+ $params['sesscourses'] = $this->sesscourses;
+ }
return $params;
}
diff --git a/lang/en/attendance.php b/lang/en/attendance.php
index e7eea16..d2bc83c 100644
--- a/lang/en/attendance.php
+++ b/lang/en/attendance.php
@@ -43,6 +43,7 @@ $string['all'] = 'All';
$string['allcourses'] = 'All courses';
$string['allpast'] = 'All past';
$string['allsessions'] = 'All sessions';
+$string['allsessionstotals'] = 'Totals for selected sessions';
$string['attendance:addinstance'] = 'Add a new attendance activity';
$string['attendance:canbelisted'] = 'Appears in the roster';
$string['attendance:changeattendances'] = 'Changing Attendances';
@@ -250,6 +251,7 @@ $string['gridcolumns'] = 'Grid columns';
$string['group'] = 'Group';
$string['groups'] = 'Groups';
$string['groupsession'] = 'Group of students';
+$string['groupsessionsby'] = 'Group sessions by';
$string['hiddensessions'] = 'Hidden sessions';
$string['hiddensessions_help'] = 'Sessions are hidden if they are scheduled before the course start date.
@@ -487,7 +489,12 @@ $string['sessionduplicate'] = 'A duplicate session exists for course: {$a->cours
$string['sessionexist'] = 'Session not added (already exists)!';
$string['sessiongenerated'] = 'One session was successfully generated';
$string['sessions'] = 'Sessions';
+$string['sessionsallcourses'] = 'All courses';
+$string['sessionsbyactivity'] = 'Attendance Instance';
+$string['sessionsbycourse'] = 'Course';
+$string['sessionsbydate'] = 'Week';
$string['sessionscompleted'] = 'Taken sessions';
+$string['sessionscurrentcourses'] = 'Current courses';
$string['sessionsgenerated'] = '{$a} sessions were successfully generated';
$string['sessionsids'] = 'IDs of sessions: ';
$string['sessionsnotfound'] = 'There is no sessions in the selected timespan';
@@ -531,6 +538,7 @@ $string['statusset'] = 'Status set {$a}';
$string['statussetsettings'] = 'Status set';
$string['statusunselected'] = 'unselected';
$string['strftimedm'] = '%b %d';
+$string['strftimedmw'] = '%a %b %d';
$string['strftimedmy'] = '%d %b %Y';
$string['strftimedmyhm'] = '%d %b %Y %I.%M%p'; // Line added to allow multiple sessions in the same day.
$string['strftimedmyw'] = '%a %d %b %Y';
@@ -583,6 +591,7 @@ $string['thiscourse'] = 'This course';
$string['time'] = 'Time';
$string['timeahead'] = 'Multiple sessions that exceed one year cannot be created, please adjust the start and end dates.';
$string['to'] = 'to:';
+$string['todate'] = 'to date';
$string['triggered'] = 'First notified';
$string['tuseremail'] = 'Email';
$string['tusername'] = 'Full name';
@@ -616,5 +625,6 @@ $string['warnings'] = 'Warnings set';
$string['warningthreshold'] = 'Warning threshold';
$string['warningupdated'] = 'Updated warnings';
$string['week'] = 'week(s)';
+$string['weekcommencing'] = 'Week Commencing';
$string['weeks'] = 'Weeks';
$string['youcantdo'] = 'You can\'t do anything';
\ No newline at end of file
diff --git a/locallib.php b/locallib.php
index 3a8aef4..3c44506 100644
--- a/locallib.php
+++ b/locallib.php
@@ -114,13 +114,49 @@ function attendance_get_setname($attid, $statusset, $includevalues = true) {
* @param int $userid
* @return array
*/
-function get_user_sessions_log_full($userid) {
+function get_user_sessions_log_full($userid, $pageparams) {
global $DB;
// All taken sessions (including previous groups).
$usercourses = enrol_get_users_courses($userid);
list($usql, $uparams) = $DB->get_in_or_equal(array_keys($usercourses), SQL_PARAMS_NAMED, 'cid0');
+ // If we base on structure->get_user_filtered_sessions_log_extended:
+ /* if ($this->pageparams->startdate && $this->pageparams->enddate) { */
+ /* $where = "ats.sessdate >= :csdate AND */
+ /* ats.sessdate >= :sdate AND ats.sessdate < :edate"; */
+ /* } else { */
+ /* $where = "ats.attendanceid = :aid AND ats.sessdate >= :csdate"; */
+ /* } */
+
+ $coursesql = "(1 = 1)";
+ $courseparams = array();
+ $now = time();
+ if ($pageparams->sesscourses === 'current') {
+ $coursesql = "(c.startdate = 0 OR c.startdate <= :now1) AND (c.enddate = 0 OR c.enddate >= :now2)";
+ $courseparams = array(
+ 'now1' => $now,
+ 'now2' => $now,
+ );
+ }
+
+ $datesql = "(1 = 1)";
+ $dateparams = array();
+ if ($pageparams->startdate && $pageparams->enddate) {
+ $datesql = "ats.sessdate >= :sdate AND ats.sessdate < :edate";
+ $dateparams = array(
+ 'sdate' => $pageparams->startdate,
+ 'edate' => $pageparams->enddate,
+ );
+ }
+
+ if ($pageparams->groupby === 'date') {
+ $ordersql = "ats.sessdate ASC, c.fullname ASC, att.name ASC, att.id ASC";
+ }
+ else {
+ $ordersql = "c.fullname ASC, att.name ASC, att.id ASC, ats.sessdate ASC";
+ }
+
// WHERE clause is important:
// gm.userid not null => get unmarked attendances for user's current groups
// ats.groupid 0 => get all sessions that are for all students enrolled in course
@@ -141,13 +177,17 @@ function get_user_sessions_log_full($userid) {
ON (ats.groupid = gm.groupid AND gm.userid = :uid1)
WHERE (gm.userid IS NOT NULL OR ats.groupid = 0 OR al.id IS NOT NULL)
AND att.course $usql
- ORDER BY c.fullname ASC, att.name ASC, att.id ASC, ats.sessdate ASC";
+ AND $datesql
+ AND $coursesql
+ ORDER BY $ordersql";
$params = array(
'uid' => $userid,
'uid1' => $userid,
);
$params = array_merge($params, $uparams);
+ $params = array_merge($params, $dateparams);
+ $params = array_merge($params, $courseparams);
$sessions = $DB->get_records_sql($sql, $params);
foreach ($sessions as $sess) {
diff --git a/renderables.php b/renderables.php
index c4cee51..1271006 100644
--- a/renderables.php
+++ b/renderables.php
@@ -516,7 +516,7 @@ class attendance_user_data implements renderable {
$this->filtercontrols = new attendance_filter_controls($att);
}
- $this->sessionslog = get_user_sessions_log_full($userid);
+ $this->sessionslog = get_user_sessions_log_full($userid, $this->pageparams);
foreach ($this->sessionslog as $sessid => $sess) {
$this->sessionslog[$sessid]->cmid = $this->coursesatts[$sess->attendanceid]->cmid;
diff --git a/renderer.php b/renderer.php
index 066c8da..926b2c3 100644
--- a/renderer.php
+++ b/renderer.php
@@ -56,21 +56,41 @@ class mod_attendance_renderer extends plugin_renderer_base {
* @return string html code
*/
protected function render_attendance_filter_controls(attendance_filter_controls $fcontrols) {
+ $classes = 'attfiltercontrols';
$filtertable = new html_table();
$filtertable->attributes['class'] = ' ';
$filtertable->width = '100%';
$filtertable->align = array('left', 'center', 'right', 'right');
- $filtertable->data[0][] = $this->render_sess_group_selector($fcontrols);
+ if ($fcontrols->pageparams->mode === mod_attendance_view_page_params::MODE_ALL_SESSIONS) {
+ $classes .= ' float-right';
- $filtertable->data[0][] = $this->render_curdate_controls($fcontrols);
+ $row = array();
+ $row[] = '';
+ $row[] = '';
+ $row[] = '';
+ $row[] = $this->render_grouping_controls($fcontrols);
+ $filtertable->data[] = $row;
- $filtertable->data[0][] = $this->render_paging_controls($fcontrols);
+ $row = array();
+ $row[] = '';
+ $row[] = '';
+ $row[] = '';
+ $row[] = $this->render_course_controls($fcontrols);
+ $filtertable->data[] = $row;
+ }
+
+ $row = array();
- $filtertable->data[0][] = $this->render_view_controls($fcontrols);
+ $row[] = $this->render_sess_group_selector($fcontrols);
+ $row[] = $this->render_curdate_controls($fcontrols);
+ $row[] = $this->render_paging_controls($fcontrols);
+ $row[] = $this->render_view_controls($fcontrols);
+
+ $filtertable->data[] = $row;
$o = html_writer::table($filtertable);
- $o = $this->output->container($o, 'attfiltercontrols');
+ $o = $this->output->container($o, $classes);
return $o;
}
@@ -198,6 +218,59 @@ class mod_attendance_renderer extends plugin_renderer_base {
return $curdatecontrols;
}
+ /**
+ * Render grouping controls (for all sessions report).
+ *
+ * @param attendance_filter_controls $fcontrols
+ * @return string
+ */
+ protected function render_grouping_controls(attendance_filter_controls $fcontrols) {
+ if ($fcontrols->pageparams->mode === mod_attendance_view_page_params::MODE_ALL_SESSIONS) {
+ $groupoptions = array(
+ 'date' => get_string('sessionsbydate', 'attendance'),
+ 'activity' => get_string('sessionsbyactivity', 'attendance'),
+ 'course' => get_string('sessionsbycourse', 'attendance')
+ );
+ $groupcontrols = get_string('groupsessionsby', 'attendance') . ":";
+ foreach ($groupoptions as $key => $opttext) {
+ if ($key != $fcontrols->pageparams->groupby) {
+ $link = html_writer::link($fcontrols->url(array('groupby' => $key)), $opttext);
+ $groupcontrols .= html_writer::tag('span', $link, array('class' => 'attbtn'));
+ } else {
+ $groupcontrols .= html_writer::tag('span', $opttext, array('class' => 'attcurbtn'));
+ }
+ }
+ return html_writer::tag('nobr', $groupcontrols);
+ }
+ return "";
+ }
+
+ /**
+ * Render course controls (for all sessions report).
+ *
+ * @param attendance_filter_controls $fcontrols
+ * @return string
+ */
+ protected function render_course_controls(attendance_filter_controls $fcontrols) {
+ if ($fcontrols->pageparams->mode === mod_attendance_view_page_params::MODE_ALL_SESSIONS) {
+ $courseoptions = array(
+ 'all' => get_string('sessionsallcourses', 'attendance'),
+ 'current' => get_string('sessionscurrentcourses', 'attendance')
+ );
+ $coursecontrols = "";
+ foreach ($courseoptions as $key => $opttext) {
+ if ($key != $fcontrols->pageparams->sesscourses) {
+ $link = html_writer::link($fcontrols->url(array('sesscourses' => $key)), $opttext);
+ $coursecontrols .= html_writer::tag('span', $link, array('class' => 'attbtn'));
+ } else {
+ $coursecontrols .= html_writer::tag('span', $opttext, array('class' => 'attcurbtn'));
+ }
+ }
+ return html_writer::tag('nobr', $coursecontrols);
+ }
+ return "";
+ }
+
/**
* Render view controls.
*
@@ -960,7 +1033,8 @@ class mod_attendance_renderer extends plugin_renderer_base {
$o = $this->render_user_report_tabs($userdata);
- if ($USER->id == $userdata->user->id) {
+ if ($USER->id == $userdata->user->id ||
+ $userdata->pageparams->mode === mod_attendance_view_page_params::MODE_ALL_SESSIONS) {
$o .= $this->construct_user_data($userdata);
@@ -993,11 +1067,14 @@ class mod_attendance_renderer extends plugin_renderer_base {
$userdata->url()->out(true, array('mode' => mod_attendance_view_page_params::MODE_THIS_COURSE)),
get_string('thiscourse', 'attendance'));
- // Skip the 'all courses' tab for 'temporary' users.
+ // Skip the 'all courses' and 'all sessions' tabs for 'temporary' users.
if ($userdata->user->type == 'standard') {
$tabs[] = new tabobject(mod_attendance_view_page_params::MODE_ALL_COURSES,
$userdata->url()->out(true, array('mode' => mod_attendance_view_page_params::MODE_ALL_COURSES)),
get_string('allcourses', 'attendance'));
+ $tabs[] = new tabobject(mod_attendance_view_page_params::MODE_ALL_SESSIONS,
+ $userdata->url()->out(true, array('mode' => mod_attendance_view_page_params::MODE_ALL_SESSIONS)),
+ get_string('allsessions', 'attendance'));
}
return print_tabs(array($tabs), $userdata->pageparams->mode, null, null, true);
@@ -1023,8 +1100,21 @@ class mod_attendance_renderer extends plugin_renderer_base {
$o .= construct_user_data_stat($userdata->summary->get_all_sessions_summary_for($userdata->user->id),
$userdata->pageparams->view);
} else if ($userdata->pageparams->mode == mod_attendance_view_page_params::MODE_ALL_SESSIONS) {
+ $allsessions = $this->construct_user_allsessions_log($userdata);
+ $o .= html_writer::start_div('allsessionssummary');
+ $o .= html_writer::start_div('float-left');
+ $o .= html_writer::start_div('float-left');
+ $o .= $this->user_picture($userdata->user, array('size' => 100, 'class' => 'userpicture float-left'));
+ $o .= html_writer::end_div();
+ $o .= html_writer::start_div('float-right');
+ $o .= $allsessions->summary;
+ $o .= html_writer::end_div();
+ $o .= html_writer::end_div();
+ $o .= html_writer::start_div('float-right');
$o .= $this->render_attendance_filter_controls($userdata->filtercontrols);
- $o .= $this->construct_user_allsessions_log($userdata);
+ $o .= html_writer::end_div();
+ $o .= html_writer::end_div();
+ $o .= $allsessions->detail;
} else {
$table = new html_table();
$table->head = array(get_string('course'),
@@ -1238,6 +1328,8 @@ class mod_attendance_renderer extends plugin_renderer_base {
private function construct_user_allsessions_log(attendance_user_data $userdata) {
global $OUTPUT, $USER;
+ $allsessions = new stdClass();
+
$shortform = false;
if ($USER->id == $userdata->user->id) {
// This is a user viewing their own stuff - hide non-relevant columns.
@@ -1246,21 +1338,69 @@ class mod_attendance_renderer extends plugin_renderer_base {
$context = context_module::instance($userdata->filtercontrols->cm->id);
+ $groupby = $userdata->pageparams->groupby;
+ //$groupby = 'course';
+ //$groupby = 'activity';
+ //$groupby = 'date';
+
$table = new html_table();
- $table->attributes['class'] = 'generaltable attwidth boxaligncenter';
+ $table->attributes['class'] = 'generaltable attwidth boxaligncenter allsessions';
$table->head = array();
$table->align = array();
$table->size = array();
$table->colclasses = array();
+ $colcount = 0;
+ $summarywidth = 0;
+
+ // If grouping by date, we need some form of date up front.
+ // Only need course column if we are not using course to group
+ // (currently date is only option which does not use course)
+ if ($groupby === 'date') {
+ $table->head[] = '';
+ $table->align[] = 'left';
+ $table->colclasses[] = 'grouper';
+ $table->size[] = '1px';
- $table->head[] = get_string('course');
- $table->align[] = 'left';
- $table->colclasses[] = 'colcourse';
+ $table->head[] = get_string('date');
+ $table->align[] = 'left';
+ $table->colclasses[] = 'datecol';
+ $table->size[] = '1px';
+ $colcount++;
- $table->head[] = get_string('pluginname', 'mod_attendance');
- $table->align[] = 'left';
- $table->colclasses[] = 'colcourse';
- $table->size[] = '*';
+ $table->head[] = get_string('course');
+ $table->align[] = 'left';
+ $table->colclasses[] = 'colcourse';
+ $colcount++;
+ } else {
+ $table->head[] = '';
+ $table->align[] = 'left';
+ $table->colclasses[] = 'grouper';
+ $table->size[] = '1px';
+ if ($groupby === 'activity') {
+ $table->head[] = '';
+ $table->align[] = 'left';
+ $table->colclasses[] = 'grouper';
+ $table->size[] = '1px';
+ }
+ }
+
+ // Need activity column unless we are using activity to group
+ if ($groupby !== 'activity') {
+ $table->head[] = get_string('pluginname', 'mod_attendance');
+ $table->align[] = 'left';
+ $table->colclasses[] = 'colcourse';
+ $table->size[] = '*';
+ $colcount++;
+ }
+
+ // If grouping by date, it belongs up front rather than here
+ if ($groupby !== 'date') {
+ $table->head[] = get_string('date');
+ $table->align[] = 'left';
+ $table->colclasses[] = 'datecol';
+ $table->size[] = '1px';
+ $colcount++;
+ }
// use "session" instead
//$table->head[] = get_string('description', 'attendance');
@@ -1268,125 +1408,509 @@ class mod_attendance_renderer extends plugin_renderer_base {
$table->align[] = 'left';
$table->colclasses[] = 'desccol';
$table->size[] = '*';
+ $colcount++;
if (!$shortform) {
$table->head[] = get_string('sessiontypeshort', 'attendance');
$table->align[] = '';
$table->size[] = '1px';
$table->colclasses[] = '';
+ $colcount++;
}
- $table->head[] = get_string('date');
- $table->align[] = 'left';
- $table->colclasses[] = 'datecol';
- $table->size[] = '1px';
-
- $table->head[] = get_string('status', 'attendance');
- $table->align[] = 'center';
- $table->colclasses[] = 'statuscol';
- $table->size[] = '*';
+ if (!empty($USER->editing)) {
+ $table->head[] = get_string('status', 'attendance');
+ $table->align[] = 'center';
+ $table->colclasses[] = 'statuscol';
+ $table->size[] = '*';
+ $colcount++;
+ $summarywidth++;
- $table->head[] = get_string('points', 'attendance');
- $table->align[] = 'center';
- $table->colclasses[] = 'pointscol';
- $table->size[] = '1px';
+ $table->head[] = get_string('remarks', 'attendance');
+ $table->align[] = 'center';
+ $table->colclasses[] = 'remarkscol';
+ $table->size[] = '*';
+ $colcount++;
+ $summarywidth++;
+ } else {
+ $table->head[] = get_string('status', 'attendance');
+ $table->align[] = 'center';
+ $table->colclasses[] = 'statuscol';
+ $table->size[] = '*';
+ $colcount++;
+ $summarywidth++;
- $table->head[] = get_string('remarks', 'attendance');
- $table->align[] = 'center';
- $table->colclasses[] = 'remarkscol';
- $table->size[] = '*';
+ $table->head[] = get_string('points', 'attendance');
+ $table->align[] = 'center';
+ $table->colclasses[] = 'pointscol';
+ $table->size[] = '1px';
+ $colcount++;
+ $summarywidth++;
- if (has_capability('mod/attendance:takeattendances', $context)) {
- $table->head[] = get_string('action');
- $table->align[] = '';
- $table->colclasses[] = 'actioncol';
- $table->size[] = '';
+ $table->head[] = get_string('remarks', 'attendance');
+ $table->align[] = 'center';
+ $table->colclasses[] = 'remarkscol';
+ $table->size[] = '*';
+ $colcount++;
+ $summarywidth++;
}
+ /* if (has_capability('mod/attendance:takeattendances', $context)) { */
+ /* $table->head[] = get_string('action'); */
+ /* $table->align[] = ''; */
+ /* $table->colclasses[] = 'actioncol'; */
+ /* $table->size[] = ''; */
+ /* $colcount++; */
+ /* $summarywidth++; */
+ /* } */
+
$statusmaxpoints = array();
foreach ($userdata->statuses as $attid => $attstatuses) {
$statusmaxpoints[$attid] = attendance_get_statusset_maxpoints($attstatuses);
}
- $i = 0;
- foreach ($userdata->sessionslog as $sess) {
- $i++;
-
- $statussetmaxpoints = $statusmaxpoints[$sess->attendanceid];
+ $lastgroup = array(null, null);
+ $groups = array();
+ $stats = array(
+ 'course' => array(),
+ 'activity' => array(),
+ 'date' => array(),
+ 'overall' => array(
+ 'points' => 0,
+ 'maxpointstodate' => 0,
+ 'maxpoints' => 0,
+ 'pcpointstodate' => null,
+ 'pcpoints' => null,
+ 'statuses' => array()
+ )
+ );
+ $group = null;
+ if ($userdata->sessionslog) {
+ foreach ($userdata->sessionslog as $sess) {
+ if ($groupby === 'date') {
+ $weekformat = date("YW", $sess->sessdate);
+ if ($weekformat != $lastgroup[0]) {
+ if ($group !== null) {
+ array_push($groups, $group);
+ }
+ $group = array();
+ $lastgroup[0] = $weekformat;
+ }
+ if (!array_key_exists($weekformat, $stats['date'])) {
+ $stats['date'][$weekformat] = array(
+ 'points' => 0,
+ 'maxpointstodate' => 0,
+ 'maxpoints' => 0,
+ 'pcpointstodate' => null,
+ 'pcpoints' => null,
+ 'statuses' => array()
+ );
+ }
+ $statussetmaxpoints = $statusmaxpoints[$sess->attendanceid];
+ // ensure all possible acronyms for current sess's statusset are available as
+ // keys in status array for period
+ //
+ // A bit yucky because we can't tell whether we've seen statusset before, and
+ // we usually will have, so much wasted spinning.
+ if ($sess->id == 163) {
+ error_log("STATUSSET: ".print_r($sess->statusset, true));
+ }
+ foreach ($userdata->statuses[$sess->attendanceid] as $attstatus) {
+ if ($attstatus->setnumber === $sess->statusset) {
+ if (!array_key_exists($attstatus->acronym, $stats['date'][$weekformat]['statuses'])) {
+ $stats['date'][$weekformat]['statuses'][$attstatus->acronym] = array('count' => 0, 'description' => $attstatus->description);
+ }
+ if (!array_key_exists($attstatus->acronym, $stats['overall']['statuses'])) {
+ $stats['overall']['statuses'][$attstatus->acronym] = array('count' => 0, 'description' => $attstatus->description);
+ }
+ }
+ }
+ // array_key_exists check is for hidden statuses
+ if (isset($sess->statusid) && array_key_exists($sess->statusid, $userdata->statuses[$sess->attendanceid])) {
+ $status = $userdata->statuses[$sess->attendanceid][$sess->statusid];
+ $stats['date'][$weekformat]['statuses'][$status->acronym]['count']++;
+ $stats['date'][$weekformat]['points'] += $status->grade;
+ $stats['date'][$weekformat]['maxpointstodate'] += $statussetmaxpoints[$sess->statusset];
+ $stats['overall']['statuses'][$status->acronym]['count']++;
+ $stats['overall']['points'] += $status->grade;
+ $stats['overall']['maxpointstodate'] += $statussetmaxpoints[$sess->statusset];
+ }
+ $stats['date'][$weekformat]['maxpoints'] += $statussetmaxpoints[$sess->statusset];
+ $stats['overall']['maxpoints'] += $statussetmaxpoints[$sess->statusset];
+ }
+ else {
+ // By course and perhaps activity
+ if (
+ ($sess->courseid != $lastgroup[0]) ||
+ ($groupby === 'activity' && $sess->cmid != $lastgroup[1])
+ ) {
+ if ($group !== null) {
+ array_push($groups, $group);
+ }
+ $group = array();
+ $lastgroup[0] = $sess->courseid;
+ $lastgroup[1] = $sess->cmid;
+ }
+ if (!array_key_exists($sess->courseid, $stats['course'])) {
+ $stats['course'][$sess->courseid] = array(
+ 'points' => 0,
+ 'maxpointstodate' => 0,
+ 'maxpoints' => 0,
+ 'pcpointstodate' => null,
+ 'pcpoints' => null,
+ 'statuses' => array()
+ );
+ }
+ $statussetmaxpoints = $statusmaxpoints[$sess->attendanceid];
+ // ensure all possible acronyms for current sess's statusset are available as
+ // keys in status array for course
+ //
+ // A bit yucky because we can't tell whether we've seen statusset before, and
+ // we usually will have, so much wasted spinning.
+ foreach ($userdata->statuses[$sess->attendanceid] as $attstatus) {
+ if ($attstatus->setnumber === $sess->statusset) {
+ if (!array_key_exists($attstatus->acronym, $stats['course'][$sess->courseid]['statuses'])) {
+ $stats['course'][$sess->courseid]['statuses'][$attstatus->acronym] = array('count' => 0, 'description' => $attstatus->description);
+ }
+ if (!array_key_exists($attstatus->acronym, $stats['overall']['statuses'])) {
+ $stats['overall']['statuses'][$attstatus->acronym] = array('count' => 0, 'description' => $attstatus->description);
+ }
+ }
+ }
+ // array_key_exists check is for hidden statuses
+ if (isset($sess->statusid) && array_key_exists($sess->statusid, $userdata->statuses[$sess->attendanceid])) {
+ $status = $userdata->statuses[$sess->attendanceid][$sess->statusid];
+ $stats['course'][$sess->courseid]['statuses'][$status->acronym]['count']++;
+ $stats['course'][$sess->courseid]['points'] += $status->grade;
+ $stats['course'][$sess->courseid]['maxpointstodate'] += $statussetmaxpoints[$sess->statusset];
+ $stats['overall']['statuses'][$status->acronym]['count']++;
+ $stats['overall']['points'] += $status->grade;
+ $stats['overall']['maxpointstodate'] += $statussetmaxpoints[$sess->statusset];
+ }
+ $stats['course'][$sess->courseid]['maxpoints'] += $statussetmaxpoints[$sess->statusset];
+ $stats['overall']['maxpoints'] += $statussetmaxpoints[$sess->statusset];
+
+ if (!array_key_exists($sess->cmid, $stats['activity'])) {
+ $stats['activity'][$sess->cmid] = array(
+ 'points' => 0,
+ 'maxpointstodate' => 0,
+ 'maxpoints' => 0,
+ 'pcpointstodate' => null,
+ 'pcpoints' => null,
+ 'statuses' => array()
+ );
+ }
+ $statussetmaxpoints = $statusmaxpoints[$sess->attendanceid];
+ // ensure all possible acronyms for current sess's statusset are available as
+ // keys in status array for period
+ //
+ // A bit yucky because we can't tell whether we've seen statusset before, and
+ // we usually will have, so much wasted spinning.
+ foreach ($userdata->statuses[$sess->attendanceid] as $attstatus) {
+ if ($attstatus->setnumber === $sess->statusset) {
+ if (!array_key_exists($attstatus->acronym, $stats['activity'][$sess->cmid]['statuses'])) {
+ $stats['activity'][$sess->cmid]['statuses'][$attstatus->acronym] = array('count' => 0, 'description' => $attstatus->description);
+ }
+ if (!array_key_exists($attstatus->acronym, $stats['overall']['statuses'])) {
+ $stats['overall']['statuses'][$attstatus->acronym] = array('count' => 0, 'description' => $attstatus->description);
+ }
+ }
+ }
+ // array_key_exists check is for hidden statuses
+ if (isset($sess->statusid) && array_key_exists($sess->statusid, $userdata->statuses[$sess->attendanceid])) {
+ $status = $userdata->statuses[$sess->attendanceid][$sess->statusid];
+ $stats['activity'][$sess->cmid]['statuses'][$status->acronym]['count']++;
+ $stats['activity'][$sess->cmid]['points'] += $status->grade;
+ $stats['activity'][$sess->cmid]['maxpointstodate'] += $statussetmaxpoints[$sess->statusset];
+ $stats['overall']['statuses'][$status->acronym]['count']++;
+ $stats['overall']['points'] += $status->grade;
+ $stats['overall']['maxpointstodate'] += $statussetmaxpoints[$sess->statusset];
+ }
+ $stats['activity'][$sess->cmid]['maxpoints'] += $statussetmaxpoints[$sess->statusset];
+ $stats['overall']['maxpoints'] += $statussetmaxpoints[$sess->statusset];
+ }
+ array_push($group, $sess);
+ }
+ array_push($groups, $group);
+ }
+ $points = $stats['overall']['points'];
+ $maxpoints = $stats['overall']['maxpointstodate'];
+ $summary = '';
+ $summarytable = new html_table();
+ $summarytable->attributes['class'] = 'generaltable table-bordered table-condensed';
+ $row = new html_table_row();
+ $cell = new html_table_cell(get_string('allsessionstotals', 'attendance'));
+ $cell->colspan = 2;
+ $cell->header = true;
+ $row->cells[] = $cell;
+ $summarytable->data[] = $row;
+ foreach ($stats['overall']['statuses'] as $acronym => $status) {
$row = new html_table_row();
+ $row->cells[] = $status['description'] . ":";
+ $row->cells[] = $status['count'];
+ $summarytable->data[] = $row;
+ }
+ /* $row = new html_table_row(); */
+ /* $summarytable->data[] = $row; */
+ $row = new html_table_row();
+ if ($maxpoints !== 0) {
+ $pctodate = format_float( $points * 100 / $maxpoints);
+ $pointsinfo = get_string('points', 'attendance') . ": " . $points . "/" . $maxpoints;
+ $pointsinfo .= " (" . $pctodate . "%)";
+ } else {
+ $pointsinfo = get_string('points', 'attendance') . ": " . $points . "/" . $maxpoints;
+ }
+ $pointsinfo .= " " . get_string('todate', 'attendance');
+ $cell = new html_table_cell($pointsinfo);
+ $cell->colspan = 2;
+ $row->cells[] = $cell;
+ $summarytable->data[] = $row;
+ $allsessions->summary = html_writer::table($summarytable);
- // course / activity / session / type / date / status / points / remarks / action
- //
- $courseurl = new moodle_url('/course/view.php', array('id' => $sess->courseid));
- $row->cells[] = html_writer::link($courseurl, $sess->cname);
+ $lastgroup = array(null, null);
+ foreach ($groups as $group) {
- $attendanceurl = new moodle_url('/mod/attendance/view.php', array('id' => $sess->cmid,
- 'studentid' => $userdata->user->id,
- 'view' => ATT_VIEW_ALL));
- $row->cells[] = html_writer::link($attendanceurl, $sess->attname);
+ $statussetmaxpoints = $statusmaxpoints[$sess->attendanceid];
- $row->cells[] = $sess->description;
+ // For use in headings etc.
+ $sess = $group[0];
- if (!$shortform) {
- if ($sess->groupid) {
- $sessiontypeshort = get_string('group') . ': ' . $userdata->groups[$sess->courseid][$sess->groupid]->name;
+ if ($groupby === 'date') {
+ $row = new html_table_row();
+ $row->attributes['class'] = 'grouper';
+ $cell = new html_table_cell();
+ $cell->rowspan = sizeof($group) + 2;
+ $row->cells[] = $cell;
+ $week = date("W", $sess->sessdate);
+ $year = date("Y", $sess->sessdate);
+ // ISO week starts on day 1, Monday
+ $weekstart = date_timestamp_get(date_isodate_set(date_create(), $year, $week, 1));
+ $dmywformat = get_string('strftimedmyw', 'attendance');
+ $cell = new html_table_cell(get_string('weekcommencing', 'attendance') . ": " . userdate($weekstart, $dmywformat));
+ $cell->colspan = $colcount - $summarywidth;
+ $cell->rowspan = 2;
+ $cell->attributes['class'] = 'groupheading';
+ $row->cells[] = $cell;
+ $weekformat = date("YW", $sess->sessdate);
+ $points = $stats['date'][$weekformat]['points'];
+ $maxpoints = $stats['date'][$weekformat]['maxpointstodate'];
+ if ($maxpoints !== 0) {
+ $pctodate = format_float( $points * 100 / $maxpoints);
+ $summary = get_string('points', 'attendance') . ": " . $points . "/" . $maxpoints;
+ $summary .= " (" . $pctodate . "%)";
} else {
- $sessiontypeshort = get_string('commonsession', 'attendance');
+ $summary = get_string('points', 'attendance') . ": " . $points . "/" . $maxpoints;
}
- $row->cells[] = html_writer::tag('nobr', $sessiontypeshort);
+ $summary .= " " . get_string('todate', 'attendance');
+ $cell = new html_table_cell($summary);
+ $cell->colspan = $summarywidth;
+ $row->cells[] = $cell;
+ $table->data[] = $row;
+ $row = new html_table_row();
+ $row->attributes['class'] = 'grouper';
+ $summary = array();
+ foreach ($stats['date'][$weekformat]['statuses'] as $acronym => $status) {
+ array_push($summary, html_writer::tag('b', $acronym) . $status['count']);
+ }
+ $cell = new html_table_cell(implode(" ", $summary));
+ $cell->colspan = $summarywidth;
+ $row->cells[] = $cell;
+ $table->data[] = $row;
+ $lastgroup[0] = date("YW", $weekstart);
+ }
+ else {
+ if ($groupby === 'course' || $sess->courseid !== $lastgroup[0]) {
+ $row = new html_table_row();
+ $row->attributes['class'] = 'grouper';
+ $cell = new html_table_cell();
+ $cell->rowspan = sizeof($group) + 2;
+ if ($groupby === 'activity') {
+ $headcell = $cell; // keep ref to be able to adjust rowspan later
+ $cell->rowspan += 2;
+ $row->cells[] = $cell;
+ $cell = new html_table_cell();
+ $cell->rowspan = 2;
+ }
+ $row->cells[] = $cell;
+ $courseurl = new moodle_url('/course/view.php', array('id' => $sess->courseid));
+ $cell = new html_table_cell(get_string('course', 'attendance') . ": " . html_writer::link($courseurl, $sess->cname));
+ $cell->colspan = $colcount - $summarywidth;
+ $cell->rowspan = 2;
+ $cell->attributes['class'] = 'groupheading';
+ $row->cells[] = $cell;
+ $points = $stats['course'][$sess->courseid]['points'];
+ $maxpoints = $stats['course'][$sess->courseid]['maxpointstodate'];
+ if ($maxpoints !== 0) {
+ $pctodate = format_float( $points * 100 / $maxpoints);
+ $summary = get_string('points', 'attendance') . ": " . $points . "/" . $maxpoints;
+ $summary .= " (" . $pctodate . "%)";
+ } else {
+ $summary = get_string('points', 'attendance') . ": " . $points . "/" . $maxpoints;
+ }
+ $summary .= " " . get_string('todate', 'attendance');
+ $cell = new html_table_cell($summary);
+ $cell->colspan = $summarywidth;
+ $row->cells[] = $cell;
+ $table->data[] = $row;
+ $row = new html_table_row();
+ $row->attributes['class'] = 'grouper';
+ $summary = array();
+ foreach ($stats['course'][$sess->courseid]['statuses'] as $acronym => $status) {
+ array_push($summary, html_writer::tag('b', $acronym) . $status['count']);
+ }
+ $cell = new html_table_cell(implode(" ", $summary));
+ $cell->colspan = $summarywidth;
+ $row->cells[] = $cell;
+ $table->data[] = $row;
+ }
+ if ($groupby === 'activity') {
+ if ($sess->courseid === $lastgroup[0]) {
+ $headcell->rowspan += sizeof($group) + 2;
+ }
+ $row = new html_table_row();
+ $row->attributes['class'] = 'grouper';
+ $cell = new html_table_cell();
+ $cell->rowspan = sizeof($group) + 2;
+ $row->cells[] = $cell;
+ $attendanceurl = new moodle_url('/mod/attendance/view.php', array('id' => $sess->cmid,
+ 'studentid' => $userdata->user->id,
+ 'view' => ATT_VIEW_ALL));
+ $cell = new html_table_cell(get_string('pluginname', 'mod_attendance') . ": " . html_writer::link($attendanceurl, $sess->attname));
+ $cell->colspan = $colcount - $summarywidth;
+ $cell->rowspan = 2;
+ $cell->attributes['class'] = 'groupheading';
+ $row->cells[] = $cell;
+ $points = $stats['activity'][$sess->cmid]['points'];
+ $maxpoints = $stats['activity'][$sess->cmid]['maxpointstodate'];
+ if ($maxpoints !== 0) {
+ $pctodate = format_float( $points * 100 / $maxpoints);
+ $summary = get_string('points', 'attendance') . ": " . $points . "/" . $maxpoints;
+ $summary .= " (" . $pctodate . "%)";
+ } else {
+ $summary = get_string('points', 'attendance') . ": " . $points . "/" . $maxpoints;
+ }
+ $summary .= " " . get_string('todate', 'attendance');
+ $cell = new html_table_cell($summary);
+ $cell->colspan = $summarywidth;
+ $row->cells[] = $cell;
+ $table->data[] = $row;
+ $row = new html_table_row();
+ $row->attributes['class'] = 'grouper';
+ $summary = array();
+ foreach ($stats['activity'][$sess->cmid]['statuses'] as $acronym => $status) {
+ array_push($summary, html_writer::tag('b', $acronym) . $status['count']);
+ }
+ $cell = new html_table_cell(implode(" ", $summary));
+ $cell->colspan = $summarywidth;
+ $row->cells[] = $cell;
+ $table->data[] = $row;
+ }
+ $lastgroup[0] = $sess->courseid;
+ $lastgroup[1] = $sess->cmid;
}
- $row->cells[] = userdate($sess->sessdate, get_string('strftimedmyw', 'attendance')) .
- " ". $this->construct_time($sess->sessdate, $sess->duration);
+ // Now iterate over sessions in group...
- if (!empty($sess->statusid)) {
- $status = $userdata->statuses[$sess->attendanceid][$sess->statusid];
- $row->cells[] = $status->description;
- $row->cells[] = format_float($status->grade, 1, true, true) . ' / ' .
- format_float($statussetmaxpoints[$status->setnumber], 1, true, true);
- $row->cells[] = $sess->remarks;
- } else if (($sess->sessdate + $sess->duration) < $userdata->user->enrolmentstart) {
- $cell = new html_table_cell(get_string('enrolmentstart', 'attendance',
- userdate($userdata->user->enrolmentstart, '%d.%m.%Y')));
- $cell->colspan = 3;
- $row->cells[] = $cell;
- } else if ($userdata->user->enrolmentend and $sess->sessdate > $userdata->user->enrolmentend) {
- $cell = new html_table_cell(get_string('enrolmentend', 'attendance',
- userdate($userdata->user->enrolmentend, '%d.%m.%Y')));
- $cell->colspan = 3;
- $row->cells[] = $cell;
- } else {
- list($canmark, $reason) = attendance_can_student_mark($sess, false);
- if ($canmark) {
- // Student can mark their own attendance.
- // URL to the page that lets the student modify their attendance.
+ foreach($group as $sess) {
+ $row = new html_table_row();
+
+ // partialdate? / course? / activity? / date? / session / type / status / points / remarks / action
+ //
+
+ // If grouping by date, we need some form of date up front.
+ // Only need course column if we are not using course to group
+ // (currently date is only option which does not use course)
+ //
+ if ($groupby === 'date') {
+ // What part of date do we want if grouped by it already?
+ $row->cells[] = userdate($sess->sessdate, get_string('strftimedmw', 'attendance')) .
+ " ". $this->construct_time($sess->sessdate, $sess->duration);
- $url = new moodle_url('/mod/attendance/attendance.php',
+ $courseurl = new moodle_url('/course/view.php', array('id' => $sess->courseid));
+ $row->cells[] = html_writer::link($courseurl, $sess->cname);
+ }
+
+ // Need activity column unless we are using activity to group
+ //
+ if ($groupby !== 'activity') {
+ $attendanceurl = new moodle_url('/mod/attendance/view.php', array('id' => $sess->cmid,
+ 'studentid' => $userdata->user->id,
+ 'view' => ATT_VIEW_ALL));
+ $row->cells[] = html_writer::link($attendanceurl, $sess->attname);
+ }
+
+ // If grouping by date, it belongs up front rather than here
+ //
+ if ($groupby !== 'date') {
+ $row->cells[] = userdate($sess->sessdate, get_string('strftimedmyw', 'attendance')) .
+ " ". $this->construct_time($sess->sessdate, $sess->duration);
+ }
+
+ $sesscontext = context_module::instance($sess->cmid);
+ if (has_capability('mod/attendance:takeattendances', $sesscontext)) {
+ $sessionurl = new moodle_url('/mod/attendance/take.php', array('id' => $sess->cmid,
+ 'sessionid' => $sess->id,
+ 'grouptype' => $sess->groupid));
+ $description = html_writer::link($sessionurl, $sess->description);
+ } else {
+ $description = $sess->description;
+ }
+ $row->cells[] = $description;
+
+ if (!$shortform) {
+ if ($sess->groupid) {
+ $sessiontypeshort = get_string('group') . ': ' . $userdata->groups[$sess->courseid][$sess->groupid]->name;
+ } else {
+ $sessiontypeshort = get_string('commonsession', 'attendance');
+ }
+ $row->cells[] = html_writer::tag('nobr', $sessiontypeshort);
+ }
+
+ if (!empty($USER->editing)) {
+ // TODO!
+ } else {
+ if (!empty($sess->statusid)) {
+ $status = $userdata->statuses[$sess->attendanceid][$sess->statusid];
+ $row->cells[] = $status->description;
+ $row->cells[] = format_float($status->grade, 1, true, true) . ' / ' .
+ format_float($statussetmaxpoints[$status->setnumber], 1, true, true);
+ $row->cells[] = $sess->remarks;
+ } else if (($sess->sessdate + $sess->duration) < $userdata->user->enrolmentstart) {
+ $cell = new html_table_cell(get_string('enrolmentstart', 'attendance',
+ userdate($userdata->user->enrolmentstart, '%d.%m.%Y')));
+ $cell->colspan = 3;
+ $row->cells[] = $cell;
+ } else if ($userdata->user->enrolmentend and $sess->sessdate > $userdata->user->enrolmentend) {
+ $cell = new html_table_cell(get_string('enrolmentend', 'attendance',
+ userdate($userdata->user->enrolmentend, '%d.%m.%Y')));
+ $cell->colspan = 3;
+ $row->cells[] = $cell;
+ } else {
+ list($canmark, $reason) = attendance_can_student_mark($sess, false);
+ if ($canmark) {
+ // Student can mark their own attendance.
+ // URL to the page that lets the student modify their attendance.
+
+ $url = new moodle_url('/mod/attendance/attendance.php',
array('sessid' => $sess->id, 'sesskey' => sesskey()));
- $cell = new html_table_cell(html_writer::link($url, get_string('submitattendance', 'attendance')));
- $cell->colspan = 3;
- $row->cells[] = $cell;
- } else { // Student cannot mark their own attendace.
- $row->cells[] = '?';
- $row->cells[] = '? / ' . format_float($statussetmaxpoints[$sess->statusset], 1, true, true);
- $row->cells[] = '';
+ $cell = new html_table_cell(html_writer::link($url, get_string('submitattendance', 'attendance')));
+ $cell->colspan = 3;
+ $row->cells[] = $cell;
+ } else { // Student cannot mark their own attendace.
+ $row->cells[] = '?';
+ $row->cells[] = '? / ' . format_float($statussetmaxpoints[$sess->statusset], 1, true, true);
+ $row->cells[] = '';
+ }
+ }
}
- }
- if (has_capability('mod/attendance:takeattendances', $context)) {
- $params = array('id' => $userdata->filtercontrols->cm->id,
- 'sessionid' => $sess->id,
- 'grouptype' => $sess->groupid);
- $url = new moodle_url('/mod/attendance/take.php', $params);
- $icon = $OUTPUT->pix_icon('redo', get_string('changeattendance', 'attendance'), 'attendance');
- $row->cells[] = html_writer::link($url, $icon);
+ $table->data[] = $row;
}
-
- $table->data[] = $row;
}
- return html_writer::table($table);
+ $allsessions->detail = html_writer::table($table);
+ return $allsessions;
}
/**
diff --git a/styles.css b/styles.css
index 6b1a0d8..9432581 100644
--- a/styles.css
+++ b/styles.css
@@ -4,6 +4,7 @@
margin-left: 2px;
margin-right: 2px;
padding: 5px;
+ display: inline-block;
}
.path-mod-attendance .attcurbtn {
@@ -16,7 +17,7 @@
margin-bottom: 10px;
margin-left: auto;
margin-right: auto;
- width: 90%;
+/* width: 90%; */
}
.path-mod-attendance .attfiltercontrols #currentdate {
@@ -105,9 +106,27 @@
background-color: #eee;
padding: 30px 10px;
}
+.path-mod-attendance table.userinfobox .userpicture {
+ margin: 0;
+}
.path-mod-attendance table.attlist td.c0 {
text-align: right;
}
+.path-mod-attendance table.allsessions tr.grouper td {
+ background-color: #eeeeee;
+}
+.path-mod-attendance table.allsessions td.groupheading {
+ font-weight: bold;
+}
+.path-mod-attendance .allsessionssummary > * {
+ display: inline-block;
+}
+.path-mod-attendance .allsessionssummary .float-right {
+ float: right;
+}
+.path-mod-attendance .allsessionssummary .float-left {
+ float: left;
+}
#page-mod-attendance-preferences .generalbox {
text-align: center;
diff --git a/view.php b/view.php
index dc5da51..748c3ed 100644
--- a/view.php
+++ b/view.php
@@ -33,6 +33,8 @@ $pageparams->studentid = optional_param('studentid', null, PARAM_INT);
$pageparams->mode = optional_param('mode', mod_attendance_view_page_params::MODE_THIS_COURSE, PARAM_INT);
$pageparams->view = optional_param('view', null, PARAM_INT);
$pageparams->curdate = optional_param('curdate', null, PARAM_INT);
+$pageparams->groupby = optional_param('groupby', 'course', PARAM_ALPHA);
+$pageparams->sesscourses = optional_param('sesscourses', 'current', PARAM_ALPHA);
$cm = get_coursemodule_from_id('attendance', $id, 0, false, MUST_EXIST);
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
@@ -60,7 +62,7 @@ if (!$pageparams->studentid) {
}
}
-$PAGE->set_url($att->url_view());
+$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);