Feature: Prevent students from sharing device while self-marking.
[moodle-mod_attendance.git] / db / upgrade.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17 /**
18 * upgrade processes for this module.
19 *
20 * @package mod_attendance
21 * @copyright 2011 Artem Andreev <andreev.artem@gmail.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25 defined('MOODLE_INTERNAL') || die();
26 require_once(dirname(__FILE__) . '/upgradelib.php');
27
28 /**
29 * upgrade this attendance instance - this function could be skipped but it will be needed later
30 * @param int $oldversion The old version of the attendance module
31 * @return bool
32 */
33 function xmldb_attendance_upgrade($oldversion=0) {
34
35 global $DB;
36 $dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes.
37
38 $result = true;
39
40 if ($oldversion < 2014112000) {
41 $table = new xmldb_table('attendance_sessions');
42
43 $field = new xmldb_field('studentscanmark');
44 $field->set_attributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
45 if (!$dbman->field_exists($table, $field)) {
46 $dbman->add_field($table, $field);
47 }
48
49 upgrade_mod_savepoint(true, 2014112000, 'attendance');
50 }
51
52 if ($oldversion < 2014112001) {
53 // Replace values that reference old module "attforblock" to "attendance".
54 $sql = "UPDATE {grade_items}
55 SET itemmodule = 'attendance'
56 WHERE itemmodule = 'attforblock'";
57
58 $DB->execute($sql);
59
60 $sql = "UPDATE {grade_items_history}
61 SET itemmodule = 'attendance'
62 WHERE itemmodule = 'attforblock'";
63
64 $DB->execute($sql);
65
66 /*
67 * The user's custom capabilities need to be preserved due to the module renaming.
68 * Capabilities with a modifierid = 0 value are installed by default.
69 * Only update the user's custom capabilities where modifierid is not zero.
70 */
71 $sql = $DB->sql_like('capability', '?').' AND modifierid <> 0';
72 $rs = $DB->get_recordset_select('role_capabilities', $sql, array('%mod/attforblock%'));
73 foreach ($rs as $cap) {
74 $renamedcapability = str_replace('mod/attforblock', 'mod/attendance', $cap->capability);
75 $exists = $DB->record_exists('role_capabilities', array('roleid' => $cap->roleid, 'capability' => $renamedcapability));
76 if (!$exists) {
77 $DB->update_record('role_capabilities', array('id' => $cap->id, 'capability' => $renamedcapability));
78 }
79 }
80
81 // Delete old role capabilities.
82 $sql = $DB->sql_like('capability', '?');
83 $DB->delete_records_select('role_capabilities', $sql, array('%mod/attforblock%'));
84
85 // Delete old capabilities.
86 $DB->delete_records_select('capabilities', 'component = ?', array('mod_attforblock'));
87
88 upgrade_mod_savepoint(true, 2014112001, 'attendance');
89 }
90
91 if ($oldversion < 2015040501) {
92 // Define table attendance_tempusers to be created.
93 $table = new xmldb_table('attendance_tempusers');
94
95 // Adding fields to table attendance_tempusers.
96 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
97 $table->add_field('studentid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
98 $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
99 $table->add_field('fullname', XMLDB_TYPE_CHAR, '100', null, null, null, null);
100 $table->add_field('email', XMLDB_TYPE_CHAR, '100', null, null, null, null);
101 $table->add_field('created', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
102
103 // Adding keys to table attendance_tempusers.
104 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
105
106 // Conditionally launch create table for attendance_tempusers.
107 if (!$dbman->table_exists($table)) {
108 $dbman->create_table($table);
109 }
110
111 // Conditionally launch add index courseid.
112 $index = new xmldb_index('courseid', XMLDB_INDEX_NOTUNIQUE, array('courseid'));
113 if (!$dbman->index_exists($table, $index)) {
114 $dbman->add_index($table, $index);
115 }
116
117 // Conditionally launch add index studentid.
118 $index = new xmldb_index('studentid', XMLDB_INDEX_UNIQUE, array('studentid'));
119 if (!$dbman->index_exists($table, $index)) {
120 $dbman->add_index($table, $index);
121 }
122
123 // Attendance savepoint reached.
124 upgrade_mod_savepoint(true, 2015040501, 'attendance');
125 }
126
127 if ($oldversion < 2015040502) {
128
129 // Define field setnumber to be added to attendance_statuses.
130 $table = new xmldb_table('attendance_statuses');
131 $field = new xmldb_field('setnumber', XMLDB_TYPE_INTEGER, '5', null, XMLDB_NOTNULL, null, '0', 'deleted');
132
133 // Conditionally launch add field setnumber.
134 if (!$dbman->field_exists($table, $field)) {
135 $dbman->add_field($table, $field);
136 }
137
138 // Define field statusset to be added to attendance_sessions.
139 $table = new xmldb_table('attendance_sessions');
140 $field = new xmldb_field('statusset', XMLDB_TYPE_INTEGER, '5', null, XMLDB_NOTNULL, null, '0', 'descriptionformat');
141
142 // Conditionally launch add field statusset.
143 if (!$dbman->field_exists($table, $field)) {
144 $dbman->add_field($table, $field);
145 }
146
147 // Attendance savepoint reached.
148 upgrade_mod_savepoint(true, 2015040502, 'attendance');
149 }
150
151 if ($oldversion < 2015040503) {
152
153 // Changing type of field grade on table attendance_statuses to number.
154 $table = new xmldb_table('attendance_statuses');
155 $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '5, 2', null, XMLDB_NOTNULL, null, '0', 'description');
156
157 // Launch change of type for field grade.
158 $dbman->change_field_type($table, $field);
159
160 // Attendance savepoint reached.
161 upgrade_mod_savepoint(true, 2015040503, 'attendance');
162 }
163
164 if ($oldversion < 2016052202) {
165 // Adding field to store calendar event ids.
166 $table = new xmldb_table('attendance_sessions');
167 $field = new xmldb_field('caleventid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', null);
168
169 // Conditionally launch add field statusset.
170 if (!$dbman->field_exists($table, $field)) {
171 $dbman->add_field($table, $field);
172 }
173
174 // Creating events for all existing sessions.
175 attendance_upgrade_create_calendar_events();
176
177 // Attendance savepoint reached.
178 upgrade_mod_savepoint(true, 2016052202, 'attendance');
179 }
180
181 if ($oldversion < 2016082900) {
182
183 // Define field timemodified to be added to attendance.
184 $table = new xmldb_table('attendance');
185 $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'grade');
186
187 // Conditionally launch add field timemodified.
188 if (!$dbman->field_exists($table, $field)) {
189 $dbman->add_field($table, $field);
190 }
191
192 // Attendance savepoint reached.
193 upgrade_mod_savepoint(true, 2016082900, 'attendance');
194 }
195 if ($oldversion < 2016112100) {
196 $table = new xmldb_table('attendance');
197 $newfield = $table->add_field('subnet', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'timemodified');
198 if (!$dbman->field_exists($table, $newfield)) {
199 $dbman->add_field($table, $newfield);
200 }
201 upgrade_mod_savepoint(true, 2016112100, 'attendance');
202 }
203
204 if ($oldversion < 2016121300) {
205 $table = new xmldb_table('attendance');
206 $field = new xmldb_field('sessiondetailspos', XMLDB_TYPE_CHAR, '5', null, null, null, 'left', 'subnet');
207 if (!$dbman->field_exists($table, $field)) {
208 $dbman->add_field($table, $field);
209 }
210 $field = new xmldb_field('showsessiondetails', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1', 'subnet');
211 if (!$dbman->field_exists($table, $field)) {
212 $dbman->add_field($table, $field);
213 }
214 upgrade_mod_savepoint(true, 2016121300, 'attendance');
215 }
216
217 if ($oldversion < 2017020700) {
218 // Define field timemodified to be added to attendance.
219 $table = new xmldb_table('attendance');
220
221 $fields = [];
222 $fields[] = new xmldb_field('intro', XMLDB_TYPE_TEXT, null, null, null, null, null, 'timemodified');
223 $fields[] = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, 0, 'intro');
224
225 // Conditionally launch add field.
226 foreach ($fields as $field) {
227 if (!$dbman->field_exists($table, $field)) {
228 $dbman->add_field($table, $field);
229 }
230 }
231
232 // Attendance savepoint reached.
233 upgrade_mod_savepoint(true, 2017020700, 'attendance');
234 }
235
236 if ($oldversion < 2017042800) {
237 $table = new xmldb_table('attendance_sessions');
238
239 $field = new xmldb_field('studentpassword');
240 $field->set_attributes(XMLDB_TYPE_CHAR, '50', null, false, null, '', 'studentscanmark');
241 if (!$dbman->field_exists($table, $field)) {
242 $dbman->add_field($table, $field);
243 }
244
245 upgrade_mod_savepoint(true, 2017042800, 'attendance');
246 }
247
248 if ($oldversion < 2017051101) {
249
250 // Define field studentavailability to be added to attendance_statuses.
251 $table = new xmldb_table('attendance_statuses');
252 $field = new xmldb_field('studentavailability', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'grade');
253
254 // Conditionally launch add field studentavailability.
255 if (!$dbman->field_exists($table, $field)) {
256 $dbman->add_field($table, $field);
257 }
258
259 // Attendance savepoint reached.
260 upgrade_mod_savepoint(true, 2017051101, 'attendance');
261 }
262
263 if ($oldversion < 2017051103) {
264 $table = new xmldb_table('attendance_sessions');
265 $newfield = $table->add_field('subnet', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'studentpassword');
266 if (!$dbman->field_exists($table, $newfield)) {
267 $dbman->add_field($table, $newfield);
268 }
269 upgrade_mod_savepoint(true, 2017051103, 'attendance');
270 }
271
272 if ($oldversion < 2017051104) {
273 // The meaning of the subnet in the attendance table has changed - it is now the "default" value - find all existing
274 // Attendance with subnet set and set the session subnet for these.
275 $attendances = $DB->get_recordset_select('attendance', 'subnet IS NOT NULL');
276 foreach ($attendances as $attendance) {
277 if (!empty($attendance->subnet)) {
278 // Get all sessions for this attendance.
279 $sessions = $DB->get_recordset('attendance_sessions', array('attendanceid' => $attendance->id));
280 foreach ($sessions as $session) {
281 $session->subnet = $attendance->subnet;
282 $DB->update_record('attendance_sessions', $session);
283 }
284 $sessions->close();
285 }
286 }
287 $attendances->close();
288
289 upgrade_mod_savepoint(true, 2017051104, 'attendance');
290 }
291
292 if ($oldversion < 2017051900) {
293 // Define field setunmarked to be added to attendance_statuses.
294 $table = new xmldb_table('attendance_statuses');
295 $field = new xmldb_field('setunmarked', XMLDB_TYPE_INTEGER, '2', null, null, null, null, 'studentavailability');
296
297 // Conditionally launch add field studentavailability.
298 if (!$dbman->field_exists($table, $field)) {
299 $dbman->add_field($table, $field);
300 }
301
302 // Attendance savepoint reached.
303 upgrade_mod_savepoint(true, 2017051900, 'attendance');
304 }
305
306 if ($oldversion < 2017052201) {
307 // Define field setunmarked to be added to attendance_statuses.
308 $table = new xmldb_table('attendance_sessions');
309 $field = new xmldb_field('automark', XMLDB_TYPE_INTEGER, '1', null, true, null, '0', 'subnet');
310
311 // Conditionally launch add field automark.
312 if (!$dbman->field_exists($table, $field)) {
313 $dbman->add_field($table, $field);
314 }
315
316 $field = new xmldb_field('automarkcompleted', XMLDB_TYPE_INTEGER, '1', null, true, null, '0', 'automark');
317
318 // Conditionally launch add field automarkcompleted.
319 if (!$dbman->field_exists($table, $field)) {
320 $dbman->add_field($table, $field);
321 }
322
323 // Attendance savepoint reached.
324 upgrade_mod_savepoint(true, 2017052201, 'attendance');
325 }
326
327 if ($oldversion < 2017060900) {
328 // Automark values changed.
329 $default = get_config('attendance', 'automark_default');
330 if (!empty($default)) { // Change default if set.
331 set_config('automark_default', 2, 'attendance');
332 }
333 // Update any sessions set to use automark = 1.
334 $sql = "UPDATE {attendance_sessions} SET automark = 2 WHERE automark = 1";
335 $DB->execute($sql);
336
337 // Update automarkcompleted to 2 if already complete.
338 $sql = "UPDATE {attendance_sessions} SET automarkcompleted = 2 WHERE automarkcompleted = 1";
339 $DB->execute($sql);
340
341 upgrade_mod_savepoint(true, 2017060900, 'attendance');
342 }
343
344 if ($oldversion < 2017062000) {
345
346 // Define table attendance_warning_done to be created.
347 $table = new xmldb_table('attendance_warning_done');
348
349 // Adding fields to table attendance_warning_done.
350 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
351 $table->add_field('notifyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
352 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
353 $table->add_field('timesent', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
354
355 // Adding keys to table attendance_warning_done.
356 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
357
358 // Adding indexes to table attendance_warning_done.
359 $table->add_index('notifyid_userid', XMLDB_INDEX_UNIQUE, array('notifyid', 'userid'));
360
361 // Conditionally launch create table for attendance_warning_done.
362 if (!$dbman->table_exists($table)) {
363 $dbman->create_table($table);
364 }
365
366 // Attendance savepoint reached.
367 upgrade_mod_savepoint(true, 2017062000, 'attendance');
368 }
369
370 if ($oldversion < 2017071305) {
371
372 // Define table attendance_warning to be created.
373 $table = new xmldb_table('attendance_warning');
374
375 if (!$dbman->table_exists($table)) {
376 // Adding fields to table attendance_warning.
377 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
378 $table->add_field('idnumber', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
379 $table->add_field('warningpercent', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
380 $table->add_field('warnafter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
381 $table->add_field('emailuser', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null);
382 $table->add_field('emailsubject', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
383 $table->add_field('emailcontent', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
384 $table->add_field('emailcontentformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null);
385 $table->add_field('thirdpartyemails', XMLDB_TYPE_TEXT, null, null, null, null, null);
386
387 // Adding keys to table attendance_warning.
388 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
389 $table->add_key('level_id', XMLDB_KEY_UNIQUE, array('idnumber, warningpercent, warnafter'));
390
391 // Conditionally launch create table for attendance_warning.
392 $dbman->create_table($table);
393
394 } else {
395 // Key definition is probably incorrect so fix it - drop_key dml function doesn't seem to work.
396 $indexes = $DB->get_indexes('attendance_warning');
397 foreach ($indexes as $name => $index) {
398 if ($DB->get_dbfamily() === 'mysql') {
399 $DB->execute("ALTER TABLE {attendance_warning} DROP INDEX ". $name);
400 } else {
401 $DB->execute("DROP INDEX ". $name);
402 }
403 }
404 $index = new xmldb_key('level_id', XMLDB_KEY_UNIQUE, array('idnumber, warningpercent', 'warnafter'));
405 $dbman->add_key($table, $index);
406 }
407 // Attendance savepoint reached.
408 upgrade_mod_savepoint(true, 2017071305, 'attendance');
409 }
410
411 if ($oldversion < 2017071800) {
412 // Define field setunmarked to be added to attendance_statuses.
413 $table = new xmldb_table('attendance_warning');
414 $field = new xmldb_field('maxwarn', XMLDB_TYPE_INTEGER, '10', null, true, null, '1', 'warnafter');
415
416 // Conditionally launch add field automark.
417 if (!$dbman->field_exists($table, $field)) {
418 $dbman->add_field($table, $field);
419 }
420 // Attendance savepoint reached.
421 upgrade_mod_savepoint(true, 2017071800, 'attendance');
422 }
423
424 if ($oldversion < 2017071802) {
425 // Define field setunmarked to be added to attendance_statuses.
426 $table = new xmldb_table('attendance_warning_done');
427
428 $index = new xmldb_index('notifyid_userid', XMLDB_INDEX_UNIQUE, array('notifyid', 'userid'));
429 $dbman->drop_index($table, $index);
430
431 $index = new xmldb_index('notifyid', XMLDB_INDEX_NOTUNIQUE, array('notifyid', 'userid'));
432 $dbman->add_index($table, $index);
433
434 // Attendance savepoint reached.
435 upgrade_mod_savepoint(true, 2017071802, 'attendance');
436 }
437
438 if ($oldversion < 2017082200) {
439 // Warnings idnumber field should use attendanceid instead of cmid.
440 $sql = "SELECT cm.id, cm.instance
441 FROM {course_modules} cm
442 JOIN {modules} md ON md.id = cm.module AND md.name = 'attendance'";
443 $idnumbers = $DB->get_records_sql_menu($sql);
444 $warnings = $DB->get_recordset('attendance_warning');
445 foreach ($warnings as $warning) {
446 if (!empty($warning->idnumber) && !empty($idnumbers[$warning->idnumber])) {
447 $warning->idnumber = $idnumbers[$warning->idnumber];
448 $DB->update_record("attendance_warning", $warning);
449 }
450 }
451 $warnings->close();
452
453 // Attendance savepoint reached.
454 upgrade_mod_savepoint(true, 2017082200, 'attendance');
455 }
456
457 if ($oldversion < 2017120700) {
458 $table = new xmldb_table('attendance_sessions');
459
460 $field = new xmldb_field('absenteereport');
461 $field->set_attributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1', 'statusset');
462 if (!$dbman->field_exists($table, $field)) {
463 $dbman->add_field($table, $field);
464 }
465
466 upgrade_mod_savepoint(true, 2017120700, 'attendance');
467 }
468
469 if ($oldversion < 2017120801) {
470 $table = new xmldb_table('attendance_sessions');
471
472 $field = new xmldb_field('autoassignstatus');
473 $field->set_attributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'studentscanmark');
474 if (!$dbman->field_exists($table, $field)) {
475 $dbman->add_field($table, $field);
476 }
477
478 upgrade_mod_savepoint(true, 2017120801, 'attendance');
479 }
480
481 if ($oldversion < 2018022204) {
482 $table = new xmldb_table('attendance');
483 $field = new xmldb_field('showextrauserdetails', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED,
484 XMLDB_NOTNULL, null, '1', 'showsessiondetails');
485 if (!$dbman->field_exists($table, $field)) {
486 $dbman->add_field($table, $field);
487 }
488 upgrade_mod_savepoint(true, 2018022204, 'attendance');
489 }
490
491 if ($oldversion < 2018050100) {
492 $table = new xmldb_table('attendance_sessions');
493 $field = new xmldb_field('preventsharedip', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED,
494 XMLDB_NOTNULL, null, '0', 'absenteereport');
495 if (!$dbman->field_exists($table, $field)) {
496 $dbman->add_field($table, $field);
497 }
498 $field = new xmldb_field('preventsharediptime', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
499 null, null, null, 'preventsharedip');
500 if (!$dbman->field_exists($table, $field)) {
501 $dbman->add_field($table, $field);
502 }
503
504 $table = new xmldb_table('attendance_log');
505 $field = new xmldb_field('ipaddress', XMLDB_TYPE_CHAR, '45', null,
506 null, null, '', 'remarks');
507 if (!$dbman->field_exists($table, $field)) {
508 $dbman->add_field($table, $field);
509 }
510
511 upgrade_mod_savepoint(true, 2018050100, 'attendance');
512 }
513
514 return $result;
515 }