Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]
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 namespace mod_quiz; 18 19 use stdClass; 20 21 defined('MOODLE_INTERNAL') || die(); 22 23 /** 24 * The repaginate class will rearrange questions in pages. 25 * 26 * The quiz setting allows users to write quizzes with one question per page, 27 * n questions per page, or all questions on one page. 28 * 29 * @package mod_quiz 30 * @copyright 2014 The Open University 31 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 */ 33 class repaginate { 34 35 /** @var int means join pages. */ 36 const LINK = 1; 37 /** @var int means split pages. */ 38 const UNLINK = 2; 39 40 /** @var int the id of the quiz being manipulated. */ 41 private $quizid; 42 /** @var array the quiz_slots for that quiz. */ 43 private $slots; 44 45 /** 46 * Constructor. 47 * @param int $quizid the id of the quiz being manipulated. 48 * @param stdClass[] $slots the quiz_slots for that quiz. 49 */ 50 public function __construct($quizid = 0, $slots = null) { 51 global $DB; 52 $this->quizid = $quizid; 53 if (!$this->quizid) { 54 $this->slots = []; 55 } 56 if (!$slots) { 57 $this->slots = $DB->get_records('quiz_slots', ['quizid' => $this->quizid], 'slot'); 58 } else { 59 $this->slots = $slots; 60 } 61 } 62 63 /** 64 * Repaginate a given slot with the given pagenumber. 65 * @param stdClass $slot 66 * @param int $newpagenumber 67 * @return stdClass 68 */ 69 protected function repaginate_this_slot($slot, $newpagenumber) { 70 $newslot = clone($slot); 71 $newslot->page = $newpagenumber; 72 return $newslot; 73 } 74 75 /** 76 * Return current slot object. 77 * @param array $slots 78 * @param int $slotnumber 79 * @return stdClass $slot 80 */ 81 protected function get_this_slot($slots, $slotnumber) { 82 foreach ($slots as $slot) { 83 if ($slot->slot == $slotnumber) { 84 return $slot; 85 } 86 } 87 return null; 88 } 89 90 /** 91 * Return array of slots with slot number as key 92 * @param stdClass[] $slots 93 * @return stdClass[] 94 */ 95 protected function get_slots_by_slot_number($slots) { 96 if (!$slots) { 97 return []; 98 } 99 $newslots = []; 100 foreach ($slots as $slot) { 101 $newslots[$slot->slot] = $slot; 102 } 103 return $newslots; 104 } 105 106 /** 107 * Return array of slots with slot id as key 108 * @param stdClass[] $slots 109 * @return stdClass[] 110 */ 111 protected function get_slots_by_slotid($slots) { 112 if (!$slots) { 113 return []; 114 } 115 $newslots = []; 116 foreach ($slots as $slot) { 117 $newslots[$slot->id] = $slot; 118 } 119 return $newslots; 120 } 121 122 /** 123 * Repaginate, update DB and slots object. 124 * 125 * @param int $nextslotnumber 126 * @param int $type repaginate::LINK or repaginate::UNLINK. 127 */ 128 public function repaginate_slots($nextslotnumber, $type) { 129 global $DB; 130 $this->slots = $DB->get_records('quiz_slots', ['quizid' => $this->quizid], 'slot'); 131 $nextslot = null; 132 $newslots = []; 133 foreach ($this->slots as $slot) { 134 if ($slot->slot < $nextslotnumber) { 135 $newslots[$slot->id] = $slot; 136 } else if ($slot->slot == $nextslotnumber) { 137 $nextslot = $this->repaginate_next_slot($nextslotnumber, $type); 138 139 // Update DB. 140 $DB->update_record('quiz_slots', $nextslot, true); 141 142 // Update returning object. 143 $newslots[$slot->id] = $nextslot; 144 } 145 } 146 if ($nextslot) { 147 $newslots = array_merge($newslots, $this->repaginate_the_rest($this->slots, $nextslotnumber, $type)); 148 $this->slots = $this->get_slots_by_slotid($newslots); 149 } 150 } 151 152 /** 153 * Repaginate next slot and return the modified slot object. 154 * 155 * @param int $nextslotnumber 156 * @param int $type repaginate::LINK or repaginate::UNLINK. 157 * @return stdClass|null 158 */ 159 public function repaginate_next_slot($nextslotnumber, $type) { 160 $currentslotnumber = $nextslotnumber - 1; 161 if (!($currentslotnumber && $nextslotnumber)) { 162 return null; 163 } 164 $currentslot = $this->get_this_slot($this->slots, $currentslotnumber); 165 $nextslot = $this->get_this_slot($this->slots, $nextslotnumber); 166 167 if ($type === self::LINK) { 168 return $this->repaginate_this_slot($nextslot, $currentslot->page); 169 } else if ($type === self::UNLINK) { 170 return $this->repaginate_this_slot($nextslot, $nextslot->page + 1); 171 } 172 return null; 173 } 174 175 /** 176 * Return the slots with the new pagination, regardless of current pagination. 177 * @param stdClass[] $slots the slots to repaginate. 178 * @param int $number number of question per page 179 * @return stdClass[] the updated slots. 180 */ 181 public function repaginate_n_question_per_page($slots, $number) { 182 $slots = $this->get_slots_by_slot_number($slots); 183 $newslots = []; 184 $count = 0; 185 $page = 1; 186 foreach ($slots as $slot) { 187 for (; $page < ($number + $count + 1); $page++) { 188 if ($slot->slot >= $page) { 189 $slot->page = $page; 190 $count++; 191 } 192 } 193 $newslots[$slot->id] = $slot; 194 } 195 return $newslots; 196 } 197 198 /** 199 * Repaginate the rest. 200 * 201 * @param stdClass[] $quizslots 202 * @param int $slotfrom 203 * @param int $type 204 * @param bool $dbupdate 205 * @return stdClass[] 206 */ 207 public function repaginate_the_rest($quizslots, $slotfrom, $type, $dbupdate = true) { 208 global $DB; 209 if (!$quizslots) { 210 return null; 211 } 212 $newslots = []; 213 foreach ($quizslots as $slot) { 214 if ($type == self::LINK) { 215 if ($slot->slot <= $slotfrom) { 216 continue; 217 } 218 $slot->page = $slot->page - 1; 219 } else if ($type == self::UNLINK) { 220 if ($slot->slot <= $slotfrom - 1) { 221 continue; 222 } 223 $slot->page = $slot->page + 1; 224 } 225 // Update DB. 226 if ($dbupdate) { 227 $DB->update_record('quiz_slots', $slot); 228 } 229 $newslots[$slot->id] = $slot; 230 } 231 return $newslots; 232 } 233 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body