Proyectos de Subversion Moodle

Rev

Rev 11 | Rev 712 | Ir a la última revisión | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 11 Rev 704
Línea 43... Línea 43...
43
 * @package   mod_quiz
43
 * @package   mod_quiz
44
 * @category  output
44
 * @category  output
45
 * @copyright 2011 The Open University
45
 * @copyright 2011 The Open University
46
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
46
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
47
 */
47
 */
48
class renderer extends plugin_renderer_base {
48
class renderer extends plugin_renderer_base
-
 
49
{
49
    /**
50
    /**
50
     * Builds the review page
51
     * Builds the review page
51
     *
52
     *
52
     * @param quiz_attempt $attemptobj an instance of quiz_attempt.
53
     * @param quiz_attempt $attemptobj an instance of quiz_attempt.
53
     * @param array $slots of slots to be displayed.
54
     * @param array $slots of slots to be displayed.
Línea 57... Línea 58...
57
     * @param display_options $displayoptions instance of display_options.
58
     * @param display_options $displayoptions instance of display_options.
58
     * @param attempt_summary_information|array $summarydata summary information about the attempt.
59
     * @param attempt_summary_information|array $summarydata summary information about the attempt.
59
     *      Passing an array is deprecated.
60
     *      Passing an array is deprecated.
60
     * @return string HTML to display.
61
     * @return string HTML to display.
61
     */
62
     */
62
    public function review_page(quiz_attempt $attemptobj, $slots, $page, $showall,
63
    public function review_page(
-
 
64
        quiz_attempt $attemptobj,
-
 
65
        $slots,
-
 
66
        $page,
-
 
67
        $showall,
-
 
68
        $lastpage,
63
            $lastpage, display_options $displayoptions, $summarydata) {
69
        display_options $displayoptions,
-
 
70
        $summarydata
-
 
71
    ) {
64
        if (is_array($summarydata)) {
72
        if (is_array($summarydata)) {
-
 
73
            debugging(
65
            debugging('Since Moodle 4.4, $summarydata passed to review_page should be a attempt_summary_information.',
74
                'Since Moodle 4.4, $summarydata passed to review_page should be a attempt_summary_information.',
66
                DEBUG_DEVELOPER);
75
                DEBUG_DEVELOPER
-
 
76
            );
67
            $summarydata = $this->filter_review_summary_table($summarydata, $page);
77
            $summarydata = $this->filter_review_summary_table($summarydata, $page);
68
            $summarydata = attempt_summary_information::create_from_legacy_array($summarydata);
78
            $summarydata = attempt_summary_information::create_from_legacy_array($summarydata);
69
        }
79
        }
Línea 70... Línea 80...
70
 
80
 
71
        $output = '';
81
        $output = '';
72
        $output .= $this->header();
82
        $output .= $this->header();
73
        $output .= $this->review_attempt_summary($summarydata, $page);
83
        $output .= $this->review_attempt_summary($summarydata, $page);
-
 
84
        $output .= $this->review_form(
-
 
85
            $page,
-
 
86
            $showall,
74
        $output .= $this->review_form($page, $showall, $displayoptions,
87
            $displayoptions,
75
                $this->questions($attemptobj, true, $slots, $page, $showall, $displayoptions),
88
            $this->questions($attemptobj, true, $slots, $page, $showall, $displayoptions),
-
 
89
            $attemptobj
Línea 76... Línea 90...
76
                $attemptobj);
90
        );
77
 
91
 
78
        $output .= $this->review_next_navigation($attemptobj, $page, $lastpage, $showall);
92
        $output .= $this->review_next_navigation($attemptobj, $page, $lastpage, $showall);
79
        $output .= $this->footer();
93
        $output .= $this->footer();
Línea 89... Línea 103...
89
     * @param display_options $displayoptions instance of display_options.
103
     * @param display_options $displayoptions instance of display_options.
90
     * @param attempt_summary_information|array $summarydata summary information about the attempt.
104
     * @param attempt_summary_information|array $summarydata summary information about the attempt.
91
     *      Passing an array is deprecated.
105
     *      Passing an array is deprecated.
92
     * @return string HTML to display.
106
     * @return string HTML to display.
93
     */
107
     */
94
    public function review_question_page(quiz_attempt $attemptobj, $slot, $seq,
108
    public function review_question_page(
-
 
109
        quiz_attempt $attemptobj,
-
 
110
        $slot,
-
 
111
        $seq,
95
            display_options $displayoptions, $summarydata) {
112
        display_options $displayoptions,
-
 
113
        $summarydata
-
 
114
    ) {
96
        if (is_array($summarydata)) {
115
        if (is_array($summarydata)) {
-
 
116
            debugging(
97
            debugging('Since Moodle 4.4, $summarydata passed to review_question_page should be a attempt_summary_information.',
117
                'Since Moodle 4.4, $summarydata passed to review_question_page should be a attempt_summary_information.',
98
                DEBUG_DEVELOPER);
118
                DEBUG_DEVELOPER
-
 
119
            );
99
            $summarydata = attempt_summary_information::create_from_legacy_array($summarydata);
120
            $summarydata = attempt_summary_information::create_from_legacy_array($summarydata);
100
        }
121
        }
Línea 101... Línea 122...
101
 
122
 
102
        $output = '';
123
        $output = '';
Línea 119... Línea 140...
119
     *
140
     *
120
     * @param quiz_attempt $attemptobj an instance of quiz_attempt.
141
     * @param quiz_attempt $attemptobj an instance of quiz_attempt.
121
     * @param string $message Why the review is not allowed.
142
     * @param string $message Why the review is not allowed.
122
     * @return string html to output.
143
     * @return string html to output.
123
     */
144
     */
124
    public function review_question_not_allowed(quiz_attempt $attemptobj, $message) {
145
    public function review_question_not_allowed(quiz_attempt $attemptobj, $message)
-
 
146
    {
125
        $output = '';
147
        $output = '';
126
        $output .= $this->header();
148
        $output .= $this->header();
127
        $output .= $this->heading(format_string($attemptobj->get_quiz_name(), true,
149
        $output .= $this->heading(format_string(
-
 
150
            $attemptobj->get_quiz_name(),
-
 
151
            true,
128
                ["context" => $attemptobj->get_quizobj()->get_context()]));
152
            ["context" => $attemptobj->get_quizobj()->get_context()]
-
 
153
        ));
129
        $output .= $this->notification($message);
154
        $output .= $this->notification($message);
130
        $output .= $this->close_window_button();
155
        $output .= $this->close_window_button();
131
        $output .= $this->footer();
156
        $output .= $this->footer();
132
        return $output;
157
        return $output;
133
    }
158
    }
Línea 171... Línea 196...
171
     * @param array $summarydata contains row data for table
196
     * @param array $summarydata contains row data for table
172
     * @param int $page the current page number
197
     * @param int $page the current page number
173
     * @return array updated version of the $summarydata array.
198
     * @return array updated version of the $summarydata array.
174
     * @deprecated since Moodle 4.4. Replaced by filter_review_attempt_summary.
199
     * @deprecated since Moodle 4.4. Replaced by filter_review_attempt_summary.
175
     */
200
     */
176
    protected function filter_review_summary_table($summarydata, $page) {
201
    protected function filter_review_summary_table($summarydata, $page)
-
 
202
    {
177
        debugging('filter_review_summary_table() is deprecated. Replaced by filter_review_attempt_summary().', DEBUG_DEVELOPER);
203
        debugging('filter_review_summary_table() is deprecated. Replaced by filter_review_attempt_summary().', DEBUG_DEVELOPER);
178
        if ($page == 0) {
204
        if ($page == 0) {
179
            return $summarydata;
205
            return $summarydata;
180
        }
206
        }
Línea 195... Línea 221...
195
     * @param array $summarydata contains row data for table
221
     * @param array $summarydata contains row data for table
196
     * @param int $page contains the current page number
222
     * @param int $page contains the current page number
197
     * @return string HTML to display.
223
     * @return string HTML to display.
198
     * @deprecated since Moodle 4.4. Replaced by review_attempt_summary.
224
     * @deprecated since Moodle 4.4. Replaced by review_attempt_summary.
199
     */
225
     */
200
    public function review_summary_table($summarydata, $page) {
226
    public function review_summary_table($summarydata, $page)
-
 
227
    {
201
        debugging('review_summary_table() is deprecated. Please use review_attempt_summary() instead.', DEBUG_DEVELOPER);
228
        debugging('review_summary_table() is deprecated. Please use review_attempt_summary() instead.', DEBUG_DEVELOPER);
202
        $summarydata = $this->filter_review_summary_table($summarydata, $page);
229
        $summarydata = $this->filter_review_summary_table($summarydata, $page);
203
        $this->render(attempt_summary_information::create_from_legacy_array($summarydata));
230
        $this->render(attempt_summary_information::create_from_legacy_array($summarydata));
204
    }
231
    }
Línea 211... Línea 238...
211
     * @param array $slots array of integers relating to questions
238
     * @param array $slots array of integers relating to questions
212
     * @param int $page current page number
239
     * @param int $page current page number
213
     * @param bool $showall if true shows attempt on single page
240
     * @param bool $showall if true shows attempt on single page
214
     * @param display_options $displayoptions instance of display_options
241
     * @param display_options $displayoptions instance of display_options
215
     */
242
     */
-
 
243
    public function questions(
216
    public function questions(quiz_attempt $attemptobj, $reviewing, $slots, $page, $showall,
244
        quiz_attempt $attemptobj,
-
 
245
        $reviewing,
-
 
246
        $slots,
-
 
247
        $page,
-
 
248
        $showall,
217
            display_options $displayoptions) {
249
        display_options $displayoptions
-
 
250
    ) {
218
        $output = '';
251
        $output = '';
219
        foreach ($slots as $slot) {
252
        foreach ($slots as $slot) {
220
            $output .= $attemptobj->render_question($slot, $reviewing, $this,
253
            $output .= $attemptobj->render_question(
-
 
254
                $slot,
-
 
255
                $reviewing,
-
 
256
                $this,
221
                    $attemptobj->review_url($slot, $page, $showall));
257
                $attemptobj->review_url($slot, $page, $showall)
-
 
258
            );
222
        }
259
        }
223
        return $output;
260
        return $output;
224
    }
261
    }
Línea 225... Línea 262...
225
 
262
 
Línea 231... Línea 268...
231
     * @param display_options $displayoptions instance of display_options
268
     * @param display_options $displayoptions instance of display_options
232
     * @param string $content the rendered display of each question
269
     * @param string $content the rendered display of each question
233
     * @param quiz_attempt $attemptobj instance of quiz_attempt
270
     * @param quiz_attempt $attemptobj instance of quiz_attempt
234
     * @return string HTML to display.
271
     * @return string HTML to display.
235
     */
272
     */
236
    public function review_form($page, $showall, $displayoptions, $content, $attemptobj) {
273
    public function review_form($page, $showall, $displayoptions, $content, $attemptobj)
-
 
274
    {
237
        if ($displayoptions->flags != question_display_options::EDITABLE) {
275
        if ($displayoptions->flags != question_display_options::EDITABLE) {
238
            return $content;
276
            return $content;
239
        }
277
        }
Línea 240... Línea 278...
240
 
278
 
-
 
279
        $this->page->requires->js_init_call(
-
 
280
            'M.mod_quiz.init_review_form',
-
 
281
            null,
241
        $this->page->requires->js_init_call('M.mod_quiz.init_review_form', null, false,
282
            false,
-
 
283
            quiz_get_js_module()
Línea 242... Línea 284...
242
                quiz_get_js_module());
284
        );
243
 
285
 
-
 
286
        $output = '';
-
 
287
        $output .= html_writer::start_tag('form', ['action' => $attemptobj->review_url(
-
 
288
            null,
244
        $output = '';
289
            $page,
245
        $output .= html_writer::start_tag('form', ['action' => $attemptobj->review_url(null,
290
            $showall
246
                $page, $showall), 'method' => 'post', 'class' => 'questionflagsaveform']);
291
        ), 'method' => 'post', 'class' => 'questionflagsaveform']);
247
        $output .= html_writer::start_tag('div');
292
        $output .= html_writer::start_tag('div');
-
 
293
        $output .= $content;
-
 
294
        $output .= html_writer::empty_tag('input', [
248
        $output .= $content;
295
            'type' => 'hidden',
-
 
296
            'name' => 'sesskey',
249
        $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'sesskey',
297
            'value' => sesskey()
250
                'value' => sesskey()]);
298
        ]);
-
 
299
        $output .= html_writer::start_tag('div', ['class' => 'submitbtns']);
251
        $output .= html_writer::start_tag('div', ['class' => 'submitbtns']);
300
        $output .= html_writer::empty_tag('input', [
-
 
301
            'type' => 'submit',
252
        $output .= html_writer::empty_tag('input', ['type' => 'submit',
302
            'class' => 'questionflagsavebutton btn btn-secondary',
-
 
303
            'name' => 'savingflags',
253
                'class' => 'questionflagsavebutton btn btn-secondary', 'name' => 'savingflags',
304
            'value' => get_string('saveflags', 'question')
254
                'value' => get_string('saveflags', 'question')]);
305
        ]);
255
        $output .= html_writer::end_tag('div');
306
        $output .= html_writer::end_tag('div');
Línea 256... Línea 307...
256
        $output .= html_writer::end_tag('div');
307
        $output .= html_writer::end_tag('div');
Línea 262... Línea 313...
262
    /**
313
    /**
263
     * Returns either a link or button.
314
     * Returns either a link or button.
264
     *
315
     *
265
     * @param quiz_attempt $attemptobj instance of quiz_attempt
316
     * @param quiz_attempt $attemptobj instance of quiz_attempt
266
     */
317
     */
267
    public function finish_review_link(quiz_attempt $attemptobj) {
318
    public function finish_review_link(quiz_attempt $attemptobj)
-
 
319
    {
268
        $url = $attemptobj->view_url();
320
        $url = $attemptobj->view_url();
Línea 269... Línea 321...
269
 
321
 
-
 
322
        if ($attemptobj->get_access_manager(time())->attempt_must_be_in_popup()) {
270
        if ($attemptobj->get_access_manager(time())->attempt_must_be_in_popup()) {
323
            $this->page->requires->js_init_call(
-
 
324
                'M.mod_quiz.secure_window.init_close_button',
-
 
325
                [$url->out(false)],
271
            $this->page->requires->js_init_call('M.mod_quiz.secure_window.init_close_button',
326
                false,
-
 
327
                quiz_get_js_module()
272
                    [$url->out(false)], false, quiz_get_js_module());
328
            );
-
 
329
            return html_writer::empty_tag('input', [
273
            return html_writer::empty_tag('input', ['type' => 'button',
330
                'type' => 'button',
274
                    'value' => get_string('finishreview', 'quiz'),
331
                'value' => get_string('finishreview', 'quiz'),
275
                    'id' => 'secureclosebutton',
332
                'id' => 'secureclosebutton',
276
                    'class' => 'mod_quiz-next-nav btn btn-primary']);
333
                'class' => 'mod_quiz-next-nav btn btn-primary'
277
 
334
            ]);
-
 
335
        } else {
-
 
336
            return html_writer::link(
278
        } else {
337
                $url,
279
            return html_writer::link($url, get_string('finishreview', 'quiz'),
338
                get_string('finishreview', 'quiz'),
-
 
339
                ['class' => 'mod_quiz-next-nav']
280
                    ['class' => 'mod_quiz-next-nav']);
340
            );
281
        }
341
        }
Línea 282... Línea 342...
282
    }
342
    }
283
 
343
 
Línea 293... Línea 353...
293
     * @param bool|null $showall if true, the URL will be to review the entire attempt on one page,
353
     * @param bool|null $showall if true, the URL will be to review the entire attempt on one page,
294
     *      and $page will be ignored. If null, a sensible default will be chosen.
354
     *      and $page will be ignored. If null, a sensible default will be chosen.
295
     *
355
     *
296
     * @return string HTML fragment.
356
     * @return string HTML fragment.
297
     */
357
     */
298
    public function review_next_navigation(quiz_attempt $attemptobj, $page, $lastpage, $showall = null) {
358
    public function review_next_navigation(quiz_attempt $attemptobj, $page, $lastpage, $showall = null)
-
 
359
    {
299
        $nav = '';
360
        $nav = '';
300
        if ($page > 0) {
361
        if ($page > 0) {
-
 
362
            $nav .= link_arrow_left(
301
            $nav .= link_arrow_left(get_string('navigateprevious', 'quiz'),
363
                get_string('navigateprevious', 'quiz'),
302
                    $attemptobj->review_url(null, $page - 1, $showall), false, 'mod_quiz-prev-nav');
364
                $attemptobj->review_url(null, $page - 1, $showall),
-
 
365
                false,
-
 
366
                'mod_quiz-prev-nav'
-
 
367
            );
303
        }
368
        }
304
        if ($lastpage) {
369
        if ($lastpage) {
305
            $nav .= $this->finish_review_link($attemptobj);
370
            $nav .= $this->finish_review_link($attemptobj);
306
        } else {
371
        } else {
-
 
372
            $nav .= link_arrow_right(
307
            $nav .= link_arrow_right(get_string('navigatenext', 'quiz'),
373
                get_string('navigatenext', 'quiz'),
308
                    $attemptobj->review_url(null, $page + 1, $showall), false, 'mod_quiz-next-nav');
374
                $attemptobj->review_url(null, $page + 1, $showall),
-
 
375
                false,
-
 
376
                'mod_quiz-next-nav'
-
 
377
            );
309
        }
378
        }
310
        return html_writer::tag('div', $nav, ['class' => 'submitbtns']);
379
        return html_writer::tag('div', $nav, ['class' => 'submitbtns']);
311
    }
380
    }
Línea 312... Línea 381...
312
 
381
 
Línea 315... Línea 384...
315
     *
384
     *
316
     * @param quiz_attempt $attemptobj instance of quiz_attempt
385
     * @param quiz_attempt $attemptobj instance of quiz_attempt
317
     * @param int $timenow timestamp to use as 'now'.
386
     * @param int $timenow timestamp to use as 'now'.
318
     * @return string HTML content.
387
     * @return string HTML content.
319
     */
388
     */
320
    public function countdown_timer(quiz_attempt $attemptobj, $timenow) {
389
    public function countdown_timer(quiz_attempt $attemptobj, $timenow)
-
 
390
    {
Línea 321... Línea 391...
321
 
391
 
322
        $timeleft = $attemptobj->get_time_left_display($timenow);
392
        $timeleft = $attemptobj->get_time_left_display($timenow);
323
        if ($timeleft !== false) {
393
        if ($timeleft !== false) {
324
            $ispreview = $attemptobj->is_preview();
394
            $ispreview = $attemptobj->is_preview();
Línea 337... Línea 407...
337
    /**
407
    /**
338
     * Create a preview link
408
     * Create a preview link
339
     *
409
     *
340
     * @param moodle_url $url URL to restart the attempt.
410
     * @param moodle_url $url URL to restart the attempt.
341
     */
411
     */
342
    public function restart_preview_button($url) {
412
    public function restart_preview_button($url)
-
 
413
    {
343
        return $this->single_button($url, get_string('startnewpreview', 'quiz'));
414
        return $this->single_button($url, get_string('startnewpreview', 'quiz'));
344
    }
415
    }
Línea 345... Línea 416...
345
 
416
 
346
    /**
417
    /**
347
     * Outputs the navigation block panel
418
     * Outputs the navigation block panel
348
     *
419
     *
349
     * @param navigation_panel_base $panel
420
     * @param navigation_panel_base $panel
350
     */
421
     */
-
 
422
    public function navigation_panel(navigation_panel_base $panel)
Línea 351... Línea 423...
351
    public function navigation_panel(navigation_panel_base $panel) {
423
    {
352
 
424
 
353
        $output = '';
425
        $output = '';
354
        $userpicture = $panel->user_picture();
426
        $userpicture = $panel->user_picture();
355
        if ($userpicture) {
427
        if ($userpicture) {
356
            $fullname = fullname($userpicture->user);
428
            $fullname = fullname($userpicture->user);
357
            if ($userpicture->size) {
429
            if ($userpicture->size) {
-
 
430
                $fullname = html_writer::div($fullname);
-
 
431
            }
358
                $fullname = html_writer::div($fullname);
432
            $output .= html_writer::tag(
359
            }
433
                'div',
-
 
434
                $this->render($userpicture) . $fullname,
360
            $output .= html_writer::tag('div', $this->render($userpicture) . $fullname,
435
                ['id' => 'user-picture', 'class' => 'clearfix']
361
                    ['id' => 'user-picture', 'class' => 'clearfix']);
436
            );
Línea 362... Línea 437...
362
        }
437
        }
363
        $output .= $panel->render_before_button_bits($this);
438
        $output .= $panel->render_before_button_bits($this);
364
 
439
 
365
        $bcc = $panel->get_button_container_class();
440
        $bcc = $panel->get_button_container_class();
366
        $output .= html_writer::start_tag('div', ['class' => "qn_buttons clearfix $bcc"]);
441
        $output .= html_writer::start_tag('div', ['class' => "qn_buttons clearfix $bcc"]);
367
        foreach ($panel->get_question_buttons() as $button) {
442
        foreach ($panel->get_question_buttons() as $button) {
Línea -... Línea 443...
-
 
443
            $output .= $this->render($button);
-
 
444
        }
368
            $output .= $this->render($button);
445
        $output .= html_writer::end_tag('div');
369
        }
446
 
-
 
447
        $output .= html_writer::tag(
Línea 370... Línea 448...
370
        $output .= html_writer::end_tag('div');
448
            'div',
-
 
449
            $panel->render_end_bits($this),
-
 
450
            ['class' => 'othernav']
-
 
451
        );
371
 
452
 
-
 
453
        $this->page->requires->js_init_call(
Línea 372... Línea 454...
372
        $output .= html_writer::tag('div', $panel->render_end_bits($this),
454
            'M.mod_quiz.nav.init',
373
                ['class' => 'othernav']);
455
            null,
Línea 374... Línea 456...
374
 
456
            false,
375
        $this->page->requires->js_init_call('M.mod_quiz.nav.init', null, false,
457
            quiz_get_js_module()
376
                quiz_get_js_module());
458
        );
377
 
459
 
378
        return $output;
460
        return $output;
379
    }
461
    }
380
 
462
 
-
 
463
    /**
381
    /**
464
     * Display a quiz navigation button.
382
     * Display a quiz navigation button.
465
     *
Línea 383... Línea 466...
383
     *
466
     * @param navigation_question_button $button
384
     * @param navigation_question_button $button
467
     * @return string HTML fragment.
Línea 412... Línea 495...
412
 
495
 
413
        $a = new stdClass();
496
        $a = new stdClass();
414
        $a->number = s($button->number);
497
        $a->number = s($button->number);
415
        $a->attributes = implode(' ', $extrainfo);
498
        $a->attributes = implode(' ', $extrainfo);
416
        $tagcontents = html_writer::tag('span', '', ['class' => 'thispageholder']) .
499
        $tagcontents = html_writer::tag('span', '', ['class' => 'thispageholder']) .
417
                html_writer::tag('span', '', ['class' => 'trafficlight']) .
500
            html_writer::tag('span', '', ['class' => 'trafficlight']) .
-
 
501
            get_string($qnostring, 'quiz', $a);
418
                get_string($qnostring, 'quiz', $a);
502
        $tagattributes = [
-
 
503
            'class' => implode(' ', $classes),
-
 
504
            'id' => $button->id,
419
        $tagattributes = ['class' => implode(' ', $classes), 'id' => $button->id,
505
            'title' => $tooltip,
-
 
506
            'data-quiz-page' => $button->page
Línea 420... Línea 507...
420
                'title' => $tooltip, 'data-quiz-page' => $button->page];
507
        ];
421
 
508
 
422
        if ($button->url) {
509
        if ($button->url) {
423
            return html_writer::link($button->url, $tagcontents, $tagattributes);
510
            return html_writer::link($button->url, $tagcontents, $tagattributes);
Línea 430... Línea 517...
430
     * Display a quiz navigation heading.
517
     * Display a quiz navigation heading.
431
     *
518
     *
432
     * @param navigation_section_heading $heading the heading.
519
     * @param navigation_section_heading $heading the heading.
433
     * @return string HTML fragment.
520
     * @return string HTML fragment.
434
     */
521
     */
435
    protected function render_navigation_section_heading(navigation_section_heading $heading) {
522
    protected function render_navigation_section_heading(navigation_section_heading $heading)
-
 
523
    {
436
        if (empty($heading->heading)) {
524
        if (empty($heading->heading)) {
437
            $headingtext = get_string('sectionnoname', 'quiz');
525
            $headingtext = get_string('sectionnoname', 'quiz');
438
            $class = ' dimmed_text';
526
            $class = ' dimmed_text';
439
        } else {
527
        } else {
440
            $headingtext = $heading->heading;
528
            $headingtext = $heading->heading;
Línea 448... Línea 536...
448
     *
536
     *
449
     * @param links_to_other_attempts $links
537
     * @param links_to_other_attempts $links
450
     * @return string HTML fragment.
538
     * @return string HTML fragment.
451
     */
539
     */
452
    protected function render_links_to_other_attempts(
540
    protected function render_links_to_other_attempts(
453
            links_to_other_attempts $links) {
541
        links_to_other_attempts $links
-
 
542
    ) {
454
        $attemptlinks = [];
543
        $attemptlinks = [];
455
        foreach ($links->links as $attempt => $url) {
544
        foreach ($links->links as $attempt => $url) {
456
            if (!$url) {
545
            if (!$url) {
457
                $attemptlinks[] = html_writer::tag('strong', $attempt);
546
                $attemptlinks[] = html_writer::tag('strong', $attempt);
458
            } else {
547
            } else {
Línea 473... Línea 562...
473
     * having this renderer method allows themes to override the default rendering.
562
     * having this renderer method allows themes to override the default rendering.
474
     *
563
     *
475
     * @param grade_out_of $grade
564
     * @param grade_out_of $grade
476
     * @return string HTML to output.
565
     * @return string HTML to output.
477
     */
566
     */
478
    protected function render_grade_out_of(grade_out_of $grade): string {
567
    protected function render_grade_out_of(grade_out_of $grade): string
-
 
568
    {
-
 
569
        return get_string(
479
        return get_string($grade->get_string_key(), 'quiz',
570
            $grade->get_string_key(),
-
 
571
            'quiz',
480
                $grade->style_formatted_values($grade->get_formatted_values()));
572
            $grade->style_formatted_values($grade->get_formatted_values())
-
 
573
        );
481
    }
574
    }
Línea 482... Línea 575...
482
 
575
 
483
    /**
576
    /**
484
     * Render the 'start attempt' page.
577
     * Render the 'start attempt' page.
Línea 488... Línea 581...
488
     *
581
     *
489
     * @param \mod_quiz\quiz_settings $quizobj
582
     * @param \mod_quiz\quiz_settings $quizobj
490
     * @param preflight_check_form $mform
583
     * @param preflight_check_form $mform
491
     * @return string
584
     * @return string
492
     */
585
     */
493
    public function start_attempt_page(quiz_settings $quizobj, preflight_check_form $mform) {
586
    public function start_attempt_page(quiz_settings $quizobj, preflight_check_form $mform)
-
 
587
    {
494
        $output = '';
588
        $output = '';
495
        $output .= $this->header();
589
        $output .= $this->header();
496
        $output .= $this->during_attempt_tertiary_nav($quizobj->view_url());
590
        $output .= $this->during_attempt_tertiary_nav($quizobj->view_url());
497
        $output .= $this->heading(format_string($quizobj->get_quiz_name(), true,
591
        $output .= $this->heading(format_string(
-
 
592
            $quizobj->get_quiz_name(),
-
 
593
            true,
498
                ["context" => $quizobj->get_context()]));
594
            ["context" => $quizobj->get_context()]
-
 
595
        ));
499
        $output .= $this->quiz_intro($quizobj->get_quiz(), $quizobj->get_cm());
596
        $output .= $this->quiz_intro($quizobj->get_quiz(), $quizobj->get_cm());
500
        $output .= $mform->render();
597
        $output .= $mform->render();
501
        $output .= $this->footer();
598
        $output .= $this->footer();
502
        return $output;
599
        return $output;
503
    }
600
    }
Línea 512... Línea 609...
512
     * @param array $slots Contains an array of integers that relate to questions
609
     * @param array $slots Contains an array of integers that relate to questions
513
     * @param int $id The ID of an attempt
610
     * @param int $id The ID of an attempt
514
     * @param int $nextpage The number of the next page
611
     * @param int $nextpage The number of the next page
515
     * @return string HTML to output.
612
     * @return string HTML to output.
516
     */
613
     */
517
    public function attempt_page($attemptobj, $page, $accessmanager, $messages, $slots, $id,
614
    public function attempt_page(
-
 
615
        $attemptobj,
-
 
616
        $page,
-
 
617
        $accessmanager,
-
 
618
        $messages,
-
 
619
        $slots,
-
 
620
        $id,
518
            $nextpage) {
621
        $nextpage
-
 
622
    ) {
519
        $output = '';
623
        $output = '';
520
        $output .= $this->header();
624
        $output .= $this->header();
521
        $output .= $this->during_attempt_tertiary_nav($attemptobj->view_url());
625
        $output .= $this->during_attempt_tertiary_nav($attemptobj->view_url());
522
        $output .= $this->quiz_notices($messages);
626
        $output .= $this->quiz_notices($messages);
523
        $output .= $this->countdown_timer($attemptobj, time());
627
        $output .= $this->countdown_timer($attemptobj, time());
Línea 530... Línea 634...
530
     * Render the tertiary navigation for pages during the attempt.
634
     * Render the tertiary navigation for pages during the attempt.
531
     *
635
     *
532
     * @param string|moodle_url $quizviewurl url of the view.php page for this quiz.
636
     * @param string|moodle_url $quizviewurl url of the view.php page for this quiz.
533
     * @return string HTML to output.
637
     * @return string HTML to output.
534
     */
638
     */
535
    public function during_attempt_tertiary_nav($quizviewurl): string {
639
    public function during_attempt_tertiary_nav($quizviewurl): string
-
 
640
    {
536
        $output = '';
641
        $output = '';
537
        $output .= html_writer::start_div('container-fluid tertiary-navigation');
642
        $output .= html_writer::start_div('container-fluid tertiary-navigation', ['style' => 'width: fit-content;']);
538
        $output .= html_writer::start_div('row');
643
        $output .= html_writer::start_div('row');
539
        $output .= html_writer::start_div('navitem');
644
        $output .= html_writer::start_div('navitem');
540
        $output .= html_writer::link($quizviewurl, get_string('back'),
645
        $output .= html_writer::link(
-
 
646
            $quizviewurl,
-
 
647
            get_string('back'),
541
                ['class' => 'btn btn-secondary']);
648
            ['class' => 'btn btn-secondary']
-
 
649
        );
542
        $output .= html_writer::end_div();
650
        $output .= html_writer::end_div();
543
        $output .= html_writer::end_div();
651
        $output .= html_writer::end_div();
544
        $output .= html_writer::end_div();
652
        $output .= html_writer::end_div();
545
        return $output;
653
        return $output;
546
    }
654
    }
Línea 548... Línea 656...
548
    /**
656
    /**
549
     * Returns any notices.
657
     * Returns any notices.
550
     *
658
     *
551
     * @param array $messages
659
     * @param array $messages
552
     */
660
     */
553
    public function quiz_notices($messages) {
661
    public function quiz_notices($messages)
-
 
662
    {
554
        if (!$messages) {
663
        if (!$messages) {
555
            return '';
664
            return '';
556
        }
665
        }
557
        return $this->notification(
666
        return $this->notification(
558
                html_writer::tag('p', get_string('accessnoticesheader', 'quiz')) . $this->access_messages($messages),
667
            html_writer::tag('p', get_string('accessnoticesheader', 'quiz')) . $this->access_messages($messages),
559
                'warning',
668
            'warning',
560
                false
669
            false
561
        );
670
        );
562
    }
671
    }
Línea 563... Línea 672...
563
 
672
 
564
    /**
673
    /**
Línea 568... Línea 677...
568
     * @param int $page Current page number
677
     * @param int $page Current page number
569
     * @param array $slots Array of integers relating to questions
678
     * @param array $slots Array of integers relating to questions
570
     * @param int $id ID of the attempt
679
     * @param int $id ID of the attempt
571
     * @param int $nextpage Next page number
680
     * @param int $nextpage Next page number
572
     */
681
     */
573
    public function attempt_form($attemptobj, $page, $slots, $id, $nextpage) {
682
    public function attempt_form($attemptobj, $page, $slots, $id, $nextpage)
-
 
683
    {
574
        $output = '';
684
        $output = '';
Línea 575... Línea 685...
575
 
685
 
576
        // Start the form.
686
        // Start the form.
-
 
687
        $output .= html_writer::start_tag(
-
 
688
            'form',
-
 
689
            [
577
        $output .= html_writer::start_tag('form',
690
                'action' => new moodle_url(
578
                ['action' => new moodle_url($attemptobj->processattempt_url(),
691
                    $attemptobj->processattempt_url(),
-
 
692
                    ['cmid' => $attemptobj->get_cmid()]
-
 
693
                ),
579
                        ['cmid' => $attemptobj->get_cmid()]), 'method' => 'post',
694
                'method' => 'post',
-
 
695
                'enctype' => 'multipart/form-data',
580
                        'enctype' => 'multipart/form-data', 'accept-charset' => 'utf-8',
696
                'accept-charset' => 'utf-8',
-
 
697
                'id' => 'responseform'
-
 
698
            ]
581
                        'id' => 'responseform']);
699
        );
Línea 582... Línea 700...
582
        $output .= html_writer::start_tag('div');
700
        $output .= html_writer::start_tag('div');
583
 
701
 
584
        // Print all the questions.
702
        // Print all the questions.
-
 
703
        foreach ($slots as $slot) {
-
 
704
            $output .= $attemptobj->render_question(
-
 
705
                $slot,
585
        foreach ($slots as $slot) {
706
                false,
-
 
707
                $this,
586
            $output .= $attemptobj->render_question($slot, false, $this,
708
                $attemptobj->attempt_url($slot, $page)
Línea 587... Línea 709...
587
                    $attemptobj->attempt_url($slot, $page));
709
            );
588
        }
710
        }
Línea 589... Línea 711...
589
 
711
 
590
        $navmethod = $attemptobj->get_quiz()->navmethod;
712
        $navmethod = $attemptobj->get_quiz()->navmethod;
-
 
713
        $output .= $this->attempt_navigation_buttons($page, $attemptobj->is_last_page($page), $navmethod);
-
 
714
 
591
        $output .= $this->attempt_navigation_buttons($page, $attemptobj->is_last_page($page), $navmethod);
715
        // Some hidden fields to track what is going on.
-
 
716
        $output .= html_writer::empty_tag('input', [
592
 
717
            'type' => 'hidden',
-
 
718
            'name' => 'attempt',
-
 
719
            'value' => $attemptobj->get_attemptid()
-
 
720
        ]);
593
        // Some hidden fields to track what is going on.
721
        $output .= html_writer::empty_tag('input', [
-
 
722
            'type' => 'hidden',
594
        $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'attempt',
723
            'name' => 'thispage',
-
 
724
            'value' => $page,
-
 
725
            'id' => 'followingpage'
595
                'value' => $attemptobj->get_attemptid()]);
726
        ]);
-
 
727
        $output .= html_writer::empty_tag('input', [
596
        $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'thispage',
728
            'type' => 'hidden',
-
 
729
            'name' => 'nextpage',
597
                'value' => $page, 'id' => 'followingpage']);
730
            'value' => $nextpage
-
 
731
        ]);
-
 
732
        $output .= html_writer::empty_tag('input', [
-
 
733
            'type' => 'hidden',
598
        $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'nextpage',
734
            'name' => 'timeup',
-
 
735
            'value' => '0',
-
 
736
            'id' => 'timeup'
599
                'value' => $nextpage]);
737
        ]);
-
 
738
        $output .= html_writer::empty_tag('input', [
600
        $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'timeup',
739
            'type' => 'hidden',
-
 
740
            'name' => 'sesskey',
601
                'value' => '0', 'id' => 'timeup']);
741
            'value' => sesskey()
-
 
742
        ]);
-
 
743
        $output .= html_writer::empty_tag('input', [
-
 
744
            'type' => 'hidden',
Línea 602... Línea 745...
602
        $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'sesskey',
745
            'name' => 'mdlscrollto',
603
                'value' => sesskey()]);
746
            'value' => '',
604
        $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'mdlscrollto',
747
            'id' => 'mdlscrollto'
605
                'value' => '', 'id' => 'mdlscrollto']);
748
        ]);
-
 
749
 
-
 
750
        // Add a hidden field with questionids. Do this at the end of the form, so
606
 
751
        // if you navigate before the form has finished loading, it does not wipe all
-
 
752
        // the student's answers.
Línea 607... Línea 753...
607
        // Add a hidden field with questionids. Do this at the end of the form, so
753
        $output .= html_writer::empty_tag('input', [
608
        // if you navigate before the form has finished loading, it does not wipe all
754
            'type' => 'hidden',
609
        // the student's answers.
755
            'name' => 'slots',
Línea 625... Línea 771...
625
     * @param int $page the page number. Starts at 0 for the first page.
771
     * @param int $page the page number. Starts at 0 for the first page.
626
     * @param bool $lastpage is this the last page in the quiz?
772
     * @param bool $lastpage is this the last page in the quiz?
627
     * @param string $navmethod Optional quiz attribute, 'free' (default) or 'sequential'
773
     * @param string $navmethod Optional quiz attribute, 'free' (default) or 'sequential'
628
     * @return string HTML fragment.
774
     * @return string HTML fragment.
629
     */
775
     */
630
    protected function attempt_navigation_buttons($page, $lastpage, $navmethod = 'free') {
776
    protected function attempt_navigation_buttons($page, $lastpage, $navmethod = 'free')
-
 
777
    {
631
        $output = '';
778
        $output = '';
Línea 632... Línea 779...
632
 
779
 
633
        $output .= html_writer::start_tag('div', ['class' => 'submitbtns']);
780
        $output .= html_writer::start_tag('div', ['class' => 'submitbtns']);
634
        if ($page > 0 && $navmethod == 'free') {
781
        if ($page > 0 && $navmethod == 'free') {
-
 
782
            $output .= html_writer::empty_tag('input', [
-
 
783
                'type' => 'submit',
635
            $output .= html_writer::empty_tag('input', ['type' => 'submit', 'name' => 'previous',
784
                'name' => 'previous',
-
 
785
                'value' => get_string('navigateprevious', 'quiz'),
636
                    'value' => get_string('navigateprevious', 'quiz'), 'class' => 'mod_quiz-prev-nav btn btn-secondary',
786
                'class' => 'mod_quiz-prev-nav btn btn-secondary',
-
 
787
                'id' => 'mod_quiz-prev-nav'
637
                    'id' => 'mod_quiz-prev-nav']);
788
            ]);
638
            $this->page->requires->js_call_amd('core_form/submit', 'init', ['mod_quiz-prev-nav']);
789
            $this->page->requires->js_call_amd('core_form/submit', 'init', ['mod_quiz-prev-nav']);
639
        }
790
        }
640
        if ($lastpage) {
791
        if ($lastpage) {
641
            $nextlabel = get_string('endtest', 'quiz');
792
            $nextlabel = get_string('endtest', 'quiz');
642
        } else {
793
        } else {
643
            $nextlabel = get_string('navigatenext', 'quiz');
794
            $nextlabel = get_string('navigatenext', 'quiz');
644
        }
795
        }
-
 
796
        $output .= html_writer::empty_tag('input', [
-
 
797
            'type' => 'submit',
-
 
798
            'name' => 'next',
645
        $output .= html_writer::empty_tag('input', ['type' => 'submit', 'name' => 'next',
799
            'value' => $nextlabel,
-
 
800
            'class' => 'mod_quiz-next-nav btn btn-primary',
-
 
801
            'id' => 'mod_quiz-next-nav'
646
                'value' => $nextlabel, 'class' => 'mod_quiz-next-nav btn btn-primary', 'id' => 'mod_quiz-next-nav']);
802
        ]);
647
        $output .= html_writer::end_tag('div');
803
        $output .= html_writer::end_tag('div');
Línea 648... Línea 804...
648
        $this->page->requires->js_call_amd('core_form/submit', 'init', ['mod_quiz-next-nav']);
804
        $this->page->requires->js_call_amd('core_form/submit', 'init', ['mod_quiz-next-nav']);
649
 
805
 
Línea 655... Línea 811...
655
     *
811
     *
656
     * @param int $slot the number of the slot to generate the button for.
812
     * @param int $slot the number of the slot to generate the button for.
657
     * @param bool $disabled if true, output the button disabled.
813
     * @param bool $disabled if true, output the button disabled.
658
     * @return string HTML fragment.
814
     * @return string HTML fragment.
659
     */
815
     */
660
    public function redo_question_button($slot, $disabled) {
816
    public function redo_question_button($slot, $disabled)
-
 
817
    {
-
 
818
        $attributes = [
-
 
819
            'type' => 'submit',
661
        $attributes = ['type' => 'submit', 'name' => 'redoslot' . $slot,
820
            'name' => 'redoslot' . $slot,
662
                'value' => get_string('redoquestion', 'quiz'),
821
            'value' => get_string('redoquestion', 'quiz'),
663
                'class' => 'mod_quiz-redo_question_button btn btn-secondary',
822
            'class' => 'mod_quiz-redo_question_button btn btn-secondary',
664
                'id' => 'redoslot' . $slot . '-submit',
823
            'id' => 'redoslot' . $slot . '-submit',
665
                'data-savescrollposition' => 'true',
824
            'data-savescrollposition' => 'true',
666
            ];
825
        ];
667
        if ($disabled) {
826
        if ($disabled) {
668
            $attributes['disabled'] = 'disabled';
827
            $attributes['disabled'] = 'disabled';
669
        } else {
828
        } else {
670
            $this->page->requires->js_call_amd('core_question/question_engine', 'initSubmitButton', [$attributes['id']]);
829
            $this->page->requires->js_call_amd('core_question/question_engine', 'initSubmitButton', [$attributes['id']]);
671
        }
830
        }
Línea 676... Línea 835...
676
     * Initialise the JavaScript required to initialise the countdown timer.
835
     * Initialise the JavaScript required to initialise the countdown timer.
677
     *
836
     *
678
     * @param int $timerstartvalue time remaining, in seconds.
837
     * @param int $timerstartvalue time remaining, in seconds.
679
     * @param bool $ispreview true if this is a preview attempt.
838
     * @param bool $ispreview true if this is a preview attempt.
680
     */
839
     */
681
    public function initialise_timer($timerstartvalue, $ispreview) {
840
    public function initialise_timer($timerstartvalue, $ispreview)
-
 
841
    {
682
        $options = [$timerstartvalue, (bool) $ispreview];
842
        $options = [$timerstartvalue, (bool) $ispreview];
683
        $this->page->requires->js_init_call('M.mod_quiz.timer.init', $options, false, quiz_get_js_module());
843
        $this->page->requires->js_init_call('M.mod_quiz.timer.init', $options, false, quiz_get_js_module());
684
    }
844
    }
Línea 685... Línea 845...
685
 
845
 
Línea 689... Línea 849...
689
     *
849
     *
690
     * @param moodle_url $url the URL to redirect the parent window to.
850
     * @param moodle_url $url the URL to redirect the parent window to.
691
     * @param string $message message to display before closing the window. (optional)
851
     * @param string $message message to display before closing the window. (optional)
692
     * @return string HTML to output.
852
     * @return string HTML to output.
693
     */
853
     */
694
    public function close_attempt_popup($url, $message = '') {
854
    public function close_attempt_popup($url, $message = '')
-
 
855
    {
695
        $output = '';
856
        $output = '';
696
        $output .= $this->header();
857
        $output .= $this->header();
697
        $output .= $this->box_start();
858
        $output .= $this->box_start();
Línea 698... Línea 859...
698
 
859
 
Línea 702... Línea 863...
702
            $delay = 5;
863
            $delay = 5;
703
        } else {
864
        } else {
704
            $output .= html_writer::tag('p', get_string('pleaseclose', 'quiz'));
865
            $output .= html_writer::tag('p', get_string('pleaseclose', 'quiz'));
705
            $delay = 0;
866
            $delay = 0;
706
        }
867
        }
707
        $this->page->requires->js_init_call('M.mod_quiz.secure_window.close',
868
        $this->page->requires->js_init_call(
-
 
869
            'M.mod_quiz.secure_window.close',
708
            [$url->out(false), $delay], false, quiz_get_js_module());
870
            [$url->out(false), $delay],
-
 
871
            false,
-
 
872
            quiz_get_js_module()
-
 
873
        );
Línea 709... Línea 874...
709
 
874
 
710
        $output .= $this->box_end();
875
        $output .= $this->box_end();
711
        $output .= $this->footer();
876
        $output .= $this->footer();
712
        return $output;
877
        return $output;
Línea 716... Línea 881...
716
     * Print each message in an array, surrounded by <p>, </p> tags.
881
     * Print each message in an array, surrounded by <p>, </p> tags.
717
     *
882
     *
718
     * @param array $messages the array of message strings.
883
     * @param array $messages the array of message strings.
719
     * @return string HTML to output.
884
     * @return string HTML to output.
720
     */
885
     */
721
    public function access_messages($messages) {
886
    public function access_messages($messages)
-
 
887
    {
722
        $output = '';
888
        $output = '';
723
        foreach ($messages as $message) {
889
        foreach ($messages as $message) {
724
            $output .= html_writer::tag('p', $message, ['class' => 'text-left']);
890
            $output .= html_writer::tag('p', $message, ['class' => 'text-left']);
725
        }
891
        }
726
        return $output;
892
        return $output;
Línea 733... Línea 899...
733
     * Create the summary page
899
     * Create the summary page
734
     *
900
     *
735
     * @param quiz_attempt $attemptobj
901
     * @param quiz_attempt $attemptobj
736
     * @param display_options $displayoptions
902
     * @param display_options $displayoptions
737
     */
903
     */
738
    public function summary_page($attemptobj, $displayoptions) {
904
    public function summary_page($attemptobj, $displayoptions)
-
 
905
    {
739
        $output = '';
906
        $output = '';
740
        $output .= $this->header();
907
        $output .= $this->header();
741
        $output .= $this->during_attempt_tertiary_nav($attemptobj->view_url());
908
        $output .= $this->during_attempt_tertiary_nav($attemptobj->view_url());
742
        $output .= $this->heading(format_string($attemptobj->get_quiz_name()));
909
        $output .= $this->heading(format_string($attemptobj->get_quiz_name()));
743
        $output .= $this->heading(get_string('summaryofattempt', 'quiz'), 3);
910
        $output .= $this->heading(get_string('summaryofattempt', 'quiz'), 3);
Línea 751... Línea 918...
751
     * Generates the table of summarydata
918
     * Generates the table of summarydata
752
     *
919
     *
753
     * @param quiz_attempt $attemptobj
920
     * @param quiz_attempt $attemptobj
754
     * @param display_options $displayoptions
921
     * @param display_options $displayoptions
755
     */
922
     */
756
    public function summary_table($attemptobj, $displayoptions) {
923
    public function summary_table($attemptobj, $displayoptions)
-
 
924
    {
757
        // Prepare the summary table header.
925
        // Prepare the summary table header.
758
        $table = new html_table();
926
        $table = new html_table();
759
        $table->attributes['class'] = 'generaltable quizsummaryofattempt boxaligncenter';
927
        $table->attributes['class'] = 'generaltable quizsummaryofattempt boxaligncenter';
760
        $table->head = [get_string('question', 'quiz'), get_string('status', 'quiz')];
928
        $table->head = [get_string('question', 'quiz'), get_string('status', 'quiz')];
761
        $table->align = ['left', 'left'];
929
        $table->align = ['left', 'left'];
Línea 801... Línea 969...
801
 
969
 
802
            // Real question, show it.
970
            // Real question, show it.
803
            $flag = '';
971
            $flag = '';
804
            if ($attemptobj->is_question_flagged($slot)) {
972
            if ($attemptobj->is_question_flagged($slot)) {
-
 
973
                // Quiz has custom JS manipulating these image tags - so we can't use the pix_icon method here.
805
                // Quiz has custom JS manipulating these image tags - so we can't use the pix_icon method here.
974
                $flag = html_writer::empty_tag('img', [
806
                $flag = html_writer::empty_tag('img', ['src' => $this->image_url('i/flagged'),
975
                    'src' => $this->image_url('i/flagged'),
-
 
976
                    'alt' => get_string('flagged', 'question'),
-
 
977
                    'class' => 'questionflag icon-post'
807
                        'alt' => get_string('flagged', 'question'), 'class' => 'questionflag icon-post']);
978
                ]);
808
            }
979
            }
-
 
980
            if ($attemptobj->can_navigate_to($slot)) {
-
 
981
                $row = [
809
            if ($attemptobj->can_navigate_to($slot)) {
982
                    html_writer::link(
810
                $row = [html_writer::link($attemptobj->attempt_url($slot),
983
                        $attemptobj->attempt_url($slot),
-
 
984
                        $attemptobj->get_question_number($slot) . $flag
811
                        $attemptobj->get_question_number($slot) . $flag),
985
                    ),
-
 
986
                    $attemptobj->get_question_status($slot, $displayoptions->correctness)
812
                        $attemptobj->get_question_status($slot, $displayoptions->correctness)];
987
                ];
-
 
988
            } else {
813
            } else {
989
                $row = [
814
                $row = [$attemptobj->get_question_number($slot) . $flag,
990
                    $attemptobj->get_question_number($slot) . $flag,
-
 
991
                    $attemptobj->get_question_status($slot, $displayoptions->correctness)
815
                        $attemptobj->get_question_status($slot, $displayoptions->correctness)];
992
                ];
816
            }
993
            }
817
            if ($markscolumn) {
994
            if ($markscolumn) {
818
                $row[] = $attemptobj->get_question_mark($slot);
995
                $row[] = $attemptobj->get_question_mark($slot);
819
            }
996
            }
820
            $table->data[] = $row;
997
            $table->data[] = $row;
-
 
998
            $table->rowclasses[] = 'quizsummary' . $slot . ' ' . $attemptobj->get_question_state_class(
821
            $table->rowclasses[] = 'quizsummary' . $slot . ' ' . $attemptobj->get_question_state_class(
999
                $slot,
-
 
1000
                $displayoptions->correctness
822
                            $slot, $displayoptions->correctness);
1001
            );
Línea 823... Línea 1002...
823
        }
1002
        }
824
 
1003
 
825
        // Print the summary table.
1004
        // Print the summary table.
Línea 829... Línea 1008...
829
    /**
1008
    /**
830
     * Creates any controls the page should have.
1009
     * Creates any controls the page should have.
831
     *
1010
     *
832
     * @param quiz_attempt $attemptobj
1011
     * @param quiz_attempt $attemptobj
833
     */
1012
     */
834
    public function summary_page_controls($attemptobj) {
1013
    public function summary_page_controls($attemptobj)
-
 
1014
    {
835
        $output = '';
1015
        $output = '';
Línea 836... Línea 1016...
836
 
1016
 
837
        // Return to place button.
1017
        // Return to place button.
838
        if ($attemptobj->get_state() == quiz_attempt::IN_PROGRESS) {
1018
        if ($attemptobj->get_state() == quiz_attempt::IN_PROGRESS) {
839
            $button = new single_button(
1019
            $button = new single_button(
840
                    new moodle_url($attemptobj->attempt_url(null, $attemptobj->get_currentpage())),
1020
                new moodle_url($attemptobj->attempt_url(null, $attemptobj->get_currentpage())),
-
 
1021
                get_string('returnattempt', 'quiz')
841
                    get_string('returnattempt', 'quiz'));
1022
            );
-
 
1023
            $output .= $this->container($this->container(
-
 
1024
                $this->render($button),
842
            $output .= $this->container($this->container($this->render($button),
1025
                'controls'
843
                    'controls'), 'submitbtns mdl-align');
1026
            ), 'submitbtns mdl-align');
Línea 844... Línea 1027...
844
        }
1027
        }
845
 
1028
 
846
        // Finish attempt button.
1029
        // Finish attempt button.
847
        $options = [
1030
        $options = [
848
                'attempt' => $attemptobj->get_attemptid(),
1031
            'attempt' => $attemptobj->get_attemptid(),
849
                'finishattempt' => 1,
1032
            'finishattempt' => 1,
850
                'timeup' => 0,
1033
            'timeup' => 0,
851
                'slots' => '',
1034
            'slots' => '',
852
                'cmid' => $attemptobj->get_cmid(),
1035
            'cmid' => $attemptobj->get_cmid(),
Línea 853... Línea 1036...
853
                'sesskey' => sesskey(),
1036
            'sesskey' => sesskey(),
854
        ];
1037
        ];
855
 
1038
 
-
 
1039
        $button = new single_button(
856
        $button = new single_button(
1040
            new moodle_url($attemptobj->processattempt_url(), $options),
857
                new moodle_url($attemptobj->processattempt_url(), $options),
1041
            get_string('submitallandfinish', 'quiz')
858
                get_string('submitallandfinish', 'quiz'));
1042
        );
859
        $button->class = 'btn-finishattempt';
1043
        $button->class = 'btn-finishattempt';
860
        $button->formid = 'frm-finishattempt';
1044
        $button->formid = 'frm-finishattempt';
Línea 870... Línea 1054...
870
 
1054
 
871
        $duedate = $attemptobj->get_due_date();
1055
        $duedate = $attemptobj->get_due_date();
872
        $message = '';
1056
        $message = '';
873
        if ($attemptobj->get_state() == quiz_attempt::OVERDUE) {
1057
        if ($attemptobj->get_state() == quiz_attempt::OVERDUE) {
874
            $message = get_string('overduemustbesubmittedby', 'quiz', userdate($duedate));
-
 
875
 
1058
            $message = get_string('overduemustbesubmittedby', 'quiz', userdate($duedate));
876
        } else {
1059
        } else {
877
            if ($duedate) {
1060
            if ($duedate) {
878
                $message = get_string('mustbesubmittedby', 'quiz', userdate($duedate));
1061
                $message = get_string('mustbesubmittedby', 'quiz', userdate($duedate));
879
            }
1062
            }
Línea 880... Línea 1063...
880
        }
1063
        }
881
 
1064
 
-
 
1065
        $output .= $this->countdown_timer($attemptobj, time());
-
 
1066
        $output .= $this->container($message . $this->container(
882
        $output .= $this->countdown_timer($attemptobj, time());
1067
            $this->render($button),
Línea 883... Línea 1068...
883
        $output .= $this->container($message . $this->container(
1068
            'controls'
884
                        $this->render($button), 'controls'), 'submitbtns mdl-align');
1069
        ), 'submitbtns mdl-align');
Línea 885... Línea 1070...
885
 
1070
 
Línea 897... Línea 1082...
897
     * @param stdClass $cm the course_module settings row from the database.
1082
     * @param stdClass $cm the course_module settings row from the database.
898
     * @param context_module $context the quiz context.
1083
     * @param context_module $context the quiz context.
899
     * @param view_page $viewobj
1084
     * @param view_page $viewobj
900
     * @return string HTML to display
1085
     * @return string HTML to display
901
     */
1086
     */
902
    public function view_page($course, $quiz, $cm, $context, $viewobj) {
1087
    public function view_page($course, $quiz, $cm, $context, $viewobj)
-
 
1088
    {
903
        $output = '';
1089
        $output = '';
Línea 904... Línea 1090...
904
 
1090
 
905
        $output .= $this->view_page_tertiary_nav($viewobj);
1091
        $output .= $this->view_page_tertiary_nav($viewobj);
906
        $output .= $this->view_information($quiz, $cm, $context, $viewobj->infomessages);
1092
        $output .= $this->view_information($quiz, $cm, $context, $viewobj->infomessages);
Línea 914... Línea 1100...
914
     * Render the tertiary navigation for the view page.
1100
     * Render the tertiary navigation for the view page.
915
     *
1101
     *
916
     * @param view_page $viewobj the information required to display the view page.
1102
     * @param view_page $viewobj the information required to display the view page.
917
     * @return string HTML to output.
1103
     * @return string HTML to output.
918
     */
1104
     */
919
    public function view_page_tertiary_nav(view_page $viewobj): string {
1105
    public function view_page_tertiary_nav(view_page $viewobj): string
-
 
1106
    {
920
        $content = '';
1107
        $content = '';
Línea 921... Línea 1108...
921
 
1108
 
922
        if ($viewobj->buttontext) {
1109
        if ($viewobj->buttontext) {
-
 
1110
            $attemptbtn = $this->start_attempt_button(
-
 
1111
                $viewobj->buttontext,
923
            $attemptbtn = $this->start_attempt_button($viewobj->buttontext,
1112
                $viewobj->startattempturl,
924
                    $viewobj->startattempturl, $viewobj->preflightcheckform,
1113
                $viewobj->preflightcheckform,
-
 
1114
                $viewobj->popuprequired,
-
 
1115
                $viewobj->popupoptions
925
                    $viewobj->popuprequired, $viewobj->popupoptions);
1116
            );
926
            $content .= $attemptbtn;
1117
            $content .= $attemptbtn;
Línea 927... Línea 1118...
927
        }
1118
        }
-
 
1119
 
-
 
1120
        if ($viewobj->canedit && !$viewobj->quizhasquestions) {
928
 
1121
            $content .= html_writer::link(
929
        if ($viewobj->canedit && !$viewobj->quizhasquestions) {
1122
                $viewobj->editurl,
-
 
1123
                get_string('addquestion', 'quiz'),
930
            $content .= html_writer::link($viewobj->editurl, get_string('addquestion', 'quiz'),
1124
                ['class' => 'btn btn-secondary']
Línea 931... Línea 1125...
931
                    ['class' => 'btn btn-secondary']);
1125
            );
932
        }
1126
        }
933
 
1127
 
Línea 943... Línea 1137...
943
     * at the end of the review page.
1137
     * at the end of the review page.
944
     *
1138
     *
945
     * @param view_page $viewobj the information required to display the view page.
1139
     * @param view_page $viewobj the information required to display the view page.
946
     * @return string HTML to output.
1140
     * @return string HTML to output.
947
     */
1141
     */
948
    public function view_page_buttons(view_page $viewobj) {
1142
    public function view_page_buttons(view_page $viewobj)
-
 
1143
    {
949
        $output = '';
1144
        $output = '';
Línea 950... Línea 1145...
950
 
1145
 
951
        if (!$viewobj->quizhasquestions) {
1146
        if (!$viewobj->quizhasquestions) {
952
            $output .= html_writer::div(
1147
            $output .= html_writer::div(
953
                    $this->notification(get_string('noquestions', 'quiz'), 'warning', false),
1148
                $this->notification(get_string('noquestions', 'quiz'), 'warning', false),
-
 
1149
                'text-left mb-3'
954
                    'text-left mb-3');
1150
            );
955
        }
1151
        }
Línea 956... Línea 1152...
956
        $output .= $this->access_messages($viewobj->preventmessages);
1152
        $output .= $this->access_messages($viewobj->preventmessages);
957
 
1153
 
-
 
1154
        if ($viewobj->showbacktocourse) {
958
        if ($viewobj->showbacktocourse) {
1155
            $output .= $this->single_button(
-
 
1156
                $viewobj->backtocourseurl,
959
            $output .= $this->single_button($viewobj->backtocourseurl,
1157
                get_string('backtocourse', 'quiz'),
-
 
1158
                'get',
960
                    get_string('backtocourse', 'quiz'), 'get',
1159
                ['class' => 'continuebutton']
Línea 961... Línea 1160...
961
                    ['class' => 'continuebutton']);
1160
            );
962
        }
1161
        }
Línea 972... Línea 1171...
972
     * @param preflight_check_form|null $preflightcheckform deprecated.
1171
     * @param preflight_check_form|null $preflightcheckform deprecated.
973
     * @param bool $popuprequired whether the attempt needs to be opened in a pop-up.
1172
     * @param bool $popuprequired whether the attempt needs to be opened in a pop-up.
974
     * @param array $popupoptions the options to use if we are opening a popup.
1173
     * @param array $popupoptions the options to use if we are opening a popup.
975
     * @return string HTML fragment.
1174
     * @return string HTML fragment.
976
     */
1175
     */
977
    public function start_attempt_button($buttontext, moodle_url $url,
1176
    public function start_attempt_button(
-
 
1177
        $buttontext,
-
 
1178
        moodle_url $url,
978
            preflight_check_form $preflightcheckform = null,
1179
        preflight_check_form $preflightcheckform = null,
979
            $popuprequired = false, $popupoptions = null) {
1180
        $popuprequired = false,
-
 
1181
        $popupoptions = null
-
 
1182
    ) {
Línea 980... Línea 1183...
980
 
1183
 
981
        $button = new single_button($url, $buttontext, 'post', single_button::BUTTON_PRIMARY);
1184
        $button = new single_button($url, $buttontext, 'post', single_button::BUTTON_PRIMARY);
982
        $button->class .= ' quizstartbuttondiv';
1185
        $button->class .= ' quizstartbuttondiv';
983
        if ($popuprequired) {
1186
        if ($popuprequired) {
Línea 988... Línea 1191...
988
        if ($popuprequired && $popupoptions) {
1191
        if ($popuprequired && $popupoptions) {
989
            $action = new popup_action('click', $url, 'popup', $popupoptions);
1192
            $action = new popup_action('click', $url, 'popup', $popupoptions);
990
            $popupjsoptions = $action->get_js_options();
1193
            $popupjsoptions = $action->get_js_options();
991
        }
1194
        }
Línea 992... Línea 1195...
992
 
1195
 
-
 
1196
        $this->page->requires->js_call_amd(
-
 
1197
            'mod_quiz/preflightcheck',
-
 
1198
            'init',
993
        $this->page->requires->js_call_amd('mod_quiz/preflightcheck', 'init',
1199
            [
-
 
1200
                '.quizstartbuttondiv [type=submit]',
994
                ['.quizstartbuttondiv [type=submit]', get_string('startattempt', 'quiz'),
1201
                get_string('startattempt', 'quiz'),
-
 
1202
                '#mod_quiz_preflight_form',
-
 
1203
                $popupjsoptions
-
 
1204
            ]
Línea 995... Línea 1205...
995
                        '#mod_quiz_preflight_form', $popupjsoptions]);
1205
        );
996
 
1206
 
Línea 997... Línea 1207...
997
        return $this->render($button) . ($preflightcheckform ? $preflightcheckform->render() : '');
1207
        return $this->render($button) . ($preflightcheckform ? $preflightcheckform->render() : '');
Línea 1005... Línea 1215...
1005
     * @param moodle_url $editurl URL of the edit quiz page.
1215
     * @param moodle_url $editurl URL of the edit quiz page.
1006
     * @return string HTML to output.
1216
     * @return string HTML to output.
1007
     *
1217
     *
1008
     * @deprecated since Moodle 4.0 MDL-71915 - please do not use this function any more.
1218
     * @deprecated since Moodle 4.0 MDL-71915 - please do not use this function any more.
1009
     */
1219
     */
1010
    public function no_questions_message($canedit, $editurl) {
1220
    public function no_questions_message($canedit, $editurl)
-
 
1221
    {
1011
        debugging('no_questions_message() is deprecated, please use generate_no_questions_message() instead.', DEBUG_DEVELOPER);
1222
        debugging('no_questions_message() is deprecated, please use generate_no_questions_message() instead.', DEBUG_DEVELOPER);
Línea 1012... Línea 1223...
1012
 
1223
 
1013
        $output = html_writer::start_tag('div', ['class' => 'card text-center mb-3']);
1224
        $output = html_writer::start_tag('div', ['class' => 'card text-center mb-3']);
Línea 1031... Línea 1242...
1031
     * @param stdClass $cm the course_module settings row from the database.
1242
     * @param stdClass $cm the course_module settings row from the database.
1032
     * @param context_module $context the quiz context.
1243
     * @param context_module $context the quiz context.
1033
     * @param array $messages Array containing any messages
1244
     * @param array $messages Array containing any messages
1034
     * @param view_page $viewobj
1245
     * @param view_page $viewobj
1035
     */
1246
     */
1036
    public function view_page_guest($course, $quiz, $cm, $context, $messages, $viewobj) {
1247
    public function view_page_guest($course, $quiz, $cm, $context, $messages, $viewobj)
-
 
1248
    {
1037
        $output = '';
1249
        $output = '';
1038
        $output .= $this->view_page_tertiary_nav($viewobj);
1250
        $output .= $this->view_page_tertiary_nav($viewobj);
1039
        $output .= $this->view_information($quiz, $cm, $context, $messages);
1251
        $output .= $this->view_information($quiz, $cm, $context, $messages);
1040
        $guestno = html_writer::tag('p', get_string('guestsno', 'quiz'));
1252
        $guestno = html_writer::tag('p', get_string('guestsno', 'quiz'));
1041
        $liketologin = html_writer::tag('p', get_string('liketologin'));
1253
        $liketologin = html_writer::tag('p', get_string('liketologin'));
Línea 1052... Línea 1264...
1052
     * @param stdClass $cm the course_module settings row from the database.
1264
     * @param stdClass $cm the course_module settings row from the database.
1053
     * @param context_module $context the quiz context.
1265
     * @param context_module $context the quiz context.
1054
     * @param array $messages Array containing any messages
1266
     * @param array $messages Array containing any messages
1055
     * @param view_page $viewobj
1267
     * @param view_page $viewobj
1056
     */
1268
     */
1057
    public function view_page_notenrolled($course, $quiz, $cm, $context, $messages, $viewobj) {
1269
    public function view_page_notenrolled($course, $quiz, $cm, $context, $messages, $viewobj)
-
 
1270
    {
1058
        global $CFG;
1271
        global $CFG;
1059
        $output = '';
1272
        $output = '';
1060
        $output .= $this->view_page_tertiary_nav($viewobj);
1273
        $output .= $this->view_page_tertiary_nav($viewobj);
1061
        $output .= $this->view_information($quiz, $cm, $context, $messages);
1274
        $output .= $this->view_information($quiz, $cm, $context, $messages);
1062
        $youneedtoenrol = html_writer::tag('p', get_string('youneedtoenrol', 'quiz'));
1275
        $youneedtoenrol = html_writer::tag('p', get_string('youneedtoenrol', 'quiz'));
1063
        $button = html_writer::tag('p',
1276
        $button = html_writer::tag(
-
 
1277
            'p',
1064
                $this->continue_button($CFG->wwwroot . '/course/view.php?id=' . $course->id));
1278
            $this->continue_button($CFG->wwwroot . '/course/view.php?id=' . $course->id)
-
 
1279
        );
1065
        $output .= $this->box($youneedtoenrol . "\n\n" . $button . "\n", 'generalbox', 'notice');
1280
        $output .= $this->box($youneedtoenrol . "\n\n" . $button . "\n", 'generalbox', 'notice');
1066
        return $output;
1281
        return $output;
1067
    }
1282
    }
Línea 1068... Línea 1283...
1068
 
1283
 
Línea 1074... Línea 1289...
1074
     * @param context $context the quiz context.
1289
     * @param context $context the quiz context.
1075
     * @param array $messages any access messages that should be described.
1290
     * @param array $messages any access messages that should be described.
1076
     * @param bool $quizhasquestions does quiz has questions added.
1291
     * @param bool $quizhasquestions does quiz has questions added.
1077
     * @return string HTML to output.
1292
     * @return string HTML to output.
1078
     */
1293
     */
1079
    public function view_information($quiz, $cm, $context, $messages, bool $quizhasquestions = false) {
1294
    public function view_information($quiz, $cm, $context, $messages, bool $quizhasquestions = false)
-
 
1295
    {
1080
        $output = '';
1296
        $output = '';
Línea 1081... Línea 1297...
1081
 
1297
 
1082
        // Output any access messages.
1298
        // Output any access messages.
1083
        if ($messages) {
1299
        if ($messages) {
1084
            $output .= $this->box($this->access_messages($messages), 'quizinfo');
1300
            $output .= $this->box($this->access_messages($messages), 'quizinfo');
Línea 1085... Línea 1301...
1085
        }
1301
        }
1086
 
1302
 
1087
        // Show number of attempts summary to those who can view reports.
1303
        // Show number of attempts summary to those who can view reports.
-
 
1304
        if (has_capability('mod/quiz:viewreports', $context)) {
-
 
1305
            if ($strattemptnum = $this->quiz_attempt_summary_link_to_reports(
1088
        if (has_capability('mod/quiz:viewreports', $context)) {
1306
                $quiz,
-
 
1307
                $cm,
1089
            if ($strattemptnum = $this->quiz_attempt_summary_link_to_reports($quiz, $cm,
1308
                $context
-
 
1309
            )) {
-
 
1310
                $output .= html_writer::tag(
1090
                    $context)) {
1311
                    'div',
-
 
1312
                    $strattemptnum,
1091
                $output .= html_writer::tag('div', $strattemptnum,
1313
                    ['class' => 'quizattemptcounts']
1092
                        ['class' => 'quizattemptcounts']);
1314
                );
Línea 1093... Línea 1315...
1093
            }
1315
            }
1094
        }
1316
        }
Línea 1107... Línea 1329...
1107
     *
1329
     *
1108
     * @param stdClass $quiz the quiz settings.
1330
     * @param stdClass $quiz the quiz settings.
1109
     * @param stdClass $cm the course_module object.
1331
     * @param stdClass $cm the course_module object.
1110
     * @return string HTML to output.
1332
     * @return string HTML to output.
1111
     */
1333
     */
1112
    public function quiz_intro($quiz, $cm) {
1334
    public function quiz_intro($quiz, $cm)
-
 
1335
    {
1113
        if (html_is_blank($quiz->intro)) {
1336
        if (html_is_blank($quiz->intro)) {
1114
            return '';
1337
            return '';
1115
        }
1338
        }
Línea 1116... Línea 1339...
1116
 
1339
 
1117
        return $this->box(format_module_intro('quiz', $quiz, $cm->id), 'generalbox', 'intro');
1340
        return $this->box(format_module_intro('quiz', $quiz, $cm->id), 'generalbox', 'intro');
Línea 1118... Línea 1341...
1118
    }
1341
    }
1119
 
1342
 
1120
    /**
1343
    /**
1121
     * Generates the table heading.
1344
     * Generates the table heading.
-
 
1345
     */
1122
     */
1346
    public function view_table_heading()
1123
    public function view_table_heading() {
1347
    {
Línea 1124... Línea 1348...
1124
        return $this->heading(get_string('summaryofattempts', 'quiz'), 3);
1348
        return $this->heading(get_string('summaryofattempts', 'quiz'), 3);
1125
    }
1349
    }
Línea 1130... Línea 1354...
1130
     * @param stdClass $quiz the quiz settings.
1354
     * @param stdClass $quiz the quiz settings.
1131
     * @param context_module $context the quiz context.
1355
     * @param context_module $context the quiz context.
1132
     * @param view_page $viewobj
1356
     * @param view_page $viewobj
1133
     * @deprecated Since 4.4 please use the {@see list_of_attempts} renderable instead.
1357
     * @deprecated Since 4.4 please use the {@see list_of_attempts} renderable instead.
1134
     */
1358
     */
1135
    public function view_table($quiz, $context, $viewobj) {
1359
    public function view_table($quiz, $context, $viewobj)
-
 
1360
    {
1136
        debugging('view_table has been deprecated since 4.4 please use the list_of_attempts renderable instead.');
1361
        debugging('view_table has been deprecated since 4.4 please use the list_of_attempts renderable instead.');
1137
        if (!$viewobj->attempts) {
1362
        if (!$viewobj->attempts) {
1138
            return '';
1363
            return '';
1139
        }
1364
        }
Línea 1154... Línea 1379...
1154
        $table->head[] = get_string('attemptstate', 'quiz');
1379
        $table->head[] = get_string('attemptstate', 'quiz');
1155
        $table->align[] = 'left';
1380
        $table->align[] = 'left';
1156
        $table->size[] = '';
1381
        $table->size[] = '';
1157
        if ($viewobj->markcolumn) {
1382
        if ($viewobj->markcolumn) {
1158
            $table->head[] = get_string('marks', 'quiz') . ' / ' .
1383
            $table->head[] = get_string('marks', 'quiz') . ' / ' .
1159
                    quiz_format_grade($quiz, $quiz->sumgrades);
1384
                quiz_format_grade($quiz, $quiz->sumgrades);
1160
            $table->align[] = 'center';
1385
            $table->align[] = 'center';
1161
            $table->size[] = '';
1386
            $table->size[] = '';
1162
        }
1387
        }
1163
        if ($viewobj->gradecolumn) {
1388
        if ($viewobj->gradecolumn) {
1164
            $table->head[] = get_string('gradenoun') . ' / ' .
1389
            $table->head[] = get_string('gradenoun') . ' / ' .
1165
                    quiz_format_grade($quiz, $quiz->grade);
1390
                quiz_format_grade($quiz, $quiz->grade);
1166
            $table->align[] = 'center';
1391
            $table->align[] = 'center';
1167
            $table->size[] = '';
1392
            $table->size[] = '';
1168
        }
1393
        }
1169
        if ($viewobj->canreviewmine) {
1394
        if ($viewobj->canreviewmine) {
1170
            $table->head[] = get_string('review', 'quiz');
1395
            $table->head[] = get_string('review', 'quiz');
Línea 1192... Línea 1417...
1192
            }
1417
            }
Línea 1193... Línea 1418...
1193
 
1418
 
Línea 1194... Línea 1419...
1194
            $row[] = $this->attempt_state($attemptobj);
1419
            $row[] = $this->attempt_state($attemptobj);
-
 
1420
 
1195
 
1421
            if ($viewobj->markcolumn) {
1196
            if ($viewobj->markcolumn) {
1422
                if (
-
 
1423
                    $attemptoptions->marks >= question_display_options::MARK_AND_MAX &&
1197
                if ($attemptoptions->marks >= question_display_options::MARK_AND_MAX &&
1424
                    $attemptobj->is_finished()
1198
                        $attemptobj->is_finished()) {
1425
                ) {
1199
                    $row[] = quiz_format_grade($quiz, $attemptobj->get_sum_marks());
1426
                    $row[] = quiz_format_grade($quiz, $attemptobj->get_sum_marks());
1200
                } else {
1427
                } else {
1201
                    $row[] = '';
1428
                    $row[] = '';
Línea 1202... Línea 1429...
1202
                }
1429
                }
1203
            }
1430
            }
Línea 1204... Línea 1431...
1204
 
1431
 
-
 
1432
            // Outside the if because we may be showing feedback but not grades.
1205
            // Outside the if because we may be showing feedback but not grades.
1433
            $attemptgrade = quiz_rescale_grade($attemptobj->get_sum_marks(), $quiz, false);
1206
            $attemptgrade = quiz_rescale_grade($attemptobj->get_sum_marks(), $quiz, false);
1434
 
-
 
1435
            if ($viewobj->gradecolumn) {
Línea 1207... Línea 1436...
1207
 
1436
                if (
-
 
1437
                    $attemptoptions->marks >= question_display_options::MARK_AND_MAX &&
1208
            if ($viewobj->gradecolumn) {
1438
                    $attemptobj->is_finished()
1209
                if ($attemptoptions->marks >= question_display_options::MARK_AND_MAX &&
1439
                ) {
1210
                        $attemptobj->is_finished()) {
1440
 
1211
 
1441
                    // Highlight the highest grade if appropriate.
1212
                    // Highlight the highest grade if appropriate.
1442
                    if (
-
 
1443
                        $viewobj->overallstats && !$attemptobj->is_preview()
1213
                    if ($viewobj->overallstats && !$attemptobj->is_preview()
1444
                        && $viewobj->numattempts > 1 && !is_null($viewobj->mygrade)
1214
                            && $viewobj->numattempts > 1 && !is_null($viewobj->mygrade)
1445
                        && $attemptobj->get_state() == quiz_attempt::FINISHED
Línea 1215... Línea 1446...
1215
                            && $attemptobj->get_state() == quiz_attempt::FINISHED
1446
                        && $attemptgrade == $viewobj->mygrade
1216
                            && $attemptgrade == $viewobj->mygrade
1447
                        && $quiz->grademethod == QUIZ_GRADEHIGHEST
1217
                            && $quiz->grademethod == QUIZ_GRADEHIGHEST) {
1448
                    ) {
1218
                        $table->rowclasses[$attemptobj->get_attempt_number()] = 'bestrow';
1449
                        $table->rowclasses[$attemptobj->get_attempt_number()] = 'bestrow';
1219
                    }
1450
                    }
Línea 1220... Línea 1451...
1220
 
1451
 
1221
                    $row[] = quiz_format_grade($quiz, $attemptgrade);
1452
                    $row[] = quiz_format_grade($quiz, $attemptgrade);
-
 
1453
                } else {
1222
                } else {
1454
                    $row[] = '';
-
 
1455
                }
-
 
1456
            }
1223
                    $row[] = '';
1457
 
Línea 1224... Línea 1458...
1224
                }
1458
            if ($viewobj->canreviewmine) {
1225
            }
1459
                $row[] = $viewobj->accessmanager->make_review_link(
1226
 
1460
                    $attemptobj->get_attempt(),
Línea 1254... Línea 1488...
1254
     * Generate a brief textual description of the current state of an attempt.
1488
     * Generate a brief textual description of the current state of an attempt.
1255
     *
1489
     *
1256
     * @param quiz_attempt $attemptobj the attempt
1490
     * @param quiz_attempt $attemptobj the attempt
1257
     * @return string the appropriate lang string to describe the state.
1491
     * @return string the appropriate lang string to describe the state.
1258
     */
1492
     */
1259
    public function attempt_state($attemptobj) {
1493
    public function attempt_state($attemptobj)
-
 
1494
    {
1260
        switch ($attemptobj->get_state()) {
1495
        switch ($attemptobj->get_state()) {
1261
            case quiz_attempt::IN_PROGRESS:
1496
            case quiz_attempt::IN_PROGRESS:
1262
                return get_string('stateinprogress', 'quiz');
1497
                return get_string('stateinprogress', 'quiz');
Línea 1263... Línea 1498...
1263
 
1498
 
1264
            case quiz_attempt::OVERDUE:
1499
            case quiz_attempt::OVERDUE:
-
 
1500
                return get_string('stateoverdue', 'quiz') . html_writer::tag(
-
 
1501
                    'span',
1265
                return get_string('stateoverdue', 'quiz') . html_writer::tag('span',
1502
                    get_string(
-
 
1503
                        'stateoverduedetails',
1266
                                get_string('stateoverduedetails', 'quiz',
1504
                        'quiz',
-
 
1505
                        userdate($attemptobj->get_due_date())
1267
                                        userdate($attemptobj->get_due_date())),
1506
                    ),
-
 
1507
                    ['class' => 'statedetails']
Línea 1268... Línea 1508...
1268
                                ['class' => 'statedetails']);
1508
                );
1269
 
1509
 
-
 
1510
            case quiz_attempt::FINISHED:
-
 
1511
                return get_string('statefinished', 'quiz') . html_writer::tag(
1270
            case quiz_attempt::FINISHED:
1512
                    'span',
-
 
1513
                    get_string(
1271
                return get_string('statefinished', 'quiz') . html_writer::tag('span',
1514
                        'statefinisheddetails',
-
 
1515
                        'quiz',
1272
                                get_string('statefinisheddetails', 'quiz',
1516
                        userdate($attemptobj->get_submitted_date())
-
 
1517
                    ),
Línea 1273... Línea 1518...
1273
                                        userdate($attemptobj->get_submitted_date())),
1518
                    ['class' => 'statedetails']
1274
                                ['class' => 'statedetails']);
1519
                );
Línea 1275... Línea 1520...
1275
 
1520
 
Línea 1288... Línea 1533...
1288
     * @param context_module $context The quiz context.
1533
     * @param context_module $context The quiz context.
1289
     * @param stdClass|cm_info $cm The course module information.
1534
     * @param stdClass|cm_info $cm The course module information.
1290
     * @param view_page $viewobj
1535
     * @param view_page $viewobj
1291
     * @return string HTML to display.
1536
     * @return string HTML to display.
1292
     */
1537
     */
1293
    public function view_result_info($quiz, $context, $cm, $viewobj) {
1538
    public function view_result_info($quiz, $context, $cm, $viewobj)
-
 
1539
    {
1294
        $output = '';
1540
        $output = '';
1295
        if (!$viewobj->numattempts && !$viewobj->gradecolumn && is_null($viewobj->mygrade)) {
1541
        if (!$viewobj->numattempts && !$viewobj->gradecolumn && is_null($viewobj->mygrade)) {
1296
            return $output;
1542
            return $output;
1297
        }
1543
        }
1298
        $resultinfo = '';
1544
        $resultinfo = '';
Línea 1313... Línea 1559...
1313
            }
1559
            }
1314
        }
1560
        }
Línea 1315... Línea 1561...
1315
 
1561
 
Línea -... Línea 1562...
-
 
1562
        if ($viewobj->mygradeoverridden) {
-
 
1563
 
1316
        if ($viewobj->mygradeoverridden) {
1564
            $resultinfo .= html_writer::tag(
1317
 
1565
                'p',
-
 
1566
                get_string('overriddennotice', 'grades'),
1318
            $resultinfo .= html_writer::tag('p', get_string('overriddennotice', 'grades'),
1567
                ['class' => 'overriddennotice']
1319
                            ['class' => 'overriddennotice']) . "\n";
1568
            ) . "\n";
1320
        }
1569
        }
1321
        if ($viewobj->gradebookfeedback) {
1570
        if ($viewobj->gradebookfeedback) {
1322
            $resultinfo .= $this->heading(get_string('comment', 'quiz'), 3);
1571
            $resultinfo .= $this->heading(get_string('comment', 'quiz'), 3);
1323
            $resultinfo .= html_writer::div($viewobj->gradebookfeedback, 'quizteacherfeedback') . "\n";
1572
            $resultinfo .= html_writer::div($viewobj->gradebookfeedback, 'quizteacherfeedback') . "\n";
1324
        }
1573
        }
1325
        if ($viewobj->feedbackcolumn) {
1574
        if ($viewobj->feedbackcolumn) {
1326
            $resultinfo .= $this->heading(get_string('overallfeedback', 'quiz'), 3);
1575
            $resultinfo .= $this->heading(get_string('overallfeedback', 'quiz'), 3);
1327
            $resultinfo .= html_writer::div(
1576
            $resultinfo .= html_writer::div(
-
 
1577
                quiz_feedback_for_grade($viewobj->mygrade, $quiz, $context),
1328
                            quiz_feedback_for_grade($viewobj->mygrade, $quiz, $context),
1578
                'quizgradefeedback'
Línea 1329... Línea 1579...
1329
                            'quizgradefeedback') . "\n";
1579
            ) . "\n";
1330
        }
1580
        }
1331
 
1581
 
Línea 1342... Línea 1592...
1342
     * @param moodle_url $url of the target page.
1592
     * @param moodle_url $url of the target page.
1343
     * @param bool $reviewinpopup whether a pop-up is required.
1593
     * @param bool $reviewinpopup whether a pop-up is required.
1344
     * @param array $popupoptions options to pass to the popup_action constructor.
1594
     * @param array $popupoptions options to pass to the popup_action constructor.
1345
     * @return string HTML to output.
1595
     * @return string HTML to output.
1346
     */
1596
     */
1347
    public function review_link($url, $reviewinpopup, $popupoptions) {
1597
    public function review_link($url, $reviewinpopup, $popupoptions)
-
 
1598
    {
1348
        if ($reviewinpopup) {
1599
        if ($reviewinpopup) {
1349
            $button = new single_button($url, get_string('review', 'quiz'));
1600
            $button = new single_button($url, get_string('review', 'quiz'));
1350
            $button->add_action(new popup_action('click', $url, 'quizpopup', $popupoptions));
1601
            $button->add_action(new popup_action('click', $url, 'quizpopup', $popupoptions));
1351
            return $this->render($button);
1602
            return $this->render($button);
1352
 
-
 
1353
        } else {
1603
        } else {
-
 
1604
            return html_writer::link(
-
 
1605
                $url,
1354
            return html_writer::link($url, get_string('review', 'quiz'),
1606
                get_string('review', 'quiz'),
1355
                    ['title' => get_string('reviewthisattempt', 'quiz')]);
1607
                ['title' => get_string('reviewthisattempt', 'quiz')]
-
 
1608
            );
1356
        }
1609
        }
1357
    }
1610
    }
Línea 1358... Línea 1611...
1358
 
1611
 
1359
    /**
1612
    /**
1360
     * Displayed where there might normally be a review link, to explain why the
1613
     * Displayed where there might normally be a review link, to explain why the
1361
     * review is not available at this time.
1614
     * review is not available at this time.
1362
     *
1615
     *
1363
     * @param string $message optional message explaining why the review is not possible.
1616
     * @param string $message optional message explaining why the review is not possible.
1364
     * @return string HTML to output.
1617
     * @return string HTML to output.
1365
     */
1618
     */
-
 
1619
    public function no_review_message($message)
1366
    public function no_review_message($message) {
1620
    {
-
 
1621
        return html_writer::nonempty_tag(
-
 
1622
            'span',
1367
        return html_writer::nonempty_tag('span', $message,
1623
            $message,
-
 
1624
            ['class' => 'noreviewmessage']
1368
                ['class' => 'noreviewmessage']);
1625
        );
Línea 1369... Línea 1626...
1369
    }
1626
    }
1370
 
1627
 
1371
    /**
1628
    /**
Línea 1379... Línea 1636...
1379
     *      instead of 'Attempts: 0'.
1636
     *      instead of 'Attempts: 0'.
1380
     * @param int $currentgroup if there is a concept of current group where this method is being
1637
     * @param int $currentgroup if there is a concept of current group where this method is being
1381
     *      called (e.g. a report) pass it in here. Default 0 which means no current group.
1638
     *      called (e.g. a report) pass it in here. Default 0 which means no current group.
1382
     * @return string HTML fragment for the link.
1639
     * @return string HTML fragment for the link.
1383
     */
1640
     */
1384
    public function quiz_attempt_summary_link_to_reports($quiz, $cm, $context,
1641
    public function quiz_attempt_summary_link_to_reports(
-
 
1642
        $quiz,
-
 
1643
        $cm,
-
 
1644
        $context,
1385
            $returnzero = false, $currentgroup = 0) {
1645
        $returnzero = false,
-
 
1646
        $currentgroup = 0
-
 
1647
    ) {
1386
        global $CFG;
1648
        global $CFG;
1387
        $summary = quiz_num_attempt_summary($quiz, $cm, $returnzero, $currentgroup);
1649
        $summary = quiz_num_attempt_summary($quiz, $cm, $returnzero, $currentgroup);
1388
        if (!$summary) {
1650
        if (!$summary) {
1389
            return '';
1651
            return '';
1390
        }
1652
        }
Línea 1391... Línea 1653...
1391
 
1653
 
1392
        require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
1654
        require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
-
 
1655
        $url = new moodle_url('/mod/quiz/report.php', [
1393
        $url = new moodle_url('/mod/quiz/report.php', [
1656
            'id' => $cm->id,
-
 
1657
            'mode' => quiz_report_default_report($context)
1394
                'id' => $cm->id, 'mode' => quiz_report_default_report($context)]);
1658
        ]);
1395
        return html_writer::link($url, $summary);
1659
        return html_writer::link($url, $summary);
Línea 1396... Línea 1660...
1396
    }
1660
    }
1397
 
1661
 
Línea 1401... Línea 1665...
1401
     * @param stdClass $quiz the quiz settings.
1665
     * @param stdClass $quiz the quiz settings.
1402
     * @param cm_info|stdClass $cm the cm object.
1666
     * @param cm_info|stdClass $cm the cm object.
1403
     * @param int $currentgroup currently selected group, if there is one.
1667
     * @param int $currentgroup currently selected group, if there is one.
1404
     * @return string HTML fragment for the link.
1668
     * @return string HTML fragment for the link.
1405
     */
1669
     */
1406
    public function quiz_override_summary_links(stdClass $quiz, cm_info|stdClass $cm, $currentgroup = 0): string {
1670
    public function quiz_override_summary_links(stdClass $quiz, cm_info|stdClass $cm, $currentgroup = 0): string
-
 
1671
    {
Línea 1407... Línea 1672...
1407
 
1672
 
1408
        $baseurl = new moodle_url('/mod/quiz/overrides.php', ['cmid' => $cm->id]);
1673
        $baseurl = new moodle_url('/mod/quiz/overrides.php', ['cmid' => $cm->id]);
Línea 1409... Línea 1674...
1409
        $counts = quiz_override_summary($quiz, $cm, $currentgroup);
1674
        $counts = quiz_override_summary($quiz, $cm, $currentgroup);
1410
 
1675
 
-
 
1676
        $links = [];
1411
        $links = [];
1677
        if ($counts['group']) {
1412
        if ($counts['group']) {
1678
            $links[] = html_writer::link(
-
 
1679
                new moodle_url($baseurl, ['mode' => 'group']),
1413
            $links[] = html_writer::link(new moodle_url($baseurl, ['mode' => 'group']),
1680
                get_string('overridessummarygroup', 'quiz', $counts['group'])
1414
                    get_string('overridessummarygroup', 'quiz', $counts['group']));
1681
            );
-
 
1682
        }
1415
        }
1683
        if ($counts['user']) {
1416
        if ($counts['user']) {
1684
            $links[] = html_writer::link(
-
 
1685
                new moodle_url($baseurl, ['mode' => 'user']),
1417
            $links[] = html_writer::link(new moodle_url($baseurl, ['mode' => 'user']),
1686
                get_string('overridessummaryuser', 'quiz', $counts['user'])
Línea 1418... Línea 1687...
1418
                    get_string('overridessummaryuser', 'quiz', $counts['user']));
1687
            );
1419
        }
1688
        }
1420
 
1689
 
Línea 1444... Línea 1713...
1444
     * @param \core\chart_base $chart The chart.
1713
     * @param \core\chart_base $chart The chart.
1445
     * @param string $title The title to display above the graph.
1714
     * @param string $title The title to display above the graph.
1446
     * @param array $attrs extra container html attributes.
1715
     * @param array $attrs extra container html attributes.
1447
     * @return string HTML of the graph.
1716
     * @return string HTML of the graph.
1448
     */
1717
     */
1449
    public function chart(\core\chart_base $chart, $title, $attrs = []) {
1718
    public function chart(\core\chart_base $chart, $title, $attrs = [])
-
 
1719
    {
1450
        return $this->heading($title, 3) . html_writer::tag('div',
1720
        return $this->heading($title, 3) . html_writer::tag(
-
 
1721
            'div',
-
 
1722
            $this->render($chart),
1451
                        $this->render($chart), array_merge(['class' => 'graph'], $attrs));
1723
            array_merge(['class' => 'graph'], $attrs)
-
 
1724
        );
1452
    }
1725
    }
Línea 1453... Línea 1726...
1453
 
1726
 
1454
    /**
1727
    /**
1455
     * Output a graph, or a message saying that GD is required.
1728
     * Output a graph, or a message saying that GD is required.
1456
     *
1729
     *
1457
     * @param moodle_url $url the URL of the graph.
1730
     * @param moodle_url $url the URL of the graph.
1458
     * @param string $title the title to display above the graph.
1731
     * @param string $title the title to display above the graph.
1459
     * @return string HTML of the graph.
1732
     * @return string HTML of the graph.
1460
     */
1733
     */
-
 
1734
    public function graph(moodle_url $url, $title)
1461
    public function graph(moodle_url $url, $title) {
1735
    {
Línea 1462... Línea 1736...
1462
        $graph = html_writer::empty_tag('img', ['src' => $url, 'alt' => $title]);
1736
        $graph = html_writer::empty_tag('img', ['src' => $url, 'alt' => $title]);
1463
 
1737
 
Línea 1464... Línea 1738...
1464
        return $this->heading($title, 3) . html_writer::tag('div', $graph, ['class' => 'graph']);
1738
        return $this->heading($title, 3) . html_writer::tag('div', $graph, ['class' => 'graph']);
1465
    }
1739
    }
1466
 
1740
 
1467
    /**
1741
    /**
1468
     * Output the connection warning messages, which are initially hidden, and
1742
     * Output the connection warning messages, which are initially hidden, and
-
 
1743
     * only revealed by JavaScript if necessary.
1469
     * only revealed by JavaScript if necessary.
1744
     */
1470
     */
1745
    public function connection_warning()
1471
    public function connection_warning() {
1746
    {
1472
        $options = ['filter' => false, 'newlines' => false];
1747
        $options = ['filter' => false, 'newlines' => false];
-
 
1748
        $warning = format_text(get_string('connectionerror', 'quiz'), FORMAT_MARKDOWN, $options);
-
 
1749
        $ok = format_text(get_string('connectionok', 'quiz'), FORMAT_MARKDOWN, $options);
1473
        $warning = format_text(get_string('connectionerror', 'quiz'), FORMAT_MARKDOWN, $options);
1750
        return html_writer::tag(
-
 
1751
            'div',
1474
        $ok = format_text(get_string('connectionok', 'quiz'), FORMAT_MARKDOWN, $options);
1752
            $warning,
1475
        return html_writer::tag('div', $warning,
1753
            ['id' => 'connection-error', 'style' => 'display: none;', 'role' => 'alert']
Línea 1476... Línea 1754...
1476
                        ['id' => 'connection-error', 'style' => 'display: none;', 'role' => 'alert']) .
1754
        ) .
1477
                html_writer::tag('div', $ok, ['id' => 'connection-ok', 'style' => 'display: none;', 'role' => 'alert']);
1755
            html_writer::tag('div', $ok, ['id' => 'connection-ok', 'style' => 'display: none;', 'role' => 'alert']);
1478
    }
1756
    }
1479
 
1757
 
1480
    /**
1758
    /**
1481
     * Deprecated version of render_links_to_other_attempts.
1759
     * Deprecated version of render_links_to_other_attempts.
1482
     *
1760
     *
1483
     * @param links_to_other_attempts $links
1761
     * @param links_to_other_attempts $links
1484
     * @return string HTML fragment.
1762
     * @return string HTML fragment.
-
 
1763
     * @deprecated since Moodle 4.2. Please use render_links_to_other_attempts instead.
1485
     * @deprecated since Moodle 4.2. Please use render_links_to_other_attempts instead.
1764
     * @todo MDL-76612 Final deprecation in Moodle 4.6
1486
     * @todo MDL-76612 Final deprecation in Moodle 4.6
1765
     */
Línea 1487... Línea 1766...
1487
     */
1766
    protected function render_mod_quiz_links_to_other_attempts(links_to_other_attempts $links)
1488
    protected function render_mod_quiz_links_to_other_attempts(links_to_other_attempts $links) {
1767
    {
Línea 1495... Línea 1774...
1495
     * @param navigation_question_button $button
1774
     * @param navigation_question_button $button
1496
     * @return string HTML fragment.
1775
     * @return string HTML fragment.
1497
     * @deprecated since Moodle 4.2. Please use render_links_to_other_attempts instead.
1776
     * @deprecated since Moodle 4.2. Please use render_links_to_other_attempts instead.
1498
     * @todo MDL-76612 Final deprecation in Moodle 4.6
1777
     * @todo MDL-76612 Final deprecation in Moodle 4.6
1499
     */
1778
     */
1500
    protected function render_quiz_nav_question_button(navigation_question_button $button) {
1779
    protected function render_quiz_nav_question_button(navigation_question_button $button)
-
 
1780
    {
1501
        return $this->render_navigation_question_button($button);
1781
        return $this->render_navigation_question_button($button);
1502
    }
1782
    }
Línea 1503... Línea 1783...
1503
 
1783
 
1504
    /**
1784
    /**
Línea 1507... Línea 1787...
1507
     * @param navigation_section_heading $heading the heading.
1787
     * @param navigation_section_heading $heading the heading.
1508
     * @return string HTML fragment.
1788
     * @return string HTML fragment.
1509
     * @deprecated since Moodle 4.2. Please use render_links_to_other_attempts instead.
1789
     * @deprecated since Moodle 4.2. Please use render_links_to_other_attempts instead.
1510
     * @todo MDL-76612 Final deprecation in Moodle 4.6
1790
     * @todo MDL-76612 Final deprecation in Moodle 4.6
1511
     */
1791
     */
1512
    protected function render_quiz_nav_section_heading(navigation_section_heading $heading) {
1792
    protected function render_quiz_nav_section_heading(navigation_section_heading $heading)
-
 
1793
    {
1513
        return $this->render_navigation_section_heading($heading);
1794
        return $this->render_navigation_section_heading($heading);
1514
    }
1795
    }
1515
}
1796
}