Browse Source

Allow an attendance instance to have multiple status sets

The set to use can be selected per session
MOODLE_28_STABLE
Davo Smith 10 years ago
parent
commit
4302b21840
  1. 13
      add_form.php
  2. 2
      db/install.xml
  3. 24
      db/upgrade.php
  4. 3
      lang/en/attendance.php
  5. 12
      lib.php
  6. 79
      locallib.php
  7. 12
      preferences.php
  8. 36
      renderables.php
  9. 27
      renderer.php
  10. 4
      sessions.php
  11. 50
      tests/behat/extra_features.feature
  12. 6
      update_form.php
  13. 2
      version.php

13
add_form.php

@ -148,6 +148,19 @@ class mod_attendance_add_form extends moodleform {
$mform->addGroup($periodgroup, 'periodgroup', get_string('period', 'attendance'), array(' '), false);
$mform->disabledIf('periodgroup', 'addmultiply', 'notchecked');
// Select which status set to use:
$maxstatusset = attendance_get_max_statusset($this->_customdata['att']->id);
if ($maxstatusset > 0) {
$opts = array();
for ($i=0; $i<=$maxstatusset; $i++) {
$opts[$i] = att_get_setname($this->_customdata['att']->id, $i);
}
$mform->addElement('select', 'statusset', get_string('usestatusset', 'mod_attendance'), $opts);
} else {
$mform->addElement('hidden', 'statusset', 0);
$mform->setType('statusset', PARAM_INT);
}
$mform->addElement('editor', 'sdescription', get_string('description', 'attendance'),
null, array('maxfiles'=>EDITOR_UNLIMITED_FILES, 'noclean'=>true, 'context'=>$modcontext));
$mform->setType('sdescription', PARAM_RAW);

2
db/install.xml

@ -31,6 +31,7 @@
<FIELD NAME="description" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="descriptionformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="studentscanmark" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="statusset" TYPE="int" LENGTH="5" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Which set of statuses to use"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for attendance_sessions"/>
@ -70,6 +71,7 @@
<FIELD NAME="grade" TYPE="int" LENGTH="3" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="visible" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
<FIELD NAME="deleted" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="setnumber" TYPE="int" LENGTH="5" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Allows different sets of statuses to be allocated to different sessions"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for attendance_settings"/>

24
db/upgrade.php

@ -121,5 +121,29 @@ function xmldb_attendance_upgrade($oldversion=0) {
upgrade_mod_savepoint(true, 2015040501, 'attendance');
}
if ($oldversion < 2015040502) {
// Define field setnumber to be added to attendance_statuses.
$table = new xmldb_table('attendance_statuses');
$field = new xmldb_field('setnumber', XMLDB_TYPE_INTEGER, '5', null, XMLDB_NOTNULL, null, '0', 'deleted');
// Conditionally launch add field setnumber.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Define field statusset to be added to attendance_sessions.
$table = new xmldb_table('attendance_sessions');
$field = new xmldb_field('statusset', XMLDB_TYPE_INTEGER, '5', null, XMLDB_NOTNULL, null, '0', 'descriptionformat');
// Conditionally launch add field statusset.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Attendance savepoint reached.
upgrade_mod_savepoint(true, 2015040502, 'attendance');
}
return $result;
}

3
lang/en/attendance.php

@ -143,6 +143,7 @@ $string['moreattendance'] = 'Attendance has been successfully taken for this pag
$string['myvariables'] = 'My Variables';
$string['newdate'] = 'New date';
$string['newduration'] = 'New duration';
$string['newstatusset'] = 'New set of statuses';
$string['noattforuser'] = 'No attendance records exist for the user';
$string['nodescription'] = 'Regular class session';
$string['noguest'] = 'Guest can\'t see attendance';
@ -240,6 +241,7 @@ $string['startofperiod'] = 'Start of period';
$string['status'] = 'Status';
$string['statuses'] = 'Statuses';
$string['statusdeleted'] = 'Status deleted';
$string['statusset'] = 'Status set {$a}';
$string['strftimedm'] = '%d.%m';
$string['strftimedmy'] = '%d.%m.%Y';
$string['strftimedmyhm'] = '%d.%m.%Y %H.%M'; // Line added to allow multiple sessions in the same day.
@ -263,6 +265,7 @@ $string['tempusermerge'] = 'Merge temporary user';
$string['tuseremail'] = 'Email';
$string['tusername'] = 'Full name';
$string['update'] = 'Update';
$string['usestatusset'] = 'Use status set';
$string['userexists'] = 'There is already a real user with this email address';
$string['variable'] = 'variable';
$string['variablesupdated'] = 'Variables successfully updated';

