From: Dan Marsden Date: Wed, 21 Jun 2017 02:53:23 +0000 (+1200) Subject: Merge notification/warning feature into master. (#267) X-Git-Url: http://cameron1729.xyz/?a=commitdiff_plain;h=00f95df6fb790fd0d08ab2bfbf01f4c615616c97;p=moodle-mod_attendance.git Merge notification/warning feature into (#267) New feature/reports to allow warning thresholds to be set and e-mail notifications. --- diff --git a/CHANGELOG.md b/CHANGELOG.md index b02c23c..918c731 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ### [Unreleased] - New Feature: Allow automatic marking using site logs. +- New Feature: Warn users when attendance drops below threshold. - Improvement: Allow default view for teachers to be set at admin level. - Improvement: All courses user report now displays as table. - Bug fix: Restored attendances do not create calendar events correctly. diff --git a/atrisk.php b/atrisk.php new file mode 100644 index 0000000..86cb146 --- /dev/null +++ b/atrisk.php @@ -0,0 +1,141 @@ +. + +/** + * Attendance course summary report. + * + * @package mod_attendance + * @copyright 2017 onwards Dan Marsden http://danmarsden.com + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../../config.php'); +require_once($CFG->dirroot.'/mod/attendance/lib.php'); +require_once($CFG->dirroot.'/mod/attendance/locallib.php'); +require_once($CFG->libdir.'/tablelib.php'); +require_once($CFG->libdir.'/coursecatlib.php'); + +$category = optional_param('category', 0, PARAM_INT); +$attendancecm = optional_param('id', 0, PARAM_INT); +$download = optional_param('download', '', PARAM_ALPHA); +$sort = optional_param('tsort', '', PARAM_ALPHA); + +if (!empty($category)) { + $context = context_coursecat::instance($category); + $coursecat = coursecat::get($category); + $courses = $coursecat->get_courses(array('recursive' => true, 'idonly' => true)); + $PAGE->set_category_by_id($category); + require_login(); +} else if (!empty($attendancecm)) { + $cm = get_coursemodule_from_id('attendance', $attendancecm, 0, false, MUST_EXIST); + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $att = $DB->get_record('attendance', array('id' => $cm->instance), '*', MUST_EXIST); + $courses = array($course->id); + $context = context_module::instance($cm->id); + require_login($course, false, $cm); +} else { + $context = context_system::instance(); + $courses = array(); // Show all courses. + $PAGE->set_context($context); + require_login(); +} +// Check permissions. +require_capability('mod/attendance:viewreports', $context); + +$exportfilename = 'attendanceatrisk.csv'; + +$PAGE->set_url('/mod/attendance/atrisk.php', array('category' => $category)); + +$PAGE->set_heading($SITE->fullname); + +$table = new flexible_table('attendanceatrisk'); +$table->define_baseurl($PAGE->url); + +if (!$table->is_downloading($download, $exportfilename)) { + if (!empty($attendancecm)) { + $pageparams = new mod_attendance_sessions_page_params(); + $att = new mod_attendance_structure($att, $cm, $course, $context, $pageparams); + $output = $PAGE->get_renderer('mod_attendance'); + $tabs = new attendance_tabs($att, attendance_tabs::TAB_ATRISK); + echo $output->header(); + echo $output->heading(get_string('attendanceforthecourse', 'attendance').' :: ' .format_string($course->fullname)); + echo $output->render($tabs); + } else { + echo $OUTPUT->header(); + echo $OUTPUT->heading(get_string('atriskreport', 'mod_attendance')); + if (empty($category)) { + // Only show tabs if displaying via the admin page. + $tabmenu = attendance_print_settings_tabs('atrisk'); + echo $tabmenu; + } + } + +} + +$table->define_columns(array('course', 'attendance', 'userid', 'numtakensessions', 'percent', 'timesent')); +$table->define_headers(array(get_string('course'), + get_string('pluginname', 'attendance'), + get_string('user'), + get_string('takensessions', 'attendance'), + get_string('averageattendance', 'attendance'), + get_string('triggered', 'attendance'))); +$table->sortable(true); +$table->no_sorting('course'); +$table->set_attribute('cellspacing', '0'); +$table->set_attribute('class', 'generaltable generalbox'); +$table->show_download_buttons_at(array(TABLE_P_BOTTOM)); +$table->setup(); + +// Work out direction of sort required. +$sortcolumns = $table->get_sort_columns(); +// Now do sorting if specified. + +$orderby = ' ORDER BY percent ASC'; +if (!empty($sort)) { + $direction = ' DESC'; + if (!empty($sortcolumns[$sort]) && $sortcolumns[$sort] == SORT_ASC) { + $direction = ' ASC'; + } + $orderby = " ORDER BY $sort $direction"; + +} + +$records = attendance_get_users_to_notify($courses, $orderby); +foreach ($records as $record) { + if (!$table->is_downloading($download, $exportfilename)) { + $url = new moodle_url('/mod/attendance/index.php', array('id' => $record->courseid)); + $name = html_writer::link($url, $record->coursename); + } else { + $name = $record->coursename; + } + $url = new moodle_url('/mod/attendance/view.php', array('studentid' => $record->userid, + 'id' => $record->cmid, 'view' => ATT_VIEW_ALL)); + $attendancename = html_writer::link($url, $record->aname); + + $username = html_writer::link($url, fullname($record)); + $percent = round($record->percent * 100)."%"; + $timesent = "-"; + if (!empty($record->timesent)) { + $timesent = userdate($record->timesent); + } + + $table->add_data(array($name, $attendancename, $username, $record->numtakensessions, $percent, $timesent)); +} +$table->finish_output(); + +if (!$table->is_downloading()) { + echo $OUTPUT->footer(); +} \ No newline at end of file diff --git a/backup/moodle2/backup_attendance_stepslib.php b/backup/moodle2/backup_attendance_stepslib.php index 1d67563..9275784 100644 --- a/backup/moodle2/backup_attendance_stepslib.php +++ b/backup/moodle2/backup_attendance_stepslib.php @@ -50,6 +50,10 @@ class backup_attendance_activity_structure_step extends backup_activity_structur $status = new backup_nested_element('status', array('id'), array( 'acronym', 'description', 'grade', 'studentavailability', 'setunmarked', 'visible', 'deleted', 'setnumber')); + $warnings = new backup_nested_element('warnings'); + $warning = new backup_nested_element('warning', array('id'), array( + 'warningpercent', 'warnafter', 'emailuser', 'emailsubject', 'emailcontent', 'emailcontentformat', 'thirdpartyemails')); + $sessions = new backup_nested_element('sessions'); $session = new backup_nested_element('session', array('id'), array( 'groupid', 'sessdate', 'duration', 'lasttaken', 'lasttakenby', @@ -65,6 +69,9 @@ class backup_attendance_activity_structure_step extends backup_activity_structur $attendance->add_child($statuses); $statuses->add_child($status); + $attendance->add_child($warnings); + $warnings->add_child($warning); + $attendance->add_child($sessions); $sessions->add_child($session); @@ -77,6 +84,9 @@ class backup_attendance_activity_structure_step extends backup_activity_structur $status->set_source_table('attendance_statuses', array('attendanceid' => backup::VAR_PARENTID)); + $warning->set_source_table('attendance_warning', + array('idnumber' => backup::VAR_PARENTID)); + $session->set_source_table('attendance_sessions', array('attendanceid' => backup::VAR_PARENTID)); // Data sources - user related data. diff --git a/backup/moodle2/restore_attendance_stepslib.php b/backup/moodle2/restore_attendance_stepslib.php index ba6b6fd..8a11e11 100644 --- a/backup/moodle2/restore_attendance_stepslib.php +++ b/backup/moodle2/restore_attendance_stepslib.php @@ -49,6 +49,9 @@ class restore_attendance_activity_structure_step extends restore_activity_struct $paths[] = new restore_path_element('attendance_status', '/activity/attendance/statuses/status'); + $paths[] = new restore_path_element('attendance_warning', + '/activity/attendance/warnings/warning'); + $paths[] = new restore_path_element('attendance_session', '/activity/attendance/sessions/session'); @@ -101,6 +104,21 @@ class restore_attendance_activity_structure_step extends restore_activity_struct } /** + * Process attendance warning restore + * @param object $data The data in object form + * @return void + */ + protected function process_attendance_warning($data) { + global $DB; + + $data = (object)$data; + + $data->idnumber = $this->get_new_parentid('attendance'); + + $DB->insert_record('attendance_warning', $data); + } + + /** * Process attendance session restore * @param object $data The data in object form * @return void diff --git a/classes/add_warning_form.php b/classes/add_warning_form.php new file mode 100644 index 0000000..a8682a2 --- /dev/null +++ b/classes/add_warning_form.php @@ -0,0 +1,108 @@ +. + +/** + * Contains class mod_attendance_add_warning_form + * + * @package mod_attendance + * @copyright 2017 Dan Marsden + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Class mod_attendance_add_warning_form + * + * @package mod_attendance + * @copyright 2017 Dan Marsden + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class mod_attendance_add_warning_form extends moodleform { + /** + * Form definition + */ + public function definition() { + global $COURSE; + $mform = $this->_form; + + // Load global defaults. + $config = get_config('attendance'); + + $options = array(); + for ($i = 1; $i <= 100; $i++) { + $options[$i] = "$i%"; + } + $mform->addElement('select', 'warningpercent', get_string('warningpercent', 'mod_attendance'), $options); + $mform->addHelpButton('warningpercent', 'warningpercent', 'mod_attendance'); + $mform->setType('warningpercent', PARAM_INT); + $mform->setDefault('warningpercent', $config->warningpercent); + + $options = array(); + for ($i = 1; $i <= 50; $i++) { + $options[$i] = "$i"; + } + $mform->addElement('select', 'warnafter', get_string('warnafter', 'mod_attendance'), $options); + $mform->addHelpButton('warnafter', 'warnafter', 'mod_attendance'); + $mform->setType('warnafter', PARAM_INT); + $mform->setDefault('warnafter', $config->warnafter); + + $mform->addElement('checkbox', 'emailuser', get_string('emailuser', 'mod_attendance')); + $mform->addHelpButton('emailuser', 'emailuser', 'mod_attendance'); + $mform->setDefault('emailuser', $config->emailuser); + + $mform->addElement('text', 'emailsubject', get_string('emailsubject', 'mod_attendance'), array('size' => '64')); + $mform->setType('emailsubject', PARAM_TEXT); + $mform->addRule('emailsubject', get_string('maximumchars', '', 255), 'maxlength', 255, 'client'); + $mform->addHelpButton('emailsubject', 'emailsubject', 'mod_attendance'); + $mform->setDefault('emailsubject', $config->emailsubject); + + $mform->addElement('editor', 'emailcontent', get_string('emailcontent', 'mod_attendance'), null, null); + $mform->setDefault('emailcontent', array('text' => format_text($config->emailcontent))); + $mform->setType('emailcontent', PARAM_RAW); + $mform->addHelpButton('emailcontent', 'emailcontent', 'mod_attendance'); + + $users = get_users_by_capability(context_course::instance($COURSE->id), 'mod/attendance:viewreports'); + $options = array(); + foreach ($users as $user) { + $options[$user->id] = fullname($user); + } + + $select = $mform->addElement('searchableselector', 'thirdpartyemails', + get_string('thirdpartyemails', 'mod_attendance'), $options); + $mform->setType('thirdpartyemails', PARAM_TEXT); + $mform->addHelpButton('thirdpartyemails', 'thirdpartyemails', 'mod_attendance'); + $select->setMultiple(true); + + // Need to set hidden elements when adding default options. + $mform->addElement('hidden', 'idnumber', 0); // Default options use 0 as the idnumber. + $mform->setType('idnumber', PARAM_INT); + + $mform->addElement('hidden', 'notid', 0); // The id of warning record. + $mform->setType('notid', PARAM_INT); + + $mform->addElement('hidden', 'id', $this->_customdata['id']); // The id of course module record if attendance level. + $mform->setType('id', PARAM_INT); + + if (!empty($this->_customdata['notid'])) { + $btnstring = get_string('update', 'attendance'); + } else { + $btnstring = get_string('add', 'attendance'); + } + $this->add_action_buttons(true, $btnstring); + + } +} \ No newline at end of file diff --git a/classes/structure.php b/classes/structure.php index f1bfe67..d517ccf 100644 --- a/classes/structure.php +++ b/classes/structure.php @@ -369,6 +369,16 @@ class mod_attendance_structure { } /** + * Get url for report. + * @param array $params + * @return moodle_url of report.php for attendance instance + */ + public function url_atrisk($params=array()) { + $params = array_merge(array('id' => $this->cm->id), $params); + return new moodle_url('/mod/attendance/atrisk.php', $params); + } + + /** * Get url for export. * * @return moodle_url of export.php for attendance instance @@ -393,6 +403,20 @@ class mod_attendance_structure { } /** + * Get preferences url + * @param array $params + * @return moodle_url of attsettings.php for attendance instance + */ + public function url_warnings($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/warnings.php', $params); + } + + /** * Get take url. * @param array $params * @return moodle_url of attendances.php for attendance instance diff --git a/classes/task/notify.php b/classes/task/notify.php new file mode 100644 index 0000000..01531b1 --- /dev/null +++ b/classes/task/notify.php @@ -0,0 +1,122 @@ +. + +/** + * Attendance task - Send warnings. + * + * @package mod_attendance + * @copyright 2017 onwards Dan Marsden http://danmarsden.com + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace mod_attendance\task; +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/mod/attendance/locallib.php'); +/** + * Task class + * + * @package mod_attendance + * @copyright 2017 onwards Dan Marsden http://danmarsden.com + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class notify extends \core\task\scheduled_task { + public function get_name() { + // Shown in admin screens. + return get_string('notifytask', 'mod_attendance'); + } + public function execute() { + global $DB; + if (empty(get_config('attendance', 'enablewarnings'))) { + return; // Warnings not enabled. + } + $now = time(); // Store current time to use in queries so they all match nicely. + $lastrun = get_config('mod_attendance', 'notifylastrun'); + if (empty($lastrun)) { + $lastrun = 0; + } + + $orderby = 'ORDER BY cm.id, atl.studentid, n.warningpercent ASC'; + $records = attendance_get_users_to_notify(array(), $orderby, $lastrun, true); + $sentnotifications = array(); + $thirdpartynotifications = array(); + $numsentusers = 0; + $numsentthird = 0; + foreach ($records as $record) { + if (empty($sentnotifications[$record->userid])) { + $sentnotifications[$record->userid] = array(); + } + + if (!empty($record->emailuser)) { + // Only send one warning to this user from each attendance in this run. - flag any higher percent notifications as sent. + if (empty($sentnotifications[$record->userid]) || !in_array($record->aid, $sentnotifications[$record->userid])) { + // Convert variables in emailcontent. + $record = attendance_template_variables($record); + $user = $DB->get_record('user', array('id' => $record->userid)); + $from = \core_user::get_noreply_user(); + + $emailcontent = format_text($record->emailcontent, $record->emailcontentformat); + + email_to_user($user, $from, $record->emailsubject, $emailcontent, $emailcontent); + + $sentnotifications[$record->userid][] = $record->aid; + $numsentusers++; + } + } + // Only send one warning to this user from each attendance in this run. - flag any higher percent notifications as sent. + if (!empty($record->thirdpartyemails)) { + $sendto = explode(',', $record->thirdpartyemails); + $record->percent = round($record->percent * 100)."%"; + foreach ($sendto as $senduser) { + if (empty($thirdpartynotifications[$senduser])) { + $thirdpartynotifications[$senduser] = array(); + } + if (!isset($thirdpartynotifications[$senduser][$record->aid.'_'.$record->userid])) { + $thirdpartynotifications[$senduser][$record->aid.'_'.$record->userid] = get_string('thirdpartyemailtext', 'attendance', $record); + } + } + } + + $notify = new \stdClass(); + $notify->userid = $record->userid; + $notify->notifyid = $record->notifyid; + $notify->timesent = $now; + $DB->insert_record('attendance_warning_done', $notify); + } + if (!empty($numsentusers)) { + mtrace($numsentusers ." user emails sent"); + } + if (!empty($thirdpartynotifications)) { + foreach ($thirdpartynotifications as $sendid => $notifications) { + $user = $DB->get_record('user', array('id' => $sendid)); + $from = \core_user::get_noreply_user(); + + $emailcontent = implode("\n", $notifications); + $emailcontent .= "\n\n".get_string('thirdpartyemailtextfooter', 'attendance'); + $emailcontent = format_text($emailcontent); + $emailsubject = get_string('thirdpartyemailsubject', 'attendance'); + + email_to_user($user, $from, $emailsubject, $emailcontent, $emailcontent); + $numsentthird++; + } + if (!empty($numsentthird)) { + mtrace($numsentthird ." thirdparty emails sent"); + } + } + + set_config('notifylastrun', $now, 'mod_attendance'); + } +} \ No newline at end of file diff --git a/db/install.xml b/db/install.xml index f1900bb..b310deb 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,5 +1,5 @@ - @@ -113,5 +113,36 @@ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
-
+ \ No newline at end of file diff --git a/db/tasks.php b/db/tasks.php index 0abad70..361f9f3 100644 --- a/db/tasks.php +++ b/db/tasks.php @@ -32,5 +32,13 @@ $tasks = array( 'hour' => '*', 'day' => '*', 'dayofweek' => '*', + 'month' => '*'), + array( + 'classname' => 'mod_attendance\task\notify', + 'blocking' => 0, + 'minute' => '30', + 'hour' => '1', + 'day' => '*', + 'dayofweek' => '*', 'month' => '*') ); \ No newline at end of file diff --git a/db/upgrade.php b/db/upgrade.php index e4489b3..1e61e16 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -340,5 +340,62 @@ function xmldb_attendance_upgrade($oldversion=0) { upgrade_mod_savepoint(true, 2017060900, 'attendance'); } + + // Add new warning table. + if ($oldversion < 2017061600) { + + // Define table attendance_warning to be created. + $table = new xmldb_table('attendance_warning'); + + // Adding fields to table attendance_warning. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('idnumber', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('warningpercent', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('warnafter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('emailuser', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null); + $table->add_field('emailsubject', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); + $table->add_field('emailcontent', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); + $table->add_field('emailcontentformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null); + $table->add_field('thirdpartyemails', XMLDB_TYPE_TEXT, null, null, null, null, null); + + // Adding keys to table attendance_warning. + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $table->add_key('level_id', XMLDB_KEY_UNIQUE, array('idnumber, warningpercent')); + + // Conditionally launch create table for attendance_warning. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Attendance savepoint reached. + upgrade_mod_savepoint(true, 2017061600, 'attendance'); + } + + if ($oldversion < 2017062000) { + + // Define table attendance_warning_done to be created. + $table = new xmldb_table('attendance_warning_done'); + + // Adding fields to table attendance_warning_done. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('notifyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('timesent', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + + // Adding keys to table attendance_warning_done. + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + + // Adding indexes to table attendance_warning_done. + $table->add_index('notifyid_userid', XMLDB_INDEX_UNIQUE, array('notifyid', 'userid')); + + // Conditionally launch create table for attendance_warning_done. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Attendance savepoint reached. + upgrade_mod_savepoint(true, 2017062000, 'attendance'); + } + return $result; } diff --git a/lang/en/attendance.php b/lang/en/attendance.php index 7669c46..a69e975 100644 --- a/lang/en/attendance.php +++ b/lang/en/attendance.php @@ -33,12 +33,14 @@ $string['Pfull'] = 'Present'; $string['acronym'] = 'Acronym'; $string['add'] = 'Add'; $string['addmultiplesessions'] = 'Multiple sessions'; +$string['addwarning'] = 'Add warning'; $string['addsession'] = 'Add session'; $string['adduser'] = 'Add user'; $string['all'] = 'All'; $string['allcourses'] = 'All courses'; $string['allpast'] = 'All past'; $string['allsessions'] = 'All sessions'; +$string['atriskreport'] = 'At-risk report'; $string['attendance:addinstance'] = 'Add a new attendance activity'; $string['attendance:canbelisted'] = 'Appears in the roster'; $string['attendance:changeattendances'] = 'Changing Attendances'; @@ -104,6 +106,9 @@ The sessions begin on the date of the base session and continue until the \'repe $string['createonesession'] = 'Create one session for the course'; $string['days'] = 'Days'; $string['defaultdisplaymode'] = 'Default display mode'; +$string['defaultwarnings'] = 'Default warning set'; +$string['defaultwarningsettings'] = 'Default warning settings'; +$string['defaultwarningsettings_help'] = 'These settings define the defaults for all new warnings'; $string['defaults'] = 'Defaults'; $string['defaultsessionsettings'] = 'Default session settings'; $string['defaultsessionsettings_help'] = 'These settings define the defaults for all new sessions'; @@ -115,6 +120,7 @@ $string['defaultsubnet_help'] = 'Attendance recording may be restricted to parti $string['defaultview'] = 'Default view on login'; $string['defaultview_desc'] = 'This is the default view shown to teachers on first login.'; $string['delete'] = 'Delete'; +$string['deletewarningconfirm'] = 'Are you sure you want to delete this warning?'; $string['deletedgroup'] = 'The group associated with this session has been deleted'; $string['deletehiddensessions'] = 'Delete all hidden sessions'; $string['deletelogs'] = 'Delete attendance data'; @@ -134,8 +140,35 @@ $string['downloadtext'] = 'Download in text format'; $string['duration'] = 'Duration'; $string['editsession'] = 'Edit Session'; $string['edituser'] = 'Edit user'; +$string['emailcontent_default'] = 'Hi %userfirstname%, +Your attendance in %coursename% %attendancename% has dropped below %warningpercent% and is currently %percent% - we hope you are ok! + +To get the most out of this course you should improve your attendance, please get in touch if you require any further support.'; +$string['emailcontent'] = 'Email content'; +$string['emailcontent_help'] = 'When a warning is sent to a student, it takes the email content from this field. The following wildcards can be used: +'; + +$string['emailsubject'] = 'Email subject'; +$string['emailsubject_help'] = 'When a warning is sent to a student, it takes the email subject from this field.'; +$string['emailsubject_default'] = 'Attendance warning'; +$string['emailuser'] = 'Email user'; +$string['emailuser_help'] = 'If checked, a warning will be sent to the student.'; $string['emptyacronym'] = 'Empty acronyms are not allowed. Status record not updated.'; $string['emptydescription'] = 'Empty descriptions are not allowed. Status record not updated.'; +$string['enablewarnings'] = 'Enable warnings'; +$string['enablewarnings_desc'] = 'This allows a warning set to be defined for an attendance and email notifications to users when attendance drops below the configured threshold.
WARNING: This is a new feature and has not been tested extensively. Please use at your own-risk and provide feeback in the moodle forums if you find it works well.'; $string['endofperiod'] = 'End of period'; $string['endtime'] = 'Session end time'; $string['enrolmentend'] = 'User enrolment ends {$a}'; @@ -175,6 +208,7 @@ $string['includeremarks'] = 'Include remarks'; $string['incorrectpassword'] = 'You have entered an incorrect password and your attendance has not been recorded, please enter the correct password.'; $string['indetail'] = 'In detail...'; $string['invalidaction'] = 'You must select an action'; +$string['invalidemails'] = 'You must specify addresses of existing user accounts, could not find: {$a}'; $string['invalidsessionenddate'] = 'This date can not be earlier than the session date'; $string['invalidsessionendtime'] = 'The end time must be greater than start time'; $string['invalidstatus'] = 'You have selected an invalid status, please try again'; @@ -217,9 +251,15 @@ $string['noofdayspresent'] = 'No of days present'; $string['nosessiondayselected'] = 'No Session day selected'; $string['nosessionexists'] = 'No Session exists for this course'; $string['nosessionsselected'] = 'No sessions selected'; +$string['warningdeleted'] = 'Warning deleted'; +$string['warningdesc'] = 'These warnings will be automatically added to any new attendance activities. If more than one warning is triggered at exactly the same time, only the warning with the lower warning threshold will be sent.'; +$string['warnings'] = 'Warnings set'; +$string['warningupdated'] = 'Updated warnings'; +$string['notifytask'] = 'Send warnings to users'; $string['notfound'] = 'Attendance activity not found in this course!'; $string['notmember'] = 'not member'; $string['noupgradefromthisversion'] = 'The Attendance module cannot upgrade from the version of attforblock you have installed. - please delete attforblock or upgrade it to the latest version before isntalling the new attendance module'; +$string['numsessions'] = 'Number of sessions'; $string['olddate'] = 'Old date'; $string['onlyselectedusers'] = 'Export specific users'; $string['overallsessions'] = 'Over all sessions'; @@ -384,10 +424,16 @@ $string['tempusermerge'] = 'Merge temporary user'; $string['tempusers'] = 'Temporary users'; $string['tempusersedit'] = 'Edit temporary user'; $string['tempuserslist'] = 'Temporary users'; +$string['thirdpartyemailsubject'] = 'Attendance warning'; +$string['thirdpartyemailtext'] = '{$a->firstname} {$a->lastname} attendance within {$a->coursename} {$a->aname} is lower than {$a->warningpercent} ({$a->percent})'; +$string['thirdpartyemailtextfooter'] = 'You are receiving this because the teacher of this course has added your email to the recipient’s list'; +$string['thirdpartyemails'] = 'Notify other users'; +$string['thirdpartyemails_help'] = 'List of other users who will be notified. (requires the capability mod/attendance:viewreports)'; $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['triggered'] = 'First triggered'; $string['tuseremail'] = 'Email'; $string['tusername'] = 'Full name'; $string['unknowngroup'] = 'Unknown group'; @@ -400,6 +446,12 @@ $string['variable'] = 'variable'; $string['variablesupdated'] = 'Variables successfully updated'; $string['versionforprinting'] = 'version for printing'; $string['viewmode'] = 'View mode'; +$string['warnafter'] = 'Number of sessions taken before warning'; +$string['warnafter_help'] = 'Warnings will only be triggered when the user has had their attendance taken for at least this number of sessions.'; +$string['warningfailed'] = 'You cannot create a warning that uses the same percentage and number of sessions.'; +$string['warningpercent'] = 'Warn if percentage falls under'; +$string['warningpercent_help'] = 'A warning will be triggered when the overall percentage falls below this number.'; +$string['warningthreshold'] = 'Warning threshold'; $string['week'] = 'week(s)'; $string['weeks'] = 'Weeks'; $string['youcantdo'] = 'You can\'t do anything'; diff --git a/lib.php b/lib.php index 61e6acb..429ef0d 100644 --- a/lib.php +++ b/lib.php @@ -70,6 +70,25 @@ function att_add_default_statuses($attid) { } /** + * Add default set of warnings to the new attendance. + * + * @param int $attid - id of attendance instance. + */ +function attendance_add_default_warnings($cmid) { + global $DB, $CFG; + require_once($CFG->dirroot.'/mod/attendance/locallib.php'); + + $warnings = $DB->get_recordset('attendance_warning', + array('idnumber' => 0), 'id'); + foreach ($warnings as $n) { + $rec = $n; + $rec->idnumber = $cmid; + $DB->insert_record('attendance_warning', $rec); + } + $warnings->close(); +} + +/** * Add new attendance instance. * * @param stdClass $attendance @@ -84,6 +103,8 @@ function attendance_add_instance($attendance) { att_add_default_statuses($attendance->id); + attendance_add_default_warnings($attendance->coursemodule); + attendance_grade_item_update($attendance); return $attendance->id; @@ -117,7 +138,8 @@ function attendance_update_instance($attendance) { * @return bool */ function attendance_delete_instance($id) { - global $DB; + global $DB, $CFG; + require_once($CFG->dirroot.'/mod/attendance/locallib.php'); if (! $attendance = $DB->get_record('attendance', array('id' => $id))) { return false; @@ -132,6 +154,8 @@ function attendance_delete_instance($id) { } $DB->delete_records('attendance_statuses', array('attendanceid' => $id)); + $DB->delete_records('attendance_warning', array('idnumber' => $id)); + $DB->delete_records('attendance', array('id' => $id)); attendance_grade_item_delete($attendance); @@ -450,9 +474,18 @@ function attendance_print_settings_tabs($selected = 'settings') { $tabs[] = new tabobject('defaultstatus', $CFG->wwwroot.'/mod/attendance/defaultstatus.php', get_string('defaultstatus', 'attendance'), get_string('defaultstatus', 'attendance'), false); + if (get_config('attendance', 'enablewarnings')) { + $tabs[] = new tabobject('defaultwarnings', $CFG->wwwroot . '/mod/attendance/warnings.php', + get_string('defaultwarnings', 'attendance'), get_string('defaultwarnings', 'attendance'), false); + } + $tabs[] = new tabobject('coursesummary', $CFG->wwwroot.'/mod/attendance/coursesummary.php', get_string('coursesummary', 'attendance'), get_string('coursesummary', 'attendance'), false); + if (get_config('attendance', 'enablewarnings')) { + $tabs[] = new tabobject('atrisk', $CFG->wwwroot . '/mod/attendance/atrisk.php', + get_string('atriskreport', 'attendance'), get_string('atriskreport', 'attendance'), false); + } ob_start(); print_tabs(array($tabs), $selected); $tabmenu = ob_get_contents(); diff --git a/locallib.php b/locallib.php index 397faee..b540213 100644 --- a/locallib.php +++ b/locallib.php @@ -42,6 +42,7 @@ define('ATT_SORT_FIRSTNAME', 2); define('ATTENDANCE_AUTOMARK_DISABLED', 0); define('ATTENDANCE_AUTOMARK_ALL', 1); define('ATTENDANCE_AUTOMARK_CLOSE', 2); + /** * Get statuses, * @@ -709,4 +710,114 @@ SELECT a.id, a.course as courseid, c.fullname as coursename, atl.studentid AS us ) p GROUP by courseid, coursename {$orderby}"; return $DB->get_records_sql($sql, $params); +} + +/** + * Generates a list of users flagged at-risk. + * + * @param array $courseids optional list of courses to return + * @param array $sincetime optional allows a list to be calculated for cron processing. + * @param bool $allfornotify get notification list for scheduled task. + * @return stdClass + */ +function attendance_get_users_to_notify($courseids = array(), $orderby = '', $sincetime = 0, $allfornotify = false) { + global $DB; + + $joingroup = 'LEFT JOIN {groups_members} gm ON (gm.userid = atl.studentid AND gm.groupid = ats.groupid)'; + $where = ' AND (ats.groupid = 0 or gm.id is NOT NULL)'; + $params = array(); + + if (!empty($courseids)) { + list($insql, $inparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED); + $where .= ' AND c.id ' . $insql; + $params = array_merge($params, $inparams); + } + if ($allfornotify) { + // Exclude warnings that have already been sent. + $where .= ' AND ns.id IS NULL '; + } + + $unames = get_all_user_name_fields(true); + $unames2 = get_all_user_name_fields(true, 'u'); + + $idfield = $DB->sql_concat('cm.id', 'atl.studentid', 'n.id'); + $sql = "SELECT {$idfield} as uniqueid, a.id as aid, {$unames2}, a.name as aname, cm.id as cmid, c.id as courseid, + c.fullname as coursename, atl.studentid AS userid, n.id as notifyid, n.warningpercent, n.emailsubject, + n.emailcontent, n.emailcontentformat, n.emailuser, n.thirdpartyemails, ns.timesent, n.warnafter, + COUNT(DISTINCT ats.id) AS numtakensessions, SUM(stg.grade) AS points, SUM(stm.maxgrade) AS maxpoints, + SUM(stg.grade) / SUM(stm.maxgrade) AS percent + FROM {attendance_sessions} ats + JOIN {attendance} a ON a.id = ats.attendanceid + JOIN {course_modules} cm ON cm.instance = a.id + JOIN {course} c on c.id = cm.course + JOIN {modules} md ON md.id = cm.module AND md.name = 'attendance' + JOIN {attendance_log} atl ON (atl.sessionid = ats.id) + JOIN {user} u ON (u.id = atl.studentid) + JOIN {attendance_statuses} stg ON (stg.id = atl.statusid AND stg.deleted = 0 AND stg.visible = 1) + JOIN {attendance_warning} n ON n.idnumber = cm.id + LEFT JOIN {attendance_warning_done} ns ON ns.notifyid = n.id AND ns.userid = atl.studentid + JOIN (SELECT attendanceid, setnumber, MAX(grade) AS maxgrade + FROM {attendance_statuses} + WHERE deleted = 0 + AND visible = 1 + GROUP BY attendanceid, setnumber) stm + ON (stm.setnumber = ats.statusset AND stm.attendanceid = ats.attendanceid) + {$joingroup} + WHERE ats.sessdate >= {$sincetime} {$where} + AND ats.lasttaken != 0 + GROUP BY uniqueid, a.id, a.name, a.course, c.fullname, atl.studentid, n.id, n.warningpercent, + n.emailsubject, n.emailcontent, n.emailcontentformat, n.warnafter, + n.emailuser, n.thirdpartyemails, ns.timesent, cm.id, c.id, {$unames2} + HAVING n.warnafter <= COUNT(DISTINCT ats.id) AND n.warningpercent > ((SUM(stg.grade) / SUM(stm.maxgrade)) * 100) + {$orderby}"; + + if (!$allfornotify) { + $idfield = $DB->sql_concat('cmid', 'userid'); + // Only show one record per attendance for teacher reports. + $sql = "SELECT {$idfield} as id, {$unames}, aid, cmid, courseid, aname, coursename, userid, MIN(warningpercent), + numtakensessions, points, maxpoints, percent, timesent + FROM ({$sql}) as m + GROUP BY id, aid, cmid, courseid, aname, userid, numtakensessions, points, maxpoints, + percent, coursename, timesent, {$unames} {$orderby}"; + } + + return $DB->get_records_sql($sql, $params); + +} + +/** + * Template variables into place in supplied email content. + * + * @param object $record db record of details + * @return array - the content of the fields after templating. + */ +function attendance_template_variables($record) { + $templatevars = array( + '/%coursename%/' => $record->coursename, + '/%courseid%/' => $record->courseid, + '/%userfirstname%/' => $record->firstname, + '/%userlastname%/' => $record->lastname, + '/%userid%/' => $record->userid, + '/%warningpercent%/' => $record->warningpercent, + '/%attendancename%/' => $record->aname, + '/%cmid%/' => $record->cmid, + '/%numtakensessions%/' => $record->numtakensessions, + '/%points%/' => $record->points, + '/%maxpoints%/' => $record->maxpoints, + '/%precent%/' => $record->percent, + ); + $extrauserfields = get_all_user_name_fields(); + foreach ($extrauserfields as $extra) { + $templatevars['/%'.$extra.'%/'] = $record->$extra; + } + $patterns = array_keys($templatevars); // The placeholders which are to be replaced. + $replacements = array_values($templatevars); // The values which are to be templated in for the placeholders. + // Array to describe which fields in reengagement object should have a template replacement. + $replacementfields = array('emailsubject', 'emailcontent'); + + // Replace %variable% with relevant value everywhere it occurs in reengagement->field. + foreach ($replacementfields as $field) { + $record->$field = preg_replace($patterns, $replacements, $record->$field); + } + return $record; } \ No newline at end of file diff --git a/renderables.php b/renderables.php index a73c98a..0f2d483 100644 --- a/renderables.php +++ b/renderables.php @@ -51,7 +51,10 @@ class attendance_tabs implements renderable { const TAB_TEMPORARYUSERS = 6; // Tab for managing temporary users. /** Update tab */ const TAB_UPDATE = 7; - + /** Warnings tab */ + const TAB_WARNINGS = 8; + /** At-risk tab */ + const TAB_ATRISK = 9; /** @var int current tab */ public $currenttab; @@ -97,6 +100,12 @@ class attendance_tabs implements renderable { get_string('report', 'attendance')); } + if (has_capability('mod/attendance:viewreports', $context) && + get_config('attendance', 'enablewarnings')) { + $toprow[] = new tabobject(self::TAB_ATRISK, $this->att->url_atrisk()->out(), + get_string('atriskreport', 'attendance')); + } + if (has_capability('mod/attendance:export', $context)) { $toprow[] = new tabobject(self::TAB_EXPORT, $this->att->url_export()->out(), get_string('export', 'attendance')); @@ -105,6 +114,11 @@ class attendance_tabs implements renderable { if (has_capability('mod/attendance:changepreferences', $context)) { $toprow[] = new tabobject(self::TAB_PREFERENCES, $this->att->url_preferences()->out(), get_string('statussetsettings', 'attendance')); + + if (get_config('attendance', 'enablewarnings')) { + $toprow[] = new tabobject(self::TAB_WARNINGS, $this->att->url_warnings()->out(), + get_string('warnings', 'attendance')); + } } if (has_capability('mod/attendance:managetemporaryusers', $context)) { $toprow[] = new tabobject(self::TAB_TEMPORARYUSERS, $this->att->url_managetemp()->out(), diff --git a/settings.php b/settings.php index 120a32b..e99e3d2 100644 --- a/settings.php +++ b/settings.php @@ -74,6 +74,10 @@ if ($ADMIN->fulltree) { get_string('defaultview', 'attendance'), get_string('defaultview_desc', 'attendance'), ATT_VIEW_WEEKS, $options)); + $settings->add(new admin_setting_configcheckbox('attendance/enablewarnings', + get_string('enablewarnings', 'attendance'), + get_string('enablewarnings_desc', 'attendance'), 0)); + $name = new lang_string('defaultsettings', 'mod_attendance'); $description = new lang_string('defaultsettings_help', 'mod_attendance'); $settings->add(new admin_setting_heading('defaultsettings', $name, $description)); @@ -98,4 +102,35 @@ if ($ADMIN->fulltree) { $settings->add(new admin_setting_configcheckbox('attendance/randompassword_default', get_string('randompassword', 'attendance'), '', 0)); + + $name = new lang_string('defaultwarningsettings', 'mod_attendance'); + $description = new lang_string('defaultwarningsettings_help', 'mod_attendance'); + $settings->add(new admin_setting_heading('defaultwarningsettings', $name, $description)); + + $options = array(); + for ($i = 1; $i <= 100; $i++) { + $options[$i] = "$i%"; + } + $settings->add(new admin_setting_configselect('attendance/warningpercent', + get_string('warningpercent', 'attendance'), get_string('warningpercent_help', 'attendance'), 70, $options)); + + $options = array(); + for ($i = 1; $i <= 50; $i++) { + $options[$i] = "$i"; + } + $settings->add(new admin_setting_configselect('attendance/warnafter', + get_string('warnafter', 'attendance'), get_string('warnafter_help', 'attendance'), 5, $options)); + + $settings->add(new admin_setting_configcheckbox('attendance/emailuser', + get_string('emailuser', 'attendance'), get_string('emailuser_help', 'attendance'), 1)); + + $settings->add(new admin_setting_configtext('attendance/emailsubject', + get_string('emailsubject', 'attendance'), get_string('emailsubject_help', 'attendance'), + get_string('emailsubject_default', 'attendance'), PARAM_RAW)); + + + $settings->add(new admin_setting_configtextarea('attendance/emailcontent', + get_string('emailcontent', 'attendance'), get_string('emailcontent_help', 'attendance'), + get_string('emailcontent_default', 'attendance'), PARAM_RAW)); + } diff --git a/tests/behat/report.feature b/tests/behat/report.feature index 6024b55..06edb2b 100644 --- a/tests/behat/report.feature +++ b/tests/behat/report.feature @@ -14,6 +14,8 @@ Feature: Visiting reports | course | user | role | timestart | | C1 | student1 | student | ##yesterday## | | C1 | teacher1 | editingteacher | ##yesterday## | + And the following config values are set as admin: + | enablewarnings | 1 | attendance | And I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on @@ -27,6 +29,12 @@ Feature: Visiting reports | id_sestime_starthour | 01 | | id_sestime_endhour | 02 | And I click on "id_submitbutton" "button" + And I follow "Warnings set" + And I press "Add warning" + And I set the following fields to these values: + | id_warningpercent | 84 | + | id_warnafter | 2 | + And I click on "id_submitbutton" "button" And I log out Scenario: Teacher takes attendance @@ -144,7 +152,7 @@ Feature: Visiting reports And I log out - Scenario: Teacher visit summary report + Scenario: Teacher visit summary report and at-risk report Given I log in as "teacher1" And I am on "Course 1" course homepage And I follow "Attendance" @@ -186,6 +194,9 @@ Feature: Visiting reports And "5 / 6" "text" should exist in the "Student 1" "table_row" And "83.3%" "text" should exist in the "Student 1" "table_row" + And I follow "At-risk report" + And I should see "Student 1" + And I log out Scenario: Student visit user report diff --git a/version.php b/version.php index 5ef2d09..6f78fbf 100644 --- a/version.php +++ b/version.php @@ -23,7 +23,7 @@ */ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017061400; +$plugin->version = 2017062000; $plugin->requires = 2017042100; $plugin->release = '3.3.8'; $plugin->maturity = MATURITY_ALPHA; diff --git a/warnings.php b/warnings.php new file mode 100644 index 0000000..d9cde6b --- /dev/null +++ b/warnings.php @@ -0,0 +1,199 @@ +. + +/** + * Allows default warnings to be modified. + * + * @package mod_attendance + * @copyright 2017 Dan Marsden http://danmarsden.com + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__.'/../../config.php'); +require_once($CFG->libdir.'/adminlib.php'); +require_once($CFG->libdir.'/formslib.php'); +require_once($CFG->dirroot.'/mod/attendance/lib.php'); +require_once($CFG->dirroot.'/mod/attendance/locallib.php'); + +$action = optional_param('action', '', PARAM_ALPHA); +$notid = optional_param('notid', 0, PARAM_INT); +$id = optional_param('id', 0, PARAM_INT); + +$url = new moodle_url('/mod/attendance/warnings.php'); + +// This page is used for configuring default set and for configuring attendance level set. +if (empty($id)) { + // This is the default status set - show appropriate admin stuff and check admin permissions. + admin_externalpage_setup('managemodules'); + + $output = $PAGE->get_renderer('mod_attendance'); + echo $OUTPUT->header(); + echo $OUTPUT->heading(get_string('defaultwarnings', 'mod_attendance')); + $tabmenu = attendance_print_settings_tabs('defaultwarnings'); + echo $tabmenu; + +} else { + // This is an attendance level config. + $cm = get_coursemodule_from_id('attendance', $id, 0, false, MUST_EXIST); + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $att = $DB->get_record('attendance', array('id' => $cm->instance), '*', MUST_EXIST); + + require_login($course, false, $cm); + $context = context_module::instance($cm->id); + require_capability('mod/attendance:changepreferences', $context); + + $att = new mod_attendance_structure($att, $cm, $course, $PAGE->context); + + $PAGE->set_url($url); + $PAGE->set_title($course->shortname. ": ".$att->name); + $PAGE->set_heading($course->fullname); + $PAGE->navbar->add($att->name); + + $output = $PAGE->get_renderer('mod_attendance'); + $tabs = new attendance_tabs($att, attendance_tabs::TAB_WARNINGS); + echo $output->header(); + echo $output->heading(get_string('attendanceforthecourse', 'attendance').' :: ' .format_string($course->fullname)); + echo $output->render($tabs); + +} + +$mform = new mod_attendance_add_warning_form($url, array('notid' => $notid, 'id' => $id)); + +if ($data = $mform->get_data()) { + if (empty($data->notid)) { + // Insert new record. + $notify = new stdClass(); + if (empty($id)) { + $notify->idnumber = 0; + } else { + $notify->idnumber = $cm->id; + } + + $notify->warningpercent = $data->warningpercent; + $notify->warnafter = $data->warnafter; + $notify->emailuser = empty($data->emailuser) ? 0 : $data->emailuser; + $notify->emailsubject = $data->emailsubject; + $notify->emailcontent = $data->emailcontent['text']; + $notify->emailcontentformat = $data->emailcontent['format']; + $notify->thirdpartyemails = ''; + if (!empty($data->thirdpartyemails)) { + $notify->thirdpartyemails = implode(',', $data->thirdpartyemails); + } + $existingrecord = $DB->record_exists('attendance_warning', array('idnumber' => $notify->idnumber, + 'warningpercent' => $notify->warningpercent)); + if (empty($existingrecord)) { + $DB->insert_record('attendance_warning', $notify); + echo $OUTPUT->notification(get_string('warningupdated', 'mod_attendance'), 'success'); + } else { + echo $OUTPUT->notification(get_string('warningfailed', 'mod_attendance'), 'warning'); + } + + } else { + $notify = $DB->get_record('attendance_warning', array('id' => $data->notid)); + if (!empty($id) && $data->idnumber != $id) { + // Someone is trying to update a record for a different attendance. + print_error('invalidcoursemodule'); + } else { + $notify = new stdClass(); + $notify->id = $data->notid; + $notify->idnumber = $data->idnumber; + $notify->warningpercent = $data->warningpercent; + $notify->warnafter = $data->warnafter; + $notify->emailuser = empty($data->emailuser) ? 0 : $data->emailuser; + $notify->emailsubject = $data->emailsubject; + $notify->emailcontentformat = $data->emailcontent['format']; + $notify->emailcontent = $data->emailcontent['text']; + $notify->thirdpartyemails = ''; + if (!empty($data->thirdpartyemails)) { + $notify->thirdpartyemails = implode(',', $data->thirdpartyemails); + } + $existingrecord = $DB->get_record('attendance_warning', array('idnumber' => $notify->idnumber, + 'warningpercent' => $notify->warningpercent)); + if (empty($existingrecord) || $existingrecord->id == $notify->id) { + $DB->update_record('attendance_warning', $notify); + echo $OUTPUT->notification(get_string('warningupdated', 'mod_attendance'), 'success'); + } else { + echo $OUTPUT->notification(get_string('warningfailed', 'mod_attendance'), 'error'); + } + } + } +} +if ($action == 'delete' && !empty($notid)) { + if (!optional_param('confirm', false, PARAM_BOOL)) { + $cancelurl = $url; + $url->params(array('action' => 'delete', 'notid' => $notid, 'sesskey' => sesskey(), 'confirm' => true, 'id' => $id)); + echo $OUTPUT->confirm(get_string('deletewarningconfirm', 'mod_attendance'), $url, $cancelurl); + echo $OUTPUT->footer(); + exit; + } else { + require_sesskey(); + $params = array('id' => $notid); + if (!empty($id)) { + // Add id/level to array. + $params['idnumber'] = $cm->id; + } + $DB->delete_records('attendance_warning', $params); + echo $OUTPUT->notification(get_string('warningdeleted', 'mod_attendance'), 'success'); + } +} +if ($action == 'update' && !empty($notid)) { + $existing = $DB->get_record('attendance_warning', array('id' => $notid)); + $content = $existing->emailcontent; + $existing->emailcontent = array(); + $existing->emailcontent['text'] = $content; + $existing->emailcontent['format'] = $existing->emailcontentformat; + $existing->notid = $existing->id; + $existing->id = $id; + $mform->set_data($existing); + $mform->display(); +} else if ($action == 'add' && confirm_sesskey()) { + $mform->display(); +} else { + if (empty($id)) { + echo $OUTPUT->box(get_string('warningdesc', 'mod_attendance'), 'generalbox', 'notice'); + + $existingnotifications = $DB->get_records('attendance_warning', + array('idnumber' => 0), + 'warningpercent'); + } else { + $existingnotifications = $DB->get_records('attendance_warning', + array('idnumber' => $cm->id), + 'warningpercent'); + } + if (!empty($existingnotifications)) { + $table = new html_table(); + $table->head = array(get_string('warningthreshold', 'mod_attendance'), + get_string('numsessions', 'mod_attendance'), + get_string('emailsubject', 'mod_attendance'), + ''); + foreach ($existingnotifications as $notification) { + $url->params(array('action' => 'delete', 'notid' => $notification->id, 'id' => $id)); + $actionbuttons = $OUTPUT->action_icon($url, new pix_icon('t/delete', + get_string('delete', 'attendance')), null, null); + $url->params(array('action' => 'update', 'notid' => $notification->id, 'id' => $id)); + $actionbuttons .= $OUTPUT->action_icon($url, new pix_icon('t/edit', + get_string('update', 'attendance')), null, null); + $table->data[] = array($notification->warningpercent, $notification->warnafter, + $notification->emailsubject, $actionbuttons); + } + echo html_writer::table($table); + } + $addurl = new moodle_url('/mod/attendance/warnings.php', array('action' => 'add', 'id' => $id)); + echo $OUTPUT->single_button($addurl, get_string('addwarning', 'mod_attendance')); + +} + +echo $OUTPUT->footer(); \ No newline at end of file