Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
namespace mod_quiz\output;
18
 
19
use mod_quiz\quiz_attempt;
20
use moodle_url;
21
use question_attempt;
22
use question_display_options;
23
use question_state;
24
use renderable;
25
use user_picture;
26
 
27
/**
28
 * Represents the navigation panel, and builds a {@see block_contents} to allow it to be output.
29
 *
30
 * This class is not currently renderable or templatable, but it probably should be in the future,
31
 * which is why it is already in the output namespace.
32
 *
33
 * @package   mod_quiz
34
 * @category  output
35
 * @copyright 2008 Tim Hunt
36
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37
 */
38
abstract class navigation_panel_base {
39
    /** @var quiz_attempt */
40
    protected $attemptobj;
41
    /** @var question_display_options */
42
    protected $options;
43
    /** @var integer */
44
    protected $page;
45
    /** @var boolean */
46
    protected $showall;
47
 
48
    /**
49
     * Constructor.
50
     *
51
     * @param quiz_attempt $attemptobj construct the panel for this attempt.
52
     * @param question_display_options $options display options in force.
53
     * @param int $page which page of the quiz attempt is being shown, -1 if all.
54
     * @param bool $showall whether all pages are being shown at once.
55
     */
56
    public function __construct(quiz_attempt $attemptobj,
57
            question_display_options $options, $page, $showall) {
58
        $this->attemptobj = $attemptobj;
59
        $this->options = $options;
60
        $this->page = $page;
61
        $this->showall = $showall;
62
    }
63
 
64
    /**
65
     * Get the buttons and section headings to go in the quiz navigation block.
66
     *
67
     * @return renderable[] the buttons, possibly interleaved with section headings.
68
     */
69
    public function get_question_buttons() {
70
        $buttons = [];
71
        foreach ($this->attemptobj->get_slots() as $slot) {
72
            $heading = $this->attemptobj->get_heading_before_slot($slot);
73
            if (!is_null($heading)) {
74
                $sections = $this->attemptobj->get_quizobj()->get_sections();
75
                if (!(empty($heading) && count($sections) == 1)) {
76
                    $buttons[] = new navigation_section_heading(format_string($heading));
77
                }
78
            }
79
 
80
            $qa = $this->attemptobj->get_question_attempt($slot);
81
            $showcorrectness = $this->options->correctness && $qa->has_marks();
82
 
83
            $button = new navigation_question_button();
84
            $button->id          = 'quiznavbutton' . $slot;
85
            $button->isrealquestion = $this->attemptobj->is_real_question($slot);
86
            $button->number      = $this->attemptobj->get_question_number($slot);
87
            $button->stateclass  = $qa->get_state_class($showcorrectness);
88
            $button->navmethod   = $this->attemptobj->get_navigation_method();
89
            if (!$showcorrectness && $button->stateclass === 'notanswered') {
90
                $button->stateclass = 'complete';
91
            }
92
            $button->statestring = $this->get_state_string($qa, $showcorrectness);
93
            $button->page        = $this->attemptobj->get_question_page($slot);
94
            $button->currentpage = $this->showall || $button->page == $this->page;
95
            $button->flagged     = $qa->is_flagged();
96
            $button->url         = $this->get_question_url($slot);
97
            if ($this->attemptobj->is_blocked_by_previous_question($slot)) {
98
                $button->url = null;
99
                $button->stateclass = 'blocked';
100
                $button->statestring = get_string('questiondependsonprevious', 'quiz');
101
            }
102
            $buttons[] = $button;
103
        }
104
 
105
        return $buttons;
106
    }
107
 
108
    /**
109
     * Get the human-readable description of the current state of a particular question.
110
     *
111
     * @param question_attempt $qa the attempt at the question of interest.
112
     * @param bool $showcorrectness whether the current use is allowed to see if they have got the question right.
113
     * @return string Human-readable description of the state.
114
     */
115
    protected function get_state_string(question_attempt $qa, $showcorrectness) {
116
        if ($qa->get_question(false)->length > 0) {
117
            return $qa->get_state_string($showcorrectness);
118
        }
119
 
120
        // Special case handling for 'information' items.
121
        if ($qa->get_state() == question_state::$todo) {
122
            return get_string('notyetviewed', 'quiz');
123
        } else {
124
            return get_string('viewed', 'quiz');
125
        }
126
    }
127
 
128
    /**
129
     * Hook for subclasses to override to do output above the question buttons.
130
     *
131
     * @param renderer $output the quiz renderer to use.
132
     * @return string HTML to output.
133
     */
134
    public function render_before_button_bits(renderer $output) {
135
        return '';
136
    }
137
 
138
    /**
139
     * Hook that subclasses must override to do output after the question buttons.
140
     *
141
     * @param renderer $output the quiz renderer to use.
142
     * @return string HTML to output.
143
     */
144
    abstract public function render_end_bits(renderer $output);
145
 
146
    /**
147
     * Render the restart preview button.
148
     *
149
     * @param renderer $output the quiz renderer to use.
150
     * @return string HTML to output.
151
     */
152
    protected function render_restart_preview_link($output) {
153
        if (!$this->attemptobj->is_own_preview()) {
154
            return '';
155
        }
156
        return $output->restart_preview_button(new moodle_url(
157
                $this->attemptobj->start_attempt_url(), ['forcenew' => true]));
158
    }
159
 
160
    /**
161
     * Get the URL to navigate to a particular question.
162
     *
163
     * @param int $slot slot number, to identify the question.
164
     * @return moodle_url|null URL if the user can navigate there, or null if they cannot.
165
     */
166
    abstract protected function get_question_url($slot);
167
 
168
    /**
169
     * Get the user picture which should be displayed, if required.
170
     *
171
     * @return user_picture|null
172
     */
173
    public function user_picture() {
174
        global $DB;
175
        if ($this->attemptobj->get_quiz()->showuserpicture == QUIZ_SHOWIMAGE_NONE) {
176
            return null;
177
        }
178
        $user = $DB->get_record('user', ['id' => $this->attemptobj->get_userid()]);
179
        $userpicture = new user_picture($user);
180
        $userpicture->courseid = $this->attemptobj->get_courseid();
181
        if ($this->attemptobj->get_quiz()->showuserpicture == QUIZ_SHOWIMAGE_LARGE) {
182
            $userpicture->size = true;
183
        }
184
        return $userpicture;
185
    }
186
 
187
    /**
188
     * Return 'allquestionsononepage' as CSS class name when $showall is set,
189
     * otherwise, return 'multipages' as CSS class name.
190
     *
191
     * @return string, CSS class name
192
     */
193
    public function get_button_container_class() {
194
        // Quiz navigation is set on 'Show all questions on one page'.
195
        if ($this->showall) {
196
            return 'allquestionsononepage';
197
        }
198
        // Quiz navigation is set on 'Show one page at a time'.
199
        return 'multipages';
200
    }
201
}