12
lib.php

@ -406,3 +406,15 @@ function attendance_pluginfile($course, $cm, $context, $filearea, $args, $forced
}
send_stored_file($file, 0, 0, true);
}
// Count the number of status sets that exist for this instance.
function attendance_get_max_statusset($attendanceid) {
global $DB;
$max = $DB->get_field_sql('SELECT MAX(setnumber) FROM {attendance_statuses} WHERE attendanceid = ? AND deleted = 0',
array($attendanceid));
if ($max) {
return $max;
}
return 0;
}

79
locallib.php

@ -524,6 +524,8 @@ class att_preferences_page_params {
public $statusid;
public $statusset;
public function get_significant_params() {
$params = array();
@ -533,6 +535,9 @@ class att_preferences_page_params {
if (isset($this->statusid)) {
$params['statusid'] = $this->statusid;
}
if (isset($this->statusset)) {
$params['statusset'] = $this->statusset;
}
return $params;
}
@ -571,6 +576,7 @@ class attendance {
private $groupmode;
private $statuses;
private $allstatuses; // Cache list of all statuses (not just one used by current session).
// Array by sessionid.
private $sessioninfo = array();
@ -815,6 +821,10 @@ class attendance {
* @return moodle_url of attsettings.php for attendance instance
*/
public function url_preferences($params=array()) {
// Add the statusset params.
if (isset($this->pageparams->statusset) && !isset($params['statusset'])) {
$params['statusset'] = $this->pageparams->statusset;
}
$params = array_merge(array('id' => $this->cm->id), $params);
return new moodle_url('/mod/attendance/preferences.php', $params);
}
@ -1177,11 +1187,24 @@ class attendance {
return $user;
}
public function get_statuses($onlyvisible = true) {
public function get_statuses($onlyvisible = true, $allsets = false) {
if (!isset($this->statuses)) {
$this->statuses = att_get_statuses($this->id, $onlyvisible);
// Get the statuses for the current set only.
$statusset = 0;
if (isset($this->pageparams->statusset)) {
$statusset = $this->pageparams->statusset;
} else if (isset($this->pageparams->sessionid)) {
$sessioninfo = $this->get_session_info($this->pageparams->sessionid);
$statusset = $sessioninfo->statusset;
}
$this->statuses = att_get_statuses($this->id, $onlyvisible, $statusset);
$this->allstatuses = att_get_statuses($this->id, $onlyvisible);
}
// Return all sets, if requested.
if ($allsets) {
return $this->allstatuses;
}
return $this->statuses;
}
@ -1320,7 +1343,7 @@ class attendance {
* @return type
*/
public function get_user_grade($userid, array $filters = null) {
return att_get_user_grade($this->get_user_statuses_stat($userid, $filters), $this->get_statuses());
return att_get_user_grade($this->get_user_statuses_stat($userid, $filters), $this->get_statuses(true, true));
}
// For getting sessions count implemented simplest method - taken sessions.
@ -1331,7 +1354,7 @@ class attendance {
// While implementing those methods we need recalculate grades of all users
// on session adding.
public function get_user_max_grade($userid) {
return att_get_user_max_grade($this->get_user_taken_sessions_count($userid), $this->get_statuses());
return att_get_user_max_grade($this->get_user_taken_sessions_count($userid), $this->get_statuses(true, true));
}
public function update_users_grade($userids) {
@ -1542,6 +1565,7 @@ class attendance {
$rec->acronym = $acronym;
$rec->description = $description;
$rec->grade = $grade;
$rec->setnumber = $this->pageparams->statusset; // Save which set it is part of.
$rec->deleted = 0;
$rec->visible = 1;
$id = $DB->insert_record('attendance_statuses', $rec);
@ -1629,20 +1653,57 @@ class attendance {
}
function att_get_statuses($attid, $onlyvisible=true) {
function att_get_statuses($attid, $onlyvisible=true, $statusset = -1) {
global $DB;
// Set selector.
$params = array('aid' => $attid);
$setsql = '';
if ($statusset >= 0) {
$params['statusset'] = $statusset;
$setsql = ' AND setnumber = :statusset ';
}
if ($onlyvisible) {
$statuses = $DB->get_records_select('attendance_statuses', "attendanceid = :aid AND visible = 1 AND deleted = 0",
array('aid' => $attid), 'grade DESC');
$statuses = $DB->get_records_select('attendance_statuses', "attendanceid = :aid AND visible = 1 AND deleted = 0 $setsql",
$params, 'setnumber ASC, grade DESC');
} else {
$statuses = $DB->get_records_select('attendance_statuses', "attendanceid = :aid AND deleted = 0",
array('aid' => $attid), 'grade DESC');
$statuses = $DB->get_records_select('attendance_statuses', "attendanceid = :aid AND deleted = 0 $setsql",
$params, 'setnumber ASC, grade DESC');
}
return $statuses;
}
/**
* Get the name of the status set.
*
* @param int $attid
* @param int $statusset
* @param bool $includevalues
* @return string
*/
function att_get_setname($attid, $statusset, $includevalues = true) {
$statusname = get_string('statusset', 'mod_attendance', $statusset + 1);
if ($includevalues) {
$statuses = att_get_statuses($attid, true, $statusset);
$statusesout = array();
foreach ($statuses as $status) {
$statusesout[] = $status->acronym;
}
if ($statusesout) {
if (count($statusesout) > 6) {
$statusesout = array_slice($statusesout, 0, 6);
$statusesout[] = '&helip;';
}
$statusesout = implode(' ', $statusesout);
$statusname .= ' ('.$statusesout.')';
}
}
return $statusname;
}
function att_get_user_taken_sessions_count($attid, $coursestartdate, $userid, $coursemodule, $startdate = '', $enddate = '') {
global $DB, $COURSE;
$groupmode = groups_get_activity_groupmode($coursemodule, $COURSE);

12
preferences.php

@ -30,6 +30,7 @@ $pageparams = new att_preferences_page_params();
$id = required_param('id', PARAM_INT);
$pageparams->action = optional_param('action', null, PARAM_INT);
$pageparams->statusid = optional_param('statusid', null, PARAM_INT);
$pageparams->statusset = optional_param('statusset', 0, PARAM_INT); // Set of statuses to view.
$cm = get_coursemodule_from_id('attendance', $id, 0, false, MUST_EXIST);
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
@ -37,6 +38,12 @@ $att = $DB->get_record('attendance', array('id' => $cm->instance), '*
require_login($course, true, $cm);
// Make sure the statusset is valid.
$maxstatusset = attendance_get_max_statusset($att->id);
if ($pageparams->statusset > $maxstatusset + 1) {
$pageparams->statusset = $maxstatusset + 1;
}
$att = new attendance($att, $cm, $course, $PAGE->context, $pageparams);
$att->perm->require_change_preferences_capability();
@ -55,6 +62,9 @@ switch ($att->pageparams->action) {
$newgrade = optional_param('newgrade', 0, PARAM_INT);
$att->add_status($newacronym, $newdescription, $newgrade);
if ($pageparams->statusset > $maxstatusset) {
$maxstatusset = $pageparams->statusset; // Make sure the new maximum is shown without a page refresh.
}
break;
case att_preferences_page_params::ACTION_DELETE:
if (att_has_logs_for_status($att->pageparams->statusid)) {
@ -109,12 +119,14 @@ switch ($att->pageparams->action) {
$output = $PAGE->get_renderer('mod_attendance');
$tabs = new attendance_tabs($att, attendance_tabs::TAB_PREFERENCES);
$prefdata = new attendance_preferences_data($att);
$setselector = new attendance_set_selector($att, $maxstatusset);
// Output starts here.
echo $output->header();
echo $output->heading(get_string('attendanceforthecourse', 'attendance').' :: ' .$course->fullname);
echo $output->render($tabs);
echo $output->render($setselector);
echo $output->render($prefdata);
echo $output->footer();

36
renderables.php

@ -369,7 +369,7 @@ class attendance_user_data implements renderable {
}
if ($this->pageparams->mode == att_view_page_params::MODE_THIS_COURSE) {
$this->statuses = $att->get_statuses();
$this->statuses = $att->get_statuses(true, true);
$this->stat = $att->get_user_stat($userid);
@ -482,8 +482,8 @@ class attendance_report_data implements renderable {
$this->sessions = $att->get_filtered_sessions();
$this->statuses = $att->get_statuses();
$this->allstatuses = $att->get_statuses(false);
$this->statuses = $att->get_statuses(true, true);
$this->allstatuses = $att->get_statuses(false, true);
$this->gradable = $att->grade > 0;
@ -559,6 +559,36 @@ class attendance_preferences_data implements renderable {
}
}
// Output a selector to change between status sets.
class attendance_set_selector implements renderable {
public $maxstatusset;
private $att;
public function __construct(attendance $att, $maxstatusset) {
$this->att = $att;
$this->maxstatusset = $maxstatusset;
}
public function url($statusset) {
$params = array();
$params['statusset'] = $statusset;
return $this->att->url_preferences($params);
}
public function get_current_statusset() {
if (isset($this->att->pageparams->statusset)) {
return $this->att->pageparams->statusset;
}
return 0;
}
public function get_status_name($statusset) {
return att_get_setname($this->att->id, $statusset, true);
}
}
class url_helpers {
public static function url_take($att, $sessionid, $grouptype) {
$params = array('sessionid' => $sessionid);

27
renderer.php

@ -918,6 +918,33 @@ class mod_attendance_renderer extends plugin_renderer_base {
}
/**
* Output the status set selector.
*
* @param attendance_set_selector $sel
* @return string
*/
protected function render_attendance_set_selector(attendance_set_selector $sel) {
$current = $sel->get_current_statusset();
$selected = null;
$opts = array();
for ($i = 0; $i <= $sel->maxstatusset; $i++) {
$url = $sel->url($i);
$display = $sel->get_status_name($i);
$opts[$url->out(false)] = $display;
if ($i == $current) {
$selected = $url->out(false);
}
}
$newurl = $sel->url($sel->maxstatusset + 1);
$opts[$newurl->out(false)] = get_string('newstatusset', 'mod_attendance');
if ($current == $sel->maxstatusset + 1) {
$selected = $newurl->out(false);
}
return $this->output->url_select($opts, $selected, null);
}
protected function render_attendance_preferences_data(attendance_preferences_data $prefdata) {
$this->page->requires->js('/mod/attendance/module.js');

4
sessions.php

@ -57,7 +57,7 @@ $PAGE->set_cacheable(true);
$PAGE->set_button($OUTPUT->update_module_button($cm->id, 'attendance'));
$PAGE->navbar->add($att->name);
$formparams = array('course' => $course, 'cm' => $cm, 'modcontext' => $PAGE->context);
$formparams = array('course' => $course, 'cm' => $cm, 'modcontext' => $PAGE->context, 'att' => $att);
switch ($att->pageparams->action) {
case att_sessions_page_params::ACTION_ADD:
$url = $att->url_sessions(array('action' => att_sessions_page_params::ACTION_ADD));
@ -230,6 +230,7 @@ function construct_sessions_data_for_add($formdata) {
if (isset($formdata->studentscanmark)) { // Students will be able to mark their own attendance.
$sess->studentscanmark = 1;
}
$sess->statusset = $formdata->statusset;
fill_groupid($formdata, $sessions, $sess);
}
@ -250,6 +251,7 @@ function construct_sessions_data_for_add($formdata) {
if (isset($formdata->studentscanmark)) { // Students will be able to mark their own attendance.
$sess->studentscanmark = 1;
}
$sess->statusset = $formdata->statusset;
fill_groupid($formdata, $sessions, $sess);
}

50
tests/behat/extra_features.feature

@ -110,3 +110,53 @@ Feature: Test the various new features in the attendance module
And "E" "text" should exist in the "Temporary user 1" "table_row"
And "A" "text" should exist in the "Student 3" "table_row"
And I should not see "Temporary user 2"
Scenario: A teacher can create and use multiple status lists
Given I log in as "teacher1"
And I follow "Course 1"
And I follow "Test attendance"
And I follow "Settings"
And I set the field "jump" to "New set of statuses"
And I set the field with xpath "//*[@id='preferencesform']/table/tbody/tr[1]/td[2]/input" to "G"
And I set the field with xpath "//*[@id='preferencesform']/table/tbody/tr[1]/td[3]/input" to "Great"
And I set the field with xpath "//*[@id='preferencesform']/table/tbody/tr[1]/td[4]/input" to "3"
And I click on "Add" "button" in the ".lastrow" "css_element"
And I set the field with xpath "//*[@id='preferencesform']/table/tbody/tr[2]/td[2]/input" to "O"
And I set the field with xpath "//*[@id='preferencesform']/table/tbody/tr[2]/td[3]/input" to "OK"
And I set the field with xpath "//*[@id='preferencesform']/table/tbody/tr[2]/td[4]/input" to "2"
And I click on "Add" "button" in the ".lastrow" "css_element"
And I set the field with xpath "//*[@id='preferencesform']/table/tbody/tr[3]/td[2]/input" to "B"
And I set the field with xpath "//*[@id='preferencesform']/table/tbody/tr[3]/td[3]/input" to "Bad"
And I set the field with xpath "//*[@id='preferencesform']/table/tbody/tr[3]/td[4]/input" to "0"
And I click on "Add" "button" in the ".lastrow" "css_element"
And I click on "Update" "button" in the "#preferencesform" "css_element"
And I follow "Add"
And I set the following fields to these values:
| Create multiple sessions | 0 |
| Use status set | Status set 1 (P L E A) |
| id_sessiondate_hour | 10 |
| id_sessiondate_minute | 0 |
And I click on "submitbutton" "button"
And I follow "Sessions"
And I follow "Add"
And I set the following fields to these values:
| Create multiple sessions | 0 |
| Use status set | Status set 2 (G O B) |
| id_sessiondate_hour | 11 |
| id_sessiondate_minute | 0 |
And I click on "submitbutton" "button"
And I follow "Sessions"
When I click on "Take attendance" "link" in the "10:00" "table_row"
Then "Set status for all users to «Present»" "link" should exist
And "Set status for all users to «Late»" "link" should exist
And "Set status for all users to «Excused»" "link" should exist
And "Set status for all users to «Absent»" "link" should exist
When I follow "Sessions"
And I click on "Take attendance" "link" in the "11:00" "table_row"
Then "Set status for all users to «Great»" "link" should exist
And "Set status for all users to «OK»" "link" should exist
And "Set status for all users to «Bad»" "link" should exist

6
update_form.php

@ -75,6 +75,12 @@ class mod_attendance_update_form extends moodleform {
$durselect[] =& $mform->createElement('select', 'minutes', '', $minutes, false, true);
$mform->addGroup($durselect, 'durtime', get_string('duration', 'attendance'), array(' '), true);
// Show which status set is in use.
$maxstatusset = attendance_get_max_statusset($this->_customdata['att']->id);
if ($maxstatusset > 0) {
$mform->addElement('static', 'statusset', get_string('usestatusset', 'mod_attendance'),
att_get_setname($this->_customdata['att']->id, $sess->statusset));
}
$mform->addElement('editor', 'sdescription', get_string('description', 'attendance'), null, $defopts);
$mform->setType('sdescription', PARAM_RAW);

2
version.php

@ -22,7 +22,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$plugin->version = 2015040501;
$plugin->version = 2015040502;
$plugin->requires = 2014042900;
$plugin->release = '2.9.1';
$plugin->maturity = MATURITY_STABLE;

Loading…
Cancel
Save