diff --git a/backup/moodle2/backup_attendance_stepslib.php b/backup/moodle2/backup_attendance_stepslib.php index 877f6e8..275903b 100644 --- a/backup/moodle2/backup_attendance_stepslib.php +++ b/backup/moodle2/backup_attendance_stepslib.php @@ -53,7 +53,7 @@ class backup_attendance_activity_structure_step extends backup_activity_structur $sessions = new backup_nested_element('sessions'); $session = new backup_nested_element('session', array('id'), array( 'groupid', 'sessdate', 'duration', 'lasttaken', 'lasttakenby', - 'timemodified', 'description', 'descriptionformat')); + 'timemodified', 'description', 'descriptionformat', 'caleventid')); // XML nodes declaration - user data. $logs = new backup_nested_element('logs'); diff --git a/backup/moodle2/restore_attendance_stepslib.php b/backup/moodle2/restore_attendance_stepslib.php index f8c0dae..97bd5ed 100644 --- a/backup/moodle2/restore_attendance_stepslib.php +++ b/backup/moodle2/restore_attendance_stepslib.php @@ -117,6 +117,7 @@ class restore_attendance_activity_structure_step extends restore_activity_struct $data->lasttaken = $this->apply_date_offset($data->lasttaken); $data->lasttakenby = $this->get_mappingid('user', $data->lasttakenby); $data->timemodified = $this->apply_date_offset($data->timemodified); + $data->caleventid = $this->get_mappingid('event', $data->caleventid); $newitemid = $DB->insert_record('attendance_sessions', $data); $this->set_mapping('attendance_session', $oldid, $newitemid, true); diff --git a/classes/calendar_helpers.php b/classes/calendar_helpers.php new file mode 100644 index 0000000..fe30c95 --- /dev/null +++ b/classes/calendar_helpers.php @@ -0,0 +1,136 @@ +. +/** + * Calendar related functions + * + * @package mod_attendance + * @copyright 2016 Vyacheslav Strelkov + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(dirname(__FILE__).'/../../../calendar/lib.php'); + +/** + * Create single calendar event bases on session data. + * + * @param stdClass $session initial sessions to take data from + * @return bool result of calendar event creation + */ +function create_calendar_event(&$session) { + // We don't want to create multiple calendar events for 1 session. + if ($session->caleventid) { + return $session->caleventid; + } + + global $DB; + $attendance = $DB->get_record('attendance', array('id' => $session->attendanceid)); + + $caleventdata = new stdClass(); + $caleventdata->name = $attendance->name; + $caleventdata->courseid = $attendance->course; + $caleventdata->groupid = $session->groupid; + $caleventdata->instance = $session->attendanceid; + $caleventdata->timestart = $session->sessdate; + $caleventdata->timeduration = $session->duration; + $caleventdata->eventtype = 'attendance'; + $caleventdata->timemodified = time(); + $caleventdata->modulename = 'attendance'; + + $calevent = new stdClass(); + if ($calevent = calendar_event::create($caleventdata, false)) { + $session->caleventid = $calevent->id; + $DB->set_field('attendance_sessions', 'caleventid', $session->caleventid, array('id' => $session->id)); + return true; + } else { + return false; + } +} + +/** + * Create multiple calendar events based on sessions data. + * + * @param array %sessionsids array of sessions ids + */ +function create_calendar_events($sessionsids) { + global $DB; + $sessions = $DB->get_recordset_list('attendance_sessions', 'id', $sessionsids); + + foreach ($sessions as $session) { + create_calendar_event($session); + if ($session->caleventid) { + $DB->update_record('attendance_sessions', $session); + } + } +} + +/** + * Update calendar event duration and date + * + * @param $caleventid int calendar event id + * @param $timeduration int duration of the event + * @param $timestart int start time of the event + * @return bool result of updating + */ +function update_calendar_event($caleventid, $timeduration, $timestart = null) { + $caleventdata = new stdClass(); + $caleventdata->timeduration = $timeduration; + $caleventdata->timestart = $timestart; + $caleventdata->timemodified = time(); + + $calendarevent = calendar_event::load($caleventid); + if ($calendarevent) { + return $calendarevent->update($caleventdata) ? true : false; + } else { + return false; + } +} + +/** + * Delete calendar events for sessions + * + * @param array %sessionsids array of sessions ids + * @return bool result of updating + */ +function delete_calendar_events($sessionsids) { + global $DB; + $caleventsids = existing_calendar_events_ids($sessionsids); + if ($caleventsids) { + $DB->delete_records_list('event', 'id', $caleventsids); + } + + $sessions = $DB->get_recordset_list('attendance_sessions', 'id', $sessionsids); + foreach ($sessions as $session) { + $session->caleventid = 0; + $DB->update_record('attendance_sessions', $session); + } +} + +/** + * Check if calendar events are created for given sessions + * + * @param array $sessionsids of sessions ids + * @return array | bool array of existing calendar events or false if none found + */ +function existing_calendar_events_ids($sessionsids) { + global $DB; + $caleventsids = array_keys($DB->get_records_list('attendance_sessions', 'id', $sessionsids, '', 'caleventid')); + $existingcaleventsids = array_filter($caleventsids); + if (! empty($existingcaleventsids)) { + return $existingcaleventsids; + } else { + return false; + } +} \ No newline at end of file diff --git a/classes/sessions_page_params.php b/classes/sessions_page_params.php index e59d8a3..0731b29 100644 --- a/classes/sessions_page_params.php +++ b/classes/sessions_page_params.php @@ -30,12 +30,14 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class mod_attendance_sessions_page_params { - const ACTION_ADD = 1; - const ACTION_UPDATE = 2; - const ACTION_DELETE = 3; - const ACTION_DELETE_SELECTED = 4; - const ACTION_CHANGE_DURATION = 5; - const ACTION_DELETE_HIDDEN = 6; + const ACTION_ADD = 1; + const ACTION_UPDATE = 2; + const ACTION_DELETE = 3; + const ACTION_DELETE_SELECTED = 4; + const ACTION_CHANGE_DURATION = 5; + const ACTION_DELETE_HIDDEN = 6; + const ACTION_CREATE_CAL_EVENTS = 7; + const ACTION_DELETE_CAL_EVENTS = 8; /** @var int view mode of taking attendance page*/ public $action; diff --git a/classes/structure.php b/classes/structure.php index a89bd20..9d67b12 100644 --- a/classes/structure.php +++ b/classes/structure.php @@ -22,6 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +require_once(dirname(__FILE__) . '/calendar_helpers.php'); + /** * Main class with all Attendance related info. * @@ -349,6 +351,9 @@ class mod_attendance_structure { $sess->description); $DB->set_field('attendance_sessions', 'description', $description, array('id' => $sess->id)); + $sess->caleventid = 0; + create_calendar_event($sess); + $infoarray = array(); $infoarray[] = construct_session_full_date_time($sess->sessdate, $sess->duration); @@ -390,6 +395,8 @@ class mod_attendance_structure { $sess->timemodified = time(); $DB->update_record('attendance_sessions', $sess); + update_calendar_event($sess->caleventid, $sess->duration, $sess->sessdate); + $info = construct_session_full_date_time($sess->sessdate, $sess->duration); $event = \mod_attendance\event\session_updated::create(array( 'objectid' => $this->id, @@ -884,6 +891,9 @@ class mod_attendance_structure { public function delete_sessions($sessionsids) { global $DB; + if (existing_calendar_events_ids($sessionsids)) { + delete_calendar_events($sessionsids); + } list($sql, $params) = $DB->get_in_or_equal($sessionsids); $DB->delete_records_select('attendance_log', "sessionid $sql", $params); @@ -905,6 +915,9 @@ class mod_attendance_structure { $sess->duration = $duration; $sess->timemodified = $now; $DB->update_record('attendance_sessions', $sess); + if ($sess->caleventid) { + update_calendar_event($sess->caleventid, $duration); + } $event = \mod_attendance\event\session_duration_updated::create(array( 'objectid' => $this->id, 'context' => $this->context, diff --git a/db/install.xml b/db/install.xml index e683ef6..bf40a99 100644 --- a/db/install.xml +++ b/db/install.xml @@ -32,6 +32,7 @@ + @@ -40,6 +41,7 @@ + diff --git a/db/upgrade.php b/db/upgrade.php index 20ae691..3494fde 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +require_once(dirname(__FILE__) . '/upgradelib.php'); + /** * upgrade processes for this module. * @@ -158,5 +160,22 @@ function xmldb_attendance_upgrade($oldversion=0) { upgrade_mod_savepoint(true, 2015040503, 'attendance'); } + if ($oldversion < 2016052202) { + // Adding field to store calendar event ids. + $table = new xmldb_table('attendance_sessions'); + $field = new xmldb_field('caleventid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', null); + + // Conditionally launch add field statusset. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Creating events for all existing sessions. + create_calendar_events(); + + // Attendance savepoint reached. + upgrade_mod_savepoint(true, 2016052202, 'attendance'); + } + return $result; } diff --git a/db/upgradelib.php b/db/upgradelib.php new file mode 100644 index 0000000..92f96c7 --- /dev/null +++ b/db/upgradelib.php @@ -0,0 +1,50 @@ +. + +/** + * Helper functions to keep upgrade.php clean. + * + * @package mod_attendance + * @copyright 2016 Vyacheslav Strelkov + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +function create_calendar_events() { + global $DB; + + $attendances = $DB->get_records('attendance', null, null, 'id, name, course'); + foreach ($attendances as $att) { + $sessionsdata = $DB->get_records('attendance_sessions', array('attendanceid' => $att->id), null, + 'id, groupid, sessdate, duration, description, descriptionformat'); + foreach ($sessionsdata as $session) { + $calevent = new stdClass(); + $calevent->name = $att->name; + $calevent->courseid = $att->course; + $calevent->groupid = $session->groupid; + $calevent->instance = $att->id; + $calevent->timestart = $session->sessdate; + $calevent->timeduration = $session->duration; + $calevent->eventtype = 'attendance'; + $calevent->timemodified = time(); + $calevent->modulename = 'attendance'; + $calevent->description = $session->description; + $calevent->format = $session->descriptionformat; + + $caleventid = $DB->insert_record('event', $calevent); + $DB->set_field('attendance_sessions', 'caleventid', $caleventid, array('id' => $session->id)); + } + } +} diff --git a/lang/en/attendance.php b/lang/en/attendance.php index edc0ec9..d1f54ab 100644 --- a/lang/en/attendance.php +++ b/lang/en/attendance.php @@ -59,6 +59,8 @@ $string['attendance:viewreports'] = 'Viewing Reports'; $string['attforblockdirstillexists'] = 'old mod/attforblock directory still exists - you must delete this directory on your server before running this upgrade.'; $string['attrecords'] = 'Attendances records'; $string['calclose'] = 'Close'; +$string['caleventcreated'] = 'Calendar event for session successfully created'; +$string['caleventdeleted'] = 'Calendar event for session successfully deleted'; $string['calmonths'] = 'January,February,March,April,May,June,July,August,September,October,November,December'; $string['calshow'] = 'Choose date'; $string['caltoday'] = 'Today'; @@ -75,6 +77,8 @@ $string['commonsessions'] = 'All students'; $string['confirmdeleteuser'] = 'Are you sure you want to delete user \'{$a->fullname}\' ({$a->email})?
All of their attendance records will be permanently deleted.'; $string['countofselected'] = 'Count of selected'; $string['copyfrom'] = 'Copy attendance data from'; +$string['createcalevents'] = 'Create calendar events'; +$string['createcheckcalevents'] = 'Are you sure you want to create the calendar events for the following sessions?'; $string['createmultiplesessions'] = 'Create multiple sessions'; $string['createmultiplesessions_help'] = 'This function allows you to create multiple sessions in one simple step. The sessions begin on the date of the base session and continue until the \'repeat until\' date. @@ -88,6 +92,8 @@ $string['days'] = 'Days'; $string['defaults'] = 'Defaults'; $string['defaultdisplaymode'] = 'Default display mode'; $string['delete'] = 'Delete'; +$string['deletecalevents'] = 'Delete calendar events'; +$string['deletecheckcalevents'] = 'Are you absolutely sure you want to delete the calendar events for the following sessions?'; $string['deletelogs'] = 'Delete attendance data'; $string['deleteselected'] = 'Delete selected'; $string['deletesession'] = 'Delete session'; diff --git a/lib.php b/lib.php index dad7d2f..f484a6f 100644 --- a/lib.php +++ b/lib.php @@ -22,6 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +require_once(dirname(__FILE__) . '/classes/calendar_helpers.php'); + /** * Returns the information if the module supports a feature * @@ -102,6 +104,9 @@ function attendance_delete_instance($id) { } if ($sessids = array_keys($DB->get_records('attendance_sessions', array('attendanceid' => $id), '', 'id'))) { + if (existing_calendar_events_ids($sessids)) { + delete_calendar_events($sessids); + } $DB->delete_records_list('attendance_log', 'sessionid', $sessids); $DB->delete_records('attendance_sessions', array('attendanceid' => $id)); } @@ -119,6 +124,9 @@ function attendance_delete_course($course, $feedback=true) { $attids = array_keys($DB->get_records('attendance', array('course' => $course->id), '', 'id')); $sessids = array_keys($DB->get_records_list('attendance_sessions', 'attendanceid', $attids, '', 'id')); + if (existing_calendar_events_ids($sessids)) { + delete_calendar_events($sessids); + } if ($sessids) { $DB->delete_records_list('attendance_log', 'sessionid', $sessids); } @@ -194,6 +202,10 @@ function attendance_reset_userdata($data) { } if (!empty($data->reset_attendance_sessions)) { + $sessionsids = array_keys($DB->get_records_list('attendance_sessions', 'attendanceid', $attids, '', 'id')); + if (existing_calendar_events_ids($sessionsids)) { + delete_calendar_events($sessionsids); + } $DB->delete_records_list('attendance_sessions', 'attendanceid', $attids); $status[] = array( diff --git a/renderer.php b/renderer.php index ec70c5d..ba328f1 100644 --- a/renderer.php +++ b/renderer.php @@ -320,7 +320,9 @@ class mod_attendance_renderer extends plugin_renderer_base { } $options = array(mod_attendance_sessions_page_params::ACTION_DELETE_SELECTED => get_string('delete'), - mod_attendance_sessions_page_params::ACTION_CHANGE_DURATION => get_string('changeduration', 'attendance')); + mod_attendance_sessions_page_params::ACTION_CHANGE_DURATION => get_string('changeduration', 'attendance'), + mod_attendance_sessions_page_params::ACTION_CREATE_CAL_EVENTS => get_string('createcalevents', 'attendance'), + mod_attendance_sessions_page_params::ACTION_DELETE_CAL_EVENTS => get_string('deletecalevents', 'attendance')); $controls = html_writer::select($options, 'action'); $attributes = array( diff --git a/sessions.php b/sessions.php index f879a1a..0ffba45 100644 --- a/sessions.php +++ b/sessions.php @@ -133,15 +133,25 @@ switch ($att->pageparams->action) { echo $OUTPUT->footer(); exit; case mod_attendance_sessions_page_params::ACTION_DELETE_SELECTED: + case mod_attendance_sessions_page_params::ACTION_CREATE_CAL_EVENTS: + case mod_attendance_sessions_page_params::ACTION_DELETE_CAL_EVENTS: $confirm = optional_param('confirm', null, PARAM_INT); + $message = get_string('deletecheckfull', '', get_string('session', 'attendance')); if (isset($confirm) && confirm_sesskey()) { $sessionsids = required_param('sessionsids', PARAM_ALPHANUMEXT); $sessionsids = explode('_', $sessionsids); - - $att->delete_sessions($sessionsids); - attendance_update_users_grade($att); - redirect($att->url_manage(), get_string('sessiondeleted', 'attendance')); + if ($att->pageparams->action == mod_attendance_sessions_page_params::ACTION_DELETE_SELECTED) { + $att->delete_sessions($sessionsids); + attendance_update_users_grade($att); + redirect($att->url_manage(), get_string('sessiondeleted', 'attendance')); + } else if ($att->pageparams->action == mod_attendance_sessions_page_params::ACTION_CREATE_CAL_EVENTS) { + create_calendar_events($sessionsids); + redirect($att->url_manage(), get_string('createcheckcalevents', 'attendance')); + } else if ($att->pageparams->action == mod_attendance_sessions_page_params::ACTION_DELETE_CAL_EVENTS) { + delete_calendar_events($sessionsids); + redirect($att->url_manage(), get_string('deletecheckcalevents', 'attendance')); + } } $sessid = optional_param_array('sessid', '', PARAM_SEQUENCE); if (empty($sessid)) { @@ -149,7 +159,12 @@ switch ($att->pageparams->action) { } $sessionsinfo = $att->get_sessions_info($sessid); - $message = get_string('deletecheckfull', '', get_string('session', 'attendance')); + if ($att->pageparams->action == mod_attendance_sessions_page_params::ACTION_CREATE_CAL_EVENTS) { + $message = get_string('createcheckcalevents', 'attendance'); + } else if ($att->pageparams->action == mod_attendance_sessions_page_params::ACTION_DELETE_CAL_EVENTS) { + $message = get_string('deletecheckcalevents', 'attendance'); + } + $message .= html_writer::empty_tag('br'); foreach ($sessionsinfo as $sessinfo) { $message .= html_writer::empty_tag('br'); diff --git a/tests/behat/calendar_features.feature b/tests/behat/calendar_features.feature new file mode 100644 index 0000000..fe3b2cf --- /dev/null +++ b/tests/behat/calendar_features.feature @@ -0,0 +1,81 @@ +@mod @mod_attendance @javascript +Feature: Test the calendar related features in the attendance module + + Background: + Given the following "courses" exist: + | fullname | shortname | + | Course 1 | C1 | + And the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | Teacher | 1 | teacher1@example.com | + | student1 | Student | 1 | student1@example.com | + And the following "course enrolments" exist: + | course | user | role | + | C1 | teacher1 | editingteacher | + | C1 | student1 | student | + And I log in as "teacher1" + And I follow "Course 1" + And I turn editing mode on + And I add a "Attendance" to section "1" and I fill the form with: + | Name | Test attendance | + And I log out + + Scenario: Calendar events can be created automatically with sessions creation + When I log in as "teacher1" + And I follow "Course 1" + And I follow "Test attendance" + And I follow "Add session" + And I set the following fields to these values: + | id_sestime_starthour | 01 | + | id_sestime_endhour | 02 | + And I click on "id_submitbutton" "button" + And I follow "Course 1" + And I follow "Go to calendar" + Then I should see "Test attendance" + And I log out + And I log in as "student1" + And I follow "Go to calendar" + Then I should see "Test attendance" + + Scenario: Teacher can delete and create calendar events for sessions + When I log in as "teacher1" + And I follow "Course 1" + And I follow "Test attendance" + And I follow "Add session" + And I set the following fields to these values: + | id_sestime_starthour | 01 | + | id_sestime_endhour | 02 | + And I click on "id_submitbutton" "button" + And I set the following fields to these values: + | cb_selector | 1 | + | menuaction | Delete calendar events | + And I click on "OK" "button" + And I click on "Continue" "button" + And I follow "Course 1" + And I follow "Go to calendar" + Then I should not see "Test attendance" + And I log out + And I log in as "student1" + And I follow "Go to calendar" + Then I should not see "Test attendance" + And I log out + And I log in as "teacher1" + And I follow "Course 1" + And I follow "Test attendance" + And I follow "Add session" + And I set the following fields to these values: + | id_sestime_starthour | 01 | + | id_sestime_endhour | 02 | + And I click on "id_submitbutton" "button" + And I set the following fields to these values: + | cb_selector | 1 | + | menuaction | Create calendar events | + And I click on "OK" "button" + And I click on "Continue" "button" + And I follow "Course 1" + And I follow "Go to calendar" + Then I should see "Test attendance" + And I log out + And I log in as "student1" + And I follow "Go to calendar" + Then I should see "Test attendance" \ No newline at end of file diff --git a/version.php b/version.php index baff4bf..4ed5a32 100644 --- a/version.php +++ b/version.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$plugin->version = 2016052201; +$plugin->version = 2016052202; $plugin->requires = 2016052300; $plugin->release = '3.1.1.0'; $plugin->maturity = MATURITY_STABLE;