[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/feedback/ -> lib.php (source)

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1