[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/mod/quiz/classes/ -> structure.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   * Defines the \mod_quiz\structure class.
  19   *
  20   * @package   mod_quiz
  21   * @copyright 2013 The Open University
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace mod_quiz;
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  /**
  29   * Quiz structure class.
  30   *
  31   * The structure of the quiz. That is, which questions it is built up
  32   * from. This is used on the Edit quiz page (edit.php) and also when
  33   * starting an attempt at the quiz (startattempt.php). Once an attempt
  34   * has been started, then the attempt holds the specific set of questions
  35   * that that student should answer, and we no longer use this class.
  36   *
  37   * @copyright 2014 The Open University
  38   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  39   */
  40  class structure {
  41      /** @var \quiz the quiz this is the structure of. */
  42      protected $quizobj = null;
  43  
  44      /**
  45       * @var \stdClass[] the questions in this quiz. Contains the row from the questions
  46       * table, with the data from the quiz_slots table added, and also question_categories.contextid.
  47       */
  48      protected $questions = array();
  49  
  50      /** @var \stdClass[] quiz_slots.id => the quiz_slots rows for this quiz, agumented by sectionid. */
  51      protected $slots = array();
  52  
  53      /** @var \stdClass[] quiz_slots.slot => the quiz_slots rows for this quiz, agumented by sectionid. */
  54      protected $slotsinorder = array();
  55  
  56      /**
  57       * @var \stdClass[] currently a dummy. Holds data that will match the
  58       * quiz_sections, once it exists.
  59       */
  60      protected $sections = array();
  61  
  62      /** @var bool caches the results of can_be_edited. */
  63      protected $canbeedited = null;
  64  
  65      /**
  66       * Create an instance of this class representing an empty quiz.
  67       * @return structure
  68       */
  69      public static function create() {
  70          return new self();
  71      }
  72  
  73      /**
  74       * Create an instance of this class representing the structure of a given quiz.
  75       * @param \quiz $quizobj the quiz.
  76       * @return structure
  77       */
  78      public static function create_for_quiz($quizobj) {
  79          $structure = self::create();
  80          $structure->quizobj = $quizobj;
  81          $structure->populate_structure($quizobj->get_quiz());
  82          return $structure;
  83      }
  84  
  85      /**
  86       * Whether there are any questions in the quiz.
  87       * @return bool true if there is at least one question in the quiz.
  88       */
  89      public function has_questions() {
  90          return !empty($this->questions);
  91      }
  92  
  93      /**
  94       * Get the number of questions in the quiz.
  95       * @return int the number of questions in the quiz.
  96       */
  97      public function get_question_count() {
  98          return count($this->questions);
  99      }
 100  
 101      /**
 102       * Get the information about the question with this id.
 103       * @param int $questionid The question id.
 104       * @return \stdClass the data from the questions table, augmented with
 105       * question_category.contextid, and the quiz_slots data for the question in this quiz.
 106       */
 107      public function get_question_by_id($questionid) {
 108          return $this->questions[$questionid];
 109      }
 110  
 111      /**
 112       * Get the information about the question in a given slot.
 113       * @param int $slotnumber the index of the slot in question.
 114       * @return \stdClass the data from the questions table, augmented with
 115       * question_category.contextid, and the quiz_slots data for the question in this quiz.
 116       */
 117      public function get_question_in_slot($slotnumber) {
 118          return $this->questions[$this->slotsinorder[$slotnumber]->questionid];
 119      }
 120  
 121      /**
 122       * Get the course module id of the quiz.
 123       * @return int the course_modules.id for the quiz.
 124       */
 125      public function get_cmid() {
 126          return $this->quizobj->get_cmid();
 127      }
 128  
 129      /**
 130       * Get id of the quiz.
 131       * @return int the quiz.id for the quiz.
 132       */
 133      public function get_quizid() {
 134          return $this->quizobj->get_quizid();
 135      }
 136  
 137      /**
 138       * Get the quiz object.
 139       * @return \stdClass the quiz settings row from the database.
 140       */
 141      public function get_quiz() {
 142          return $this->quizobj->get_quiz();
 143      }
 144  
 145      /**
 146       * Whether the question in the quiz are shuffled for each attempt.
 147       * @return bool true if the questions are shuffled.
 148       */
 149      public function is_shuffled() {
 150          return $this->quizobj->get_quiz()->shufflequestions;
 151      }
 152  
 153      /**
 154       * Quizzes can only be repaginated if they have not been attempted, the
 155       * questions are not shuffled, and there are two or more questions.
 156       * @return bool whether this quiz can be repaginated.
 157       */
 158      public function can_be_repaginated() {
 159          return !$this->is_shuffled() && $this->can_be_edited()
 160                  && $this->get_question_count() >= 2;
 161      }
 162  
 163      /**
 164       * Quizzes can only be edited if they have not been attempted.
 165       * @return bool whether the quiz can be edited.
 166       */
 167      public function can_be_edited() {
 168          if ($this->canbeedited === null) {
 169              $this->canbeedited = !quiz_has_attempts($this->quizobj->get_quizid());
 170          }
 171          return $this->canbeedited;
 172      }
 173  
 174      /**
 175       * This quiz can only be edited if they have not been attempted.
 176       * Throw an exception if this is not the case.
 177       */
 178      public function check_can_be_edited() {
 179          if (!$this->can_be_edited()) {
 180              $reportlink = quiz_attempt_summary_link_to_reports($this->get_quiz(),
 181                      $this->quizobj->get_cm(), $this->quizobj->get_context());
 182              throw new \moodle_exception('cannoteditafterattempts', 'quiz',
 183                      new \moodle_url('/mod/quiz/edit.php', array('cmid' => $this->get_cmid())), $reportlink);
 184          }
 185      }
 186  
 187      /**
 188       * How many questions are allowed per page in the quiz.
 189       * This setting controls how frequently extra page-breaks should be inserted
 190       * automatically when questions are added to the quiz.
 191       * @return int the number of questions that should be on each page of the
 192       * quiz by default.
 193       */
 194      public function get_questions_per_page() {
 195          return $this->quizobj->get_quiz()->questionsperpage;
 196      }
 197  
 198      /**
 199       * Get quiz slots.
 200       * @return \stdClass[] the slots in this quiz.
 201       */
 202      public function get_slots() {
 203          return $this->slots;
 204      }
 205  
 206      /**
 207       * Is this slot the first one on its page?
 208       * @param int $slotnumber the index of the slot in question.
 209       * @return bool whether this slot the first one on its page.
 210       */
 211      public function is_first_slot_on_page($slotnumber) {
 212          if ($slotnumber == 1) {
 213              return true;
 214          }
 215          return $this->slotsinorder[$slotnumber]->page != $this->slotsinorder[$slotnumber - 1]->page;
 216      }
 217  
 218      /**
 219       * Is this slot the last one on its page?
 220       * @param int $slotnumber the index of the slot in question.
 221       * @return bool whether this slot the last one on its page.
 222       */
 223      public function is_last_slot_on_page($slotnumber) {
 224          if (!isset($this->slotsinorder[$slotnumber + 1])) {
 225              return true;
 226          }
 227          return $this->slotsinorder[$slotnumber]->page != $this->slotsinorder[$slotnumber + 1]->page;
 228      }
 229  
 230      /**
 231       * Is this slot the last one in the quiz?
 232       * @param int $slotnumber the index of the slot in question.
 233       * @return bool whether this slot the last one in the quiz.
 234       */
 235      public function is_last_slot_in_quiz($slotnumber) {
 236          end($this->slotsinorder);
 237          return $slotnumber == key($this->slotsinorder);
 238      }
 239  
 240      /**
 241       * Get the final slot in the quiz.
 242       * @return \stdClass the quiz_slots for for the final slot in the quiz.
 243       */
 244      public function get_last_slot() {
 245          return end($this->slotsinorder);
 246      }
 247  
 248      /**
 249       * Get a slot by it's id. Throws an exception if it is missing.
 250       * @param int $slotid the slot id.
 251       * @return \stdClass the requested quiz_slots row.
 252       */
 253      public function get_slot_by_id($slotid) {
 254          if (!array_key_exists($slotid, $this->slots)) {
 255              throw new \coding_exception('The \'slotid\' could not be found.');
 256          }
 257          return $this->slots[$slotid];
 258      }
 259  
 260      /**
 261       * Get all the questions in a section of the quiz.
 262       * @param int $sectionid the section id.
 263       * @return \stdClass[] of question/slot objects.
 264       */
 265      public function get_questions_in_section($sectionid) {
 266          $questions = array();
 267          foreach ($this->slotsinorder as $slot) {
 268              if ($slot->sectionid == $sectionid) {
 269                  $questions[] = $this->questions[$slot->questionid];
 270              }
 271          }
 272          return $questions;
 273      }
 274  
 275      /**
 276       * Get all the sections of the quiz.
 277       * @return \stdClass[] the sections in this quiz.
 278       */
 279      public function get_quiz_sections() {
 280          return $this->sections;
 281      }
 282  
 283      /**
 284       * Get any warnings to show at the top of the edit page.
 285       * @return string[] array of strings.
 286       */
 287      public function get_edit_page_warnings() {
 288          $warnings = array();
 289  
 290          if (quiz_has_attempts($this->quizobj->get_quizid())) {
 291              $reviewlink = quiz_attempt_summary_link_to_reports($this->quizobj->get_quiz(),
 292                      $this->quizobj->get_cm(), $this->quizobj->get_context());
 293              $warnings[] = get_string('cannoteditafterattempts', 'quiz', $reviewlink);
 294          }
 295  
 296          if ($this->is_shuffled()) {
 297              $updateurl = new \moodle_url('/course/mod.php',
 298                      array('return' => 'true', 'update' => $this->quizobj->get_cmid(), 'sesskey' => sesskey()));
 299              $updatelink = '<a href="'.$updateurl->out().'">' . get_string('updatethis', '',
 300                      get_string('modulename', 'quiz')) . '</a>';
 301              $warnings[] = get_string('shufflequestionsselected', 'quiz', $updatelink);
 302          }
 303  
 304          return $warnings;
 305      }
 306  
 307      /**
 308       * Get the date information about the current state of the quiz.
 309       * @return string[] array of two strings. First a short summary, then a longer
 310       * explanation of the current state, e.g. for a tool-tip.
 311       */
 312      public function get_dates_summary() {
 313          $timenow = time();
 314          $quiz = $this->quizobj->get_quiz();
 315  
 316          // Exact open and close dates for the tool-tip.
 317          $dates = array();
 318          if ($quiz->timeopen > 0) {
 319              if ($timenow > $quiz->timeopen) {
 320                  $dates[] = get_string('quizopenedon', 'quiz', userdate($quiz->timeopen));
 321              } else {
 322                  $dates[] = get_string('quizwillopen', 'quiz', userdate($quiz->timeopen));
 323              }
 324          }
 325          if ($quiz->timeclose > 0) {
 326              if ($timenow > $quiz->timeclose) {
 327                  $dates[] = get_string('quizclosed', 'quiz', userdate($quiz->timeclose));
 328              } else {
 329                  $dates[] = get_string('quizcloseson', 'quiz', userdate($quiz->timeclose));
 330              }
 331          }
 332          if (empty($dates)) {
 333              $dates[] = get_string('alwaysavailable', 'quiz');
 334          }
 335          $explanation = implode(', ', $dates);
 336  
 337          // Brief summary on the page.
 338          if ($timenow < $quiz->timeopen) {
 339              $currentstatus = get_string('quizisclosedwillopen', 'quiz',
 340                      userdate($quiz->timeopen, get_string('strftimedatetimeshort', 'langconfig')));
 341          } else if ($quiz->timeclose && $timenow <= $quiz->timeclose) {
 342              $currentstatus = get_string('quizisopenwillclose', 'quiz',
 343                      userdate($quiz->timeclose, get_string('strftimedatetimeshort', 'langconfig')));
 344          } else if ($quiz->timeclose && $timenow > $quiz->timeclose) {
 345              $currentstatus = get_string('quizisclosed', 'quiz');
 346          } else {
 347              $currentstatus = get_string('quizisopen', 'quiz');
 348          }
 349  
 350          return array($currentstatus, $explanation);
 351      }
 352  
 353      /**
 354       * Set up this class with the structure for a given quiz.
 355       * @param \stdClass $quiz the quiz settings.
 356       */
 357      public function populate_structure($quiz) {
 358          global $DB;
 359  
 360          $slots = $DB->get_records_sql("
 361                  SELECT slot.id AS slotid, slot.slot, slot.questionid, slot.page, slot.maxmark,
 362                         q.*, qc.contextid
 363                    FROM {quiz_slots} slot
 364                    LEFT JOIN {question} q ON q.id = slot.questionid
 365                    LEFT JOIN {question_categories} qc ON qc.id = q.category
 366                   WHERE slot.quizid = ?
 367                ORDER BY slot.slot", array($quiz->id));
 368  
 369          $slots = $this->populate_missing_questions($slots);
 370  
 371          $this->questions = array();
 372          $this->slots = array();
 373          $this->slotsinorder = array();
 374          foreach ($slots as $slotdata) {
 375              $this->questions[$slotdata->questionid] = $slotdata;
 376  
 377              $slot = new \stdClass();
 378              $slot->id = $slotdata->slotid;
 379              $slot->slot = $slotdata->slot;
 380              $slot->quizid = $quiz->id;
 381              $slot->page = $slotdata->page;
 382              $slot->questionid = $slotdata->questionid;
 383              $slot->maxmark = $slotdata->maxmark;
 384  
 385              $this->slots[$slot->id] = $slot;
 386              $this->slotsinorder[$slot->slot] = $slot;
 387          }
 388  
 389          $section = new \stdClass();
 390          $section->id = 1;
 391          $section->quizid = $quiz->id;
 392          $section->heading = '';
 393          $section->firstslot = 1;
 394          $section->shuffle = false;
 395          $this->sections = array(1 => $section);
 396  
 397          $this->populate_slots_with_sectionids();
 398          $this->populate_question_numbers();
 399      }
 400  
 401      /**
 402       * Used by populate. Make up fake data for any missing questions.
 403       * @param \stdClass[] $slots the data about the slots and questions in the quiz.
 404       * @return \stdClass[] updated $slots array.
 405       */
 406      protected function populate_missing_questions($slots) {
 407          // Address missing question types.
 408          foreach ($slots as $slot) {
 409              if ($slot->qtype === null) {
 410                  // If the questiontype is missing change the question type.
 411                  $slot->id = $slot->questionid;
 412                  $slot->category = 0;
 413                  $slot->qtype = 'missingtype';
 414                  $slot->name = get_string('missingquestion', 'quiz');
 415                  $slot->slot = $slot->slot;
 416                  $slot->maxmark = 0;
 417                  $slot->questiontext = ' ';
 418                  $slot->questiontextformat = FORMAT_HTML;
 419                  $slot->length = 1;
 420  
 421              } else if (!\question_bank::qtype_exists($slot->qtype)) {
 422                  $slot->qtype = 'missingtype';
 423              }
 424          }
 425  
 426          return $slots;
 427      }
 428  
 429      /**
 430       * Fill in the section ids for each slot.
 431       */
 432      public function populate_slots_with_sectionids() {
 433          $nextsection = reset($this->sections);
 434          foreach ($this->slotsinorder as $slot) {
 435              if ($slot->slot == $nextsection->firstslot) {
 436                  $currentsectionid = $nextsection->id;
 437                  $nextsection = next($this->sections);
 438                  if (!$nextsection) {
 439                      $nextsection = new \stdClass();
 440                      $nextsection->firstslot = -1;
 441                  }
 442              }
 443  
 444              $slot->sectionid = $currentsectionid;
 445          }
 446      }
 447  
 448      /**
 449       * Number the questions.
 450       */
 451      protected function populate_question_numbers() {
 452          $number = 1;
 453          foreach ($this->slots as $slot) {
 454              $question = $this->questions[$slot->questionid];
 455              if ($question->length == 0) {
 456                  $question->displayednumber = get_string('infoshort', 'quiz');
 457              } else {
 458                  $question->displayednumber = $number;
 459                  $number += 1;
 460              }
 461          }
 462      }
 463  
 464      /**
 465       * Move a slot from its current location to a new location.
 466       *
 467       * After callig this method, this class will be in an invalid state, and
 468       * should be discarded if you want to manipulate the structure further.
 469       *
 470       * @param int $idmove id of slot to be moved
 471       * @param int $idbefore id of slot to come before slot being moved
 472       * @param int $page new page number of slot being moved
 473       * @return void
 474       */
 475      public function move_slot($idmove, $idbefore, $page) {
 476          global $DB;
 477  
 478          $this->check_can_be_edited();
 479  
 480          $movingslot = $this->slots[$idmove];
 481          if (empty($movingslot)) {
 482              throw new moodle_exception('Bad slot ID ' . $idmove);
 483          }
 484          $movingslotnumber = (int) $movingslot->slot;
 485  
 486          // Empty target slot means move slot to first.
 487          if (empty($idbefore)) {
 488              $targetslotnumber = 0;
 489          } else {
 490              $targetslotnumber = (int) $this->slots[$idbefore]->slot;
 491          }
 492  
 493          // Work out how things are being moved.
 494          $slotreorder = array();
 495          if ($targetslotnumber > $movingslotnumber) {
 496              $slotreorder[$movingslotnumber] = $targetslotnumber;
 497              for ($i = $movingslotnumber; $i < $targetslotnumber; $i++) {
 498                  $slotreorder[$i + 1] = $i;
 499              }
 500          } else if ($targetslotnumber < $movingslotnumber - 1) {
 501              $slotreorder[$movingslotnumber] = $targetslotnumber + 1;
 502              for ($i = $targetslotnumber + 1; $i < $movingslotnumber; $i++) {
 503                  $slotreorder[$i] = $i + 1;
 504              }
 505          }
 506  
 507          $trans = $DB->start_delegated_transaction();
 508  
 509          // Slot has moved record new order.
 510          if ($slotreorder) {
 511              update_field_with_unique_index('quiz_slots', 'slot', $slotreorder,
 512                      array('quizid' => $this->get_quizid()));
 513          }
 514  
 515          // Page has changed. Record it.
 516          if (!$page) {
 517              $page = 1;
 518          }
 519          if ($movingslot->page != $page) {
 520              $DB->set_field('quiz_slots', 'page', $page,
 521                      array('id' => $movingslot->id));
 522          }
 523  
 524          $emptypages = $DB->get_fieldset_sql("
 525                  SELECT DISTINCT page - 1
 526                    FROM {quiz_slots} slot
 527                   WHERE quizid = ?
 528                     AND page > 1
 529                     AND NOT EXISTS (SELECT 1 FROM {quiz_slots} WHERE quizid = ? AND page = slot.page - 1)
 530                ORDER BY page - 1 DESC
 531                  ", array($this->get_quizid(), $this->get_quizid()));
 532  
 533          foreach ($emptypages as $page) {
 534              $DB->execute("
 535                      UPDATE {quiz_slots}
 536                         SET page = page - 1
 537                       WHERE quizid = ?
 538                         AND page > ?
 539                      ", array($this->get_quizid(), $page));
 540          }
 541  
 542          $trans->allow_commit();
 543      }
 544  
 545      /**
 546       * Refresh page numbering of quiz slots.
 547       * @param \stdClass $quiz the quiz object.
 548       * @param \stdClass[] $slots (optional) array of slot objects.
 549       * @return \stdClass[] array of slot objects.
 550       */
 551      public function refresh_page_numbers($quiz, $slots=array()) {
 552          global $DB;
 553          // Get slots ordered by page then slot.
 554          if (!count($slots)) {
 555              $slots = $DB->get_records('quiz_slots', array('quizid' => $quiz->id), 'slot, page');
 556          }
 557  
 558          // Loop slots. Start Page number at 1 and increment as required.
 559          $pagenumbers = array('new' => 0, 'old' => 0);
 560  
 561          foreach ($slots as $slot) {
 562              if ($slot->page !== $pagenumbers['old']) {
 563                  $pagenumbers['old'] = $slot->page;
 564                  ++$pagenumbers['new'];
 565              }
 566  
 567              if ($pagenumbers['new'] == $slot->page) {
 568                  continue;
 569              }
 570              $slot->page = $pagenumbers['new'];
 571          }
 572  
 573          return $slots;
 574      }
 575  
 576      /**
 577       * Refresh page numbering of quiz slots and save to the database.
 578       * @param \stdClass $quiz the quiz object.
 579       * @return \stdClass[] array of slot objects.
 580       */
 581      public function refresh_page_numbers_and_update_db($quiz) {
 582          global $DB;
 583          $this->check_can_be_edited();
 584  
 585          $slots = $this->refresh_page_numbers($quiz);
 586  
 587          // Record new page order.
 588          foreach ($slots as $slot) {
 589              $DB->set_field('quiz_slots', 'page', $slot->page,
 590                      array('id' => $slot->id));
 591          }
 592  
 593          return $slots;
 594      }
 595  
 596      /**
 597       * Remove a slot from a quiz
 598       * @param \stdClass $quiz the quiz object.
 599       * @param int $slotnumber The number of the slot to be deleted.
 600       */
 601      public function remove_slot($quiz, $slotnumber) {
 602          global $DB;
 603  
 604          $this->check_can_be_edited();
 605  
 606          $slot = $DB->get_record('quiz_slots', array('quizid' => $quiz->id, 'slot' => $slotnumber));
 607          $maxslot = $DB->get_field_sql('SELECT MAX(slot) FROM {quiz_slots} WHERE quizid = ?', array($quiz->id));
 608          if (!$slot) {
 609              return;
 610          }
 611  
 612          $trans = $DB->start_delegated_transaction();
 613          $DB->delete_records('quiz_slots', array('id' => $slot->id));
 614          for ($i = $slot->slot + 1; $i <= $maxslot; $i++) {
 615              $DB->set_field('quiz_slots', 'slot', $i - 1,
 616                      array('quizid' => $quiz->id, 'slot' => $i));
 617          }
 618  
 619          $qtype = $DB->get_field('question', 'qtype', array('id' => $slot->questionid));
 620          if ($qtype === 'random') {
 621              // This function automatically checks if the question is in use, and won't delete if it is.
 622              question_delete_question($slot->questionid);
 623          }
 624  
 625          unset($this->questions[$slot->questionid]);
 626  
 627          $this->refresh_page_numbers_and_update_db($quiz);
 628  
 629          $trans->allow_commit();
 630      }
 631  
 632      /**
 633       * Change the max mark for a slot.
 634       *
 635       * Saves changes to the question grades in the quiz_slots table and any
 636       * corresponding question_attempts.
 637       * It does not update 'sumgrades' in the quiz table.
 638       *
 639       * @param \stdClass $slot row from the quiz_slots table.
 640       * @param float $maxmark the new maxmark.
 641       * @return bool true if the new grade is different from the old one.
 642       */
 643      public function update_slot_maxmark($slot, $maxmark) {
 644          global $DB;
 645  
 646          if (abs($maxmark - $slot->maxmark) < 1e-7) {
 647              // Grade has not changed. Nothing to do.
 648              return false;
 649          }
 650  
 651          $trans = $DB->start_delegated_transaction();
 652          $slot->maxmark = $maxmark;
 653          $DB->update_record('quiz_slots', $slot);
 654          \question_engine::set_max_mark_in_attempts(new \qubaids_for_quiz($slot->quizid),
 655                  $slot->slot, $maxmark);
 656          $trans->allow_commit();
 657  
 658          return true;
 659      }
 660  
 661      /**
 662       * Add/Remove a pagebreak.
 663       *
 664       * Saves changes to the slot page relationship in the quiz_slots table and reorders the paging
 665       * for subsequent slots.
 666       *
 667       * @param \stdClass $quiz the quiz object.
 668       * @param int $slotid id of slot.
 669       * @param int $type repaginate::LINK or repaginate::UNLINK.
 670       * @return \stdClass[] array of slot objects.
 671       */
 672      public function update_page_break($quiz, $slotid, $type) {
 673          global $DB;
 674  
 675          $this->check_can_be_edited();
 676  
 677          $quizslots = $DB->get_records('quiz_slots', array('quizid' => $quiz->id), 'slot');
 678          $repaginate = new \mod_quiz\repaginate($quiz->id, $quizslots);
 679          $repaginate->repaginate_slots($quizslots[$slotid]->slot, $type);
 680          $slots = $this->refresh_page_numbers_and_update_db($quiz);
 681  
 682          return $slots;
 683      }
 684  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1