Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}