MDL-19488 - allow the creation of a "Public" feedback
[moodle.git] / mod / feedback / lib.php
CommitLineData
32be99dc 1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Library of functions and constants for module feedback
20 * includes the main-part of feedback-functions
21 *
22 * @package mod-feedback
23 * @copyright Andreas Grabs
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
27/** Include eventslib.php */
3b120e46 28require_once($CFG->libdir.'/eventslib.php');
9f42276c
SH
29/** Include calendar/lib.php */
30require_once($CFG->dirroot.'/calendar/lib.php');
c70ad9f7 31
c70ad9f7 32define('FEEDBACK_ANONYMOUS_YES', 1);
33define('FEEDBACK_ANONYMOUS_NO', 2);
34define('FEEDBACK_MIN_ANONYMOUS_COUNT_IN_GROUP', 2);
35define('FEEDBACK_DECIMAL', '.');
36define('FEEDBACK_THOUSAND', ',');
37define('FEEDBACK_RESETFORM_RESET', 'feedback_reset_data_');
38define('FEEDBACK_RESETFORM_DROP', 'feedback_drop_feedback_');
39define('FEEDBACK_MAX_PIX_LENGTH', '400'); //max. Breite des grafischen Balkens in der Auswertung
8a23b38c 40define('FEEDBACK_DEFAULT_PAGE_COUNT', 20);
c70ad9f7 41
29081d02 42/**
32be99dc 43 * @uses FEATURE_GROUPS
44 * @uses FEATURE_GROUPINGS
45 * @uses FEATURE_GROUPMEMBERSONLY
46 * @uses FEATURE_MOD_INTRO
47 * @uses FEATURE_COMPLETION_TRACKS_VIEWS
48 * @uses FEATURE_GRADE_HAS_GRADE
49 * @uses FEATURE_GRADE_OUTCOMES
29081d02 50 * @param string $feature FEATURE_xx constant for requested feature
51 * @return mixed True if module supports feature, null if doesn't know
52 */
53function feedback_supports($feature) {
54 switch($feature) {
42f103be 55 case FEATURE_GROUPS: return true;
56 case FEATURE_GROUPINGS: return true;
57 case FEATURE_GROUPMEMBERSONLY: return true;
dc5c2bd9 58 case FEATURE_MOD_INTRO: return true;
29081d02 59 case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
8a41eb4f 60 case FEATURE_COMPLETION_HAS_RULES: return true;
42f103be 61 case FEATURE_GRADE_HAS_GRADE: return false;
62 case FEATURE_GRADE_OUTCOMES: return false;
cb3dcd78 63 case FEATURE_BACKUP_MOODLE2: return true;
3e4c2435 64 case FEATURE_SHOW_DESCRIPTION: return true;
42f103be 65
29081d02 66 default: return null;
67 }
68}
3b120e46 69
c70ad9f7 70/**
32be99dc 71 * this will create a new instance and return the id number
72 * of the new instance.
73 *
74 * @global object
75 * @param object $feedback the object given by mod_feedback_mod_form
76 * @return int
77 */
c70ad9f7 78function feedback_add_instance($feedback) {
c18269c7 79 global $DB;
c70ad9f7 80
81 $feedback->timemodified = time();
82 $feedback->id = '';
83
84 //check if openenable and/or closeenable is set and set correctly to save in db
85 if(empty($feedback->openenable)) {
86 $feedback->timeopen = 0;
87 }
88 if(empty($feedback->closeenable)) {
89 $feedback->timeclose = 0;
90 }
c184660d 91 if(empty($feedback->site_after_submit)) {
92 $feedback->site_after_submit = '';
93 }
c70ad9f7 94
95 //saving the feedback in db
a8f3a651 96 $feedbackid = $DB->insert_record("feedback", $feedback);
37b86a39 97
98 $feedback->id = $feedbackid;
99
c70ad9f7 100 feedback_set_events($feedback);
37b86a39 101
c70ad9f7 102 return $feedbackid;
103}
104
105/**
32be99dc 106 * this will update a given instance
107 *
108 * @global object
109 * @param object $feedback the object given by mod_feedback_mod_form
110 * @return boolean
111 */
c70ad9f7 112function feedback_update_instance($feedback) {
c18269c7 113 global $DB;
c70ad9f7 114
115 $feedback->timemodified = time();
116 $feedback->id = $feedback->instance;
117
118 //check if openenable and/or closeenable is set and set correctly to save in db
119 if(empty($feedback->openenable)) {
120 $feedback->timeopen = 0;
121 }
122 if(empty($feedback->closeenable)) {
123 $feedback->timeclose = 0;
124 }
c184660d 125 if(empty($feedback->site_after_submit)) {
126 $feedback->site_after_submit = '';
127 }
c70ad9f7 128
129 //save the feedback into the db
9d749339 130 $DB->update_record("feedback", $feedback);
c70ad9f7 131
132 //create or update the new events
133 feedback_set_events($feedback);
37b86a39 134
c70ad9f7 135 return true;
136}
137
a59ff6b0
AG
138/**
139 * Serves the files included in feedback items like label. Implements needed access control ;-)
140 *
485ec594
AG
141 * There are two situations in general where the files will be sent.
142 * 1) filearea = item, 2) filearea = template
143 *
a59ff6b0 144 * @param object $course
64f93798 145 * @param object $cm
a59ff6b0
AG
146 * @param object $context
147 * @param string $filearea
148 * @param array $args
149 * @param bool $forcedownload
150 * @return bool false if file not found, does not return if found - justsend the file
151 */
64f93798 152function feedback_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
a59ff6b0
AG
153 global $CFG, $DB;
154
32d2ddab 155 $itemid = (int)array_shift($args);
a59ff6b0 156
485ec594 157 //get the item what includes the file
32d2ddab
AG
158 if (!$item = $DB->get_record('feedback_item', array('id'=>$itemid))) {
159 return false;
160 }
485ec594
AG
161
162 //if the filearea is "item" so we check the permissions like view/complete the feedback
163 if($filearea === 'item') {
164 //get the feedback
165 if(!$feedback = $DB->get_record('feedback', array('id'=>$item->feedback))) {
166 return false;
167 }
a59ff6b0 168
485ec594
AG
169 $canload = false;
170 //first check whether the user has the complete capability
171 if(has_capability('mod/feedback:complete', $context)) {
172 $canload = true;
173 }
174
175 //now we check whether the user has the view capability
176 if(has_capability('mod/feedback:view', $context)) {
177 $canload = true;
178 }
179
180 //if the feedback is on frontpage and anonymous and the fullanonymous is allowed
181 //so the file can be loaded too.
182 if(isset($CFG->feedback_allowfullanonymous)
183 AND $CFG->feedback_allowfullanonymous
184 AND $course->id == SITEID
185 AND $feedback->anonymous == FEEDBACK_ANONYMOUS_YES ) {
186 $canload = true;
187 }
188
189 if(!$canload) {
190 return false;
191 }
192 }else if($filearea === 'template') { //now we check files in templates
193 if(!$template = $DB->get_record('feedback_template', array('id'=>$item->template))) {
194 return false;
195 }
196
197 //if the file is not public so the capability edititems has to be there
198 if(!$template->ispublic) {
199 if(!has_capability('mod/feedback:edititems', $context)) {
200 return false;
201 }
202 }else { //on public templates, at least the user has to be logged in
203 if(!isloggedin()) {
204 return false;
205 }
206 }
207 }else {
32d2ddab
AG
208 return false;
209 }
a59ff6b0 210
32d2ddab
AG
211 if ($context->contextlevel == CONTEXT_MODULE) {
212 if ($filearea !== 'item') {
a59ff6b0
AG
213 return false;
214 }
0f21a964 215
64f93798 216 if ($item->feedback == $cm->instance) {
32d2ddab 217 $filecontext = $context;
a59ff6b0
AG
218 } else {
219 return false;
220 }
32d2ddab 221 }
a59ff6b0 222
32d2ddab
AG
223 if ($context->contextlevel == CONTEXT_COURSE) {
224 if ($filearea !== 'template') {
a59ff6b0
AG
225 return false;
226 }
32d2ddab 227 }
0f21a964 228
32d2ddab
AG
229 $relativepath = implode('/', $args);
230 $fullpath = "/$context->id/mod_feedback/$filearea/$itemid/$relativepath";
a59ff6b0 231
32d2ddab
AG
232 $fs = get_file_storage();
233 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
234 return false;
a59ff6b0
AG
235 }
236
32d2ddab
AG
237 // finally send the file
238 send_stored_file($file, 0, 0, true); // download MUST be forced - security!
239
a59ff6b0
AG
240 return false;
241}
242
c70ad9f7 243/**
32be99dc 244 * this will delete a given instance.
245 * all referenced data also will be deleted
246 *
247 * @global object
248 * @param int $id the instanceid of feedback
249 * @return boolean
250 */
c70ad9f7 251function feedback_delete_instance($id) {
c18269c7 252 global $DB;
253
c70ad9f7 254 //get all referenced items
c18269c7 255 $feedbackitems = $DB->get_records('feedback_item', array('feedback'=>$id));
37b86a39 256
c70ad9f7 257 //deleting all referenced items and values
258 if (is_array($feedbackitems)){
259 foreach($feedbackitems as $feedbackitem){
c18269c7 260 $DB->delete_records("feedback_value", array("item"=>$feedbackitem->id));
261 $DB->delete_records("feedback_valuetmp", array("item"=>$feedbackitem->id));
c70ad9f7 262 }
14832313
AG
263 if($delitems = $DB->get_records("feedback_item", array("feedback"=>$id))) {
264 foreach($delitems as $delitem) {
265 feedback_delete_item($delitem->id, false);
266 }
267 }
c70ad9f7 268 }
37b86a39 269
c70ad9f7 270 //deleting the referenced tracking data
c18269c7 271 $DB->delete_records('feedback_tracking', array('feedback'=>$id));
37b86a39 272
c70ad9f7 273 //deleting the completeds
c18269c7 274 $DB->delete_records("feedback_completed", array("feedback"=>$id));
37b86a39 275
c70ad9f7 276 //deleting the unfinished completeds
c18269c7 277 $DB->delete_records("feedback_completedtmp", array("feedback"=>$id));
37b86a39 278
c70ad9f7 279 //deleting old events
c18269c7 280 $DB->delete_records('event', array('modulename'=>'feedback', 'instance'=>$id));
281 return $DB->delete_records("feedback", array("id"=>$id));
c70ad9f7 282}
283
284/**
32be99dc 285 * this is called after deleting all instances if the course will be deleted.
286 * only templates have to be deleted
287 *
288 * @global object
289 * @param object $course
290 * @return boolean
291 */
c70ad9f7 292function feedback_delete_course($course) {
0085fff8 293 global $DB;
294
c70ad9f7 295 //delete all templates of given course
0085fff8 296 return $DB->delete_records('feedback_template', array('course'=>$course->id));
c70ad9f7 297}
298
299/**
32be99dc 300 * Return a small object with summary information about what a
301 * user has done with a given particular instance of this module
302 * Used for user activity reports.
303 * $return->time = the time they did it
304 * $return->info = a short text description
305 *
306 * @param object $course
307 * @param object $user
308 * @param object $mod
309 * @param object $feedback
310 * @return object
311 */
c70ad9f7 312function feedback_user_outline($course, $user, $mod, $feedback) {
0085fff8 313 return null;
c70ad9f7 314}
315
6133bd16 316/**
317 * Returns all users who has completed a specified feedback since a given time
318 * many thanks to Manolescu Dorel, who contributed these two functions
32be99dc 319 *
320 * @global object
321 * @global object
322 * @global object
323 * @global object
324 * @uses CONTEXT_MODULE
325 * @param array $activities Passed by reference
326 * @param int $index Passed by reference
327 * @param int $timemodified Timestamp
328 * @param int $courseid
329 * @param int $cmid
330 * @param int $userid
331 * @param int $groupid
332 * @return void
6133bd16 333 */
334function feedback_get_recent_mod_activity(&$activities, &$index, $timemodified, $courseid, $cmid, $userid="", $groupid="") {
335 global $CFG, $COURSE, $USER, $DB;
336
337 if ($COURSE->id == $courseid) {
338 $course = $COURSE;
339 } else {
76b7b592 340 $course = $DB->get_record('course', array('id'=>$courseid));
6133bd16 341 }
342
343 $modinfo =& get_fast_modinfo($course);
344
345 $cm = $modinfo->cms[$cmid];
6938191b 346
69f6d0b4 347 $sqlargs = array();
6133bd16 348
3a11c09f
PS
349 //TODO: user user_picture::fields;
350 $sql = " SELECT fk . * , fc . * , u.firstname, u.lastname, u.email, u.picture, u.email
69f6d0b4
AG
351 FROM {feedback_completed} fc
352 JOIN {feedback} fk ON fk.id = fc.feedback
353 JOIN {user} u ON u.id = fc.userid ";
6133bd16 354
355 if ($groupid) {
69f6d0b4 356 $sql .= " JOIN {groups_members} gm ON gm.userid=u.id ";
6133bd16 357 }
6938191b 358
69f6d0b4
AG
359 $sql .= " WHERE fc.timemodified > ? AND fk.id = ? ";
360 $sqlargs[] = $timemodified;
361 $sqlargs[] = $cm->instace;
d4b1d58c 362
69f6d0b4
AG
363 if ($userid) {
364 $sql .= " AND u.id = ? ";
365 $sqlargs[] = $userid;
6133bd16 366 }
367
69f6d0b4
AG
368 if ($groupid) {
369 $sql .= " AND gm.groupid = ? ";
370 $sqlargs[] = $groupid;
371 }
6938191b 372
69f6d0b4
AG
373 if (!$feedbackitems = $DB->get_records_sql($sql, $sqlargs)) {
374 return;
375 }
6133bd16 376
377 $cm_context = get_context_instance(CONTEXT_MODULE, $cm->id);
378 $accessallgroups = has_capability('moodle/site:accessallgroups', $cm_context);
379 $viewfullnames = has_capability('moodle/site:viewfullnames', $cm_context);
380 $groupmode = groups_get_activity_groupmode($cm, $course);
381
382 if (is_null($modinfo->groups)) {
383 $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo
384 }
385
386 $aname = format_string($cm->name,true);
387 foreach ($feedbackitems as $feedbackitem) {
388 if ($feedbackitem->userid != $USER->id) {
d4b1d58c 389
390 if ($groupmode == SEPARATEGROUPS and !$accessallgroups) {
6133bd16 391 $usersgroups = groups_get_all_groups($course->id, $feedbackitem->userid, $cm->groupingid);
392 if (!is_array($usersgroups)) {
393 continue;
394 }
395 $usersgroups = array_keys($usersgroups);
a6807ceb 396 $intersect = array_intersect($usersgroups, $modinfo->groups[$cm->id]);
6133bd16 397 if (empty($intersect)) {
398 continue;
399 }
400 }
401 }
402
39790bd8 403 $tmpactivity = new stdClass();
6133bd16 404
405 $tmpactivity->type = 'feedback';
406 $tmpactivity->cmid = $cm->id;
407 $tmpactivity->name = $aname;
408 $tmpactivity->sectionnum= $cm->sectionnum;
409 $tmpactivity->timestamp = $feedbackitem->timemodified;
d4b1d58c 410
6133bd16 411 $tmpactivity->content->feedbackid = $feedbackitem->id;
412 $tmpactivity->content->feedbackuserid = $feedbackitem->userid;
d4b1d58c 413
3a11c09f 414 //TODO: add all necessary user fields, this is not enough for user_picture
6133bd16 415 $tmpactivity->user->userid = $feedbackitem->userid;
416 $tmpactivity->user->fullname = fullname($feedbackitem, $viewfullnames);
417 $tmpactivity->user->picture = $feedbackitem->picture;
d4b1d58c 418
6133bd16 419 $activities[$index++] = $tmpactivity;
420 }
421
422 return;
423}
424
425/**
426 * Prints all users who has completed a specified feedback since a given time
427 * many thanks to Manolescu Dorel, who contributed these two functions
32be99dc 428 *
429 * @global object
430 * @param object $activity
431 * @param int $courseid
432 * @param string $detail
433 * @param array $modnames
434 * @return void Output is echo'd
6133bd16 435 */
436function feedback_print_recent_mod_activity($activity, $courseid, $detail, $modnames) {
e63f88c9 437 global $CFG, $OUTPUT;
6133bd16 438
439 echo '<table border="0" cellpadding="3" cellspacing="0" class="forum-recent">';
440
441 echo "<tr><td class=\"userpicture\" valign=\"top\">";
812dbaf7 442 echo $OUTPUT->user_picture($activity->user, array('courseid'=>$courseid));
6133bd16 443 echo "</td><td>";
444
445 if ($detail) {
446 $modname = $modnames[$activity->type];
447 echo '<div class="title">';
b5d0cafc 448 echo "<img src=\"" . $OUTPUT->pix_url('icon', $activity->type) . "\" ".
6133bd16 449 "class=\"icon\" alt=\"$modname\" />";
450 echo "<a href=\"$CFG->wwwroot/mod/feedback/view.php?id={$activity->cmid}\">{$activity->name}</a>";
451 echo '</div>';
452 }
d4b1d58c 453
78946b9b 454 echo '<div class="title">';
6133bd16 455 echo '</div>';
d4b1d58c 456
6133bd16 457 echo '<div class="user">';
458 echo "<a href=\"$CFG->wwwroot/user/view.php?id={$activity->user->userid}&amp;course=$courseid\">"
459 ."{$activity->user->fullname}</a> - ".userdate($activity->timestamp);
460 echo '</div>';
461
462 echo "</td></tr></table>";
463
464 return;
465}
466
8a41eb4f
AG
467/**
468 * Obtains the automatic completion state for this feedback based on the condition
469 * in feedback settings.
470 *
471 * @param object $course Course
472 * @param object $cm Course-module
473 * @param int $userid User ID
474 * @param bool $type Type of comparison (or/and; can be used as return value if no conditions)
475 * @return bool True if completed, false if not, $type if conditions not set.
476 */
477function feedback_get_completion_state($course, $cm, $userid, $type) {
478 global $CFG, $DB;
479
480 // Get feedback details
481 $feedback = $DB->get_record('feedback', array('id'=>$cm->instance), '*', MUST_EXIST);
482
516c5eca 483 // If completion option is enabled, evaluate it and return true/false
8a41eb4f
AG
484 if($feedback->completionsubmit) {
485 return $DB->record_exists('feedback_tracking', array('userid'=>$userid, 'feedback'=>$feedback->id));
486 } else {
487 // Completion option is not enabled so just return $type
488 return $type;
489 }
490}
491
6133bd16 492
c70ad9f7 493/**
32be99dc 494 * Print a detailed representation of what a user has done with
495 * a given particular instance of this module, for user activity reports.
d4b1d58c 496 *
32be99dc 497 * @param object $course
498 * @param object $user
499 * @param object $mod
500 * @param object $feedback
501 * @return bool
502 */
c70ad9f7 503function feedback_user_complete($course, $user, $mod, $feedback) {
c70ad9f7 504 return true;
505}
506
32be99dc 507/**
508 * @return bool true
509 */
c70ad9f7 510function feedback_cron () {
511 return true;
512}
513
32be99dc 514/**
2b04c41c 515 * @todo: deprecated - to be deleted in 2.2
32be99dc 516 * @return bool false
517 */
c70ad9f7 518function feedback_get_participants($feedbackid) {
c70ad9f7 519 return false;
520}
521
32be99dc 522
523/**
524 * @return bool false
525 */
c70ad9f7 526function feedback_scale_used ($feedbackid,$scaleid) {
0085fff8 527 return false;
c70ad9f7 528}
529
c27bb7ca
AG
530/**
531 * Checks if scale is being used by any instance of feedback
532 *
533 * This is used to find out if scale used anywhere
534 * @param $scaleid int
535 * @return boolean True if the scale is used by any assignment
536 */
537function feedback_scale_used_anywhere($scaleid) {
538 return false;
539}
540
da457a94
AG
541/**
542 * @return array
543 */
544function feedback_get_view_actions() {
545 return array('view','view all');
546}
547
548/**
549 * @return array
550 */
551function feedback_get_post_actions() {
552 return array('submit');
553}
554
1c57ce25 555/**
556 * This function is used by the reset_course_userdata function in moodlelib.
557 * This function will remove all responses from the specified feedback
558 * and clean up any related data.
32be99dc 559 *
560 * @global object
561 * @global object
562 * @uses FEEDBACK_RESETFORM_RESET
563 * @uses FEEDBACK_RESETFORM_DROP
564 * @param object $data the data submitted from the reset course.
1c57ce25 565 * @return array status array
c70ad9f7 566 */
1c57ce25 567function feedback_reset_userdata($data) {
0085fff8 568 global $CFG, $DB;
37b86a39 569
c70ad9f7 570 $resetfeedbacks = array();
571 $dropfeedbacks = array();
1c57ce25 572 $status = array();
573 $componentstr = get_string('modulenameplural', 'feedback');
37b86a39 574
c70ad9f7 575 //get the relevant entries from $data
576 foreach($data as $key => $value) {
577 switch(true) {
578 case substr($key, 0, strlen(FEEDBACK_RESETFORM_RESET)) == FEEDBACK_RESETFORM_RESET:
579 if($value == 1) {
580 $templist = explode('_', $key);
581 if(isset($templist[3]))$resetfeedbacks[] = intval($templist[3]);
582 }
583 break;
584 case substr($key, 0, strlen(FEEDBACK_RESETFORM_DROP)) == FEEDBACK_RESETFORM_DROP:
585 if($value == 1) {
586 $templist = explode('_', $key);
587 if(isset($templist[3]))$dropfeedbacks[] = intval($templist[3]);
588 }
589 break;
590 }
591 }
37b86a39 592
c70ad9f7 593 //reset the selected feedbacks
594 foreach($resetfeedbacks as $id) {
0085fff8 595 $feedback = $DB->get_record('feedback', array('id'=>$id));
c70ad9f7 596 feedback_delete_all_completeds($id);
1c57ce25 597 $status[] = array('component'=>$componentstr.':'.$feedback->name, 'item'=>get_string('resetting_data','feedback'), 'error'=>false);
c70ad9f7 598 }
37b86a39 599
c70ad9f7 600 //drop the selected feedbacks
1c57ce25 601 // foreach($dropfeedbacks as $id) {
602 // $cm = get_coursemodule_from_instance('feedback', $id);
603 // feedback_delete_instance($id);
604 // feedback_delete_course_module($cm->id);
605 // $status[] = array('component'=>$componentstr, 'item'=>get_string('drop_feedback','feedback'), 'error'=>false);
606 // }
607 return $status;
608}
609
610/**
611 * Called by course/reset.php
32be99dc 612 *
613 * @global object
614 * @uses FEEDBACK_RESETFORM_RESET
615 * @param object $mform form passed by reference
1c57ce25 616 */
617function feedback_reset_course_form_definition(&$mform) {
0085fff8 618 global $COURSE, $DB;
619
1c57ce25 620 $mform->addElement('header', 'feedbackheader', get_string('modulenameplural', 'feedback'));
37b86a39 621
0085fff8 622 if(!$feedbacks = $DB->get_records('feedback', array('course'=>$COURSE->id), 'name')){
1c57ce25 623 return;
c70ad9f7 624 }
1c57ce25 625
626 $mform->addElement('static', 'hint', get_string('resetting_data','feedback'));
627 foreach($feedbacks as $feedback) {
628 $mform->addElement('checkbox', FEEDBACK_RESETFORM_RESET.$feedback->id, $feedback->name);
629 // $mform->addElement('checkbox', FEEDBACK_RESETFORM_DROP.$feedback->id, get_string('drop_feedback','feedback'));
630 }
631}
632
633/**
634 * Course reset form defaults.
32be99dc 635 *
636 * @global object
637 * @uses FEEDBACK_RESETFORM_RESET
638 * @param object $course
1c57ce25 639 */
640function feedback_reset_course_form_defaults($course) {
0085fff8 641 global $DB;
642
1c57ce25 643 $return = array();
0085fff8 644 if(!$feedbacks = $DB->get_records('feedback', array('course'=>$course->id), 'name')){
1c57ce25 645 return;
646 }
647 foreach($feedbacks as $feedback) {
648 $return[FEEDBACK_RESETFORM_RESET.$feedback->id] = true;
649 // $return[FEEDBACK_RESETFORM_DROP.$feedback->id] = false;
650 }
651 return $return;
c70ad9f7 652}
653
37b86a39 654/**
c70ad9f7 655 * Called by course/reset.php and shows the formdata by coursereset.
656 * it prints checkboxes for each feedback available at the given course
657 * there are two checkboxes: 1) delete userdata and keep the feedback 2) delete userdata and drop the feedback
32be99dc 658 *
659 * @global object
660 * @uses FEEDBACK_RESETFORM_RESET
661 * @uses FEEDBACK_RESETFORM_DROP
c70ad9f7 662 * @param object $course
663 * @return void
664 */
665function feedback_reset_course_form($course) {
be96a472 666 global $DB, $OUTPUT;
0085fff8 667
c70ad9f7 668 echo get_string('resetting_feedbacks', 'feedback'); echo ':<br />';
0085fff8 669 if (!$feedbacks = $DB->get_records('feedback', array('course'=>$course->id), 'name')) {
670 return;
671 }
37b86a39 672
c70ad9f7 673 foreach($feedbacks as $feedback) {
674 echo '<p>';
675 echo get_string('name','feedback').': '.$feedback->name.'<br />';
2f0e96e4 676 echo html_writer::checkbox(FEEDBACK_RESETFORM_RESET.$feedback->id, 1, true, get_string('resetting_data','feedback'));
be96a472 677 echo '<br />';
2f0e96e4 678 echo html_writer::checkbox(FEEDBACK_RESETFORM_DROP.$feedback->id, 1, false, get_string('drop_feedback','feedback'));
c70ad9f7 679 echo '</p>';
680 }
681}
682
37b86a39 683/**
32be99dc 684 * This creates new events given as timeopen and closeopen by $feedback.
685 *
686 * @global object
687 * @param object $feedback
688 * @return void
c70ad9f7 689 */
690function feedback_set_events($feedback) {
c18269c7 691 global $DB;
692
c70ad9f7 693 // adding the feedback to the eventtable (I have seen this at quiz-module)
c18269c7 694 $DB->delete_records('event', array('modulename'=>'feedback', 'instance'=>$feedback->id));
c70ad9f7 695
50aa3fcc 696 if (!isset($feedback->coursemodule)) {
697 $cm = get_coursemodule_from_id('feedback', $feedback->id);
698 $feedback->coursemodule = $cm->id;
699 }
700
c70ad9f7 701 // the open-event
702 if($feedback->timeopen > 0) {
703 $event = NULL;
50aa3fcc 704 $event->name = get_string('start', 'feedback').' '.$feedback->name;
705 $event->description = format_module_intro('feedback', $feedback, $feedback->coursemodule);
c70ad9f7 706 $event->courseid = $feedback->course;
707 $event->groupid = 0;
50aa3fcc 708 $event->userid = 0;
709 $event->modulename = 'feedback';
c18269c7 710 $event->instance = $feedback->id;
c70ad9f7 711 $event->eventtype = 'open';
712 $event->timestart = $feedback->timeopen;
713 $event->visible = instance_is_visible('feedback', $feedback);
714 if($feedback->timeclose > 0) {
715 $event->timeduration = ($feedback->timeclose - $feedback->timeopen);
716 } else {
717 $event->timeduration = 0;
718 }
37b86a39 719
9f42276c 720 calendar_event::create($event);
c70ad9f7 721 }
722
723 // the close-event
724 if($feedback->timeclose > 0) {
725 $event = NULL;
50aa3fcc 726 $event->name = get_string('stop', 'feedback').' '.$feedback->name;
727 $event->description = format_module_intro('feedback', $feedback, $feedback->coursemodule);
c70ad9f7 728 $event->courseid = $feedback->course;
729 $event->groupid = 0;
50aa3fcc 730 $event->userid = 0;
731 $event->modulename = 'feedback';
c18269c7 732 $event->instance = $feedback->id;
c70ad9f7 733 $event->eventtype = 'close';
734 $event->timestart = $feedback->timeclose;
735 $event->visible = instance_is_visible('feedback', $feedback);
736 $event->timeduration = 0;
737
9f42276c 738 calendar_event::create($event);
c70ad9f7 739 }
740}
741
37b86a39 742/**
c70ad9f7 743 * this function is called by {@link feedback_delete_userdata()}
744 * it drops the feedback-instance from the course_module table
32be99dc 745 *
746 * @global object
c70ad9f7 747 * @param int $id the id from the coursemodule
748 * @return boolean
749 */
750function feedback_delete_course_module($id) {
0085fff8 751 global $DB;
752
753 if (!$cm = $DB->get_record('course_modules', array('id'=>$id))) {
c70ad9f7 754 return true;
755 }
0085fff8 756 return $DB->delete_records('course_modules', array('id'=>$cm->id));
c70ad9f7 757}
758
759
760
761////////////////////////////////////////////////
762//functions to handle capabilities
763////////////////////////////////////////////////
764
37b86a39 765/**
c70ad9f7 766 * returns the context-id related to the given coursemodule-id
32be99dc 767 *
768 * @staticvar object $context
c70ad9f7 769 * @param int $cmid the coursemodule-id
770 * @return object $context
771 */
772function feedback_get_context($cmid) {
773 static $context;
37b86a39 774
c70ad9f7 775 if(isset($context)) return $context;
37b86a39 776
c70ad9f7 777 if (!$context = get_context_instance(CONTEXT_MODULE, $cmid)) {
778 print_error('badcontext');
779 }
780 return $context;
781}
782
37b86a39 783/**
c70ad9f7 784 * returns true if the current role is faked by switching role feature
32be99dc 785 *
786 * @global object
c70ad9f7 787 * @return boolean
788 */
789function feedback_check_is_switchrole(){
790 global $USER;
791 if(isset($USER->switchrole) AND is_array($USER->switchrole) AND count($USER->switchrole) > 0) {
792 return true;
793 }
794 return false;
795}
796
8d7b8286
AG
797/**
798 * count users which have not completed the feedback
799 *
800 * @global object
801 * @uses CONTEXT_MODULE
802 * @param object $cm
803 * @param int $group single groupid
3a787259
AG
804 * @param string $sort
805 * @param int $startpage
806 * @param int $pagecount
8d7b8286
AG
807 * @return object the userrecords
808 */
809function feedback_get_incomplete_users($cm, $group = false, $sort = '', $startpage = false, $pagecount = false) {
810 global $DB;
6938191b 811
8d7b8286 812 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
6938191b 813
8d7b8286
AG
814 //first get all user who can complete this feedback
815 $cap = 'mod/feedback:complete';
816 $fields = 'u.id, u.username';
817 if(!$allusers = get_users_by_capability($context, $cap, $fields, $sort, '', '', $group, '', true)) {
818 return false;
819 }
820 $allusers = array_keys($allusers);
821
822 //now get all completeds
823 if(!$completedusers = $DB->get_records_menu('feedback_completed', array('feedback'=>$cm->instance), '', 'userid,id')){
3fac763e 824 return $allusers;
8d7b8286
AG
825 }
826 $completedusers = array_keys($completedusers);
6938191b 827
8d7b8286
AG
828 //now strike all completedusers from allusers
829 $allusers = array_diff($allusers, $completedusers);
830
831 //for paging I use array_slice()
832 if($startpage !== false AND $pagecount !== false) {
833 $allusers = array_slice($allusers, $startpage, $pagecount);
834 }
835
836 return $allusers;
837}
838
839/**
840 * count users which have not completed the feedback
841 *
842 * @global object
8d7b8286
AG
843 * @param object $cm
844 * @param int $group single groupid
3a787259 845 * @return int count of userrecords
8d7b8286
AG
846 */
847function feedback_count_incomplete_users($cm, $group = false) {
848 if($allusers = feedback_get_incomplete_users($cm, $group)) {
849 return count($allusers);
850 }
851 return 0;
852}
853
d4b1d58c 854/**
3a787259 855 * count users which have completed a feedback
32be99dc 856 *
857 * @global object
3a787259 858 * @uses FEEDBACK_ANONYMOUS_NO
32be99dc 859 * @param object $cm
860 * @param int $group single groupid
3a787259 861 * @return int count of userrecords
c70ad9f7 862 */
248bafd6
AG
863function feedback_count_complete_users($cm, $group = false) {
864 global $DB;
865
866 $params = array(FEEDBACK_ANONYMOUS_NO, $cm->instance);
867
868 $fromgroup = '';
869 $wheregroup = '';
870 if($group) {
871 $fromgroup = ', {groups_members} g';
872 $wheregroup = ' AND g.groupid = ? AND g.userid = c.userid';
873 $params[] = $group;
874 }
6938191b 875
248bafd6
AG
876 $sql = 'SELECT COUNT(u.id) FROM {user} u, {feedback_completed} c'.$fromgroup.'
877 WHERE anonymous_response = ? AND u.id = c.userid AND c.feedback = ?
878 '.$wheregroup;
879 ;
6938191b 880
248bafd6
AG
881 return $DB->count_records_sql($sql, $params);
882
883}
884
885/**
3a787259 886 * get users which have completed a feedback
248bafd6
AG
887 *
888 * @global object
889 * @uses CONTEXT_MODULE
3a787259 890 * @uses FEEDBACK_ANONYMOUS_NO
248bafd6
AG
891 * @param object $cm
892 * @param int $group single groupid
0f21a964
PS
893 * @param string $where a sql where condition (must end with " AND ")
894 * @param array parameters used in $where
248bafd6 895 * @param string $sort a table field
3a787259
AG
896 * @param int $startpage
897 * @param int $pagecount
248bafd6
AG
898 * @return object the userrecords
899 */
0f21a964 900function feedback_get_complete_users($cm, $group = false, $where = '', array $params = NULL, $sort = '', $startpage = false, $pagecount = false) {
a600ad35 901 global $DB;
d4b1d58c 902
a600ad35 903 if (!$context = get_context_instance(CONTEXT_MODULE, $cm->id)) {
c70ad9f7 904 print_error('badcontext');
905 }
37b86a39 906
0f21a964
PS
907 $params = (array)$params;
908
909 $params['anon'] = FEEDBACK_ANONYMOUS_NO;
910 $params['instance'] = $cm->instance;
a600ad35 911
912 $fromgroup = '';
913 $wheregroup = '';
0f21a964 914 if ($group) {
a600ad35 915 $fromgroup = ', {groups_members} g';
0f21a964
PS
916 $wheregroup = ' AND g.groupid = :group AND g.userid = c.userid';
917 $params['group'] = $group;
a600ad35 918 }
6938191b 919
0f21a964 920 if ($sort) {
248bafd6 921 $sortsql = ' ORDER BY '.$sort;
0f21a964 922 } else {
248bafd6
AG
923 $sortsql = '';
924 }
6938191b 925
eae1948c 926 $ufields = user_picture::fields('u');
0f21a964
PS
927 $sql = 'SELECT DISTINCT '.$ufields.' FROM {user} u, {feedback_completed} c '.$fromgroup.'
928 WHERE '.$where.' anonymous_response = :anon AND u.id = c.userid AND c.feedback = :instance
248bafd6 929 '.$wheregroup.$sortsql;
6938191b 930
0f21a964 931 if ($startpage === false OR $pagecount === false) {
248bafd6
AG
932 $startpage = false;
933 $pagecount = false;
934 }
935 return $DB->get_records_sql($sql, $params, $startpage, $pagecount);
c70ad9f7 936}
937
37b86a39 938/**
32be99dc 939 * get users which have the viewreports-capability
940 *
941 * @uses CONTEXT_MODULE
942 * @param int $cmid
943 * @param mixed $groups single groupid or array of groupids - group(s) user is in
944 * @return object the userrecords
c70ad9f7 945 */
946function feedback_get_viewreports_users($cmid, $groups = false) {
947
948 if (!$context = get_context_instance(CONTEXT_MODULE, $cmid)) {
949 print_error('badcontext');
950 }
37b86a39 951
c70ad9f7 952 //description of the call below: get_users_by_capability($context, $capability, $fields='', $sort='', $limitfrom='', $limitnum='', $groups='', $exceptions='', $doanything=true)
953 return get_users_by_capability($context, 'mod/feedback:viewreports', '', 'lastname', '', '', $groups, '', false);
954}
955
37b86a39 956/**
32be99dc 957 * get users which have the receivemail-capability
958 *
959 * @uses CONTEXT_MODULE
960 * @param int $cmid
961 * @param mixed $groups single groupid or array of groupids - group(s) user is in
962 * @return object the userrecords
c184660d 963 */
964function feedback_get_receivemail_users($cmid, $groups = false) {
965
966 if (!$context = get_context_instance(CONTEXT_MODULE, $cmid)) {
967 print_error('badcontext');
968 }
37b86a39 969
c184660d 970 //description of the call below: get_users_by_capability($context, $capability, $fields='', $sort='', $limitfrom='', $limitnum='', $groups='', $exceptions='', $doanything=true)
c65e59ba 971 return get_users_by_capability($context, 'mod/feedback:receivemail', '', 'lastname', '', '', $groups, '', false);
c184660d 972}
973
c70ad9f7 974////////////////////////////////////////////////
975//functions to handle the templates
976////////////////////////////////////////////////
977////////////////////////////////////////////////
978
37b86a39 979/**
32be99dc 980 * creates a new template-record.
981 *
982 * @global object
983 * @param int $courseid
984 * @param string $name the name of template shown in the templatelist
985 * @param int $ispublic 0:privat 1:public
986 * @return int the new templateid
c70ad9f7 987 */
988function feedback_create_template($courseid, $name, $ispublic = 0) {
0085fff8 989 global $DB;
990
39790bd8 991 $templ = new stdClass();
7b1126fd 992 $templ->course = ($ispublic ? 0 : $courseid);
0085fff8 993 $templ->name = $name;
c70ad9f7 994 $templ->ispublic = $ispublic;
0085fff8 995
14832313
AG
996 $templid = $DB->insert_record('feedback_template', $templ);
997 return $DB->get_record('feedback_template', array('id'=>$templid));
c70ad9f7 998}
999
37b86a39 1000/**
32be99dc 1001 * creates new template items.
1002 * all items will be copied and the attribute feedback will be set to 0
1003 * and the attribute template will be set to the new templateid
1004 *
1005 * @global object
3a787259
AG
1006 * @uses CONTEXT_MODULE
1007 * @uses CONTEXT_COURSE
32be99dc 1008 * @param object $feedback
1009 * @param string $name the name of template shown in the templatelist
1010 * @param int $ispublic 0:privat 1:public
1011 * @return boolean
c70ad9f7 1012 */
1013function feedback_save_as_template($feedback, $name, $ispublic = 0) {
0085fff8 1014 global $DB;
14832313 1015 $fs = get_file_storage();
0085fff8 1016
1017 if (!$feedbackitems = $DB->get_records('feedback_item', array('feedback'=>$feedback->id))) {
c70ad9f7 1018 return false;
1019 }
37b86a39 1020
0085fff8 1021 if (!$newtempl = feedback_create_template($feedback->course, $name, $ispublic)) {
c70ad9f7 1022 return false;
1023 }
6938191b 1024
7b1126fd
AG
1025 //files in the template_item are in the context of the current course or
1026 //if the template is public the files are in the system context
14832313 1027 //files in the feedback_item are in the feedback_context of the feedback
7b1126fd
AG
1028 if($ispublic) {
1029 $s_context = get_system_context();
1030 }else {
1031 $s_context = get_context_instance(CONTEXT_COURSE, $newtempl->course);
1032 }
14832313
AG
1033 $cm = get_coursemodule_from_instance('feedback', $feedback->id);
1034 $f_context = get_context_instance(CONTEXT_MODULE, $cm->id);
6938191b 1035
c70ad9f7 1036 //create items of this new template
73043833
AG
1037 //depend items we are storing temporary in an mapping list array(new id => dependitem)
1038 //we also store a mapping of all items array(oldid => newid)
1039 $dependitemsmap = array();
1040 $itembackup = array();
c70ad9f7 1041 foreach($feedbackitems as $item) {
6938191b 1042
14832313 1043 $t_item = clone($item);
6938191b 1044
14832313
AG
1045 unset($t_item->id);
1046 $t_item->feedback = 0;
1047 $t_item->template = $newtempl->id;
1048 $t_item->id = $DB->insert_record('feedback_item', $t_item);
1049 //copy all included files to the feedback_template filearea
64f93798 1050 if ($itemfiles = $fs->get_area_files($f_context->id, 'mod_feedback', 'item', $item->id, "id", false)) {
14832313 1051 foreach($itemfiles as $ifile) {
39790bd8 1052 $file_record = new stdClass();
7b1126fd 1053 $file_record->contextid = $s_context->id;
64f93798
PS
1054 $file_record->component = 'mod_feedback';
1055 $file_record->filearea = 'template';
14832313
AG
1056 $file_record->itemid = $t_item->id;
1057 $fs->create_file_from_storedfile($file_record, $ifile);
1058 }
1059 }
6938191b 1060
73043833
AG
1061 $itembackup[$item->id] = $t_item->id;
1062 if($t_item->dependitem) {
1063 $dependitemsmap[$t_item->id] = $t_item->dependitem;
1064 }
6938191b 1065
c70ad9f7 1066 }
6938191b 1067
73043833
AG
1068 //remapping the dependency
1069 foreach($dependitemsmap as $key => $dependitem) {
1070 $newitem = $DB->get_record('feedback_item', array('id'=>$key));
1071 $newitem->dependitem = $itembackup[$newitem->dependitem];
1072 $DB->update_record('feedback_item', $newitem);
1073 }
6938191b 1074
c70ad9f7 1075 return true;
1076}
1077
37b86a39 1078/**
32be99dc 1079 * deletes all feedback_items related to the given template id
1080 *
1081 * @global object
3a787259 1082 * @uses CONTEXT_COURSE
7b1126fd 1083 * @param object $template the template
32be99dc 1084 * @return void
c70ad9f7 1085 */
7b1126fd 1086function feedback_delete_template($template) {
0085fff8 1087 global $DB;
1088
7b1126fd
AG
1089 //deleting the files from the item is done by feedback_delete_item
1090 if($t_items = $DB->get_records("feedback_item", array("template"=>$template->id))) {
14832313 1091 foreach($t_items as $t_item) {
7b1126fd 1092 feedback_delete_item($t_item->id, false, $template);
14832313
AG
1093 }
1094 }
7b1126fd 1095 $DB->delete_records("feedback_template", array("id"=>$template->id));
c70ad9f7 1096}
1097
37b86a39 1098/**
32be99dc 1099 * creates new feedback_item-records from template.
1100 * if $deleteold is set true so the existing items of the given feedback will be deleted
1101 * if $deleteold is set false so the new items will be appanded to the old items
1102 *
1103 * @global object
3a787259
AG
1104 * @uses CONTEXT_COURSE
1105 * @uses CONTEXT_MODULE
32be99dc 1106 * @param object $feedback
1107 * @param int $templateid
1108 * @param boolean $deleteold
c70ad9f7 1109 */
1110function feedback_items_from_template($feedback, $templateid, $deleteold = false) {
516c5eca
PS
1111 global $DB, $CFG;
1112
1113 require_once($CFG->libdir.'/completionlib.php');
1114
14832313 1115 $fs = get_file_storage();
0085fff8 1116
485ec594
AG
1117 if(!$template = $DB->get_record('feedback_template', array('id'=>$templateid))) {
1118 return false;
1119 }
c70ad9f7 1120 //get all templateitems
0085fff8 1121 if(!$templitems = $DB->get_records('feedback_item', array('template'=>$templateid))) {
c70ad9f7 1122 return false;
1123 }
37b86a39 1124
14832313
AG
1125 //files in the template_item are in the context of the current course
1126 //files in the feedback_item are in the feedback_context of the feedback
485ec594 1127 if($template->ispublic) {
7b1126fd 1128 $s_context = get_system_context();
485ec594 1129 }else {
7b1126fd 1130 $s_context = get_context_instance(CONTEXT_COURSE, $feedback->course);
485ec594 1131 }
8a41eb4f 1132 $course = $DB->get_record('course', array('id'=>$feedback->course));
14832313
AG
1133 $cm = get_coursemodule_from_instance('feedback', $feedback->id);
1134 $f_context = get_context_instance(CONTEXT_MODULE, $cm->id);
1135
c70ad9f7 1136 //if deleteold then delete all old items before
1137 //get all items
1138 if($deleteold) {
0085fff8 1139 if($feedbackitems = $DB->get_records('feedback_item', array('feedback'=>$feedback->id))) {
c70ad9f7 1140 //delete all items of this feedback
1141 foreach($feedbackitems as $item) {
1142 feedback_delete_item($item->id, false);
1143 }
1144 //delete tracking-data
0085fff8 1145 $DB->delete_records('feedback_tracking', array('feedback'=>$feedback->id));
516c5eca 1146
8a41eb4f
AG
1147 if($completeds = $DB->get_records('feedback_completed', array('feedback'=>$feedback->id))) {
1148 $completion = new completion_info($course);
1149 foreach($completeds as $completed) {
1150 // Update completion state
1151 if ($completion->is_enabled($cm) && $feedback->completionsubmit) {
1152 $completion->update_state($cm, COMPLETION_INCOMPLETE, $completed->userid);
1153 }
1154 $DB->delete_records('feedback_completed', array('id'=>$completed->id));
1155 }
1156 }
0085fff8 1157 $DB->delete_records('feedback_completedtmp', array('feedback'=>$feedback->id));
c70ad9f7 1158 }
194dd279 1159 $positionoffset = 0;
0085fff8 1160 } else {
c70ad9f7 1161 //if the old items are kept the new items will be appended
1162 //therefor the new position has an offset
0085fff8 1163 $positionoffset = $DB->count_records('feedback_item', array('feedback'=>$feedback->id));
c70ad9f7 1164 }
37b86a39 1165
73043833
AG
1166 //create items of this new template
1167 //depend items we are storing temporary in an mapping list array(new id => dependitem)
1168 //we also store a mapping of all items array(oldid => newid)
1169 $dependitemsmap = array();
1170 $itembackup = array();
14832313
AG
1171 foreach($templitems as $t_item) {
1172 $item = clone($t_item);
1173 unset($item->id);
1174 $item->feedback = $feedback->id;
1175 $item->template = 0;
1176 $item->position = $item->position + $positionoffset;
1177
1178 $item->id = $DB->insert_record('feedback_item', $item);
485ec594 1179
14832313 1180 //TODO: moving the files to the new items
7b1126fd 1181 if ($templatefiles = $fs->get_area_files($s_context->id, 'mod_feedback', 'template', $t_item->id, "id", false)) {
14832313 1182 foreach($templatefiles as $tfile) {
39790bd8 1183 $file_record = new stdClass();
14832313 1184 $file_record->contextid = $f_context->id;
64f93798
PS
1185 $file_record->component = 'mod_feedback';
1186 $file_record->filearea = 'item';
14832313
AG
1187 $file_record->itemid = $item->id;
1188 $fs->create_file_from_storedfile($file_record, $tfile);
1189 }
1190 }
6938191b 1191
73043833
AG
1192 $itembackup[$t_item->id] = $item->id;
1193 if($item->dependitem) {
1194 $dependitemsmap[$item->id] = $item->dependitem;
1195 }
c70ad9f7 1196 }
6938191b 1197
73043833
AG
1198 //remapping the dependency
1199 foreach($dependitemsmap as $key => $dependitem) {
1200 $newitem = $DB->get_record('feedback_item', array('id'=>$key));
1201 $newitem->dependitem = $itembackup[$newitem->dependitem];
1202 $DB->update_record('feedback_item', $newitem);
6938191b 1203 }
c70ad9f7 1204}
1205
37b86a39 1206/**
32be99dc 1207 * get the list of available templates.
1208 * if the $onlyown param is set true so only templates from own course will be served
1209 * this is important for droping templates
1210 *
1211 * @global object
1212 * @param object $course
485ec594 1213 * @param string $onlyownorpublic
32be99dc 1214 * @return array the template recordsets
c70ad9f7 1215 */
485ec594
AG
1216function feedback_get_template_list($course, $onlyownorpublic = '') {
1217 global $DB, $CFG;
0085fff8 1218
485ec594
AG
1219 switch($onlyownorpublic) {
1220 case '':
1221 $templates = $DB->get_records_select('feedback_template', 'course = ? OR ispublic = 1', array($course->id), 'name');
1222 break;
1223 case 'own':
1224 $templates = $DB->get_records('feedback_template', array('course'=>$course->id), 'name');
1225 break;
1226 case 'public':
7b1126fd 1227 $templates = $DB->get_records('feedback_template', array('ispublic'=>1), 'name');
485ec594 1228 break;
c70ad9f7 1229 }
1230 return $templates;
1231}
1232
1233////////////////////////////////////////////////
1234//Handling der Items
1235////////////////////////////////////////////////
1236////////////////////////////////////////////////
1237
6cc1599e
AG
1238/**
1239 * load the lib.php from item-plugin-dir and returns the instance of the itemclass
1240 *
1241 * @global object
1242 * @param object $item
1243 * @return object the instanz of itemclass
1244 */
1245function feedback_get_item_class($typ) {
1246 global $CFG;
6938191b 1247
6cc1599e
AG
1248 //get the class of item-typ
1249 $itemclass = 'feedback_item_'.$typ;
1250 //get the instance of item-class
1251 if (!class_exists($itemclass)) {
1252 require_once($CFG->dirroot.'/mod/feedback/item/'.$typ.'/lib.php');
1253 }
1254 return new $itemclass();
1255}
1256
37b86a39 1257/**
32be99dc 1258 * load the available item plugins from given subdirectory of $CFG->dirroot
1259 * the default is "mod/feedback/item"
1260 *
1261 * @global object
1262 * @param string $dir the subdir
1263 * @return array pluginnames as string
c70ad9f7 1264 */
1265function feedback_load_feedback_items($dir = 'mod/feedback/item') {
1266 global $CFG;
3a787259 1267 $names = get_list_of_plugins($dir);
c70ad9f7 1268 $ret_names = array();
1269
1270 foreach($names as $name) {
1271 require_once($CFG->dirroot.'/'.$dir.'/'.$name.'/lib.php');
1272 if(class_exists('feedback_item_'.$name)) {
1273 $ret_names[] = $name;
1274 }
1275 }
1276 return $ret_names;
1277}
1278
37b86a39 1279/**
32be99dc 1280 * load the available item plugins to use as dropdown-options
1281 *
1282 * @global object
1283 * @return array pluginnames as string
c70ad9f7 1284 */
1285function feedback_load_feedback_items_options() {
1286 global $CFG;
37b86a39 1287
c70ad9f7 1288 $feedback_options = array("pagebreak" => get_string('add_pagebreak', 'feedback'));
37b86a39 1289
c70ad9f7 1290 if (!$feedback_names = feedback_load_feedback_items('mod/feedback/item')) {
1291 return array();
1292 }
37b86a39 1293
c70ad9f7 1294 foreach($feedback_names as $fn) {
1295 $feedback_options[$fn] = get_string($fn,'feedback');
1296 }
1297 asort($feedback_options);
37b86a39 1298 $feedback_options = array_merge( array(' ' => get_string('select')), $feedback_options );
c70ad9f7 1299 return $feedback_options;
1300}
1301
3a787259
AG
1302/**
1303 * load the available items for the depend item dropdown list shown in the edit_item form
1304 *
1305 * @global object
1306 * @param object $feedback
1307 * @param object $item the item of the edit_item form
1308 * @return array all items except the item $item, labels and pagebreaks
1309 */
73043833
AG
1310function feedback_get_depend_candidates_for_item($feedback, $item) {
1311 global $DB;
1312 //all items for dependitem
1313 $where = "feedback = ? AND typ != 'pagebreak' AND hasvalue = 1";
1314 $params = array($feedback->id);
1315 if(isset($item->id) AND $item->id) {
1316 $where .= ' AND id != ?';
1317 $params[] = $item->id;
1318 }
1319 $dependitems = array(0 => get_string('choose'));
1320 if(!$feedbackitems = $DB->get_records_select_menu('feedback_item', $where, $params, 'position', 'id, label')) {
1321 return $dependitems;
1322 }
1323 //adding the choose-option
1324 foreach($feedbackitems as $key=>$val) {
1325 $dependitems[$key] = $val;
1326 }
1327 return $dependitems;
1328}
1329
37b86a39 1330/**
32be99dc 1331 * creates a new item-record
1332 *
1333 * @global object
1334 * @param object $data the data from edit_item_form
1335 * @return int the new itemid
c70ad9f7 1336 */
1337function feedback_create_item($data) {
0085fff8 1338 global $DB;
1339
39790bd8 1340 $item = new stdClass();
0085fff8 1341 $item->feedback = $data->feedbackid;
c70ad9f7 1342
1343 $item->template=0;
1344 if (isset($data->templateid)) {
78946b9b 1345 $item->template = intval($data->templateid);
37b86a39 1346 }
c70ad9f7 1347
1348 $itemname = trim($data->itemname);
0085fff8 1349 $item->name = ($itemname ? $data->itemname : get_string('no_itemname', 'feedback'));
37b86a39 1350
d185ff44
SH
1351 if (!empty($data->itemlabel)) {
1352 $item->label = trim($data->itemlabel);
1353 } else {
1354 $item->label = get_string('no_itemlabel', 'feedback');
1355 }
b7a47958 1356
6cc1599e 1357 $itemobj = feedback_get_item_class($data->typ);
a59ff6b0
AG
1358 // $item->presentation = $itemobj->get_presentation($data);
1359 $item->presentation = ''; //the date comes from postupdate() of the itemobj
37b86a39 1360
c70ad9f7 1361 $item->hasvalue = $itemobj->get_hasvalue();
37b86a39 1362
c70ad9f7 1363 $item->typ = $data->typ;
1364 $item->position = $data->position;
1365
1366 $item->required=0;
ab5bd34d 1367 if (!empty($data->required)) {
1368 $item->required = $data->required;
37b86a39 1369 }
c70ad9f7 1370
a59ff6b0
AG
1371 $item->id = $DB->insert_record('feedback_item', $item);
1372
1373 //move all itemdata to the data
1374 $data->id = $item->id;
1375 $data->feedback = $item->feedback;
1376 $data->name = $item->name;
1377 $data->label = $item->label;
1378 $data->required = $item->required;
1379 return $itemobj->postupdate($data);
c70ad9f7 1380}
1381
37b86a39 1382/**
32be99dc 1383 * save the changes of a given item.
1384 *
1385 * @global object
1386 * @param object $item
32be99dc 1387 * @return boolean
c70ad9f7 1388 */
a59ff6b0 1389function feedback_update_item($item){
0085fff8 1390 global $DB;
0085fff8 1391 return $DB->update_record("feedback_item", $item);
c70ad9f7 1392}
1393
37b86a39 1394/**
3a787259 1395 * deletes an item and also deletes all related values
32be99dc 1396 *
1397 * @global object
3a787259 1398 * @uses CONTEXT_MODULE
32be99dc 1399 * @param int $itemid
1400 * @param boolean $renumber should the kept items renumbered Yes/No
7b1126fd 1401 * @param object $template if the template is given so the items are bound to it
32be99dc 1402 * @return void
c70ad9f7 1403 */
7b1126fd 1404function feedback_delete_item($itemid, $renumber = true, $template = false){
0085fff8 1405 global $DB;
6938191b
PS
1406
1407
0085fff8 1408 $item = $DB->get_record('feedback_item', array('id'=>$itemid));
6938191b 1409
14832313
AG
1410 //deleting the files from the item
1411 $fs = get_file_storage();
7b1126fd
AG
1412
1413 if($template) {
1414 if($template->ispublic) {
1415 $context = get_system_context();
1416 }else {
1417 $context = get_context_instance(CONTEXT_COURSE, $template->course);
1418 }
1419 if ($templatefiles = $fs->get_area_files($context->id, 'mod_feedback', 'template', $item->id, "id", false)) {
1420 $fs->delete_area_files($context->id, 'mod_feedback', 'template', $item->id);
1421 }
1422 }else {
1423 if (!$cm = get_coursemodule_from_instance('feedback', $item->feedback)) {
1424 return false;
1425 }
1426 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
6938191b 1427
7b1126fd
AG
1428 if ($itemfiles = $fs->get_area_files($context->id, 'mod_feedback', 'item', $item->id, "id", false)) {
1429 $fs->delete_area_files($context->id, 'mod_feedback', 'item', $item->id);
1430 }
14832313 1431 }
6938191b 1432
0085fff8 1433 $DB->delete_records("feedback_value", array("item"=>$itemid));
1434 $DB->delete_records("feedback_valuetmp", array("item"=>$itemid));
6938191b 1435
73043833
AG
1436 //remove all depends
1437 $DB->set_field('feedback_item', 'dependvalue', '', array('dependitem'=>$itemid));
1438 $DB->set_field('feedback_item', 'dependitem', 0, array('dependitem'=>$itemid));
6938191b 1439
0085fff8 1440 $DB->delete_records("feedback_item", array("id"=>$itemid));
c70ad9f7 1441 if($renumber) {
1442 feedback_renumber_items($item->feedback);
1443 }
1444}
1445
37b86a39 1446/**
32be99dc 1447 * deletes all items of the given feedbackid
1448 *
1449 * @global object
1450 * @param int $feedbackid
1451 * @return void
c70ad9f7 1452 */
1453function feedback_delete_all_items($feedbackid){
516c5eca
PS
1454 global $DB, $CFG;
1455 require_once($CFG->libdir.'/completionlib.php');
0085fff8 1456
8a41eb4f
AG
1457 if(!$feedback = $DB->get_record('feedback', array('id'=>$feedbackid))) {
1458 return false;
1459 }
516c5eca 1460
8a41eb4f
AG
1461 if (!$cm = get_coursemodule_from_instance('feedback', $feedback->id)) {
1462 return false;
1463 }
516c5eca 1464
8a41eb4f
AG
1465 if(!$course = $DB->get_record('course', array('id'=>$feedback->course))) {
1466 return false;
1467 }
516c5eca 1468
0085fff8 1469 if(!$items = $DB->get_records('feedback_item', array('feedback'=>$feedbackid))) {
c70ad9f7 1470 return;
1471 }
1472 foreach($items as $item) {
1473 feedback_delete_item($item->id, false);
1474 }
8a41eb4f
AG
1475 // $DB->delete_records('feedback_completed', array('feedback'=>$feedbackid));
1476 if($completeds = $DB->get_records('feedback_completed', array('feedback'=>$feedback->id))) {
1477 $completion = new completion_info($course);
1478 foreach($completeds as $completed) {
1479 // Update completion state
1480 if ($completion->is_enabled($cm) && $feedback->completionsubmit) {
1481 $completion->update_state($cm, COMPLETION_INCOMPLETE, $completed->userid);
1482 }
1483 $DB->delete_records('feedback_completed', array('id'=>$completed->id));
1484 }
1485 }
516c5eca 1486
0085fff8 1487 $DB->delete_records('feedback_completedtmp', array('feedback'=>$feedbackid));
516c5eca 1488
c70ad9f7 1489}
1490
37b86a39 1491/**
32be99dc 1492 * this function toggled the item-attribute required (yes/no)
1493 *
1494 * @global object
1495 * @param object $item
1496 * @return boolean
c70ad9f7 1497 */
1498function feedback_switch_item_required($item) {
6cc1599e
AG
1499 global $DB, $CFG;
1500
1501 $itemobj = feedback_get_item_class($item->typ);
0085fff8 1502
6cc1599e
AG
1503 if($itemobj->can_switch_require()) {
1504 $DB->set_field('feedback_item', 'required', (int)!(bool)$item->required, array('id'=>$item->id));
1505 }
1506 return true;
c70ad9f7 1507}
1508
37b86a39 1509/**
32be99dc 1510 * renumbers all items of the given feedbackid
1511 *
1512 * @global object
1513 * @param int $feedbackid
1514 * @return void
c70ad9f7 1515 */
1516function feedback_renumber_items($feedbackid){
0085fff8 1517 global $DB;
1518
1519 $items = $DB->get_records('feedback_item', array('feedback'=>$feedbackid), 'position');
c70ad9f7 1520 $pos = 1;
1521 if($items) {
1522 foreach($items as $item){
3a787259 1523 $DB->set_field('feedback_item', 'position', $pos, array('id'=>$item->id));
c70ad9f7 1524 $pos++;
c70ad9f7 1525 }
1526 }
1527}
1528
37b86a39 1529/**
32be99dc 1530 * this decreases the position of the given item
1531 *
1532 * @global object
1533 * @param object $item
3a787259 1534 * @return bool
c70ad9f7 1535 */
1536function feedback_moveup_item($item){
0085fff8 1537 global $DB;
1538
a59ff6b0
AG
1539 if($item->position == 1) {
1540 return true;
1541 }
6938191b 1542
a59ff6b0
AG
1543 if(!$items = $DB->get_records('feedback_item', array('feedback'=>$item->feedback), 'position')) {
1544 return false;
1545 }
6938191b 1546
a59ff6b0
AG
1547 $itembefore = null;
1548 foreach($items as $i) {
1549 if($i->id == $item->id) {
1550 if(is_null($itembefore)) {
1551 return true;
1552 }
1553 $itembefore->position = $item->position;
1554 $item->position--;
1555 feedback_update_item($itembefore);
1556 feedback_update_item($item);
1557 feedback_renumber_items($item->feedback);
1558 return true;
1559 }
1560 $itembefore = $i;
1561 }
1562 return false;
c70ad9f7 1563}
1564
37b86a39 1565/**
32be99dc 1566 * this increased the position of the given item
1567 *
1568 * @global object
1569 * @param object $item
3a787259 1570 * @return bool
c70ad9f7 1571 */
1572function feedback_movedown_item($item){
0085fff8 1573 global $DB;
1574
a59ff6b0
AG
1575 if(!$items = $DB->get_records('feedback_item', array('feedback'=>$item->feedback), 'position')) {
1576 return false;
c70ad9f7 1577 }
6938191b 1578
a59ff6b0
AG
1579 $movedownitem = null;
1580 foreach($items as $i) {
1581 if(!is_null($movedownitem) AND $movedownitem->id == $item->id) {
1582 $movedownitem->position = $i->position;
1583 $i->position--;
1584 feedback_update_item($movedownitem);
1585 feedback_update_item($i);
1586 feedback_renumber_items($item->feedback);
1587 return true;
1588 }
1589 $movedownitem = $i;
1590 }
1591 return false;
c70ad9f7 1592}
1593
37b86a39 1594/**
32be99dc 1595 * here the position of the given item will be set to the value in $pos
1596 *
1597 * @global object
1598 * @param object $moveitem
1599 * @param int $pos
1600 * @return boolean
c70ad9f7 1601 */
1602function feedback_move_item($moveitem, $pos){
0085fff8 1603 global $DB;
1604
0085fff8 1605 if (!$allitems = $DB->get_records('feedback_item', array('feedback'=>$moveitem->feedback), 'position')) {
c70ad9f7 1606 return false;
1607 }
0085fff8 1608 if (is_array($allitems)) {
c70ad9f7 1609 $index = 1;
1610 foreach($allitems as $item) {
c70ad9f7 1611 if($index == $pos) {
c70ad9f7 1612 $index++;
1613 }
a59ff6b0
AG
1614 if($item->id == $moveitem->id) {
1615 $moveitem->position = $pos;
1616 feedback_update_item($moveitem);
1617 continue;
1618 }
c70ad9f7 1619 $item->position = $index;
1620 feedback_update_item($item);
1621 $index++;
1622 }
c70ad9f7 1623 return true;
1624 }
1625 return false;
1626}
1627
9d5fbd65 1628/**
3a787259
AG
1629 * prints the given item as a preview.
1630 * each item-class has an own print_item_preview function implemented.
9d5fbd65 1631 *
3a787259 1632 * @global object
9d5fbd65
AG
1633 * @param object $item the item what we want to print out
1634 * @return void
1635 */
1636function feedback_print_item_preview($item){
1637 global $CFG;
1638 if($item->typ == 'pagebreak') {
1639 return;
1640 }
9d5fbd65 1641 //get the instance of the item-class
6cc1599e 1642 $itemobj = feedback_get_item_class($item->typ);
9d5fbd65
AG
1643 $itemobj->print_item_preview($item);
1644}
1645
37b86a39 1646/**
3a787259
AG
1647 * prints the given item in the completion form.
1648 * each item-class has an own print_item_complete function implemented.
32be99dc 1649 *
1650 * @param object $item the item what we want to print out
3a787259 1651 * @param mixed $value the value
32be99dc 1652 * @param boolean $highlightrequire if this set true and the value are false on completing so the item will be highlighted
1653 * @return void
c70ad9f7 1654 */
9d5fbd65 1655function feedback_print_item_complete($item, $value = false, $highlightrequire = false){
ab5bd34d 1656 global $CFG;
9d5fbd65
AG
1657 if($item->typ == 'pagebreak') {
1658 return;
1659 }
37b86a39 1660
c70ad9f7 1661 //get the instance of the item-class
6cc1599e 1662 $itemobj = feedback_get_item_class($item->typ);
9d5fbd65
AG
1663 $itemobj->print_item_complete($item, $value, $highlightrequire);
1664}
1665
1666/**
3a787259
AG
1667 * prints the given item in the show entries page.
1668 * each item-class has an own print_item_show_value function implemented.
9d5fbd65
AG
1669 *
1670 * @param object $item the item what we want to print out
3a787259 1671 * @param mixed $value
9d5fbd65
AG
1672 * @return void
1673 */
1674function feedback_print_item_show_value($item, $value = false){
1675 global $CFG;
1676 if($item->typ == 'pagebreak') {
1677 return;
1678 }
6938191b 1679
9d5fbd65 1680 //get the instance of the item-class
6cc1599e 1681 $itemobj = feedback_get_item_class($item->typ);
9d5fbd65 1682 $itemobj->print_item_show_value($item, $value);
c70ad9f7 1683}
1684
37b86a39 1685/**
32be99dc 1686 * if the user completes a feedback and there is a pagebreak so the values are saved temporary.
3a787259 1687 * the values are not saved permanently until the user click on save button
32be99dc 1688 *
1689 * @global object
1690 * @param object $feedbackcompleted
1691 * @return object temporary saved completed-record
c70ad9f7 1692 */
0085fff8 1693function feedback_set_tmp_values($feedbackcompleted) {
1694 global $DB;
1695
c70ad9f7 1696 //first we create a completedtmp
39790bd8 1697 $tmpcpl = new stdClass();
c70ad9f7 1698 foreach($feedbackcompleted as $key => $value) {
1699 $tmpcpl->{$key} = $value;
1700 }
1701 // $tmpcpl = $feedbackcompleted;
0085fff8 1702 unset($tmpcpl->id);
c70ad9f7 1703 $tmpcpl->timemodified = time();
7826abc7 1704 $tmpcpl->id = $DB->insert_record('feedback_completedtmp', $tmpcpl);
c70ad9f7 1705 //get all values of original-completed
0085fff8 1706 if(!$values = $DB->get_records('feedback_value', array('completed'=>$feedbackcompleted->id))) {
c70ad9f7 1707 return;
1708 }
1709 foreach($values as $value) {
0085fff8 1710 unset($value->id);
c70ad9f7 1711 $value->completed = $tmpcpl->id;
0085fff8 1712 $DB->insert_record('feedback_valuetmp', $value);
c70ad9f7 1713 }
1714 return $tmpcpl;
1715}
1716
37b86a39 1717/**
32be99dc 1718 * this saves the temporary saved values permanently
1719 *
1720 * @global object
1721 * @param object $feedbackcompletedtmp the temporary completed
1722 * @param object $feedbackcompleted the target completed
1723 * @param int $userid
1724 * @return int the id of the completed
c70ad9f7 1725 */
1726function feedback_save_tmp_values($feedbackcompletedtmp, $feedbackcompleted, $userid) {
0085fff8 1727 global $DB;
1728
c70ad9f7 1729 $tmpcplid = $feedbackcompletedtmp->id;
73043833 1730 if($feedbackcompleted) {
c70ad9f7 1731 //first drop all existing values
0085fff8 1732 $DB->delete_records('feedback_value', array('completed'=>$feedbackcompleted->id));
c70ad9f7 1733 //update the current completed
1734 $feedbackcompleted->timemodified = time();
0085fff8 1735 $DB->update_record('feedback_completed', $feedbackcompleted);
73043833
AG
1736 }else {
1737 $feedbackcompleted = clone($feedbackcompletedtmp);
1738 $feedbackcompleted->id = '';
1739 $feedbackcompleted->userid = $userid;
1740 $feedbackcompleted->timemodified = time();
1741 $feedbackcompleted->id = $DB->insert_record('feedback_completed', $feedbackcompleted);
1742 }
1743
1744 //save all the new values from feedback_valuetmp
1745 //get all values of tmp-completed
1746 if(!$values = $DB->get_records('feedback_valuetmp', array('completed'=>$feedbackcompletedtmp->id))) {
1747 return false;
1748 }
1749 foreach($values as $value) {
1750 //check if there are depend items
1751 $item = $DB->get_record('feedback_item', array('id'=>$value->item));
1752 if($item->dependitem > 0) {
1753 $check = feedback_compare_item_value($tmpcplid, $item->dependitem, $item->dependvalue, true);
1754 }else {
1755 $check = true;
c70ad9f7 1756 }
73043833 1757 if($check) {
0085fff8 1758 unset($value->id);
c70ad9f7 1759 $value->completed = $feedbackcompleted->id;
0085fff8 1760 $DB->insert_record('feedback_value', $value);
c70ad9f7 1761 }
c70ad9f7 1762 }
73043833
AG
1763 //drop all the tmpvalues
1764 $DB->delete_records('feedback_valuetmp', array('completed'=>$tmpcplid));
1765 $DB->delete_records('feedback_completedtmp', array('id'=>$tmpcplid));
1766 return $feedbackcompleted->id;
1767
c70ad9f7 1768}
1769
37b86a39 1770/**
32be99dc 1771 * deletes the given temporary completed and all related temporary values
1772 *
1773 * @global object
1774 * @param int $tmpcplid
1775 * @return void
c70ad9f7 1776 */
1777function feedback_delete_completedtmp($tmpcplid) {
0085fff8 1778 global $DB;
1779
1780 $DB->delete_records('feedback_valuetmp', array('completed'=>$tmpcplid));
1781 $DB->delete_records('feedback_completedtmp', array('id'=>$tmpcplid));
c70ad9f7 1782}
1783
1784////////////////////////////////////////////////
1785////////////////////////////////////////////////
1786////////////////////////////////////////////////
1787//functions to handle the pagebreaks
1788////////////////////////////////////////////////
1789
37b86a39 1790/**
32be99dc 1791 * this creates a pagebreak.
1792 * a pagebreak is a special kind of item
1793 *
1794 * @global object
1795 * @param int $feedbackid
1796 * @return mixed false if there already is a pagebreak on last position or the id of the pagebreak-item
c70ad9f7 1797 */
1798function feedback_create_pagebreak($feedbackid) {
0085fff8 1799 global $DB;
1800
c70ad9f7 1801 //check if there already is a pagebreak on the last position
0085fff8 1802 $lastposition = $DB->count_records('feedback_item', array('feedback'=>$feedbackid));
c70ad9f7 1803 if($lastposition == feedback_get_last_break_position($feedbackid)) {
1804 return false;
1805 }
37b86a39 1806
39790bd8 1807 $item = new stdClass();
c70ad9f7 1808 $item->feedback = $feedbackid;
1809
1810 $item->template=0;
1811
1812 $item->name = '';
37b86a39 1813
c70ad9f7 1814 $item->presentation = '';
1815 $item->hasvalue = 0;
37b86a39 1816
c70ad9f7 1817 $item->typ = 'pagebreak';
1818 $item->position = $lastposition + 1;
1819
1820 $item->required=0;
1821
0085fff8 1822 return $DB->insert_record('feedback_item', $item);
c70ad9f7 1823}
1824
37b86a39 1825/**
32be99dc 1826 * get all positions of pagebreaks in the given feedback
1827 *
1828 * @global object
1829 * @param int $feedbackid
1830 * @return array all ordered pagebreak positions
c70ad9f7 1831 */
1832function feedback_get_all_break_positions($feedbackid) {
534792cd 1833 global $DB;
1834
1835 if(!$allbreaks = $DB->get_records_menu('feedback_item', array('typ'=>'pagebreak', 'feedback'=>$feedbackid), 'position', 'id, position')) return false;
c70ad9f7 1836 return array_values($allbreaks);
1837}
1838
37b86a39 1839/**
32be99dc 1840 * get the position of the last pagebreak
d4b1d58c 1841 *
32be99dc 1842 * @param int $feedbackid
1843 * @return int the position of the last pagebreak
c70ad9f7 1844 */
1845function feedback_get_last_break_position($feedbackid) {
73043833
AG
1846 if(!$allbreaks = feedback_get_all_break_positions($feedbackid)) {
1847 return false;
1848 }
c70ad9f7 1849 return $allbreaks[count($allbreaks) - 1];
1850}
1851
37b86a39 1852/**
32be99dc 1853 * this returns the position where the user can continue the completing.
1854 *
1855 * @global object
1856 * @global object
1857 * @global object
1858 * @param int $feedbackid
1859 * @param int $courseid
1860 * @param string $guestid this id will be saved temporary and is unique
1861 * @return int the position to continue
c70ad9f7 1862 */
3a787259 1863function feedback_get_page_to_continue($feedbackid, $courseid = false, $guestid = false) {
0085fff8 1864 global $CFG, $USER, $DB;
37b86a39 1865
c70ad9f7 1866 //is there any break?
37b86a39 1867
c70ad9f7 1868 if(!$allbreaks = feedback_get_all_break_positions($feedbackid)) return false;
0085fff8 1869
1870 $params = array();
c70ad9f7 1871 if($courseid) {
05edae9f 1872 $courseselect = "AND fv.course_id = :courseid";
0085fff8 1873 $params['courseid'] = $courseid;
c70ad9f7 1874 }else {
05edae9f 1875 $courseselect = '';
c70ad9f7 1876 }
37b86a39 1877
c70ad9f7 1878 if($guestid) {
0085fff8 1879 $userselect = "AND fc.guestid = :guestid";
c70ad9f7 1880 $usergroup = "GROUP BY fc.guestid";
0085fff8 1881 $params['guestid'] = $guestid;
c70ad9f7 1882 }else {
0085fff8 1883 $userselect = "AND fc.userid = :userid";
c70ad9f7 1884 $usergroup = "GROUP BY fc.userid";
0085fff8 1885 $params['userid'] = $USER->id;
c70ad9f7 1886 }
0085fff8 1887
c70ad9f7 1888 $sql = "SELECT MAX(fi.position)
abf1c50f 1889 FROM {feedback_completedtmp} fc, {feedback_valuetmp} fv, {feedback_item} fi
0085fff8 1890 WHERE fc.id = fv.completed
1891 $userselect
1892 AND fc.feedback = :feedbackid
05edae9f 1893 $courseselect
c70ad9f7 1894 AND fi.id = fv.item
0085fff8 1895 $usergroup";
1896 $params['feedbackid'] = $feedbackid;
1897
1898 $lastpos = $DB->get_field_sql($sql, $params);
c70ad9f7 1899
1900 //the index of found pagebreak is the searched pagenumber
1901 foreach($allbreaks as $pagenr => $br) {
1902 if($lastpos < $br) return $pagenr;
1903 }
1904 return count($allbreaks);
1905}
1906
1907////////////////////////////////////////////////
1908////////////////////////////////////////////////
1909////////////////////////////////////////////////
1910//functions to handle the values
1911////////////////////////////////////////////////
1912
37b86a39 1913/**
32be99dc 1914 * this saves the values of an completed.
3a787259
AG
1915 * if the param $tmp is set true so the values are saved temporary in table feedback_valuetmp.
1916 * if there is already a completed and the userid is set so the values are updated.
1917 * on all other things new value records will be created.
d4b1d58c 1918 *
32be99dc 1919 * @global object
32be99dc 1920 * @param int $userid
1921 * @param boolean $tmp
1922 * @return mixed false on error or the completeid
c70ad9f7 1923 */
6a471fe0 1924function feedback_save_values($usrid, $tmp = false) {
0085fff8 1925 global $DB;
6938191b 1926
6a471fe0 1927 $completedid = optional_param('completedid', false, PARAM_INT);
0085fff8 1928
c70ad9f7 1929 $tmpstr = $tmp ? 'tmp' : '';
6a471fe0
AG
1930 $time = time();
1931 $timemodified = mktime(0, 0, 0, date('m', $time),date('d', $time),date('Y', $time));
1932
c70ad9f7 1933 if($usrid == 0) {
6a471fe0 1934 return feedback_create_values($usrid, $timemodified, $tmp);
c70ad9f7 1935 }
6a471fe0
AG
1936 if(!$completedid or !$completed = $DB->get_record('feedback_completed'.$tmpstr, array('id'=>$completedid))) {
1937 return feedback_create_values($usrid, $timemodified, $tmp);
c70ad9f7 1938 }else{
1939 $completed->timemodified = $timemodified;
6a471fe0 1940 return feedback_update_values($completed, $tmp);
c70ad9f7 1941 }
1942}
1943
37b86a39 1944/**
32be99dc 1945 * this saves the values from anonymous user such as guest on the main-site
1946 *
1947 * @global object
32be99dc 1948 * @param string $guestid the unique guestidentifier
1949 * @return mixed false on error or the completeid
c70ad9f7 1950 */
6a471fe0 1951function feedback_save_guest_values($guestid) {
0085fff8 1952 global $DB;
1953
6a471fe0 1954 $completedid = optional_param('completedid', false, PARAM_INT);
6938191b 1955
c70ad9f7 1956 $timemodified = time();
6a471fe0
AG
1957 if(!$completed = $DB->get_record('feedback_completedtmp', array('id'=>$completedid))) {
1958 return feedback_create_values(0, $timemodified, true, $guestid);
c70ad9f7 1959 }else {
1960 $completed->timemodified = $timemodified;
6a471fe0 1961 return feedback_update_values($completed, true);
c70ad9f7 1962 }
1963}
1964
37b86a39 1965/**
32be99dc 1966 * get the value from the given item related to the given completed.
1967 * the value can come as temporary or as permanently value. the deciding is done by $tmp
1968 *
1969 * @global object
1970 * @param int $completeid
1971 * @param int $itemid
1972 * @param boolean $tmp
1973 * @return mixed the value, the type depends on plugin-definition
c70ad9f7 1974 */
1975function feedback_get_item_value($completedid, $itemid, $tmp = false) {
0085fff8 1976 global $DB;
1977
c70ad9f7 1978 $tmpstr = $tmp ? 'tmp' : '';
0085fff8 1979 return $DB->get_field('feedback_value'.$tmpstr, 'value', array('completed'=>$completedid, 'item'=>$itemid));
c70ad9f7 1980}
1981
3a787259
AG
1982/**
1983 * compares the value of the itemid related to the completedid with the dependvalue.
1984 * this is used if a depend item is set.
1985 * the value can come as temporary or as permanently value. the deciding is done by $tmp.
1986 *
1987 * @global object
1988 * @global object
1989 * @param int $completeid
1990 * @param int $itemid
1991 * @param mixed $dependvalue
1992 * @param boolean $tmp
1993 * @return bool
1994 */
73043833
AG
1995function feedback_compare_item_value($completedid, $itemid, $dependvalue, $tmp = false) {
1996 global $DB, $CFG;
6938191b 1997
73043833 1998 $dbvalue = feedback_get_item_value($completedid, $itemid, $tmp);
6938191b 1999
73043833
AG
2000 //get the class of the given item-typ
2001 $item = $DB->get_record('feedback_item', array('id'=>$itemid));
6cc1599e 2002
73043833 2003 //get the instance of the item-class
6cc1599e 2004 $itemobj = feedback_get_item_class($item->typ);
73043833
AG
2005 return $itemobj->compare_value($item, $dbvalue, $dependvalue); //true or false
2006}
2007
37b86a39 2008/**
32be99dc 2009 * this function checks the correctness of values.
2010 * the rules for this are implemented in the class of each item.
2011 * it can be the required attribute or the value self e.g. numeric.
2012 * the params first/lastitem are given to determine the visible range between pagebreaks.
2013 *
2014 * @global object
32be99dc 2015 * @param int $firstitem the position of firstitem for checking
2016 * @param int $lastitem the position of lastitem for checking
2017 * @return boolean
c70ad9f7 2018 */
6a471fe0 2019function feedback_check_values($firstitem, $lastitem) {
ab5bd34d 2020 global $DB, $CFG;
0085fff8 2021
6a471fe0
AG
2022 $feedbackid = optional_param('feedbackid', 0, PARAM_INT);
2023
c70ad9f7 2024 //get all items between the first- and lastitem
0085fff8 2025 $select = "feedback = ?
2026 AND position >= ?
2027 AND position <= ?
c70ad9f7 2028 AND hasvalue = 1";
6a471fe0 2029 $params = array($feedbackid, $firstitem, $lastitem);
0085fff8 2030 if(!$feedbackitems = $DB->get_records_select('feedback_item', $select, $params)) {
c70ad9f7 2031 //if no values are given so no values can be wrong ;-)
2032 return true;
2033 }
2034
2035 foreach($feedbackitems as $item) {
2036 //the name of the input field of the completeform is given in a special form:
2037 //<item-typ>_<item-id> eg. numeric_234
2038 //this is the key to get the value for the correct item
2039 $formvalname = $item->typ . '_' . $item->id;
6938191b 2040
6a471fe0 2041 $value = optional_param($formvalname, NULL, PARAM_RAW);
6938191b 2042
c70ad9f7 2043 //check if the value is set
6a471fe0 2044 if(is_null($value) AND $item->required == 1) {
c70ad9f7 2045 return false;
2046 }
37b86a39 2047
c70ad9f7 2048 //get the instance of the item-class
6cc1599e 2049 $itemobj = feedback_get_item_class($item->typ);
37b86a39 2050
c70ad9f7 2051 //now we let check the value by the item-class
2052 if(!$itemobj->check_value($value, $item)) {
2053 return false;
2054 }
2055 }
2056 //if no wrong values so we can return true
2057 return true;
2058}
2059
37b86a39 2060/**
32be99dc 2061 * this function create a complete-record and the related value-records.
2062 * depending on the $tmp (true/false) the values are saved temporary or permanently
2063 *
2064 * @global object
32be99dc 2065 * @param int $userid
2066 * @param int $timemodified
2067 * @param boolean $tmp
2068 * @param string $guestid a unique identifier to save temporary data
2069 * @return mixed false on error or the completedid
c70ad9f7 2070 */
6a471fe0 2071function feedback_create_values($usrid, $timemodified, $tmp = false, $guestid = false){
0085fff8 2072 global $DB;
2073
6a471fe0
AG
2074 $feedbackid = optional_param('feedbackid', false, PARAM_INT);
2075 $anonymous_response = optional_param('anonymous_response', false, PARAM_INT);
2076 $courseid = optional_param('courseid', false, PARAM_INT);
6938191b 2077
c70ad9f7 2078 $tmpstr = $tmp ? 'tmp' : '';
2079 //first we create a new completed record
39790bd8 2080 $completed = new stdClass();
6a471fe0 2081 $completed->feedback = $feedbackid;
0085fff8 2082 $completed->userid = $usrid;
2083 $completed->guestid = $guestid;
2084 $completed->timemodified = $timemodified;
6a471fe0 2085 $completed->anonymous_response = $anonymous_response;
37b86a39 2086
a8f3a651 2087 $completedid = $DB->insert_record('feedback_completed'.$tmpstr, $completed);
37b86a39 2088
0085fff8 2089 $completed = $DB->get_record('feedback_completed'.$tmpstr, array('id'=>$completedid));
c70ad9f7 2090
6a471fe0 2091 //the keys are in the form like abc_xxx
c70ad9f7 2092 //with explode we make an array with(abc, xxx) and (abc=typ und xxx=itemnr)
6938191b 2093
6a471fe0
AG
2094 //get the items of the feedback
2095 if(!$allitems = $DB->get_records('feedback_item', array('feedback'=>$completed->feedback))) {
2096 return false;
2097 }
2098 foreach($allitems as $item) {
2099 $keyname = $item->typ.'_'.$item->id;
2100 $itemvalue = optional_param($keyname, NULL, PARAM_RAW);
2101 if(is_null($itemvalue)) {
2102 continue;
c70ad9f7 2103 }
39790bd8 2104 $value = new stdClass();
6a471fe0
AG
2105 $value->item = $item->id;
2106 $value->completed = $completed->id;
2107 $value->course_id = $courseid;
6938191b 2108
6a471fe0 2109 //get the class of item-typ
6cc1599e 2110 $itemobj = feedback_get_item_class($item->typ);
6938191b 2111
6a471fe0
AG
2112 //the kind of values can be absolutely different so we run create_value directly by the item-class
2113 $value->value = $itemobj->create_value($itemvalue);
2114 $DB->insert_record('feedback_value'.$tmpstr, $value);
c70ad9f7 2115 }
6a471fe0 2116 return $completed->id;
c70ad9f7 2117}
2118
37b86a39 2119/**
32be99dc 2120 * this function updates a complete-record and the related value-records.
2121 * depending on the $tmp (true/false) the values are saved temporary or permanently
2122 *
2123 * @global object
32be99dc 2124 * @param object $completed
2125 * @param boolean $tmp
2126 * @return int the completedid
c70ad9f7 2127 */
6a471fe0 2128function feedback_update_values($completed, $tmp = false) {
0085fff8 2129 global $DB;
6a471fe0 2130 $courseid = optional_param('courseid', false, PARAM_INT);
0085fff8 2131
c70ad9f7 2132 $tmpstr = $tmp ? 'tmp' : '';
37b86a39 2133
0085fff8 2134 $DB->update_record('feedback_completed'.$tmpstr, $completed);
c70ad9f7 2135 //get the values of this completed
0085fff8 2136 $values = $DB->get_records('feedback_value'.$tmpstr, array('completed'=>$completed->id));
37b86a39 2137
6a471fe0
AG
2138 //get the items of the feedback
2139 if(!$allitems = $DB->get_records('feedback_item', array('feedback'=>$completed->feedback))) {
2140 return false;
2141 }
2142 foreach($allitems as $item) {
2143 $keyname = $item->typ.'_'.$item->id;
2144 $itemvalue = optional_param($keyname, NULL, PARAM_RAW);
2145 //is the itemvalue set (could be a subset of items because pagebreak)?
2146 if(is_null($itemvalue)) {
2147 continue;
2148 }
6938191b 2149
39790bd8 2150 $newvalue = new stdClass();
6a471fe0
AG
2151 $newvalue->item = $item->id;
2152 $newvalue->completed = $completed->id;
2153 $newvalue->course_id = $courseid;
37b86a39 2154
6a471fe0 2155 //get the class of item-typ
6cc1599e 2156 $itemobj = feedback_get_item_class($item->typ);
6a471fe0
AG
2157 //the kind of values can be absolutely different so we run create_value directly by the item-class
2158 $newvalue->value = $itemobj->create_value($itemvalue);
6938191b 2159
6a471fe0
AG
2160 //check, if we have to create or update the value
2161 $exist = false;
2162 foreach($values as $value){
2163 if($value->item == $newvalue->item){
2164 $newvalue->id = $value->id;
2165 $exist = true;
2166 break;
2167 }
2168 }
2169 if($exist){
2170 $DB->update_record('feedback_value'.$tmpstr, $newvalue);
2171 }else {
2172 $DB->insert_record('feedback_value'.$tmpstr, $newvalue);
c70ad9f7 2173 }
2174 }
2175
2176 return $completed->id;
2177}
2178
37b86a39 2179/**
32be99dc 2180 * get the values of an item depending on the given groupid.
2181 * if the feedback is anonymous so the values are shuffled
2182 *
2183 * @global object
2184 * @global object
2185 * @param object $item
2186 * @param int $groupid
2187 * @param int $courseid
3a787259 2188 * @param bool $ignore_empty if this is set true so empty values are not delivered
32be99dc 2189 * @return array the value-records
c70ad9f7 2190 */
79473294 2191function feedback_get_group_values($item, $groupid = false, $courseid = false, $ignore_empty = false){
0085fff8 2192 global $CFG, $DB;
c70ad9f7 2193
2194 //if the groupid is given?
0085fff8 2195 if (intval($groupid) > 0) {
79473294 2196 if($ignore_empty) {
5cf4fa46 2197 $ignore_empty_select = "AND fbv.value != ''";
79473294
AG
2198 }
2199 else {
2200 $ignore_empty_select = "";
2201 }
6938191b 2202
c70ad9f7 2203 $query = 'SELECT fbv . *
abf1c50f 2204 FROM {feedback_value} fbv, {feedback_completed} fbc, {groups_members} gm
0085fff8 2205 WHERE fbv.item = ?
37b86a39 2206 AND fbv.completed = fbc.id
2207 AND fbc.userid = gm.userid
79473294 2208 '.$ignore_empty_select.'
0085fff8 2209 AND gm.groupid = ?
2210 ORDER BY fbc.timemodified';
2211 $values = $DB->get_records_sql($query, array($item->id, $groupid));
2212
2213 } else {
79473294
AG
2214 if($ignore_empty) {
2215 $ignore_empty_select = "AND value != ''";
2216 }
2217 else {
2218 $ignore_empty_select = "";
2219 }
6938191b 2220
c70ad9f7 2221 if ($courseid) {
79473294 2222 $values = $DB->get_records_select('feedback_value', "item = ? AND course_id = ? ".$ignore_empty_select, array($item->id, $courseid));
c70ad9f7 2223 } else {
79473294 2224 $values = $DB->get_records_select('feedback_value', "item = ? ".$ignore_empty_select, array($item->id));
c70ad9f7 2225 }
37b86a39 2226 }
0085fff8 2227 if ($DB->get_field('feedback', 'anonymous', array('id'=>$item->feedback)) == FEEDBACK_ANONYMOUS_YES) {
c70ad9f7 2228 if(is_array($values))
2229 shuffle($values);
2230 }
2231 return $values;
2232}
2233
37b86a39 2234/**
32be99dc 2235 * check for multiple_submit = false.
2236 * if the feedback is global so the courseid must be given
2237 *
2238 * @global object
2239 * @global object
2240 * @param int $feedbackid
2241 * @param int $courseid
2242 * @return boolean true if the feedback already is submitted otherwise false
c70ad9f7 2243 */
2244function feedback_is_already_submitted($feedbackid, $courseid = false) {
534792cd 2245 global $USER, $DB;
37b86a39 2246
534792cd 2247 if (!$trackings = $DB->get_records_menu('feedback_tracking', array('userid'=>$USER->id, 'feedback'=>$feedbackid), '', 'id, completed')) {
c70ad9f7 2248 return false;
2249 }
2250
2251 if($courseid) {
534792cd 2252 $select = 'completed IN ('.implode(',',$trackings).') AND course_id = ?';
2253 if(!$values = $DB->get_records_select('feedback_value', $select, array($courseid))) {
c70ad9f7 2254 return false;
2255 }
2256 }
2257
2258 return true;
2259}
2260
37b86a39 2261/**
32be99dc 2262 * if the completion of a feedback will be continued eg. by pagebreak or by multiple submit so the complete must be found.
2263 * if the param $tmp is set true so all things are related to temporary completeds
2264 *
2265 * @global object
2266 * @global object
2267 * @global object
2268 * @param int $feedbackid
2269 * @param boolean $tmp
2270 * @param int $courseid
2271 * @param string $guestid
2272 * @return int the id of the found completed
c70ad9f7 2273 */
2274function feedback_get_current_completed($feedbackid, $tmp = false, $courseid = false, $guestid = false) {
0085fff8 2275 global $USER, $CFG, $DB;
37b86a39 2276
c70ad9f7 2277 $tmpstr = $tmp ? 'tmp' : '';
37b86a39 2278
c70ad9f7 2279 if(!$courseid) {
2280 if($guestid) {
0085fff8 2281 return $DB->get_record('feedback_completed'.$tmpstr, array('feedback'=>$feedbackid, 'guestid'=>$guestid));
c70ad9f7 2282 }else {
0085fff8 2283 return $DB->get_record('feedback_completed'.$tmpstr, array('feedback'=>$feedbackid, 'userid'=>$USER->id));
c70ad9f7 2284 }
2285 }
37b86a39 2286
0085fff8 2287 $params = array();
37b86a39 2288
0085fff8 2289 if ($guestid) {
2290 $userselect = "AND fc.guestid = :guestid";
2291 $params['guestid'] = $guestid;
c70ad9f7 2292 }else {
0085fff8 2293 $userselect = "AND fc.userid = :userid";
2294 $params['userid'] = $USER->id;
c70ad9f7 2295 }
2296 //if courseid is set the feedback is global. there can be more than one completed on one feedback
31c0fa53 2297 $sql = "SELECT DISTINCT fc.*
abf1c50f 2298 FROM {feedback_value{$tmpstr}} fv, {feedback_completed{$tmpstr}} fc
0085fff8 2299 WHERE fv.course_id = :courseid
c70ad9f7 2300 AND fv.completed = fc.id
0085fff8 2301 $userselect
2302 AND fc.feedback = :feedbackid";
2303 $params['courseid'] = intval($courseid);
2304 $params['feedbackid'] = $feedbackid;
c70ad9f7 2305
d90e0ef3 2306 if (!$sqlresult = $DB->get_records_sql($sql, $params)) {
0085fff8 2307 return false;
2308 }
c70ad9f7 2309 foreach($sqlresult as $r) {
0085fff8 2310 return $DB->get_record('feedback_completed'.$tmpstr, array('id'=>$r->id));
c70ad9f7 2311 }
2312}
2313
37b86a39 2314/**
32be99dc 2315 * get the completeds depending on the given groupid.
2316 *
2317 * @global object
2318 * @global object
2319 * @param object $feedback
2320 * @param int $groupid
3a787259 2321 * @param int $courseid
32be99dc 2322 * @return mixed array of found completeds otherwise false
c70ad9f7 2323 */
59f89d80 2324function feedback_get_completeds_group($feedback, $groupid = false, $courseid = false) {
0085fff8 2325 global $CFG, $DB;
2326
2327 if (intval($groupid) > 0){
2328 $query = "SELECT fbc.*
abf1c50f 2329 FROM {feedback_completed} fbc, {groups_members} gm
0085fff8 2330 WHERE fbc.feedback = ?
2331 AND gm.groupid = ?
2332 AND fbc.userid = gm.userid";
2333 if ($values = $DB->get_records_sql($query, array($feedback->id, $groupid))) {
c70ad9f7 2334 return $values;
0085fff8 2335 } else {
2336 return false;
2337 }
2338 } else {
59f89d80 2339 if($courseid) {
2340 $query = "SELECT DISTINCT fbc.*
abf1c50f 2341 FROM {feedback_completed} fbc, {feedback_value} fbv
59f89d80 2342 WHERE fbc.id = fbv.completed
2343 AND fbc.feedback = ?
2344 AND fbv.course_id = ?
2345 ORDER BY random_response";
2346 if ($values = $DB->get_records_sql($query, array($feedback->id, $courseid))) {
2347 return $values;
2348 } else {
2349 return false;
2350 }
2351 }else {
2352 if ($values = $DB->get_records('feedback_completed', array('feedback'=>$feedback->id))) {
2353 return $values;
2354 } else {
2355 return false;
2356 }
0085fff8 2357 }
c70ad9f7 2358 }
2359}
2360
37b86a39 2361/**
32be99dc 2362 * get the count of completeds depending on the given groupid.
2363 *
2364 * @global object
2365 * @global object
2366 * @param object $feedback
2367 * @param int $groupid
2368 * @param int $courseid
2369 * @return mixed count of completeds or false
c70ad9f7 2370 */
2371function feedback_get_completeds_group_count($feedback, $groupid = false, $courseid = false) {
0085fff8 2372 global $CFG, $DB;
2373
2374 if ($courseid > 0 AND !$groupid <= 0) {
2375 $sql = "SELECT id, COUNT(item) AS ci
37b86a39 2376 FROM {feedback_value}
0085fff8 2377 WHERE course_id = ?
2378 GROUP BY item ORDER BY ci DESC";
2379 if ($foundrecs = $DB->get_records_sql($sql, array($courseid))) {
c70ad9f7 2380 $foundrecs = array_values($foundrecs);
2381 return $foundrecs[0]->ci;
2382 }
2383 return false;
2384 }
2385 if($values = feedback_get_completeds_group($feedback, $groupid)) {
2386 return sizeof($values);
2387 }else {
2388 return false;
2389 }
2390}
2391
37b86a39 2392/**
32be99dc 2393 * deletes all completed-recordsets from a feedback.
2394 * all related data such as values also will be deleted
2395 *
2396 * @global object
2397 * @param int $feedbackid
2398 * @return void
c70ad9f7 2399 */
2400function feedback_delete_all_completeds($feedbackid) {
0085fff8 2401 global $DB;
2402
2403 if (!$completeds = $DB->get_records('feedback_completed', array('feedback'=>$feedbackid))) {
2404 return;
2405 }
c70ad9f7 2406 foreach($completeds as $completed) {
2407 feedback_delete_completed($completed->id);
2408 }
2409}
2410
37b86a39 2411/**
32be99dc 2412 * deletes a completed given by completedid.
2413 * all related data such values or tracking data also will be deleted
d4b1d58c 2414 *
32be99dc 2415 * @global object
2416 * @param int $completedid
2417 * @return boolean
c70ad9f7 2418 */
2419function feedback_delete_completed($completedid) {
516c5eca
PS
2420 global $DB, $CFG;
2421 require_once($CFG->libdir.'/completionlib.php');
0085fff8 2422
2423 if (!$completed = $DB->get_record('feedback_completed', array('id'=>$completedid))) {
c70ad9f7 2424 return false;
2425 }
516c5eca 2426
8a41eb4f
AG
2427 if (!$feedback = $DB->get_record('feedback', array('id'=>$completed->feedback))) {
2428 return false;
2429 }
516c5eca 2430
8a41eb4f
AG
2431 if (!$course = $DB->get_record('course', array('id'=>$feedback->course))) {
2432 return false;
2433 }
516c5eca 2434
8a41eb4f
AG
2435 if (!$cm = get_coursemodule_from_instance('feedback', $feedback->id)) {
2436 return false;
2437 }
2438
c70ad9f7 2439 //first we delete all related values
0085fff8 2440 $DB->delete_records('feedback_value', array('completed'=>$completed->id));
37b86a39 2441
c70ad9f7 2442 //now we delete all tracking data
0085fff8 2443 if($tracking = $DB->get_record('feedback_tracking', array('completed'=>$completed->id, 'feedback'=>$completed->feedback))) {
2444 $DB->delete_records('feedback_tracking', array('completed'=>$completed->id));
c70ad9f7 2445 }
37b86a39 2446
8a41eb4f
AG
2447 // Update completion state
2448 $completion = new completion_info($course);
2449 if ($completion->is_enabled($cm) && $feedback->completionsubmit) {
2450 $completion->update_state($cm, COMPLETION_INCOMPLETE, $completed->userid);
2451 }
c70ad9f7 2452 //last we delete the completed-record
0085fff8 2453 return $DB->delete_records('feedback_completed', array('id'=>$completed->id));
c70ad9f7 2454}
2455
2456////////////////////////////////////////////////
2457////////////////////////////////////////////////
2458////////////////////////////////////////////////
2459//functions to handle sitecourse mapping
2460////////////////////////////////////////////////
2461
37b86a39 2462/**
32be99dc 2463 * checks if the course and the feedback is in the table feedback_sitecourse_map.
2464 *
2465 * @global object
2466 * @param int $feedbackid
2467 * @param int $courseid
2468 * @return int the count of records
c70ad9f7 2469 */
2470function feedback_is_course_in_sitecourse_map($feedbackid, $courseid) {
0085fff8 2471 global $DB;
2472 return $DB->count_records('feedback_sitecourse_map', array('feedbackid'=>$feedbackid, 'courseid'=>$courseid));
c70ad9f7 2473}
2474
37b86a39 2475/**
32be99dc 2476 * checks if the feedback is in the table feedback_sitecourse_map.
2477 *
2478 * @global object
2479 * @param int $feedbackid
2480 * @return boolean
c70ad9f7 2481 */
2482function feedback_is_feedback_in_sitecourse_map($feedbackid) {
436bbff3 2483 global $DB;
0085fff8 2484 return $DB->record_exists('feedback_sitecourse_map', array('feedbackid'=>$feedbackid));
c70ad9f7 2485}
2486
37b86a39 2487/**
32be99dc 2488 * gets the feedbacks from table feedback_sitecourse_map.
2489 * this is used to show the global feedbacks on the feedback block
2490 * all feedbacks with the following criteria will be selected:<br />
2491 *
2492 * 1) all feedbacks which id are listed together with the courseid in sitecoursemap and<br />
2493 * 2) all feedbacks which not are listed in sitecoursemap
2494 *
2495 * @global object
2496 * @param int $courseid
2497 * @return array the feedback-records
c70ad9f7 2498 */
2499function feedback_get_feedbacks_from_sitecourse_map($courseid) {
0085fff8 2500 global $DB;
37b86a39 2501
c70ad9f7 2502 //first get all feedbacks listed in sitecourse_map with named courseid
0085fff8 2503 $sql = "SELECT f.id AS id, cm.id AS cmid, f.name AS name, f.timeopen AS timeopen, f.timeclose AS timeclose
2504 FROM {feedback} f, {course_modules} cm, {feedback_sitecourse_map} sm, {modules} m
2505 WHERE f.id = cm.instance
2506 AND f.course = '".SITEID."'
37b86a39 2507 AND m.id = cm.module
0085fff8 2508 AND m.name = 'feedback'
37b86a39 2509 AND sm.courseid = ?
0085fff8 2510 AND sm.feedbackid = f.id";
37b86a39 2511
0085fff8 2512 if (!$feedbacks1 = $DB->get_records_sql($sql, array($courseid))) {
c70ad9f7 2513 $feedbacks1 = array();
2514 }
37b86a39 2515
c70ad9f7 2516 //second get all feedbacks not listed in sitecourse_map
2517 $feedbacks2 = array();
0085fff8 2518 $sql = "SELECT f.id AS id, cm.id AS cmid, f.name AS name, f.timeopen AS timeopen, f.timeclose AS timeclose
2519 FROM {feedback} f, {course_modules} cm, {modules} m
2520 WHERE f.id = cm.instance
2521 AND f.course = '".SITEID."'
2522 AND m.id = cm.module
2523 AND m.name = 'feedback'";
2524 if (!$allfeedbacks = $DB->get_records_sql($sql)) {
c70ad9f7 2525 $allfeedbacks = array();
2526 }
2527 foreach($allfeedbacks as $a) {
0085fff8 2528 if(!$DB->record_exists('feedback_sitecourse_map', array('feedbackid'=>$a->id))) {
c70ad9f7 2529 $feedbacks2[] = $a;
2530 }
2531 }
37b86a39 2532
c70ad9f7 2533 return array_merge($feedbacks1, $feedbacks2);
37b86a39 2534
c70ad9f7 2535}
2536
37b86a39 2537/**
32be99dc 2538 * gets the courses from table feedback_sitecourse_map.
2539 *
2540 * @global object
2541 * @param int $feedbackid
2542 * @return array the course-records
c70ad9f7 2543 */
2544function feedback_get_courses_from_sitecourse_map($feedbackid) {
0085fff8 2545 global $DB;
37b86a39 2546
0085fff8 2547 $sql = "SELECT f.id, f.courseid, c.fullname, c.shortname
2548 FROM {feedback_sitecourse_map} f, {course} c
2549 WHERE c.id = f.courseid
2550 AND f.feedbackid = ?
2551 ORDER BY c.fullname";
37b86a39 2552
0085fff8 2553 return $DB->get_records_sql($sql, array($feedbackid));
37b86a39 2554
c70ad9f7 2555}
2556
37b86a39 2557/**
32be99dc 2558 * removes non existing courses or feedbacks from sitecourse_map.
2559 * it shouldn't be called all too often
2560 * a good place for it could be the mapcourse.php or unmapcourse.php
d4b1d58c 2561 *
32be99dc 2562 * @global object
2563 * @return void
c70ad9f7 2564 */
2565function feedback_clean_up_sitecourse_map() {
0085fff8 2566 global $DB;
2567
2568 $maps = $DB->get_records('feedback_sitecourse_map');
c70ad9f7 2569 foreach($maps as $map) {
0085fff8 2570 if (!$DB->get_record('course', array('id'=>$map->courseid))) {
2571 $DB->delete_records('feedback_sitecourse_map', array('courseid'=>$map->courseid, 'feedbackid'=>$map->feedbackid));
c70ad9f7 2572 continue;
2573 }
0085fff8 2574 if (!$DB->get_record('feedback', array('id'=>$map->feedbackid))) {
2575 $DB->delete_records('feedback_sitecourse_map', array('courseid'=>$map->courseid, 'feedbackid'=>$map->feedbackid));
c70ad9f7 2576 continue;
2577 }
37b86a39 2578
c70ad9f7 2579 }
2580}
2581
2582////////////////////////////////////////////////
2583////////////////////////////////////////////////
2584////////////////////////////////////////////////
2585//not relatable functions
2586////////////////////////////////////////////////
2587
37b86a39 2588/**
32be99dc 2589 * prints the option items of a selection-input item (dropdownlist).
2590 * @param int $startval the first value of the list
2591 * @param int $endval the last value of the list
2592 * @param int $selectval which item should be selected
2593 * @param int $interval the stepsize from the first to the last value
2594 * @return void
c70ad9f7 2595 */
2596function feedback_print_numeric_option_list($startval, $endval, $selectval = '', $interval = 1){
2597 for($i = $startval; $i <= $endval; $i += $interval){
2598 if($selectval == ($i)){
2599 $selected = 'selected="selected"';
2600 }else{
2601 $selected = '';
2602 }
2603 echo '<option '.$selected.'>'.$i.'</option>';
2604 }
2605}
2606
37b86a39 2607/**
32be99dc 2608 * sends an email to the teachers of the course where the given feedback is placed.
2609 *
2610 * @global object
2611 * @global object
2612 * @uses FEEDBACK_ANONYMOUS_NO
2613 * @uses FORMAT_PLAIN
2614 * @param object $cm the coursemodule-record
2615 * @param object $feedback
2616 * @param object $course
2617 * @param int $userid
2618 * @return void
c70ad9f7 2619 */
c184660d 2620function feedback_send_email($cm, $feedback, $course, $userid) {
c6307ef2 2621 global $CFG, $DB;
37b86a39 2622
c70ad9f7 2623 if ($feedback->email_notification == 0) { // No need to do anything
2624 return;
2625 }
37b86a39 2626
0085fff8 2627 $user = $DB->get_record('user', array('id'=>$userid));
37b86a39 2628
84973212 2629 if (isset($cm->groupmode) && empty($course->groupmodeforce)) {
2630 $groupmode = $cm->groupmode;
2631 } else {
2632 $groupmode = $course->groupmode;
2633 }
2634
2635 if ($groupmode == SEPARATEGROUPS) {
c6307ef2 2636 $groups = $DB->get_records_sql_menu("SELECT g.name, g.id
2637 FROM {groups} g, {groups_members} m
2638 WHERE g.courseid = ?
2639 AND g.id = m.groupid
2640 AND m.userid = ?
2641 ORDER BY name ASC", array($course->id, $userid));
c70ad9f7 2642 $groups = array_values($groups);
37b86a39 2643
c184660d 2644 $teachers = feedback_get_receivemail_users($cm->id, $groups);
c70ad9f7 2645 } else {
c184660d 2646 $teachers = feedback_get_receivemail_users($cm->id);
c70ad9f7 2647 }
37b86a39 2648
c70ad9f7 2649 if ($teachers) {
2650
2651 $strfeedbacks = get_string('modulenameplural', 'feedback');
2652 $strfeedback = get_string('modulename', 'feedback');
2653 $strcompleted = get_string('completed', 'feedback');
2654 $printusername = $feedback->anonymous == FEEDBACK_ANONYMOUS_NO ? fullname($user) : get_string('anonymous_user', 'feedback');
37b86a39 2655
c70ad9f7 2656 foreach ($teachers as $teacher) {
39790bd8 2657 $info = new stdClass();
c70ad9f7 2658 $info->username = $printusername;
2659 $info->feedback = format_string($feedback->name,true);
2660 $info->url = $CFG->wwwroot.'/mod/feedback/show_entries.php?id='.$cm->id.'&userid='.$userid.'&do_show=showentries';
2661
2662 $postsubject = $strcompleted.': '.$info->username.' -> '.$feedback->name;
c184660d 2663 $posttext = feedback_send_email_text($info, $course);
2664 $posthtml = ($teacher->mailformat == 1) ? feedback_send_email_html($info, $course, $cm) : '';
37b86a39 2665
c70ad9f7 2666 if($feedback->anonymous == FEEDBACK_ANONYMOUS_NO) {
39790bd8 2667 $eventdata = new stdClass();
51c49cc0
AG
2668 $eventdata->name = 'submission';
2669 $eventdata->component = 'mod_feedback';
3b120e46 2670 $eventdata->userfrom = $user;
2671 $eventdata->userto = $teacher;
2672 $eventdata->subject = $postsubject;
2673 $eventdata->fullmessage = $posttext;
2674 $eventdata->fullmessageformat = FORMAT_PLAIN;
2675 $eventdata->fullmessagehtml = $posthtml;
2676 $eventdata->smallmessage = '';
7c7d3afa 2677 message_send($eventdata);
c70ad9f7 2678 }else {
39790bd8 2679 $eventdata = new stdClass();
51c49cc0
AG
2680 $eventdata->name = 'submission';
2681 $eventdata->component = 'mod_feedback';
3b120e46 2682 $eventdata->userfrom = $teacher;
2683 $eventdata->userto = $teacher;
2684 $eventdata->subject = $postsubject;
2685 $eventdata->fullmessage = $posttext;
2686 $eventdata->fullmessageformat = FORMAT_PLAIN;
2687 $eventdata->fullmessagehtml = $posthtml;
2688 $eventdata->smallmessage = '';
7c7d3afa 2689 message_send($eventdata);
c70ad9f7 2690 }
2691 }
2692 }
2693}
2694
37b86a39 2695/**
32be99dc 2696 * sends an email to the teachers of the course where the given feedback is placed.
2697 *
2698 * @global object
2699 * @uses FORMAT_PLAIN
2700 * @param object $cm the coursemodule-record
2701 * @param object $feedback
2702 * @param object $course
2703 * @return void
c70ad9f7 2704 */
c184660d 2705function feedback_send_email_anonym($cm, $feedback, $course) {
c70ad9f7 2706 global $CFG;
37b86a39 2707
c70ad9f7 2708 if ($feedback->email_notification == 0) { // No need to do anything
2709 return;
2710 }
37b86a39 2711
c184660d 2712 $teachers = feedback_get_receivemail_users($cm->id);
c70ad9f7 2713
2714 if ($teachers) {
2715
2716 $strfeedbacks = get_string('modulenameplural', 'feedback');
2717 $strfeedback = get_string('modulename', 'feedback');
2718 $strcompleted = get_string('completed', 'feedback');
2719 $printusername = get_string('anonymous_user', 'feedback');
37b86a39 2720
c70ad9f7 2721 foreach ($teachers as $teacher) {
39790bd8 2722 $info = new stdClass();
c70ad9f7 2723 $info->username = $printusername;
2724 $info->feedback = format_string($feedback->name,true);
2725 $info->url = $CFG->wwwroot.'/mod/feedback/show_entries_anonym.php?id='.$cm->id;
2726
2727 $postsubject = $strcompleted.': '.$info->username.' -> '.$feedback->name;
c184660d 2728 $posttext = feedback_send_email_text($info, $course);
2729 $posthtml = ($teacher->mailformat == 1) ? feedback_send_email_html($info, $course, $cm) : '';
37b86a39 2730
39790bd8 2731 $eventdata = new stdClass();
51c49cc0
AG
2732 $eventdata->name = 'submission';
2733 $eventdata->component = 'mod_feedback';
3b120e46 2734 $eventdata->userfrom = $teacher;
2735 $eventdata->userto = $teacher;
2736 $eventdata->subject = $postsubject;
2737 $eventdata->fullmessage = $posttext;
2738 $eventdata->fullmessageformat = FORMAT_PLAIN;
2739 $eventdata->fullmessagehtml = $posthtml;
2740 $eventdata->smallmessage = '';
7c7d3afa 2741 message_send($eventdata);
c70ad9f7 2742 }
2743 }
2744}
2745
37b86a39 2746/**
32be99dc 2747 * send the text-part of the email
2748 *
2749 * @param object $info includes some infos about the feedback you want to send
2750 * @param object $course
2751 * @return string the text you want to post
c70ad9f7 2752 */
c184660d 2753function feedback_send_email_text($info, $course) {
8ebbb06a
SH
2754 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
2755 $courseshortname = format_string($course->shortname, true, array('context' => $coursecontext));
2756 $posttext = $courseshortname.' -> '.get_string('modulenameplural', 'feedback').' -> '.
c70ad9f7 2757 $info->feedback."\n";
2758 $posttext .= '---------------------------------------------------------------------'."\n";
2759 $posttext .= get_string("emailteachermail", "feedback", $info)."\n";
2760 $posttext .= '---------------------------------------------------------------------'."\n";
2761 return $posttext;
2762}
2763
2764
37b86a39 2765/**
32be99dc 2766 * send the html-part of the email
2767 *
2768 * @global object
2769 * @param object $info includes some infos about the feedback you want to send
2770 * @param object $course
2771 * @return string the text you want to post
c70ad9f7 2772 */
c184660d 2773function feedback_send_email_html($info, $course, $cm) {
c70ad9f7 2774 global $CFG;
8ebbb06a
SH
2775 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
2776 $courseshortname = format_string($course->shortname, true, array('context' => $coursecontext));
2777
c70ad9f7 2778 $posthtml = '<p><font face="sans-serif">'.
8ebbb06a 2779 '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">'.$courseshortname.'</a> ->'.
5dee2210
AG
2780 '<a href="'.$CFG->wwwroot.'/mod/feedback/index.php?id='.$course->id.'">'.get_string('modulenameplural', 'feedback').'</a> ->'.
2781 '<a href="'.$CFG->wwwroot.'/mod/feedback/view.php?id='.$cm->id.'">'.$info->feedback.'</a></font></p>';
c70ad9f7 2782 $posthtml .= '<hr /><font face="sans-serif">';
2783 $posthtml .= '<p>'.get_string('emailteachermailhtml', 'feedback', $info).'</p>';
2784 $posthtml .= '</font><hr />';
2785 return $posthtml;
2786}
2787
37b86a39 2788/**
32be99dc 2789 * print some errors to inform users about this.
2790 *
2791 * @global object
2792 * @return void
c70ad9f7 2793 */
2794function feedback_print_errors() {
37b86a39 2795
53b1f5da 2796 global $SESSION, $OUTPUT;
37b86a39 2797
f1b9e2df 2798 feedback_init_feedback_session();
2799
c70ad9f7 2800 if(empty($SESSION->feedback->errors)) {
78946b9b 2801 return;
c70ad9f7 2802 }
2803
d4b1d58c 2804 echo $OUTPUT->box_start('generalbox errorboxcontent boxaligncenter boxwidthnormal');
53b1f5da 2805 echo $OUTPUT->heading(get_string('handling_error', 'feedback'));
c70ad9f7 2806
2807 echo '<p align="center"><b><font color="black"><pre>';
2808 print_r($SESSION->feedback->errors) . "\n";
2809 echo '</pre></font></b></p>';
37b86a39 2810
d4b1d58c 2811 echo $OUTPUT->box_end();
c70ad9f7 2812 echo '<br /><br />';
2813 $SESSION->feedback->errors = array(); //remove errors
37b86a39 2814}
c70ad9f7 2815
32be99dc 2816/**
2817 * @param string $url
2818 * @return string
2819 */
c184660d 2820function feedback_encode_target_url($url) {
2821 if (strpos($url, '?')) {
2822 list($part1, $part2) = explode('?', $url, 2); //maximal 2 parts
2823 return $part1 . '?' . htmlentities($part2);
2824 } else {
2825 return $url;
2826 }
2827}
ab5bd34d 2828
0b29477b
SH
2829/**
2830 * Adds module specific settings to the settings block
2831 *
2832 * @param settings_navigation $settings The settings navigation object
2833 * @param navigation_node $feedbacknode The node to add module settings to
2834 */
2835function feedback_extend_settings_navigation(settings_navigation $settings, navigation_node $feedbacknode) {
2836 global $PAGE, $DB;
ab5bd34d 2837
c987dbad 2838 if (!$context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id)) {
3406acde 2839 print_error('badcontext');
c987dbad
AG
2840 }
2841
3406acde
SH
2842 if (has_capability('mod/feedback:edititems', $context)) {
2843 $questionnode = $feedbacknode->add(get_string('questions', 'feedback'));
2844 $questionnode->add(get_string('edit_items', 'feedback'), new moodle_url('/mod/feedback/edit.php', array('id'=>$PAGE->cm->id, 'do_show'=>'edit')));
2845 $questionnode->add(get_string('export_questions', 'feedback'), new moodle_url('/mod/feedback/export.php', array('id'=>$PAGE->cm->id, 'action'=>'exportfile')));
2846 $questionnode->add(get_string('import_questions', 'feedback'), new moodle_url('/mod/feedback/import.php', array('id'=>$PAGE->cm->id)));
2847 $questionnode->add(get_string('templates', 'feedback'), new moodle_url('/mod/feedback/edit.php', array('id'=>$PAGE->cm->id, 'do_show'=>'templates')));
ab5bd34d 2848 }
2849
3406acde 2850 if (has_capability('mod/feedback:viewreports', $context)) {
0b29477b 2851 $feedback = $DB->get_record('feedback', array('id'=>$PAGE->cm->instance));
ab5bd34d 2852 if($feedback->course == SITEID){
0b29477b 2853 $feedbacknode->add(get_string('analysis', 'feedback'), new moodle_url('/mod/feedback/analysis_course.php', array('id'=>$PAGE->cm->id, 'course'=>$PAGE->course->id,'do_show'=>'analysis')));
ab5bd34d 2854 }else {
0b29477b 2855 $feedbacknode->add(get_string('analysis', 'feedback'), new moodle_url('/mod/feedback/analysis.php', array('id'=>$PAGE->cm->id, 'course'=>$PAGE->course->id,'do_show'=>'analysis')));
ab5bd34d 2856 }
ab5bd34d 2857
0b29477b 2858 $feedbacknode->add(get_string('show_entries', 'feedback'), new moodle_url('/mod/feedback/show_entries.php', array('id'=>$PAGE->cm->id, 'do_show'=>'showentries')));
ab5bd34d 2859 }
c987dbad 2860}
f1b9e2df 2861
2862function feedback_init_feedback_session() {
2863 //initialize the feedback-Session - not nice at all!!
2864 global $SESSION;
2865 if (!empty($SESSION)) {
2866 if (!isset($SESSION->feedback) OR !is_object($SESSION->feedback)) {
39790bd8 2867 $SESSION->feedback = new stdClass();
f1b9e2df 2868 }
2869 }
05edae9f 2870}
b1627a92
DC
2871
2872/**
2873 * Return a list of page types
2874 * @param string $pagetype current page type
2875 * @param stdClass $parentcontext Block's parent context
2876 * @param stdClass $currentcontext Current context of block
2877 */
b38e2e28 2878function feedback_page_type_list($pagetype, $parentcontext, $currentcontext) {
b1627a92
DC
2879 $module_pagetype = array('mod-feedback-*'=>get_string('page-mod-feedback-x', 'feedback'));
2880 return $module_pagetype;
2881}