Implement data privacy provider.
[moodle-mod_attendance.git] / lib.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 * Library of functions and constants for module attendance
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__) . '/classes/calendar_helpers.php');
27
28 /**
29 * Returns the information if the module supports a feature
30 *
31 * @see plugin_supports() in lib/moodlelib.php
32 * @param string $feature FEATURE_xx constant for requested feature
33 * @return mixed true if the feature is supported, null if unknown
34 */
35 function attendance_supports($feature) {
36 switch($feature) {
37 case FEATURE_GRADE_HAS_GRADE:
38 return true;
39 case FEATURE_GROUPS:
40 return true;
41 case FEATURE_GROUPINGS:
42 return true;
43 case FEATURE_MOD_INTRO:
44 return true;
45 case FEATURE_BACKUP_MOODLE2:
46 return true;
47 // Artem Andreev: AFAIK it's not tested.
48 case FEATURE_COMPLETION_TRACKS_VIEWS:
49 return false;
50 default:
51 return null;
52 }
53 }
54
55 /**
56 * Add default set of statuses to the new attendance.
57 *
58 * @param int $attid - id of attendance instance.
59 */
60 function att_add_default_statuses($attid) {
61 global $DB;
62
63 $statuses = $DB->get_recordset('attendance_statuses', array('attendanceid' => 0), 'id');
64 foreach ($statuses as $st) {
65 $rec = $st;
66 $rec->attendanceid = $attid;
67 $DB->insert_record('attendance_statuses', $rec);
68 }
69 $statuses->close();
70 }
71
72 /**
73 * Add default set of warnings to the new attendance.
74 *
75 * @param int $id - id of attendance instance.
76 */
77 function attendance_add_default_warnings($id) {
78 global $DB, $CFG;
79 require_once($CFG->dirroot.'/mod/attendance/locallib.php');
80
81 $warnings = $DB->get_recordset('attendance_warning',
82 array('idnumber' => 0), 'id');
83 foreach ($warnings as $n) {
84 $rec = $n;
85 $rec->idnumber = $id;
86 $DB->insert_record('attendance_warning', $rec);
87 }
88 $warnings->close();
89 }
90
91 /**
92 * Add new attendance instance.
93 *
94 * @param stdClass $attendance
95 * @return bool|int
96 */
97 function attendance_add_instance($attendance) {
98 global $DB;
99
100 $attendance->timemodified = time();
101
102 $attendance->id = $DB->insert_record('attendance', $attendance);
103
104 att_add_default_statuses($attendance->id);
105
106 attendance_add_default_warnings($attendance->id);
107
108 attendance_grade_item_update($attendance);
109
110 return $attendance->id;
111 }
112
113 /**
114 * Update existing attendance instance.
115 *
116 * @param stdClass $attendance
117 * @return bool
118 */
119 function attendance_update_instance($attendance) {
120 global $DB;
121
122 $attendance->timemodified = time();
123 $attendance->id = $attendance->instance;
124
125 if (! $DB->update_record('attendance', $attendance)) {
126 return false;
127 }
128
129 attendance_grade_item_update($attendance);
130
131 return true;
132 }
133
134 /**
135 * Delete existing attendance
136 *
137 * @param int $id
138 * @return bool
139 */
140 function attendance_delete_instance($id) {
141 global $DB, $CFG;
142 require_once($CFG->dirroot.'/mod/attendance/locallib.php');
143
144 if (! $attendance = $DB->get_record('attendance', array('id' => $id))) {
145 return false;
146 }
147
148 if ($sessids = array_keys($DB->get_records('attendance_sessions', array('attendanceid' => $id), '', 'id'))) {
149 if (attendance_existing_calendar_events_ids($sessids)) {
150 attendance_delete_calendar_events($sessids);
151 }
152 $DB->delete_records_list('attendance_log', 'sessionid', $sessids);
153 $DB->delete_records('attendance_sessions', array('attendanceid' => $id));
154 }
155 $DB->delete_records('attendance_statuses', array('attendanceid' => $id));
156
157 $DB->delete_records('attendance_warning', array('idnumber' => $id));
158
159 $DB->delete_records('attendance', array('id' => $id));
160
161 attendance_grade_item_delete($attendance);
162
163 return true;
164 }
165
166 /**
167 * Called by course/reset.php
168 * @param moodleform $mform form passed by reference
169 */
170 function attendance_reset_course_form_definition(&$mform) {
171 $mform->addElement('header', 'attendanceheader', get_string('modulename', 'attendance'));
172
173 $mform->addElement('static', 'description', get_string('description', 'attendance'),
174 get_string('resetdescription', 'attendance'));
175 $mform->addElement('checkbox', 'reset_attendance_log', get_string('deletelogs', 'attendance'));
176
177 $mform->addElement('checkbox', 'reset_attendance_sessions', get_string('deletesessions', 'attendance'));
178 $mform->disabledIf('reset_attendance_sessions', 'reset_attendance_log', 'notchecked');
179
180 $mform->addElement('checkbox', 'reset_attendance_statuses', get_string('resetstatuses', 'attendance'));
181 $mform->setAdvanced('reset_attendance_statuses');
182 $mform->disabledIf('reset_attendance_statuses', 'reset_attendance_log', 'notchecked');
183 }
184
185 /**
186 * Course reset form defaults.
187 *
188 * @param stdClass $course
189 * @return array
190 */
191 function attendance_reset_course_form_defaults($course) {
192 return array('reset_attendance_log' => 0, 'reset_attendance_statuses' => 0, 'reset_attendance_sessions' => 0);
193 }
194
195 /**
196 * Reset user data within attendance.
197 *
198 * @param stdClass $data
199 * @return array
200 */
201 function attendance_reset_userdata($data) {
202 global $DB;
203
204 $status = array();
205
206 $attids = array_keys($DB->get_records('attendance', array('course' => $data->courseid), '', 'id'));
207
208 if (!empty($data->reset_attendance_log)) {
209 $sess = $DB->get_records_list('attendance_sessions', 'attendanceid', $attids, '', 'id');
210 if (!empty($sess)) {
211 list($sql, $params) = $DB->get_in_or_equal(array_keys($sess));
212 $DB->delete_records_select('attendance_log', "sessionid $sql", $params);
213 list($sql, $params) = $DB->get_in_or_equal($attids);
214 $DB->set_field_select('attendance_sessions', 'lasttaken', 0, "attendanceid $sql", $params);
215 if (empty($data->reset_attendance_sessions)) {
216 // If sessions are being retained, clear automarkcompleted value.
217 $DB->set_field_select('attendance_sessions', 'automarkcompleted', 0, "attendanceid $sql", $params);
218 }
219
220 $status[] = array(
221 'component' => get_string('modulenameplural', 'attendance'),
222 'item' => get_string('attendancedata', 'attendance'),
223 'error' => false
224 );
225 }
226 }
227
228 if (!empty($data->reset_attendance_statuses)) {
229 $DB->delete_records_list('attendance_statuses', 'attendanceid', $attids);
230 foreach ($attids as $attid) {
231 att_add_default_statuses($attid);
232 }
233
234 $status[] = array(
235 'component' => get_string('modulenameplural', 'attendance'),
236 'item' => get_string('sessions', 'attendance'),
237 'error' => false
238 );
239 }
240
241 if (!empty($data->reset_attendance_sessions)) {
242 $sessionsids = array_keys($DB->get_records_list('attendance_sessions', 'attendanceid', $attids, '', 'id'));
243 if (attendance_existing_calendar_events_ids($sessionsids)) {
244 attendance_delete_calendar_events($sessionsids);
245 }
246 $DB->delete_records_list('attendance_sessions', 'attendanceid', $attids);
247
248 $status[] = array(
249 'component' => get_string('modulenameplural', 'attendance'),
250 'item' => get_string('statuses', 'attendance'),
251 'error' => false
252 );
253 }
254
255 return $status;
256 }
257 /**
258 * Return a small object with summary information about what a
259 * user has done with a given particular instance of this module
260 * Used for user activity reports.
261 * $return->time = the time they did it
262 * $return->info = a short text description
263 *
264 * @param stdClass $course - full course record.
265 * @param stdClass $user - full user record
266 * @param stdClass $mod
267 * @param stdClass $attendance
268 * @return stdClass.
269 */
270 function attendance_user_outline($course, $user, $mod, $attendance) {
271 global $CFG;
272 require_once(dirname(__FILE__).'/locallib.php');
273 require_once($CFG->libdir.'/gradelib.php');
274
275 $grades = grade_get_grades($course->id, 'mod', 'attendance', $attendance->id, $user->id);
276
277 $result = new stdClass();
278 if (!empty($grades->items[0]->grades)) {
279 $grade = reset($grades->items[0]->grades);
280 $result->time = $grade->dategraded;
281 } else {
282 $result->time = 0;
283 }
284 if (has_capability('mod/attendance:canbelisted', $mod->context, $user->id)) {
285 $summary = new mod_attendance_summary($attendance->id, $user->id);
286 $usersummary = $summary->get_all_sessions_summary_for($user->id);
287
288 $result->info = format_float($usersummary->takensessionspoints, 1, true, true) . ' / ' .
289 format_float($usersummary->allsessionsmaxpoints, 1, true, true);
290 }
291
292 return $result;
293 }
294 /**
295 * Print a detailed representation of what a user has done with
296 * a given particular instance of this module, for user activity reports.
297 *
298 * @param stdClass $course
299 * @param stdClass $user
300 * @param stdClass $mod
301 * @param stdClass $attendance
302 */
303 function attendance_user_complete($course, $user, $mod, $attendance) {
304 global $CFG;
305
306 require_once(dirname(__FILE__).'/renderhelpers.php');
307 require_once($CFG->libdir.'/gradelib.php');
308
309 if (has_capability('mod/attendance:canbelisted', $mod->context, $user->id)) {
310 echo construct_full_user_stat_html_table($attendance, $user);
311 }
312 }
313
314 /**
315 * Dummy function - must exist to allow quick editing of module name.
316 *
317 * @param stdClass $attendance
318 * @param int $userid
319 * @param bool $nullifnone
320 */
321 function attendance_update_grades($attendance, $userid=0, $nullifnone=true) {
322 // We need this function to exist so that quick editing of module name is passed to gradebook.
323 }
324 /**
325 * Create grade item for given attendance
326 *
327 * @param stdClass $attendance object with extra cmidnumber
328 * @param mixed $grades optional array/object of grade(s); 'reset' means reset grades in gradebook
329 * @return int 0 if ok, error code otherwise
330 */
331 function attendance_grade_item_update($attendance, $grades=null) {
332 global $CFG, $DB;
333
334 require_once('locallib.php');
335
336 if (!function_exists('grade_update')) { // Workaround for buggy PHP versions.
337 require_once($CFG->libdir.'/gradelib.php');
338 }
339
340 if (!isset($attendance->courseid)) {
341 $attendance->courseid = $attendance->course;
342 }
343 if (!$DB->get_record('course', array('id' => $attendance->course))) {
344 error("Course is misconfigured");
345 }
346
347 if (!empty($attendance->cmidnumber)) {
348 $params = array('itemname' => $attendance->name, 'idnumber' => $attendance->cmidnumber);
349 } else {
350 // MDL-14303.
351 $params = array('itemname' => $attendance->name);
352 }
353
354 if ($attendance->grade > 0) {
355 $params['gradetype'] = GRADE_TYPE_VALUE;
356 $params['grademax'] = $attendance->grade;
357 $params['grademin'] = 0;
358 } else if ($attendance->grade < 0) {
359 $params['gradetype'] = GRADE_TYPE_SCALE;
360 $params['scaleid'] = -$attendance->grade;
361
362 } else {
363 $params['gradetype'] = GRADE_TYPE_NONE;
364 }
365
366 if ($grades === 'reset') {
367 $params['reset'] = true;
368 $grades = null;
369 }
370
371 return grade_update('mod/attendance', $attendance->courseid, 'mod', 'attendance', $attendance->id, 0, $grades, $params);
372 }
373
374 /**
375 * Delete grade item for given attendance
376 *
377 * @param object $attendance object
378 * @return object attendance
379 */
380 function attendance_grade_item_delete($attendance) {
381 global $CFG;
382 require_once($CFG->libdir.'/gradelib.php');
383
384 if (!isset($attendance->courseid)) {
385 $attendance->courseid = $attendance->course;
386 }
387
388 return grade_update('mod/attendance', $attendance->courseid, 'mod', 'attendance',
389 $attendance->id, 0, null, array('deleted' => 1));
390 }
391
392 /**
393 * This function returns if a scale is being used by one attendance
394 * it it has support for grading and scales. Commented code should be
395 * modified if necessary. See book, glossary or journal modules
396 * as reference.
397 *
398 * @param int $attendanceid
399 * @param int $scaleid
400 * @return boolean True if the scale is used by any attendance
401 */
402 function attendance_scale_used ($attendanceid, $scaleid) {
403 return false;
404 }
405
406 /**
407 * Checks if scale is being used by any instance of attendance
408 *
409 * This is used to find out if scale used anywhere
410 *
411 * @param int $scaleid
412 * @return bool true if the scale is used by any book
413 */
414 function attendance_scale_used_anywhere($scaleid) {
415 return false;
416 }
417
418 /**
419 * Serves the attendance sessions descriptions files.
420 *
421 * @param object $course
422 * @param object $cm
423 * @param object $context
424 * @param string $filearea
425 * @param array $args
426 * @param bool $forcedownload
427 * @return bool false if file not found, does not return if found - justsend the file
428 */
429 function attendance_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
430 global $DB;
431
432 if ($context->contextlevel != CONTEXT_MODULE) {
433 return false;
434 }
435
436 require_login($course, false, $cm);
437
438 if (!$DB->record_exists('attendance', array('id' => $cm->instance))) {
439 return false;
440 }
441
442 // Session area is served by pluginfile.php.
443 $fileareas = array('session');
444 if (!in_array($filearea, $fileareas)) {
445 return false;
446 }
447
448 $sessid = (int)array_shift($args);
449 if (!$DB->record_exists('attendance_sessions', array('id' => $sessid))) {
450 return false;
451 }
452
453 $fs = get_file_storage();
454 $relativepath = implode('/', $args);
455 $fullpath = "/$context->id/mod_attendance/$filearea/$sessid/$relativepath";
456 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
457 return false;
458 }
459 send_stored_file($file, 0, 0, true);
460 }
461
462 /**
463 * Print tabs on attendance settings page.
464 *
465 * @param string $selected - current selected tab.
466 */
467 function attendance_print_settings_tabs($selected = 'settings') {
468 global $CFG;
469 // Print tabs for different settings pages.
470 $tabs = array();
471 $tabs[] = new tabobject('settings', $CFG->wwwroot.'/admin/settings.php?section=modsettingattendance',
472 get_string('settings', 'attendance'), get_string('settings'), false);
473
474 $tabs[] = new tabobject('defaultstatus', $CFG->wwwroot.'/mod/attendance/defaultstatus.php',
475 get_string('defaultstatus', 'attendance'), get_string('defaultstatus', 'attendance'), false);
476
477 if (get_config('attendance', 'enablewarnings')) {
478 $tabs[] = new tabobject('defaultwarnings', $CFG->wwwroot . '/mod/attendance/warnings.php',
479 get_string('defaultwarnings', 'attendance'), get_string('defaultwarnings', 'attendance'), false);
480 }
481
482 $tabs[] = new tabobject('coursesummary', $CFG->wwwroot.'/mod/attendance/coursesummary.php',
483 get_string('coursesummary', 'attendance'), get_string('coursesummary', 'attendance'), false);
484
485 if (get_config('attendance', 'enablewarnings')) {
486 $tabs[] = new tabobject('absentee', $CFG->wwwroot . '/mod/attendance/absentee.php',
487 get_string('absenteereport', 'attendance'), get_string('absenteereport', 'attendance'), false);
488 }
489
490 $tabs[] = new tabobject('resetcalendar', $CFG->wwwroot.'/mod/attendance/resetcalendar.php',
491 get_string('resetcalendar', 'attendance'), get_string('resetcalendar', 'attendance'), false);
492
493 $tabs[] = new tabobject('importsessions', $CFG->wwwroot . '/mod/attendance/import/sessions.php',
494 get_string('importsessions', 'attendance'), get_string('importsessions', 'attendance'), false);
495
496 ob_start();
497 print_tabs(array($tabs), $selected);
498 $tabmenu = ob_get_contents();
499 ob_end_clean();
500
501 return $tabmenu;
502 }