Merge branch 'MDL-62983-master' of git://github.com/sarjona/moodle
[moodle.git] / mod / choice / renderer.php
blob7db91175637837eab56692626f3eb349bff15ddc
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 /**
19 * Moodle renderer used to display special elements of the lesson module
21 * @package mod_choice
22 * @copyright 2010 Rossiani Wijaya
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 **/
25 define ('DISPLAY_HORIZONTAL_LAYOUT', 0);
26 define ('DISPLAY_VERTICAL_LAYOUT', 1);
28 class mod_choice_renderer extends plugin_renderer_base {
30 /**
31 * Returns HTML to display choices of option
32 * @param object $options
33 * @param int $coursemoduleid
34 * @param bool $vertical
35 * @return string
37 public function display_options($options, $coursemoduleid, $vertical = false, $multiple = false) {
38 $layoutclass = 'horizontal';
39 if ($vertical) {
40 $layoutclass = 'vertical';
42 $target = new moodle_url('/mod/choice/view.php');
43 $attributes = array('method'=>'POST', 'action'=>$target, 'class'=> $layoutclass);
44 $disabled = empty($options['previewonly']) ? array() : array('disabled' => 'disabled');
46 $html = html_writer::start_tag('form', $attributes);
47 $html .= html_writer::start_tag('ul', array('class' => 'choices list-unstyled unstyled'));
49 $availableoption = count($options['options']);
50 $choicecount = 0;
51 foreach ($options['options'] as $option) {
52 $choicecount++;
53 $html .= html_writer::start_tag('li', array('class'=>'option'));
54 if ($multiple) {
55 $option->attributes->name = 'answer[]';
56 $option->attributes->type = 'checkbox';
57 } else {
58 $option->attributes->name = 'answer';
59 $option->attributes->type = 'radio';
61 $option->attributes->id = 'choice_'.$choicecount;
62 $option->attributes->class = 'm-x-1';
64 $labeltext = $option->text;
65 if (!empty($option->attributes->disabled)) {
66 $labeltext .= ' ' . get_string('full', 'choice');
67 $availableoption--;
70 $html .= html_writer::empty_tag('input', (array)$option->attributes + $disabled);
71 $html .= html_writer::tag('label', $labeltext, array('for'=>$option->attributes->id));
72 $html .= html_writer::end_tag('li');
74 $html .= html_writer::tag('li','', array('class'=>'clearfloat'));
75 $html .= html_writer::end_tag('ul');
76 $html .= html_writer::tag('div', '', array('class'=>'clearfloat'));
77 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=>sesskey()));
78 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'action', 'value'=>'makechoice'));
79 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'id', 'value'=>$coursemoduleid));
81 if (empty($options['previewonly'])) {
82 if (!empty($options['hascapability']) && ($options['hascapability'])) {
83 if ($availableoption < 1) {
84 $html .= html_writer::tag('label', get_string('choicefull', 'choice'));
85 } else {
86 $html .= html_writer::empty_tag('input', array(
87 'type' => 'submit',
88 'value' => get_string('savemychoice', 'choice'),
89 'class' => 'btn btn-primary'
90 ));
93 if (!empty($options['allowupdate']) && ($options['allowupdate'])) {
94 $url = new moodle_url('view.php',
95 array('id' => $coursemoduleid, 'action' => 'delchoice', 'sesskey' => sesskey()));
96 $html .= html_writer::link($url, get_string('removemychoice', 'choice'), array('class' => 'm-l-1'));
98 } else {
99 $html .= html_writer::tag('label', get_string('havetologin', 'choice'));
103 $html .= html_writer::end_tag('ul');
104 $html .= html_writer::end_tag('form');
106 return $html;
110 * Returns HTML to display choices result
111 * @param object $choices
112 * @param bool $forcepublish
113 * @return string
115 public function display_result($choices, $forcepublish = false) {
116 if (empty($forcepublish)) { //allow the publish setting to be overridden
117 $forcepublish = $choices->publish;
120 $displaylayout = $choices->display;
122 if ($forcepublish) { //CHOICE_PUBLISH_NAMES
123 return $this->display_publish_name_vertical($choices);
124 } else {
125 return $this->display_publish_anonymous($choices, $displaylayout);
130 * Returns HTML to display choices result
131 * @param object $choices
132 * @param bool $forcepublish
133 * @return string
135 public function display_publish_name_vertical($choices) {
136 global $PAGE;
137 $html ='';
138 $html .= html_writer::tag('h3',format_string(get_string("responses", "choice")));
140 $attributes = array('method'=>'POST');
141 $attributes['action'] = new moodle_url($PAGE->url);
142 $attributes['id'] = 'attemptsform';
144 if ($choices->viewresponsecapability) {
145 $html .= html_writer::start_tag('form', $attributes);
146 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'id', 'value'=> $choices->coursemoduleid));
147 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=> sesskey()));
148 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'mode', 'value'=>'overview'));
151 $table = new html_table();
152 $table->cellpadding = 0;
153 $table->cellspacing = 0;
154 $table->attributes['class'] = 'results names table table-bordered';
155 $table->tablealign = 'center';
156 $table->summary = get_string('responsesto', 'choice', format_string($choices->name));
157 $table->data = array();
159 $count = 0;
160 ksort($choices->options);
162 $columns = array();
163 $celldefault = new html_table_cell();
164 $celldefault->attributes['class'] = 'data';
166 // This extra cell is needed in order to support accessibility for screenreader. MDL-30816
167 $accessiblecell = new html_table_cell();
168 $accessiblecell->scope = 'row';
169 $accessiblecell->text = get_string('choiceoptions', 'choice');
170 $columns['options'][] = $accessiblecell;
172 $usernumberheader = clone($celldefault);
173 $usernumberheader->header = true;
174 $usernumberheader->attributes['class'] = 'header data';
175 $usernumberheader->text = get_string('numberofuser', 'choice');
176 $columns['usernumber'][] = $usernumberheader;
178 $optionsnames = [];
179 foreach ($choices->options as $optionid => $options) {
180 $celloption = clone($celldefault);
181 $cellusernumber = clone($celldefault);
182 $cellusernumber->style = 'text-align: center;';
184 $celltext = '';
185 if ($choices->showunanswered && $optionid == 0) {
186 $celltext = get_string('notanswered', 'choice');
187 } else if ($optionid > 0) {
188 $celltext = format_string($choices->options[$optionid]->text);
190 $numberofuser = 0;
191 if (!empty($options->user) && count($options->user) > 0) {
192 $numberofuser = count($options->user);
195 $celloption->text = $celltext;
196 $optionsnames[$optionid] = $celltext;
197 $cellusernumber->text = $numberofuser;
199 $columns['options'][] = $celloption;
200 $columns['usernumber'][] = $cellusernumber;
203 $table->head = $columns['options'];
204 $table->data[] = new html_table_row($columns['usernumber']);
206 $columns = array();
208 // This extra cell is needed in order to support accessibility for screenreader. MDL-30816
209 $accessiblecell = new html_table_cell();
210 $accessiblecell->text = get_string('userchoosethisoption', 'choice');
211 $accessiblecell->header = true;
212 $accessiblecell->scope = 'row';
213 $accessiblecell->attributes['class'] = 'header data';
214 $columns[] = $accessiblecell;
216 foreach ($choices->options as $optionid => $options) {
217 $cell = new html_table_cell();
218 $cell->attributes['class'] = 'data';
220 if ($choices->showunanswered || $optionid > 0) {
221 if (!empty($options->user)) {
222 $optionusers = '';
223 foreach ($options->user as $user) {
224 $data = '';
225 if (empty($user->imagealt)) {
226 $user->imagealt = '';
229 $userfullname = fullname($user, $choices->fullnamecapability);
230 $checkbox = '';
231 if ($choices->viewresponsecapability && $choices->deleterepsonsecapability) {
232 $checkboxid = 'attempt-user' . $user->id . '-option' . $optionid;
233 $checkbox .= html_writer::label($userfullname . ' ' . $optionsnames[$optionid],
234 $checkboxid, false, array('class' => 'accesshide'));
235 if ($optionid > 0) {
236 $checkboxname = 'attemptid[]';
237 $checkboxvalue = $user->answerid;
238 } else {
239 $checkboxname = 'userid[]';
240 $checkboxvalue = $user->id;
242 $checkbox .= html_writer::checkbox($checkboxname, $checkboxvalue, '', null,
243 array('id' => $checkboxid, 'class' => 'm-r-1'));
245 $userimage = $this->output->user_picture($user, array('courseid' => $choices->courseid, 'link' => false));
246 $profileurl = new moodle_url('/user/view.php', array('id' => $user->id, 'course' => $choices->courseid));
247 $profilelink = html_writer::link($profileurl, $userimage . $userfullname);
248 $data .= html_writer::div($checkbox . $profilelink, 'm-b-1');
250 $optionusers .= $data;
252 $cell->text = $optionusers;
255 $columns[] = $cell;
256 $count++;
258 $row = new html_table_row($columns);
259 $table->data[] = $row;
261 $html .= html_writer::tag('div', html_writer::table($table), array('class'=>'response'));
263 $actiondata = '';
264 if ($choices->viewresponsecapability && $choices->deleterepsonsecapability) {
265 $selecturl = new moodle_url('#');
267 $actiondata .= html_writer::start_div('selectallnone');
268 $actiondata .= html_writer::link($selecturl, get_string('selectall'), ['data-select-info' => true]) . ' / ';
270 $actiondata .= html_writer::link($selecturl, get_string('deselectall'), ['data-select-info' => false]);
272 $actiondata .= html_writer::end_div();
274 $actionurl = new moodle_url($PAGE->url, array('sesskey'=>sesskey(), 'action'=>'delete_confirmation()'));
275 $actionoptions = array('delete' => get_string('delete'));
276 foreach ($choices->options as $optionid => $option) {
277 if ($optionid > 0) {
278 $actionoptions['choose_'.$optionid] = get_string('chooseoption', 'choice', $option->text);
281 $select = new single_select($actionurl, 'action', $actionoptions, null,
282 array('' => get_string('chooseaction', 'choice')), 'attemptsform');
283 $select->set_label(get_string('withselected', 'choice'));
285 $PAGE->requires->js_call_amd('mod_choice/select_all_choices', 'init');
287 $actiondata .= $this->output->render($select);
289 $html .= html_writer::tag('div', $actiondata, array('class'=>'responseaction'));
291 if ($choices->viewresponsecapability) {
292 $html .= html_writer::end_tag('form');
295 return $html;
300 * Returns HTML to display choices result
301 * @deprecated since 3.2
302 * @param object $choices
303 * @return string
305 public function display_publish_anonymous_horizontal($choices) {
306 global $CHOICE_COLUMN_HEIGHT;
307 debugging(__FUNCTION__.'() is deprecated. Please use mod_choice_renderer::display_publish_anonymous() instead.',
308 DEBUG_DEVELOPER);
309 return $this->display_publish_anonymous($choices, CHOICE_DISPLAY_VERTICAL);
313 * Returns HTML to display choices result
314 * @deprecated since 3.2
315 * @param object $choices
316 * @return string
318 public function display_publish_anonymous_vertical($choices) {
319 global $CHOICE_COLUMN_WIDTH;
320 debugging(__FUNCTION__.'() is deprecated. Please use mod_choice_renderer::display_publish_anonymous() instead.',
321 DEBUG_DEVELOPER);
322 return $this->display_publish_anonymous($choices, CHOICE_DISPLAY_HORIZONTAL);
326 * Generate the choice result chart.
328 * Can be displayed either in the vertical or horizontal position.
330 * @param stdClass $choices Choices responses object.
331 * @param int $displaylayout The constants DISPLAY_HORIZONTAL_LAYOUT or DISPLAY_VERTICAL_LAYOUT.
332 * @return string the rendered chart.
334 public function display_publish_anonymous($choices, $displaylayout) {
335 global $OUTPUT;
336 $count = 0;
337 $data = [];
338 $numberofuser = 0;
339 $percentageamount = 0;
340 foreach ($choices->options as $optionid => $option) {
341 if (!empty($option->user)) {
342 $numberofuser = count($option->user);
344 if($choices->numberofuser > 0) {
345 $percentageamount = ((float)$numberofuser / (float)$choices->numberofuser) * 100.0;
347 $data['labels'][$count] = $option->text;
348 $data['series'][$count] = $numberofuser;
349 $data['series_labels'][$count] = $numberofuser . ' (' . format_float($percentageamount, 1) . '%)';
350 $count++;
351 $numberofuser = 0;
354 $chart = new \core\chart_bar();
355 if ($displaylayout == DISPLAY_HORIZONTAL_LAYOUT) {
356 $chart->set_horizontal(true);
358 $series = new \core\chart_series(format_string(get_string("responses", "choice")), $data['series']);
359 $series->set_labels($data['series_labels']);
360 $chart->add_series($series);
361 $chart->set_labels($data['labels']);
362 $yaxis = $chart->get_yaxis(0, true);
363 $yaxis->set_stepsize(max(1, round(max($data['series']) / 10)));
364 return $OUTPUT->render($chart);