-36 Removals
+201 Additions
<?php<?php
//Original Moodle 2.7.2 /mod/quiz/renderer.php//Modified Moodle 2.7.2 /mod/quiz/renderer.php
// This file is part of Moodle - http://moodle.org/// This file is part of Moodle - http://moodle.org/
////
// Moodle is free software: you can redistribute it and/or modify// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.// (at your option) any later version.
////
// Moodle is distributed in the hope that it will be useful,// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.// GNU General Public License for more details.
////
// You should have received a copy of the GNU General Public License// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**/**
* Defines the renderer for the quiz module. * Defines the renderer for the quiz module.
* *
* @package mod_quiz * @package mod_quiz
* @copyright 2011 The Open University * @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
defined('MOODLE_INTERNAL') || die();defined('MOODLE_INTERNAL') || die();
/**/**
* The renderer for the quiz module. * The renderer for the quiz module.
* *
* @copyright 2011 The Open University * @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class mod_quiz_renderer extends plugin_renderer_base {class mod_quiz_renderer extends plugin_renderer_base {
/** /**
* Builds the review page * Builds the review page
* *
* @param quiz_attempt $attemptobj an instance of quiz_attempt. * @param quiz_attempt $attemptobj an instance of quiz_attempt.
* @param array $slots an array of intgers relating to questions. * @param array $slots an array of intgers relating to questions.
* @param int $page the current page number * @param int $page the current page number
* @param bool $showall whether to show entire attempt on one page. * @param bool $showall whether to show entire attempt on one page.
* @param bool $lastpage if true the current page is the last page. * @param bool $lastpage if true the current page is the last page.
* @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options. * @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options.
* @param array $summarydata contains all table data * @param array $summarydata contains all table data
* @return $output containing html data. * @return $output containing html data.
*/ */
public function review_page(quiz_attempt $attemptobj, $slots, $page, $showall, public function review_page(quiz_attempt $attemptobj, $slots, $page, $showall,
$lastpage, mod_quiz_display_options $displayoptions, $lastpage, mod_quiz_display_options $displayoptions,
$summarydata) { $summarydata) {
$output = ''; $output = '';
$output .= $this->header(); $output .= $this->header();
$output .= $this->review_summary_table($summarydata, $page); $output .= $this->review_summary_table($summarydata, $page);
$output .= $this->review_form($page, $showall, $displayoptions, $output .= $this->review_form($page, $showall, $displayoptions,
$this->questions($attemptobj, true, $slots, $page, $showall, $displayoptions), $this->questions($attemptobj, true, $slots, $page, $showall, $displayoptions),
$attemptobj); $attemptobj);
$output .= $this->review_next_navigation($attemptobj, $page, $lastpage); $output .= $this->review_next_navigation($attemptobj, $page, $lastpage);
$output .= $this->footer(); $output .= $this->footer();
return $output; return $output;
} }
/** /**
* Renders the review question pop-up. * Renders the review question pop-up.
* *
* @param quiz_attempt $attemptobj an instance of quiz_attempt. * @param quiz_attempt $attemptobj an instance of quiz_attempt.
* @param int $slot which question to display. * @param int $slot which question to display.
* @param int $seq which step of the question attempt to show. null = latest. * @param int $seq which step of the question attempt to show. null = latest.
* @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options. * @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options.
* @param array $summarydata contains all table data * @param array $summarydata contains all table data
* @return $output containing html data. * @return $output containing html data.
*/ */
public function review_question_page(quiz_attempt $attemptobj, $slot, $seq, public function review_question_page(quiz_attempt $attemptobj, $slot, $seq,
mod_quiz_display_options $displayoptions, $summarydata) { mod_quiz_display_options $displayoptions, $summarydata) {
$output = ''; $output = '';
$output .= $this->header(); $output .= $this->header();
$output .= $this->review_summary_table($summarydata, 0); $output .= $this->review_summary_table($summarydata, 0);
if (!is_null($seq)) { if (!is_null($seq)) {
$output .= $attemptobj->render_question_at_step($slot, $seq, true); $output .= $attemptobj->render_question_at_step($slot, $seq, true);
} else { } else {
$output .= $attemptobj->render_question($slot, true); $output .= $attemptobj->render_question($slot, true);
} }
$output .= $this->close_window_button(); $output .= $this->close_window_button();
$output .= $this->footer(); $output .= $this->footer();
return $output; return $output;
} }
/** /**
* Renders the review question pop-up. * Renders the review question pop-up.
* *
* @param string $message Why the review is not allowed. * @param string $message Why the review is not allowed.
* @return string html to output. * @return string html to output.
*/ */
public function review_question_not_allowed($message) { public function review_question_not_allowed($message) {
$output = ''; $output = '';
$output .= $this->header(); $output .= $this->header();
$output .= $this->heading(format_string($attemptobj->get_quiz_name(), true, $output .= $this->heading(format_string($attemptobj->get_quiz_name(), true,
array("context" => $attemptobj->get_quizobj()->get_context()))); array("context" => $attemptobj->get_quizobj()->get_context())));
$output .= $this->notification($message); $output .= $this->notification($message);
$output .= $this->close_window_button(); $output .= $this->close_window_button();
$output .= $this->footer(); $output .= $this->footer();
return $output; return $output;
} }
/** /**
* Filters the summarydata array. * Filters the summarydata array.
* *
* @param array $summarydata contains row data for table * @param array $summarydata contains row data for table
* @param int $page the current page number * @param int $page the current page number
* @return $summarydata containing filtered row data * @return $summarydata containing filtered row data
*/ */
protected function filter_review_summary_table($summarydata, $page) { protected function filter_review_summary_table($summarydata, $page) {
if ($page == 0) { if ($page == 0) {
return $summarydata; return $summarydata;
} }
// Only show some of summary table on subsequent pages. // Only show some of summary table on subsequent pages.
foreach ($summarydata as $key => $rowdata) { foreach ($summarydata as $key => $rowdata) {
if (!in_array($key, array('user', 'attemptlist'))) { if (!in_array($key, array('user', 'attemptlist'))) {
unset($summarydata[$key]); unset($summarydata[$key]);
} }
} }
return $summarydata; return $summarydata;
} }
/** /**
* Outputs the table containing data from summary data array * Outputs the table containing data from summary data array
* *
* @param array $summarydata contains row data for table * @param array $summarydata contains row data for table
* @param int $page contains the current page number * @param int $page contains the current page number
*/ */
public function review_summary_table($summarydata, $page) { public function review_summary_table($summarydata, $page) {
$summarydata = $this->filter_review_summary_table($summarydata, $page); $summarydata = $this->filter_review_summary_table($summarydata, $page);
if (empty($summarydata)) { if (empty($summarydata)) {
return ''; return '';
} }
$output = ''; $output = '';
$output .= html_writer::start_tag('table', array( $output .= html_writer::start_tag('table', array(
'class' => 'generaltable generalbox quizreviewsummary')); 'class' => 'generaltable generalbox quizreviewsummary'));
$output .= html_writer::start_tag('tbody'); $output .= html_writer::start_tag('tbody');
foreach ($summarydata as $rowdata) { foreach ($summarydata as $rowdata) {
if ($rowdata['title'] instanceof renderable) { if ($rowdata['title'] instanceof renderable) {
$title = $this->render($rowdata['title']); $title = $this->render($rowdata['title']);
} else { } else {
$title = $rowdata['title']; $title = $rowdata['title'];
} }
if ($rowdata['content'] instanceof renderable) { if ($rowdata['content'] instanceof renderable) {
$content = $this->render($rowdata['content']); $content = $this->render($rowdata['content']);
} else { } else {
$content = $rowdata['content']; $content = $rowdata['content'];
} }
$output .= html_writer::tag('tr', $output .= html_writer::tag('tr',
html_writer::tag('th', $title, array('class' => 'cell', 'scope' => 'row')) . html_writer::tag('th', $title, array('class' => 'cell', 'scope' => 'row')) .
html_writer::tag('td', $content, array('class' => 'cell')) html_writer::tag('td', $content, array('class' => 'cell'))
); );
} }
$output .= html_writer::end_tag('tbody'); $output .= html_writer::end_tag('tbody');
$output .= html_writer::end_tag('table'); $output .= html_writer::end_tag('table');
return $output; return $output;
} }
/** /**
* Renders each question * Renders each question
* *
* @param quiz_attempt $attemptobj instance of quiz_attempt * @param quiz_attempt $attemptobj instance of quiz_attempt
* @param bool $reviewing * @param bool $reviewing
* @param array $slots array of intgers relating to questions * @param array $slots array of intgers relating to questions
* @param int $page current page number * @param int $page current page number
* @param bool $showall if true shows attempt on single page * @param bool $showall if true shows attempt on single page
* @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options * @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options
*/ */
public function questions(quiz_attempt $attemptobj, $reviewing, $slots, $page, $showall, public function questions(quiz_attempt $attemptobj, $reviewing, $slots, $page, $showall,
mod_quiz_display_options $displayoptions) { mod_quiz_display_options $displayoptions) {
$output = ''; $output = '';
foreach ($slots as $slot) { foreach ($slots as $slot) {
$output .= $attemptobj->render_question($slot, $reviewing, $output .= $attemptobj->render_question($slot, $reviewing,
$attemptobj->review_url($slot, $page, $showall)); $attemptobj->review_url($slot, $page, $showall));
} }
return $output; return $output;
} }
/** /**
* Renders the main bit of the review page. * Renders the main bit of the review page.
* *
* @param array $summarydata contain row data for table * @param array $summarydata contain row data for table
* @param int $page current page number * @param int $page current page number
* @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options * @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options
* @param $content contains each question * @param $content contains each question
* @param quiz_attempt $attemptobj instance of quiz_attempt * @param quiz_attempt $attemptobj instance of quiz_attempt
* @param bool $showall if true display attempt on one page * @param bool $showall if true display attempt on one page
*/ */
public function review_form($page, $showall, $displayoptions, $content, $attemptobj) { public function review_form($page, $showall, $displayoptions, $content, $attemptobj) {
if ($displayoptions->flags != question_display_options::EDITABLE) { if ($displayoptions->flags != question_display_options::EDITABLE) {
return $content; return $content;
} }
$this->page->requires->js_init_call('M.mod_quiz.init_review_form', null, false, $this->page->requires->js_init_call('M.mod_quiz.init_review_form', null, false,
quiz_get_js_module()); quiz_get_js_module());
$output = ''; $output = '';
$output .= html_writer::start_tag('form', array('action' => $attemptobj->review_url(null, $output .= html_writer::start_tag('form', array('action' => $attemptobj->review_url(null,
$page, $showall), 'method' => 'post', 'class' => 'questionflagsaveform')); $page, $showall), 'method' => 'post', 'class' => 'questionflagsaveform'));
$output .= html_writer::start_tag('div'); $output .= html_writer::start_tag('div');
$output .= $content; $output .= $content;
$output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey',
'value' => sesskey())); 'value' => sesskey()));
$output .= html_writer::start_tag('div', array('class' => 'submitbtns')); $output .= html_writer::start_tag('div', array('class' => 'submitbtns'));
$output .= html_writer::empty_tag('input', array('type' => 'submit', $output .= html_writer::empty_tag('input', array('type' => 'submit',
'class' => 'questionflagsavebutton', 'name' => 'savingflags', 'class' => 'questionflagsavebutton', 'name' => 'savingflags',
'value' => get_string('saveflags', 'question'))); 'value' => get_string('saveflags', 'question')));
$output .= html_writer::end_tag('div'); $output .= html_writer::end_tag('div');
$output .= html_writer::end_tag('div'); $output .= html_writer::end_tag('div');
$output .= html_writer::end_tag('form'); $output .= html_writer::end_tag('form');
return $output; return $output;
} }
/** /**
* Returns either a liink or button * Returns either a liink or button
* *
* @param quiz_attempt $attemptobj instance of quiz_attempt * @param quiz_attempt $attemptobj instance of quiz_attempt
*/ */
public function finish_review_link(quiz_attempt $attemptobj) { public function finish_review_link(quiz_attempt $attemptobj) {
$url = $attemptobj->view_url(); $url = $attemptobj->view_url();
if ($attemptobj->get_access_manager(time())->attempt_must_be_in_popup()) { if ($attemptobj->get_access_manager(time())->attempt_must_be_in_popup()) {
$this->page->requires->js_init_call('M.mod_quiz.secure_window.init_close_button', $this->page->requires->js_init_call('M.mod_quiz.secure_window.init_close_button',
array($url), quiz_get_js_module()); array($url), quiz_get_js_module());
return html_writer::empty_tag('input', array('type' => 'button', return html_writer::empty_tag('input', array('type' => 'button',
'value' => get_string('finishreview', 'quiz'), 'value' => get_string('finishreview', 'quiz'),
'id' => 'secureclosebutton')); 'id' => 'secureclosebutton'));
} else { } else {
return html_writer::link($url, get_string('finishreview', 'quiz')); return html_writer::link($url, get_string('finishreview', 'quiz'));
} }
} }
/** /**
* Creates a next page arrow or the finishing link * Creates a next page arrow or the finishing link
* *
* @param quiz_attempt $attemptobj instance of quiz_attempt * @param quiz_attempt $attemptobj instance of quiz_attempt
* @param int $page the current page * @param int $page the current page
* @param bool $lastpage if true current page is the last page * @param bool $lastpage if true current page is the last page
*/ */
public function review_next_navigation(quiz_attempt $attemptobj, $page, $lastpage) { public function review_next_navigation(quiz_attempt $attemptobj, $page, $lastpage) {
if ($lastpage) { if ($lastpage) {
$nav = $this->finish_review_link($attemptobj); $nav = $this->finish_review_link($attemptobj);
} else { } else {
$nav = link_arrow_right(get_string('next'), $attemptobj->review_url(null, $page + 1)); $nav = link_arrow_right(get_string('next'), $attemptobj->review_url(null, $page + 1));
} }
return html_writer::tag('div', $nav, array('class' => 'submitbtns')); return html_writer::tag('div', $nav, array('class' => 'submitbtns'));
} }
/** /**
* Return the HTML of the quiz timer. * Return the HTML of the quiz timer.
* @return string HTML content. * @return string HTML content.
*/ */
public function countdown_timer(quiz_attempt $attemptobj, $timenow) { public function countdown_timer(quiz_attempt $attemptobj, $timenow) {
$timeleft = $attemptobj->get_time_left_display($timenow); $timeleft = $attemptobj->get_time_left_display($timenow);
if ($timeleft !== false) { if ($timeleft !== false) {
$ispreview = $attemptobj->is_preview(); $ispreview = $attemptobj->is_preview();
$timerstartvalue = $timeleft; $timerstartvalue = $timeleft;
if (!$ispreview) { if (!$ispreview) {
// Make sure the timer starts just above zero. If $timeleft was <= 0, then // Make sure the timer starts just above zero. If $timeleft was <= 0, then
// this will just have the effect of causing the quiz to be submitted immediately. // this will just have the effect of causing the quiz to be submitted immediately.
$timerstartvalue = max($timerstartvalue, 1); $timerstartvalue = max($timerstartvalue, 1);
} }
$this->initialise_timer($timerstartvalue, $ispreview); $this->initialise_timer($timerstartvalue, $ispreview);
} }
return html_writer::tag('div', get_string('timeleft', 'quiz') . ' ' . return html_writer::tag('div', get_string('timeleft', 'quiz') . ' ' .
html_writer::tag('span', '', array('id' => 'quiz-time-left')), html_writer::tag('span', '', array('id' => 'quiz-time-left')),
array('id' => 'quiz-timer', 'role' => 'timer', array('id' => 'quiz-timer', 'role' => 'timer',
'aria-atomic' => 'true', 'aria-relevant' => 'text')); 'aria-atomic' => 'true', 'aria-relevant' => 'text'));
} }
/** /**
* Create a preview link * Create a preview link
* *
* @param $url contains a url to the given page * @param $url contains a url to the given page
*/ */
public function restart_preview_button($url) { public function restart_preview_button($url) {
return $this->single_button($url, get_string('startnewpreview', 'quiz')); return $this->single_button($url, get_string('startnewpreview', 'quiz'));
} }
/** /**
* Outputs the navigation block panel * Outputs the navigation block panel
* *
* @param quiz_nav_panel_base $panel instance of quiz_nav_panel_base * @param quiz_nav_panel_base $panel instance of quiz_nav_panel_base
*/ */
public function navigation_panel(quiz_nav_panel_base $panel) { public function navigation_panel(quiz_nav_panel_base $panel) {
$output = ''; $output = '';
$userpicture = $panel->user_picture(); $userpicture = $panel->user_picture();
if ($userpicture) { if ($userpicture) {
$fullname = fullname($userpicture->user); $fullname = fullname($userpicture->user);
if ($userpicture->size === true) { if ($userpicture->size === true) {
$fullname = html_writer::div($fullname); $fullname = html_writer::div($fullname);
} }
$output .= html_writer::tag('div', $this->render($userpicture) . $fullname, $output .= html_writer::tag('div', $this->render($userpicture) . $fullname,
array('id' => 'user-picture', 'class' => 'clearfix')); array('id' => 'user-picture', 'class' => 'clearfix'));
} }
$output .= $panel->render_before_button_bits($this); $output .= $panel->render_before_button_bits($this);
$bcc = $panel->get_button_container_class(); $bcc = $panel->get_button_container_class();
$output .= html_writer::start_tag('div', array('class' => "qn_buttons $bcc")); $output .= html_writer::start_tag('div', array('class' => "qn_buttons $bcc"));
foreach ($panel->get_question_buttons() as $button) { foreach ($panel->get_question_buttons() as $button) {
$output .= $this->render($button); $output .= $this->render($button);
} }
$output .= html_writer::end_tag('div'); $output .= html_writer::end_tag('div');
$output .= html_writer::tag('div', $panel->render_end_bits($this), $output .= html_writer::tag('div', $panel->render_end_bits($this),
array('class' => 'othernav')); array('class' => 'othernav'));
$this->page->requires->js_init_call('M.mod_quiz.nav.init', null, false, $this->page->requires->js_init_call('M.mod_quiz.nav.init', null, false,
quiz_get_js_module()); quiz_get_js_module());
return $output; return $output;
} }
/** /**
* Returns the quizzes navigation button * Returns the quizzes navigation button
* *
* @param quiz_nav_question_button $button * @param quiz_nav_question_button $button
*/ */
protected function render_quiz_nav_question_button(quiz_nav_question_button $button) { protected function render_quiz_nav_question_button(quiz_nav_question_button $button) {
$classes = array('qnbutton', $button->stateclass, $button->navmethod); $classes = array('qnbutton', $button->stateclass, $button->navmethod);
$attributes = array(); $attributes = array();
if ($button->currentpage) { if ($button->currentpage) {
$classes[] = 'thispage'; $classes[] = 'thispage';
$attributes[] = get_string('onthispage', 'quiz'); $attributes[] = get_string('onthispage', 'quiz');
} }
// Flagged? // Flagged?
if ($button->flagged) { if ($button->flagged) {
$classes[] = 'flagged'; $classes[] = 'flagged';
$flaglabel = get_string('flagged', 'question'); $flaglabel = get_string('flagged', 'question');
} else { } else {
$flaglabel = ''; $flaglabel = '';
} }
$attributes[] = html_writer::tag('span', $flaglabel, array('class' => 'flagstate')); $attributes[] = html_writer::tag('span', $flaglabel, array('class' => 'flagstate'));
if (is_numeric($button->number)) { if (is_numeric($button->number)) {
$qnostring = 'questionnonav'; $qnostring = 'questionnonav';
} else { } else {
$qnostring = 'questionnonavinfo'; $qnostring = 'questionnonavinfo';
} }
$a = new stdClass(); $a = new stdClass();
$a->number = $button->number; $a->number = $button->number;
$a->attributes = implode(' ', $attributes); $a->attributes = implode(' ', $attributes);
$tagcontents = html_writer::tag('span', '', array('class' => 'thispageholder')) . $tagcontents = html_writer::tag('span', '', array('class' => 'thispageholder')) .
html_writer::tag('span', '', array('class' => 'trafficlight')) . html_writer::tag('span', '', array('class' => 'trafficlight')) .
get_string($qnostring, 'quiz', $a); get_string($qnostring, 'quiz', $a);
$tagattributes = array('class' => implode(' ', $classes), 'id' => $button->id, $tagattributes = array('class' => implode(' ', $classes), 'id' => $button->id,
'title' => $button->statestring); 'title' => $button->statestring);
if ($button->url) { if ($button->url) {
return html_writer::link($button->url, $tagcontents, $tagattributes); return html_writer::link($button->url, $tagcontents, $tagattributes);
} else { } else {
return html_writer::tag('span', $tagcontents, $tagattributes); return html_writer::tag('span', $tagcontents, $tagattributes);
} }
} }
/** /**
* outputs the link the other attempts. * outputs the link the other attempts.
* *
* @param mod_quiz_links_to_other_attempts $links * @param mod_quiz_links_to_other_attempts $links
*/ */
protected function render_mod_quiz_links_to_other_attempts( protected function render_mod_quiz_links_to_other_attempts(
mod_quiz_links_to_other_attempts $links) { mod_quiz_links_to_other_attempts $links) {
$attemptlinks = array(); $attemptlinks = array();
foreach ($links->links as $attempt => $url) { foreach ($links->links as $attempt => $url) {
if ($url) { if ($url) {
$attemptlinks[] = html_writer::link($url, $attempt); $attemptlinks[] = html_writer::link($url, $attempt);
} else { } else {
$attemptlinks[] = html_writer::tag('strong', $attempt); $attemptlinks[] = html_writer::tag('strong', $attempt);
} }
} }
return implode(', ', $attemptlinks); return implode(', ', $attemptlinks);
} }
public function start_attempt_page(quiz $quizobj, mod_quiz_preflight_check_form $mform) { public function start_attempt_page(quiz $quizobj, mod_quiz_preflight_check_form $mform) {
$output = ''; $output = '';
$output .= $this->header(); $output .= $this->header();
$output .= $this->heading(format_string($quizobj->get_quiz_name(), true, $output .= $this->heading(format_string($quizobj->get_quiz_name(), true,
array("context" => $quizobj->get_context()))); array("context" => $quizobj->get_context())));
$output .= $this->quiz_intro($quizobj->get_quiz(), $quizobj->get_cm()); $output .= $this->quiz_intro($quizobj->get_quiz(), $quizobj->get_cm());
ob_start(); ob_start();
$mform->display(); $mform->display();
$output .= ob_get_clean(); $output .= ob_get_clean();
$output .= $this->footer(); $output .= $this->footer();
return $output; return $output;
} }
/** /**
* Attempt Page * Attempt Page
* *
* @param quiz_attempt $attemptobj Instance of quiz_attempt * @param quiz_attempt $attemptobj Instance of quiz_attempt
* @param int $page Current page number * @param int $page Current page number
* @param quiz_access_manager $accessmanager Instance of quiz_access_manager * @param quiz_access_manager $accessmanager Instance of quiz_access_manager
* @param array $messages An array of messages * @param array $messages An array of messages
* @param array $slots Contains an array of integers that relate to questions * @param array $slots Contains an array of integers that relate to questions
* @param int $id The ID of an attempt * @param int $id The ID of an attempt
* @param int $nextpage The number of the next page * @param int $nextpage The number of the next page
*/ */
public function attempt_page($attemptobj, $page, $accessmanager, $messages, $slots, $id, public function attempt_page($attemptobj, $page, $accessmanager, $messages, $slots, $id,
$nextpage) { $nextpage) {
$output = ''; $output = '';
$output .= $this->header(); $output .= $this->header();
$output .= $this->quiz_notices($messages); $output .= $this->quiz_notices($messages);
$output .= $this->attempt_form($attemptobj, $page, $slots, $id, $nextpage); $output .= $this->attempt_form($attemptobj, $page, $slots, $id, $nextpage);
$output .= $this->footer(); $output .= $this->footer();
return $output; return $output;
} }
/** /**
* Returns any notices. * Returns any notices.
* *
* @param array $messages * @param array $messages
*/ */
public function quiz_notices($messages) { public function quiz_notices($messages) {
if (!$messages) { if (!$messages) {
return ''; return '';
} }
return $this->box($this->heading(get_string('accessnoticesheader', 'quiz'), 3) . return $this->box($this->heading(get_string('accessnoticesheader', 'quiz'), 3) .
$this->access_messages($messages), 'quizaccessnotices'); $this->access_messages($messages), 'quizaccessnotices');
} }
/** /**
* Ouputs the form for making an attempt * Ouputs the form for making an attempt
* *
* @param quiz_attempt $attemptobj * @param quiz_attempt $attemptobj
* @param int $page Current page number * @param int $page Current page number
* @param array $slots Array of integers relating to questions * @param array $slots Array of integers relating to questions
* @param int $id ID of the attempt * @param int $id ID of the attempt
* @param int $nextpage Next page number * @param int $nextpage Next page number
*/ */
public function attempt_form($attemptobj, $page, $slots, $id, $nextpage) { public function attempt_form($attemptobj, $page, $slots, $id, $nextpage) {
$output = ''; $output = '';
// Start the form. // Start the form.
$output .= html_writer::start_tag('form', $output .= html_writer::start_tag('form',
array('action' => $attemptobj->processattempt_url(), 'method' => 'post', array('action' => $attemptobj->processattempt_url(), 'method' => 'post',
'enctype' => 'multipart/form-data', 'accept-charset' => 'utf-8', 'enctype' => 'multipart/form-data', 'accept-charset' => 'utf-8',
'id' => 'responseform')); 'id' => 'responseform'));
$output .= html_writer::start_tag('div'); $output .= html_writer::start_tag('div');
// Print all the questions. // Print all the questions.
foreach ($slots as $slot) { foreach ($slots as $slot) {
$output .= $attemptobj->render_question($slot, false, $output .= $attemptobj->render_question($slot, false,
$attemptobj->attempt_url($slot, $page)); $attemptobj->attempt_url($slot, $page));
} }
$output .= html_writer::start_tag('div', array('class' => 'submitbtns')); $output .= html_writer::start_tag('div', array('class' => 'submitbtns'));
$output .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'next', $output .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'next',
'value' => get_string('next'))); 'value' => get_string('next')));
$output .= html_writer::end_tag('div'); $output .= html_writer::end_tag('div');
// Some hidden fields to trach what is going on. // Some hidden fields to trach what is going on.
$output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'attempt', $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'attempt',
'value' => $attemptobj->get_attemptid())); 'value' => $attemptobj->get_attemptid()));
$output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'thispage', $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'thispage',
'value' => $page, 'id' => 'followingpage')); 'value' => $page, 'id' => 'followingpage'));
$output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'nextpage', $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'nextpage',
'value' => $nextpage)); 'value' => $nextpage));
$output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'timeup', $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'timeup',
'value' => '0', 'id' => 'timeup')); 'value' => '0', 'id' => 'timeup'));
$output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey',
'value' => sesskey())); 'value' => sesskey()));
$output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'scrollpos', $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'scrollpos',
'value' => '', 'id' => 'scrollpos')); 'value' => '', 'id' => 'scrollpos'));
// Add a hidden field with questionids. Do this at the end of the form, so // Add a hidden field with questionids. Do this at the end of the form, so
// if you navigate before the form has finished loading, it does not wipe all // if you navigate before the form has finished loading, it does not wipe all
// the student's answers. // the student's answers.
$output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'slots', $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'slots',
'value' => implode(',', $slots))); 'value' => implode(',', $slots)));
// Finish the form. // Finish the form.
$output .= html_writer::end_tag('div'); $output .= html_writer::end_tag('div');
$output .= html_writer::end_tag('form'); $output .= html_writer::end_tag('form');
$output .= $this->connection_warning(); $output .= $this->connection_warning();
return $output; return $output;
} }
/** /**
* Output the JavaScript required to initialise the countdown timer. * Output the JavaScript required to initialise the countdown timer.
* @param int $timerstartvalue time remaining, in seconds. * @param int $timerstartvalue time remaining, in seconds.
*/ */
public function initialise_timer($timerstartvalue, $ispreview) { public function initialise_timer($timerstartvalue, $ispreview) {
$options = array($timerstartvalue, (bool)$ispreview); $options = array($timerstartvalue, (bool)$ispreview);
$this->page->requires->js_init_call('M.mod_quiz.timer.init', $options, false, quiz_get_js_module()); $this->page->requires->js_init_call('M.mod_quiz.timer.init', $options, false, quiz_get_js_module());
} }
/** /**
* Output a page with an optional message, and JavaScript code to close the * Output a page with an optional message, and JavaScript code to close the
* current window and redirect the parent window to a new URL. * current window and redirect the parent window to a new URL.
* @param moodle_url $url the URL to redirect the parent window to. * @param moodle_url $url the URL to redirect the parent window to.
* @param string $message message to display before closing the window. (optional) * @param string $message message to display before closing the window. (optional)
* @return string HTML to output. * @return string HTML to output.
*/ */
public function close_attempt_popup($url, $message = '') { public function close_attempt_popup($url, $message = '') {
$output = ''; $output = '';
$output .= $this->header(); $output .= $this->header();
$output .= $this->box_start(); $output .= $this->box_start();
if ($message) { if ($message) {
$output .= html_writer::tag('p', $message); $output .= html_writer::tag('p', $message);
$output .= html_writer::tag('p', get_string('windowclosing', 'quiz')); $output .= html_writer::tag('p', get_string('windowclosing', 'quiz'));
$delay = 5; $delay = 5;
} else { } else {
$output .= html_writer::tag('p', get_string('pleaseclose', 'quiz')); $output .= html_writer::tag('p', get_string('pleaseclose', 'quiz'));
$delay = 0; $delay = 0;
} }
$this->page->requires->js_init_call('M.mod_quiz.secure_window.close', $this->page->requires->js_init_call('M.mod_quiz.secure_window.close',
array($url, $delay), false, quiz_get_js_module()); array($url, $delay), false, quiz_get_js_module());
$output .= $this->box_end(); $output .= $this->box_end();
$output .= $this->footer(); $output .= $this->footer();
return $output; return $output;
} }
/** /**
* Print each message in an array, surrounded by &lt;p>, &lt;/p> tags. * Print each message in an array, surrounded by &lt;p>, &lt;/p> tags.
* *
* @param array $messages the array of message strings. * @param array $messages the array of message strings.
* @param bool $return if true, return a string, instead of outputting. * @param bool $return if true, return a string, instead of outputting.
* *
* @return string HTML to output. * @return string HTML to output.
*/ */
public function access_messages($messages) { public function access_messages($messages) {
$output = ''; $output = '';
foreach ($messages as $message) { foreach ($messages as $message) {
$output .= html_writer::tag('p', $message) . "\n"; $output .= html_writer::tag('p', $message) . "\n";
} }
return $output; return $output;
} }
/* /*
* Summary Page * Summary Page
*/ */
/** /**
* Create the summary page * Create the summary page
* *
* @param quiz_attempt $attemptobj * @param quiz_attempt $attemptobj
* @param mod_quiz_display_options $displayoptions * @param mod_quiz_display_options $displayoptions
*/ */
public function summary_page($attemptobj, $displayoptions) { public function summary_page($attemptobj, $displayoptions) {
$output = ''; $output = '';
$output .= $this->header(); $output .= $this->header();
$output .= $this->heading(format_string($attemptobj->get_quiz_name())); $output .= $this->heading(format_string($attemptobj->get_quiz_name()));
$output .= $this->heading(get_string('summaryofattempt', 'quiz'), 3); $output .= $this->heading(get_string('summaryofattempt', 'quiz'), 3);
$output .= $this->summary_table($attemptobj, $displayoptions); $output .= $this->summary_table($attemptobj, $displayoptions);
$output .= $this->summary_page_controls($attemptobj); $output .= $this->summary_page_controls($attemptobj);
$output .= $this->footer(); $output .= $this->footer();
return $output; return $output;
} }
/** /**
* Generates the table of summarydata * Generates the table of summarydata
* *
* @param quiz_attempt $attemptobj * @param quiz_attempt $attemptobj
* @param mod_quiz_display_options $displayoptions * @param mod_quiz_display_options $displayoptions
*/ */
public function summary_table($attemptobj, $displayoptions) { public function summary_table($attemptobj, $displayoptions) {
// Prepare the summary table header. // Prepare the summary table header.
$table = new html_table(); $table = new html_table();
$table->attributes['class'] = 'generaltable quizsummaryofattempt boxaligncenter'; $table->attributes['class'] = 'generaltable quizsummaryofattempt boxaligncenter';
$table->head = array(get_string('question', 'quiz'), get_string('status', 'quiz'));
//$table->align = array('left', 'left');
$table->align = array('center', 'center', 'center'); // Get the summary info for each question.
$slots = $attemptobj->get_slots();
//Make a copy of the $slots array into $slots_ques array, but the difference is that $slots_ques array contains only bona-fide questions,
//not description questions!
//Frankie Kam, 29th April 2015
//
$slots_ques = array();
foreach ($slots as $slot) {
if (!$attemptobj->is_real_question($slot)) {
//Is the current question a description question? Skip it and don't copy it inside $slots_ques array!
continue;
}
//Make a copy of the question inside $slots_ques
$slots_ques[] = $slot;
}
$MAXVAL = sizeof($slots_ques);
$COLS=3;
if ($MAXVAL % $COLS > 0)
$nearest3 = $MAXVAL + ($COLS - $MAXVAL % $COLS);
else
$nearest3 = $MAXVAL;
$ROWS = $nearest3/$COLS;
if($MAXVAL>2)
$table->head = array(get_string('question', 'quiz'), get_string('status', 'quiz'), get_string('question', 'quiz'), get_string('status', 'quiz'), get_string('question', 'quiz'), get_string('status', 'quiz'));
else if($MAXVAL==2)
$table->head = array(get_string('question', 'quiz'), get_string('status', 'quiz'), get_string('question', 'quiz'), get_string('status', 'quiz'));
else if($MAXVAL==1)
$table->head = array(get_string('question', 'quiz'),get_string('status', 'quiz'));
else if($MAXVAL<=0)
$table->head = get_string('huh', 'what');
//This makes the first column of question number links, aligned to theright
//Frankie Kam, 29th April 2015
//Original was: $table->align = array('left', 'left');
$table->align = array('right', 'right','right', 'right', 'right', 'right');
$table->size = array('', ''); $table->size = array('', '');
$markscolumn = $displayoptions->marks >= question_display_options::MARK_AND_MAX; $markscolumn = $displayoptions->marks >= question_display_options::MARK_AND_MAX;
if ($markscolumn) { if ($markscolumn) {
$table->head[] = get_string('marks', 'quiz'); $table->head[] = get_string('marks', 'quiz');
$table->align[] = 'left'; $table->align[] = 'left';
$table->size[] = ''; $table->size[] = '';
} }
$table->data = array(); $table->data = array();
// Get the summary info for each question.
$slots = $attemptobj->get_slots(); for($r = 1; $r <= $ROWS; $r++)
foreach ($slots as $slot) { {
if (!$attemptobj->is_real_question($slot)) {
continue; $column1 = '';
} $column2 = '';
$flag = ''; $column3 = '';
if ($attemptobj->is_question_flagged($slot)) {
$flag = html_writer::empty_tag('img', array('src' => $this->pix_url('i/flagged'), if($r+($nearest3/$COLS)*2 <= $MAXVAL)
{
$flag1 = '';
if ($attemptobj->is_real_question($slots_ques[$r-1])) {
if ($attemptobj->is_question_flagged($slots_ques[$r-1])) {
$flag1 = html_writer::empty_tag('img', array('src' => $this->pix_url('i/flagged'),
'alt' => get_string('flagged', 'question'), 'class' => 'questionflag icon-post')); 'alt' => get_string('flagged', 'question'), 'class' => 'questionflag icon-post'));
} }
if ($attemptobj->can_navigate_to($slot)) { $column1 = html_writer::link($attemptobj->attempt_url($slots_ques[$r-1]), $attemptobj->get_question_number($slots_ques[$r-1]) . $flag1);
$row = array(html_writer::link($attemptobj->attempt_url($slot), }
$attemptobj->get_question_number($slot) . $flag),
$attemptobj->get_question_status($slot, $displayoptions->correctness),array('text-align' => 'center')); if ($attemptobj->is_real_question($slots_ques[$r-1+($nearest3/$COLS)])) {
} else { $flag2 = '';
$row = array($attemptobj->get_question_number($slot) . $flag, if ($attemptobj->is_question_flagged($slots_ques[$r-1+($nearest3/$COLS)])) {
$attemptobj->get_question_status($slot, $displayoptions->correctness)); $flag2 = html_writer::empty_tag('img', array('src' => $this->pix_url('i/flagged'),
} 'alt' => get_string('flagged', 'question'), 'class' => 'questionflag icon-post'));
if ($markscolumn) { }
$row[] = $attemptobj->get_question_mark($slot); $column2 = html_writer::link($attemptobj->attempt_url($slots_ques[$r-1+($nearest3/$COLS)]), $attemptobj->get_question_number($slots_ques[$r-1+($nearest3/$COLS)]) . $flag2);
}
if ($attemptobj->is_real_question($slots_ques[$r-1+($nearest3/$COLS)*2])) {
$flag3 = '';
if ($attemptobj->is_question_flagged($slots_ques[$r-1+($nearest3/$COLS)*2])) {
$flag3 = html_writer::empty_tag('img', array('src' => $this->pix_url('i/flagged'),
'alt' => get_string('flagged', 'question'), 'class' => 'questionflag icon-post'));
}
$column3 = html_writer::link($attemptobj->attempt_url($slots_ques[$r-1+($nearest3/$COLS)*2]), $attemptobj->get_question_number($slots_ques[$r-1+($nearest3/$COLS)*2]) . $flag3);
}
if($attemptobj->get_question_status($slots_ques[$r-1], $displayoptions->correctness)=="Not yet answered")
$stylecolor1 = 'color:#C21D25';
else
$stylecolor1 = 'color:black';
if($attemptobj->get_question_status($slots_ques[$r-1+($nearest3/$COLS)], $displayoptions->correctness)=="Not yet answered")
$stylecolor2 = 'color:#C21D25';
else
//$stylecolor2 = 'color:black; background-color:green';
$stylecolor2 = 'color:black';
if($attemptobj->get_question_status($slots_ques[$r-1+($nearest3/$COLS)*2], $displayoptions->correctness)=="Not yet answered")
$stylecolor3 = 'color:#C21D25';
else
$stylecolor3 = 'color:black';
$row =
array(
$column1,
html_writer::div($attemptobj->get_question_status($slots_ques[$r-1], $displayoptions->correctness), reddy,array('style' => $stylecolor1)),
$column2,
html_writer::div($attemptobj->get_question_status($slots_ques[$r-1+($nearest3/$COLS)], $displayoptions->correctness), reddy,array('style' => $stylecolor2)),
$column3,
html_writer::div($attemptobj->get_question_status($slots_ques[$r-1+($nearest3/$COLS)*2], $displayoptions->correctness), reddy,array('style' => $stylecolor3))
);
}
else
if($r+($nearest3/$COLS) <= $MAXVAL)
{
$column1 = '';
$column2 = '';
if ($attemptobj->is_real_question($slots_ques[$r-1])) {
$flag1 = '';
if ($attemptobj->is_question_flagged($slots_ques[$r-1])) {
$flag1 = html_writer::empty_tag('img', array('src' => $this->pix_url('i/flagged'),
'alt' => get_string('flagged', 'question'), 'class' => 'questionflag icon-post'));
}
$column1 = html_writer::link($attemptobj->attempt_url($slots_ques[$r-1]), $attemptobj->get_question_number($slots_ques[$r-1]) . $flag1);
}
if ($attemptobj->is_real_question($slots_ques[$r-1+($nearest3/$COLS)])) {
$flag2 = '';
if ($attemptobj->is_question_flagged($slots_ques[$r-1+($nearest3/$COLS)])) {
$flag2 = html_writer::empty_tag('img', array('src' => $this->pix_url('i/flagged'),
'alt' => get_string('flagged', 'question'), 'class' => 'questionflag icon-post'));
}
$column2 = html_writer::link($attemptobj->attempt_url($slots_ques[$r-1+($nearest3/$COLS)]), $attemptobj->get_question_number($slots_ques[$r-1+($nearest3/$COLS)]) . $flag2);
}
if($attemptobj->get_question_status($slots_ques[$r-1], $displayoptions->correctness)=="Not yet answered")
$stylecolor1 = 'color:#C21D25';
else
$stylecolor1 = 'color:black';
if($attemptobj->get_question_status($slots_ques[$r-1+($nearest3/$COLS)], $displayoptions->correctness)=="Not yet answered")
$stylecolor2 = 'color:#C21D25';
else
$stylecolor2 = 'color:black';
$row =
array(
$column1,
html_writer::div($attemptobj->get_question_status($slots_ques[$r-1], $displayoptions->correctness), reddy,array('style' => $stylecolor1)),
$column2,
html_writer::div($attemptobj->get_question_status($slots_ques[$r-1+($nearest3/$COLS)], $displayoptions->correctness), reddy,array('style' => $stylecolor2))
);
}
else
if($r <= $MAXVAL)
{
$column1 = '';
if ($attemptobj->is_real_question($slots_ques[$r-1])) {
$flag1 = '';
if ($attemptobj->is_question_flagged($slots_ques[$r-1])) {
$flag1 = html_writer::empty_tag('img', array('src' => $this->pix_url('i/flagged'),
'alt' => get_string('flagged', 'question'), 'class' => 'questionflag icon-post'));
}
$column1 = html_writer::link($attemptobj->attempt_url($slots_ques[$r-1]), $attemptobj->get_question_number($slots_ques[$r-1]) . $flag1);
}
if($attemptobj->get_question_status($slots_ques[$r-1], $displayoptions->correctness)=="Not yet answered")
$stylecolor1 = 'color:#C21D25';
else
$stylecolor1 = 'color:black';
$row =
array(
$column1,
html_writer::div($attemptobj->get_question_status($slots_ques[$r-1], $displayoptions->correctness), reddy,array('style' => $stylecolor1))
);
}
if ($markscolumn) {
$row[] = $attemptobj->get_question_mark($slots_ques[$r-1]);
} }
$table->data[] = $row; $table->data[] = $row;
$table->rowclasses[] = $attemptobj->get_question_state_class( $table->rowclasses[] = $attemptobj->get_question_state_class(
$slot, $displayoptions->correctness); $slots_ques[$r-1], $displayoptions->correctness);
} }
// Print the summary table. // Print the summary table.
$output = html_writer::table($table); $output = html_writer::table($table);
return $output; return $output;
} }
/** /**
* Creates any controls a the page should have. * Creates any controls a the page should have.
* *
* @param quiz_attempt $attemptobj * @param quiz_attempt $attemptobj
*/ */
public function summary_page_controls($attemptobj) { public function summary_page_controls($attemptobj) {
$output = ''; $output = '';
// Return to place button. // Return to place button.
if ($attemptobj->get_state() == quiz_attempt::IN_PROGRESS) { if ($attemptobj->get_state() == quiz_attempt::IN_PROGRESS) {
$button = new single_button( $button = new single_button(
new moodle_url($attemptobj->attempt_url(null, $attemptobj->get_currentpage())), new moodle_url($attemptobj->attempt_url(null, $attemptobj->get_currentpage())),
get_string('returnattempt', 'quiz')); get_string('returnattempt', 'quiz'));
$output .= $this->container($this->container($this->render($button), $output .= $this->container($this->container($this->render($button),
'controls'), 'submitbtns mdl-align'); 'controls'), 'submitbtns mdl-align');
} }
// Finish attempt button. // Finish attempt button.
$options = array( $options = array(
'attempt' => $attemptobj->get_attemptid(), 'attempt' => $attemptobj->get_attemptid(),
'finishattempt' => 1, 'finishattempt' => 1,
'timeup' => 0, 'timeup' => 0,
'slots' => '', 'slots' => '',
'sesskey' => sesskey(), 'sesskey' => sesskey(),
); );
$button = new single_button( $button = new single_button(
new moodle_url($attemptobj->processattempt_url(), $options), new moodle_url($attemptobj->processattempt_url(), $options),
get_string('submitallandfinish', 'quiz')); get_string('submitallandfinish', 'quiz'));
$button->id = 'responseform'; $button->id = 'responseform';
if ($attemptobj->get_state() == quiz_attempt::IN_PROGRESS) { if ($attemptobj->get_state() == quiz_attempt::IN_PROGRESS) {
$button->add_action(new confirm_action(get_string('confirmclose', 'quiz'), null, $button->add_action(new confirm_action(get_string('confirmclose', 'quiz'), null,
get_string('submitallandfinish', 'quiz'))); get_string('submitallandfinish', 'quiz')));
} }
$duedate = $attemptobj->get_due_date(); $duedate = $attemptobj->get_due_date();
$message = ''; $message = '';
if ($attemptobj->get_state() == quiz_attempt::OVERDUE) { if ($attemptobj->get_state() == quiz_attempt::OVERDUE) {
$message = get_string('overduemustbesubmittedby', 'quiz', userdate($duedate)); $message = get_string('overduemustbesubmittedby', 'quiz', userdate($duedate));
} else if ($duedate) { } else if ($duedate) {
$message = get_string('mustbesubmittedby', 'quiz', userdate($duedate)); $message = get_string('mustbesubmittedby', 'quiz', userdate($duedate));
} }
$output .= $this->countdown_timer($attemptobj, time()); $output .= $this->countdown_timer($attemptobj, time());
$output .= $this->container($message . $this->container( $output .= $this->container($message . $this->container(
$this->render($button), 'controls'), 'submitbtns mdl-align'); $this->render($button), 'controls'), 'submitbtns mdl-align');
return $output; return $output;
} }
/* /*
* View Page * View Page
*/ */
/** /**
* Generates the view page * Generates the view page
* *
* @param int $course The id of the course * @param int $course The id of the course
* @param array $quiz Array conting quiz data * @param array $quiz Array conting quiz data
* @param int $cm Course Module ID * @param int $cm Course Module ID
* @param int $context The page context ID * @param int $context The page context ID
* @param array $infomessages information about this quiz * @param array $infomessages information about this quiz
* @param mod_quiz_view_object $viewobj * @param mod_quiz_view_object $viewobj
* @param string $buttontext text for the start/continue attempt button, if * @param string $buttontext text for the start/continue attempt button, if
* it should be shown. * it should be shown.
* @param array $infomessages further information about why the student cannot * @param array $infomessages further information about why the student cannot
* attempt this quiz now, if appicable this quiz * attempt this quiz now, if appicable this quiz
*/ */
public function view_page($course, $quiz, $cm, $context, $viewobj) { public function view_page($course, $quiz, $cm, $context, $viewobj) {
$output = ''; $output = '';
$output .= $this->view_information($quiz, $cm, $context, $viewobj->infomessages); $output .= $this->view_information($quiz, $cm, $context, $viewobj->infomessages);
$output .= $this->view_table($quiz, $context, $viewobj); $output .= $this->view_table($quiz, $context, $viewobj);
$output .= $this->view_result_info($quiz, $context, $cm, $viewobj); $output .= $this->view_result_info($quiz, $context, $cm, $viewobj);
$output .= $this->box($this->view_page_buttons($viewobj), 'quizattempt'); $output .= $this->box($this->view_page_buttons($viewobj), 'quizattempt');
return $output; return $output;
} }
/** /**
* Work out, and render, whatever buttons, and surrounding info, should appear * Work out, and render, whatever buttons, and surrounding info, should appear
* at the end of the review page. * at the end of the review page.
* @param mod_quiz_view_object $viewobj the information required to display * @param mod_quiz_view_object $viewobj the information required to display
* the view page. * the view page.
* @return string HTML to output. * @return string HTML to output.
*/ */
public function view_page_buttons(mod_quiz_view_object $viewobj) { public function view_page_buttons(mod_quiz_view_object $viewobj) {
global $CFG; global $CFG;
$output = ''; $output = '';
if (!$viewobj->quizhasquestions) { if (!$viewobj->quizhasquestions) {
$output .= $this->no_questions_message($viewobj->canedit, $viewobj->editurl); $output .= $this->no_questions_message($viewobj->canedit, $viewobj->editurl);
} }
$output .= $this->access_messages($viewobj->preventmessages); $output .= $this->access_messages($viewobj->preventmessages);
if ($viewobj->buttontext) { if ($viewobj->buttontext) {
$output .= $this->start_attempt_button($viewobj->buttontext, $output .= $this->start_attempt_button($viewobj->buttontext,
$viewobj->startattempturl, $viewobj->startattemptwarning, $viewobj->startattempturl, $viewobj->startattemptwarning,
$viewobj->popuprequired, $viewobj->popupoptions); $viewobj->popuprequired, $viewobj->popupoptions);
} }
if ($viewobj->showbacktocourse) { if ($viewobj->showbacktocourse) {
$output .= $this->single_button($viewobj->backtocourseurl, $output .= $this->single_button($viewobj->backtocourseurl,
get_string('backtocourse', 'quiz'), 'get', get_string('backtocourse', 'quiz'), 'get',
array('class' => 'continuebutton')); array('class' => 'continuebutton'));
} }
return $output; return $output;
} }
/** /**
* Generates the view attempt button * Generates the view attempt button
* *
* @param int $course The course ID * @param int $course The course ID
* @param array $quiz Array containging quiz date * @param array $quiz Array containging quiz date
* @param int $cm The Course Module ID * @param int $cm The Course Module ID
* @param int $context The page Context ID * @param int $context The page Context ID
* @param mod_quiz_view_object $viewobj * @param mod_quiz_view_object $viewobj
* @param string $buttontext * @param string $buttontext
*/ */
public function start_attempt_button($buttontext, moodle_url $url, public function start_attempt_button($buttontext, moodle_url $url,
$startattemptwarning, $popuprequired, $popupoptions) { $startattemptwarning, $popuprequired, $popupoptions) {
$button = new single_button($url, $buttontext); $button = new single_button($url, $buttontext);
$button->class .= ' quizstartbuttondiv'; $button->class .= ' quizstartbuttondiv';
$warning = ''; $warning = '';
if ($popuprequired) { if ($popuprequired) {
$this->page->requires->js_module(quiz_get_js_module()); $this->page->requires->js_module(quiz_get_js_module());
$this->page->requires->js('/mod/quiz/module.js'); $this->page->requires->js('/mod/quiz/module.js');
$popupaction = new popup_action('click', $url, 'quizpopup', $popupoptions); $popupaction = new popup_action('click', $url, 'quizpopup', $popupoptions);
$button->class .= ' quizsecuremoderequired'; $button->class .= ' quizsecuremoderequired';
$button->add_action(new component_action('click', $button->add_action(new component_action('click',
'M.mod_quiz.secure_window.start_attempt_action', array( 'M.mod_quiz.secure_window.start_attempt_action', array(
'url' => $url->out(false), 'url' => $url->out(false),
'windowname' => 'quizpopup', 'windowname' => 'quizpopup',
'options' => $popupaction->get_js_options(), 'options' => $popupaction->get_js_options(),
'fullscreen' => true, 'fullscreen' => true,
'startattemptwarning' => $startattemptwarning, 'startattemptwarning' => $startattemptwarning,
))); )));
$warning = html_writer::tag('noscript', $this->heading(get_string('noscript', 'quiz'))); $warning = html_writer::tag('noscript', $this->heading(get_string('noscript', 'quiz')));
} else if ($startattemptwarning) { } else if ($startattemptwarning) {
$button->add_action(new confirm_action($startattemptwarning, null, $button->add_action(new confirm_action($startattemptwarning, null,
get_string('startattempt', 'quiz'))); get_string('startattempt', 'quiz')));
} }
return $this->render($button) . $warning; return $this->render($button) . $warning;
} }
/** /**
* Generate a message saying that this quiz has no questions, with a button to * Generate a message saying that this quiz has no questions, with a button to
* go to the edit page, if the user has the right capability. * go to the edit page, if the user has the right capability.
* @param object $quiz the quiz settings. * @param object $quiz the quiz settings.
* @param object $cm the course_module object. * @param object $cm the course_module object.
* @param object $context the quiz context. * @param object $context the quiz context.
* @return string HTML to output. * @return string HTML to output.
*/ */
public function no_questions_message($canedit, $editurl) { public function no_questions_message($canedit, $editurl) {
$output = ''; $output = '';
$output .= $this->notification(get_string('noquestions', 'quiz')); $output .= $this->notification(get_string('noquestions', 'quiz'));
if ($canedit) { if ($canedit) {
$output .= $this->single_button($editurl, get_string('editquiz', 'quiz'), 'get'); $output .= $this->single_button($editurl, get_string('editquiz', 'quiz'), 'get');
} }
return $output; return $output;
} }
/** /**
* Outputs an error message for any guests accessing the quiz * Outputs an error message for any guests accessing the quiz
* *
* @param int $course The course ID * @param int $course The course ID
* @param array $quiz Array contingin quiz data * @param array $quiz Array contingin quiz data
* @param int $cm Course Module ID * @param int $cm Course Module ID
* @param int $context The page contect ID * @param int $context The page contect ID
* @param array $messages Array containing any messages * @param array $messages Array containing any messages
*/ */
public function view_page_guest($course, $quiz, $cm, $context, $messages) { public function view_page_guest($course, $quiz, $cm, $context, $messages) {
$output = ''; $output = '';
$output .= $this->view_information($quiz, $cm, $context, $messages); $output .= $this->view_information($quiz, $cm, $context, $messages);
$guestno = html_writer::tag('p', get_string('guestsno', 'quiz')); $guestno = html_writer::tag('p', get_string('guestsno', 'quiz'));
$liketologin = html_writer::tag('p', get_string('liketologin')); $liketologin = html_writer::tag('p', get_string('liketologin'));
$output .= $this->confirm($guestno."\n\n".$liketologin."\n", get_login_url(), $output .= $this->confirm($guestno."\n\n".$liketologin."\n", get_login_url(),
get_referer(false)); get_referer(false));
return $output; return $output;
} }
/** /**
* Outputs and error message for anyone who is not enrolle don the course * Outputs and error message for anyone who is not enrolle don the course
* *
* @param int $course The course ID * @param int $course The course ID
* @param array $quiz Array contingin quiz data * @param array $quiz Array contingin quiz data
* @param int $cm Course Module ID * @param int $cm Course Module ID
* @param int $context The page contect ID * @param int $context The page contect ID
* @param array $messages Array containing any messages * @param array $messages Array containing any messages
*/ */
public function view_page_notenrolled($course, $quiz, $cm, $context, $messages) { public function view_page_notenrolled($course, $quiz, $cm, $context, $messages) {
global $CFG; global $CFG;
$output = ''; $output = '';
$output .= $this->view_information($quiz, $cm, $context, $messages); $output .= $this->view_information($quiz, $cm, $context, $messages);
$youneedtoenrol = html_writer::tag('p', get_string('youneedtoenrol', 'quiz')); $youneedtoenrol = html_writer::tag('p', get_string('youneedtoenrol', 'quiz'));
$button = html_writer::tag('p', $button = html_writer::tag('p',
$this->continue_button($CFG->wwwroot . '/course/view.php?id=' . $course->id)); $this->continue_button($CFG->wwwroot . '/course/view.php?id=' . $course->id));
$output .= $this->box($youneedtoenrol."\n\n".$button."\n", 'generalbox', 'notice'); $output .= $this->box($youneedtoenrol."\n\n".$button."\n", 'generalbox', 'notice');
return $output; return $output;
} }
/** /**
* Output the page information * Output the page information
* *
* @param object $quiz the quiz settings. * @param object $quiz the quiz settings.
* @param object $cm the course_module object. * @param object $cm the course_module object.
* @param object $context the quiz context. * @param object $context the quiz context.
* @param array $messages any access messages that should be described. * @param array $messages any access messages that should be described.
* @return string HTML to output. * @return string HTML to output.
*/ */
public function view_information($quiz, $cm, $context, $messages) { public function view_information($quiz, $cm, $context, $messages) {
global $CFG; global $CFG;
$output = ''; $output = '';
// Print quiz name and description. // Print quiz name and description.
$output .= $this->heading(format_string($quiz->name)); $output .= $this->heading(format_string($quiz->name));
$output .= $this->quiz_intro($quiz, $cm); $output .= $this->quiz_intro($quiz, $cm);
// Output any access messages. // Output any access messages.
if ($messages) { if ($messages) {
$output .= $this->box($this->access_messages($messages), 'quizinfo'); $output .= $this->box($this->access_messages($messages), 'quizinfo');
} }
// Show number of attempts summary to those who can view reports. // Show number of attempts summary to those who can view reports.
if (has_capability('mod/quiz:viewreports', $context)) { if (has_capability('mod/quiz:viewreports', $context)) {
if ($strattemptnum = $this->quiz_attempt_summary_link_to_reports($quiz, $cm, if ($strattemptnum = $this->quiz_attempt_summary_link_to_reports($quiz, $cm,
$context)) { $context)) {
$output .= html_writer::tag('div', $strattemptnum, $output .= html_writer::tag('div', $strattemptnum,
array('class' => 'quizattemptcounts')); array('class' => 'quizattemptcounts'));
} }
} }
return $output; return $output;
} }
/** /**
* Output the quiz intro. * Output the quiz intro.
* @param object $quiz the quiz settings. * @param object $quiz the quiz settings.
* @param object $cm the course_module object. * @param object $cm the course_module object.
* @return string HTML to output. * @return string HTML to output.
*/ */
public function quiz_intro($quiz, $cm) { public function quiz_intro($quiz, $cm) {
if (html_is_blank($quiz->intro)) { if (html_is_blank($quiz->intro)) {
return ''; return '';
} }
return $this->box(format_module_intro('quiz', $quiz, $cm->id), 'generalbox', 'intro'); return $this->box(format_module_intro('quiz', $quiz, $cm->id), 'generalbox', 'intro');
} }
/** /**
* Generates the table heading. * Generates the table heading.
*/ */
public function view_table_heading() { public function view_table_heading() {
return $this->heading(get_string('summaryofattempts', 'quiz'), 3); return $this->heading(get_string('summaryofattempts', 'quiz'), 3);
} }
/** /**
* Generates the table of data * Generates the table of data
* *
* @param array $quiz Array contining quiz data * @param array $quiz Array contining quiz data
* @param int $context The page context ID * @param int $context The page context ID
* @param mod_quiz_view_object $viewobj * @param mod_quiz_view_object $viewobj
*/ */
public function view_table($quiz, $context, $viewobj) { public function view_table($quiz, $context, $viewobj) {
if (!$viewobj->attempts) { if (!$viewobj->attempts) {
return ''; return '';
} }
// Prepare table header. // Prepare table header.
$table = new html_table(); $table = new html_table();
$table->attributes['class'] = 'generaltable quizattemptsummary'; $table->attributes['class'] = 'generaltable quizattemptsummary';
$table->head = array(); $table->head = array();
$table->align = array(); $table->align = array();
$table->size = array(); $table->size = array();
if ($viewobj->attemptcolumn) { if ($viewobj->attemptcolumn) {
$table->head[] = get_string('attemptnumber', 'quiz'); $table->head[] = get_string('attemptnumber', 'quiz');
$table->align[] = 'center'; $table->align[] = 'center';
$table->size[] = ''; $table->size[] = '';
} }
$table->head[] = get_string('attemptstate', 'quiz'); $table->head[] = get_string('attemptstate', 'quiz');
//$table->align[] = 'left'; $table->align[] = 'left';
$table->align[] = 'center';
$table->size[] = ''; $table->size[] = '';
if ($viewobj->markcolumn) { if ($viewobj->markcolumn) {
$table->head[] = get_string('marks', 'quiz') . ' / ' . $table->head[] = get_string('marks', 'quiz') . ' / ' .
quiz_format_grade($quiz, $quiz->sumgrades); quiz_format_grade($quiz, $quiz->sumgrades);
$table->align[] = 'center'; $table->align[] = 'center';
$table->size[] = ''; $table->size[] = '';
} }
if ($viewobj->gradecolumn) { if ($viewobj->gradecolumn) {
$table->head[] = get_string('grade') . ' / ' . $table->head[] = get_string('grade') . ' / ' .
quiz_format_grade($quiz, $quiz->grade); quiz_format_grade($quiz, $quiz->grade);
$table->align[] = 'center'; $table->align[] = 'center';
$table->size[] = ''; $table->size[] = '';
} }
if ($viewobj->canreviewmine) { if ($viewobj->canreviewmine) {
$table->head[] = get_string('review', 'quiz'); $table->head[] = get_string('review', 'quiz');
$table->align[] = 'center'; $table->align[] = 'center';
$table->size[] = ''; $table->size[] = '';
} }
if ($viewobj->feedbackcolumn) { if ($viewobj->feedbackcolumn) {
$table->head[] = get_string('feedback', 'quiz'); $table->head[] = get_string('feedback', 'quiz');
//$table->align[] = 'left'; $table->align[] = 'left';
$table->align[] = 'center';
$table->size[] = ''; $table->size[] = '';
} }
// One row for each attempt. // One row for each attempt.
foreach ($viewobj->attemptobjs as $attemptobj) { foreach ($viewobj->attemptobjs as $attemptobj) {
$attemptoptions = $attemptobj->get_display_options(true); $attemptoptions = $attemptobj->get_display_options(true);
$row = array(); $row = array();
// Add the attempt number. // Add the attempt number.
if ($viewobj->attemptcolumn) { if ($viewobj->attemptcolumn) {
if ($attemptobj->is_preview()) { if ($attemptobj->is_preview()) {
$row[] = get_string('preview', 'quiz'); $row[] = get_string('preview', 'quiz');
} else { } else {
$row[] = $attemptobj->get_attempt_number(); $row[] = $attemptobj->get_attempt_number();
} }
} }
$row[] = $this->attempt_state($attemptobj); $row[] = $this->attempt_state($attemptobj);
if ($viewobj->markcolumn) { if ($viewobj->markcolumn) {
if ($attemptoptions->marks >= question_display_options::MARK_AND_MAX && if ($attemptoptions->marks >= question_display_options::MARK_AND_MAX &&
$attemptobj->is_finished()) { $attemptobj->is_finished()) {
$row[] = quiz_format_grade($quiz, $attemptobj->get_sum_marks()); $row[] = quiz_format_grade($quiz, $attemptobj->get_sum_marks());
} else { } else {
$row[] = ''; $row[] = '';
} }
} }
// Ouside the if because we may be showing feedback but not grades. // Ouside the if because we may be showing feedback but not grades.
$attemptgrade = quiz_rescale_grade($attemptobj->get_sum_marks(), $quiz, false); $attemptgrade = quiz_rescale_grade($attemptobj->get_sum_marks(), $quiz, false);
if ($viewobj->gradecolumn) { if ($viewobj->gradecolumn) {
if ($attemptoptions->marks >= question_display_options::MARK_AND_MAX && if ($attemptoptions->marks >= question_display_options::MARK_AND_MAX &&
$attemptobj->is_finished()) { $attemptobj->is_finished()) {
// Highlight the highest grade if appropriate. // Highlight the highest grade if appropriate.
if ($viewobj->overallstats && !$attemptobj->is_preview() if ($viewobj->overallstats && !$attemptobj->is_preview()
&& $viewobj->numattempts > 1 && !is_null($viewobj->mygrade) && $viewobj->numattempts > 1 && !is_null($viewobj->mygrade)
&& $attemptobj->get_state() == quiz_attempt::FINISHED && $attemptobj->get_state() == quiz_attempt::FINISHED
&& $attemptgrade == $viewobj->mygrade && $attemptgrade == $viewobj->mygrade
&& $quiz->grademethod == QUIZ_GRADEHIGHEST) { && $quiz->grademethod == QUIZ_GRADEHIGHEST) {
$table->rowclasses[$attemptobj->get_attempt_number()] = 'bestrow'; $table->rowclasses[$attemptobj->get_attempt_number()] = 'bestrow';
} }
$row[] = quiz_format_grade($quiz, $attemptgrade); $row[] = quiz_format_grade($quiz, $attemptgrade);
} else { } else {
$row[] = ''; $row[] = '';
} }
} }
if ($viewobj->canreviewmine) { if ($viewobj->canreviewmine) {
$row[] = $viewobj->accessmanager->make_review_link($attemptobj->get_attempt(), $row[] = $viewobj->accessmanager->make_review_link($attemptobj->get_attempt(),
$attemptoptions, $this); $attemptoptions, $this);
} }
if ($viewobj->feedbackcolumn && $attemptobj->is_finished()) { if ($viewobj->feedbackcolumn && $attemptobj->is_finished()) {
if ($attemptoptions->overallfeedback) { if ($attemptoptions->overallfeedback) {
$row[] = quiz_feedback_for_grade($attemptgrade, $quiz, $context); $row[] = quiz_feedback_for_grade($attemptgrade, $quiz, $context);
} else { } else {
$row[] = ''; $row[] = '';
} }
} }
if ($attemptobj->is_preview()) { if ($attemptobj->is_preview()) {
$table->data['preview'] = $row; $table->data['preview'] = $row;
} else { } else {
$table->data[$attemptobj->get_attempt_number()] = $row; $table->data[$attemptobj->get_attempt_number()] = $row;
} }
} // End of loop over attempts. } // End of loop over attempts.
$output = ''; $output = '';
$output .= $this->view_table_heading(); $output .= $this->view_table_heading();
$output .= html_writer::table($table); $output .= html_writer::table($table);
return $output; return $output;
} }
/** /**
* Generate a brief textual desciption of the current state of an attempt. * Generate a brief textual desciption of the current state of an attempt.
* @param quiz_attempt $attemptobj the attempt * @param quiz_attempt $attemptobj the attempt
* @param int $timenow the time to use as 'now'. * @param int $timenow the time to use as 'now'.
* @return string the appropriate lang string to describe the state. * @return string the appropriate lang string to describe the state.
*/ */
public function attempt_state($attemptobj) { public function attempt_state($attemptobj) {
switch ($attemptobj->get_state()) { switch ($attemptobj->get_state()) {
case quiz_attempt::IN_PROGRESS: case quiz_attempt::IN_PROGRESS:
return get_string('stateinprogress', 'quiz'); return get_string('stateinprogress', 'quiz');
case quiz_attempt::OVERDUE: case quiz_attempt::OVERDUE:
return get_string('stateoverdue', 'quiz') . html_writer::tag('span', return get_string('stateoverdue', 'quiz') . html_writer::tag('span',
get_string('stateoverduedetails', 'quiz', get_string('stateoverduedetails', 'quiz',
userdate($attemptobj->get_due_date())), userdate($attemptobj->get_due_date())),
array('class' => 'statedetails')); array('class' => 'statedetails'));
case quiz_attempt::FINISHED: case quiz_attempt::FINISHED:
return get_string('statefinished', 'quiz') . html_writer::tag('span', return get_string('statefinished', 'quiz') . html_writer::tag('span',
get_string('statefinisheddetails', 'quiz', get_string('statefinisheddetails', 'quiz',
userdate($attemptobj->get_submitted_date())), userdate($attemptobj->get_submitted_date())),
array('class' => 'statedetails')); array('class' => 'statedetails'));
case quiz_attempt::ABANDONED: case quiz_attempt::ABANDONED:
return get_string('stateabandoned', 'quiz'); return get_string('stateabandoned', 'quiz');
} }
} }
/** /**
* Generates data pertaining to quiz results * Generates data pertaining to quiz results
* *
* @param array $quiz Array containing quiz data * @param array $quiz Array containing quiz data
* @param int $context The page context ID * @param int $context The page context ID
* @param int $cm The Course Module Id * @param int $cm The Course Module Id
* @param mod_quiz_view_object $viewobj * @param mod_quiz_view_object $viewobj
*/ */
public function view_result_info($quiz, $context, $cm, $viewobj) { public function view_result_info($quiz, $context, $cm, $viewobj) {
$output = ''; $output = '';
if (!$viewobj->numattempts && !$viewobj->gradecolumn && is_null($viewobj->mygrade)) { if (!$viewobj->numattempts && !$viewobj->gradecolumn && is_null($viewobj->mygrade)) {
return $output; return $output;
} }
$resultinfo = ''; $resultinfo = '';
if ($viewobj->overallstats) { if ($viewobj->overallstats) {
if ($viewobj->moreattempts) { if ($viewobj->moreattempts) {
$a = new stdClass(); $a = new stdClass();
$a->method = quiz_get_grading_option_name($quiz->grademethod); $a->method = quiz_get_grading_option_name($quiz->grademethod);
$a->mygrade = quiz_format_grade($quiz, $viewobj->mygrade); $a->mygrade = quiz_format_grade($quiz, $viewobj->mygrade);
$a->quizgrade = quiz_format_grade($quiz, $quiz->grade); $a->quizgrade = quiz_format_grade($quiz, $quiz->grade);
$resultinfo .= $this->heading(get_string('gradesofar', 'quiz', $a), 3); $resultinfo .= $this->heading(get_string('gradesofar', 'quiz', $a), 3);
} else { } else {
$a = new stdClass(); $a = new stdClass();
$a->grade = quiz_format_grade($quiz, $viewobj->mygrade); $a->grade = quiz_format_grade($quiz, $viewobj->mygrade);
$a->maxgrade = quiz_format_grade($quiz, $quiz->grade); $a->maxgrade = quiz_format_grade($quiz, $quiz->grade);
$a = get_string('outofshort', 'quiz', $a); $a = get_string('outofshort', 'quiz', $a);
$resultinfo .= $this->heading(get_string('yourfinalgradeis', 'quiz', $a), 3); $resultinfo .= $this->heading(get_string('yourfinalgradeis', 'quiz', $a), 3);
} }
} }
if ($viewobj->mygradeoverridden) { if ($viewobj->mygradeoverridden) {
$resultinfo .= html_writer::tag('p', get_string('overriddennotice', 'grades'), $resultinfo .= html_writer::tag('p', get_string('overriddennotice', 'grades'),
array('class' => 'overriddennotice'))."\n"; array('class' => 'overriddennotice'))."\n";
} }
if ($viewobj->gradebookfeedback) { if ($viewobj->gradebookfeedback) {
$resultinfo .= $this->heading(get_string('comment', 'quiz'), 3); $resultinfo .= $this->heading(get_string('comment', 'quiz'), 3);
$resultinfo .= html_writer::div($viewobj->gradebookfeedback, 'quizteacherfeedback') . "\n"; $resultinfo .= html_writer::div($viewobj->gradebookfeedback, 'quizteacherfeedback') . "\n";
} }
if ($viewobj->feedbackcolumn) { if ($viewobj->feedbackcolumn) {
$resultinfo .= $this->heading(get_string('overallfeedback', 'quiz'), 3); $resultinfo .= $this->heading(get_string('overallfeedback', 'quiz'), 3);
$resultinfo .= html_writer::div( $resultinfo .= html_writer::div(
quiz_feedback_for_grade($viewobj->mygrade, $quiz, $context), quiz_feedback_for_grade($viewobj->mygrade, $quiz, $context),
'quizgradefeedback') . "\n"; 'quizgradefeedback') . "\n";
} }
if ($resultinfo) { if ($resultinfo) {
$output .= $this->box($resultinfo, 'generalbox', 'feedback'); $output .= $this->box($resultinfo, 'generalbox', 'feedback');
} }
return $output; return $output;
} }
/** /**
* Output either a link to the review page for an attempt, or a button to * Output either a link to the review page for an attempt, or a button to
* open the review in a popup window. * open the review in a popup window.
* *
* @param moodle_url $url of the target page. * @param moodle_url $url of the target page.
* @param bool $reviewinpopup whether a pop-up is required. * @param bool $reviewinpopup whether a pop-up is required.
* @param array $popupoptions options to pass to the popup_action constructor. * @param array $popupoptions options to pass to the popup_action constructor.
* @return string HTML to output. * @return string HTML to output.
*/ */
public function review_link($url, $reviewinpopup, $popupoptions) { public function review_link($url, $reviewinpopup, $popupoptions) {
if ($reviewinpopup) { if ($reviewinpopup) {
$button = new single_button($url, get_string('review', 'quiz')); $button = new single_button($url, get_string('review', 'quiz'));
$button->add_action(new popup_action('click', $url, 'quizpopup', $popupoptions)); $button->add_action(new popup_action('click', $url, 'quizpopup', $popupoptions));
return $this->render($button); return $this->render($button);
} else { } else {
return html_writer::link($url, get_string('review', 'quiz'), return html_writer::link($url, get_string('review', 'quiz'),
array('title' => get_string('reviewthisattempt', 'quiz'))); array('title' => get_string('reviewthisattempt', 'quiz')));
} }
} }
/** /**
* Displayed where there might normally be a review link, to explain why the * Displayed where there might normally be a review link, to explain why the
* review is not available at this time. * review is not available at this time.
* @param string $message optional message explaining why the review is not possible. * @param string $message optional message explaining why the review is not possible.
* @return string HTML to output. * @return string HTML to output.
*/ */
public function no_review_message($message) { public function no_review_message($message) {
return html_writer::nonempty_tag('span', $message, return html_writer::nonempty_tag('span', $message,
array('class' => 'noreviewmessage')); array('class' => 'noreviewmessage'));
} }
/** /**
* Returns the same as {@link quiz_num_attempt_summary()} but wrapped in a link * Returns the same as {@link quiz_num_attempt_summary()} but wrapped in a link
* to the quiz reports. * to the quiz reports.
* *
* @param object $quiz the quiz object. Only $quiz->id is used at the moment. * @param object $quiz the quiz object. Only $quiz->id is used at the moment.
* @param object $cm the cm object. Only $cm->course, $cm->groupmode and $cm->groupingid * @param object $cm the cm object. Only $cm->course, $cm->groupmode and $cm->groupingid
* fields are used at the moment. * fields are used at the moment.
* @param object $context the quiz context. * @param object $context the quiz context.
* @param bool $returnzero if false (default), when no attempts have been made '' is returned * @param bool $returnzero if false (default), when no attempts have been made '' is returned
* instead of 'Attempts: 0'. * instead of 'Attempts: 0'.
* @param int $currentgroup if there is a concept of current group where this method is being * @param int $currentgroup if there is a concept of current group where this method is being
* called * called
* (e.g. a report) pass it in here. Default 0 which means no current group. * (e.g. a report) pass it in here. Default 0 which means no current group.
* @return string HTML fragment for the link. * @return string HTML fragment for the link.
*/ */
public function quiz_attempt_summary_link_to_reports($quiz, $cm, $context, public function quiz_attempt_summary_link_to_reports($quiz, $cm, $context,
$returnzero = false, $currentgroup = 0) { $returnzero = false, $currentgroup = 0) {
global $CFG; global $CFG;
$summary = quiz_num_attempt_summary($quiz, $cm, $returnzero, $currentgroup); $summary = quiz_num_attempt_summary($quiz, $cm, $returnzero, $currentgroup);
if (!$summary) { if (!$summary) {
return ''; return '';
} }
require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php'); require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
$url = new moodle_url('/mod/quiz/report.php', array( $url = new moodle_url('/mod/quiz/report.php', array(
'id' => $cm->id, 'mode' => quiz_report_default_report($context))); 'id' => $cm->id, 'mode' => quiz_report_default_report($context)));
return html_writer::link($url, $summary); return html_writer::link($url, $summary);
} }
/** /**
* Output a graph, or a message saying that GD is required. * Output a graph, or a message saying that GD is required.
* @param moodle_url $url the URL of the graph. * @param moodle_url $url the URL of the graph.
* @param string $title the title to display above the graph. * @param string $title the title to display above the graph.
* @return string HTML fragment for the graph. * @return string HTML fragment for the graph.
*/ */
public function graph(moodle_url $url, $title) { public function graph(moodle_url $url, $title) {
global $CFG; global $CFG;
$graph = html_writer::empty_tag('img', array('src' => $url, 'alt' => $title)); $graph = html_writer::empty_tag('img', array('src' => $url, 'alt' => $title));
return $this->heading($title, 3) . html_writer::tag('div', $graph, array('class' => 'graph')); return $this->heading($title, 3) . html_writer::tag('div', $graph, array('class' => 'graph'));
} }
/** /**
* Output the connection warning messages, which are initially hidden, and * Output the connection warning messages, which are initially hidden, and
* only revealed by JavaScript if necessary. * only revealed by JavaScript if necessary.
*/ */
public function connection_warning() { public function connection_warning() {
$options = array('filter' => false, 'newlines' => false); $options = array('filter' => false, 'newlines' => false);
$warning = format_text(get_string('connectionerror', 'quiz'), FORMAT_MARKDOWN, $options); $warning = format_text(get_string('connectionerror', 'quiz'), FORMAT_MARKDOWN, $options);
$ok = format_text(get_string('connectionok', 'quiz'), FORMAT_MARKDOWN, $options); $ok = format_text(get_string('connectionok', 'quiz'), FORMAT_MARKDOWN, $options);
return html_writer::tag('div', $warning, array('id' => 'connection-error', 'style' => 'display: none;', 'role' => 'alert')) . return html_writer::tag('div', $warning, array('id' => 'connection-error', 'style' => 'display: none;', 'role' => 'alert')) .
html_writer::tag('div', $ok, array('id' => 'connection-ok', 'style' => 'display: none;', 'role' => 'alert')); html_writer::tag('div', $ok, array('id' => 'connection-ok', 'style' => 'display: none;', 'role' => 'alert'));
} }
}}
class mod_quiz_links_to_other_attempts implements renderable {class mod_quiz_links_to_other_attempts implements renderable {
/** /**
* @var array string attempt number => url, or null for the current attempt. * @var array string attempt number => url, or null for the current attempt.
*/ */
public $links = array(); public $links = array();
}}
class mod_quiz_view_object {class mod_quiz_view_object {
/** @var array $infomessages of messages with information to display about the quiz. */ /** @var array $infomessages of messages with information to display about the quiz. */
public $infomessages; public $infomessages;
/** @var array $attempts contains all the user's attempts at this quiz. */ /** @var array $attempts contains all the user's attempts at this quiz. */
public $attempts; public $attempts;
/** @var array $attemptobjs quiz_attempt objects corresponding to $attempts. */ /** @var array $attemptobjs quiz_attempt objects corresponding to $attempts. */
public $attemptobjs; public $attemptobjs;
/** @var quiz_access_manager $accessmanager contains various access rules. */ /** @var quiz_access_manager $accessmanager contains various access rules. */
public $accessmanager; public $accessmanager;
/** @var bool $canreviewmine whether the current user has the capability to /** @var bool $canreviewmine whether the current user has the capability to
* review their own attempts. */ * review their own attempts. */
public $canreviewmine; public $canreviewmine;
/** @var bool $canedit whether the current user has the capability to edit the quiz. */ /** @var bool $canedit whether the current user has the capability to edit the quiz. */
public $canedit; public $canedit;
/** @var moodle_url $editurl the URL for editing this quiz. */ /** @var moodle_url $editurl the URL for editing this quiz. */
public $editurl; public $editurl;
/** @var int $attemptcolumn contains the number of attempts done. */ /** @var int $attemptcolumn contains the number of attempts done. */
public $attemptcolumn; public $attemptcolumn;
/** @var int $gradecolumn contains the grades of any attempts. */ /** @var int $gradecolumn contains the grades of any attempts. */
public $gradecolumn; public $gradecolumn;
/** @var int $markcolumn contains the marks of any attempt. */ /** @var int $markcolumn contains the marks of any attempt. */
public $markcolumn; public $markcolumn;
/** @var int $overallstats contains all marks for any attempt. */ /** @var int $overallstats contains all marks for any attempt. */
public $overallstats; public $overallstats;
/** @var string $feedbackcolumn contains any feedback for and attempt. */ /** @var string $feedbackcolumn contains any feedback for and attempt. */
public $feedbackcolumn; public $feedbackcolumn;
/** @var string $timenow contains a timestamp in string format. */ /** @var string $timenow contains a timestamp in string format. */
public $timenow; public $timenow;
/** @var int $numattempts contains the total number of attempts. */ /** @var int $numattempts contains the total number of attempts. */
public $numattempts; public $numattempts;
/** @var float $mygrade contains the user's final grade for a quiz. */ /** @var float $mygrade contains the user's final grade for a quiz. */
public $mygrade; public $mygrade;
/** @var bool $moreattempts whether this user is allowed more attempts. */ /** @var bool $moreattempts whether this user is allowed more attempts. */
public $moreattempts; public $moreattempts;
/** @var int $mygradeoverridden contains an overriden grade. */ /** @var int $mygradeoverridden contains an overriden grade. */
public $mygradeoverridden; public $mygradeoverridden;
/** @var string $gradebookfeedback contains any feedback for a gradebook. */ /** @var string $gradebookfeedback contains any feedback for a gradebook. */
public $gradebookfeedback; public $gradebookfeedback;
/** @var bool $unfinished contains 1 if an attempt is unfinished. */ /** @var bool $unfinished contains 1 if an attempt is unfinished. */
public $unfinished; public $unfinished;
/** @var object $lastfinishedattempt the last attempt from the attempts array. */ /** @var object $lastfinishedattempt the last attempt from the attempts array. */
public $lastfinishedattempt; public $lastfinishedattempt;
/** @var array $preventmessages of messages telling the user why they can't /** @var array $preventmessages of messages telling the user why they can't
* attempt the quiz now. */ * attempt the quiz now. */
public $preventmessages; public $preventmessages;
/** @var string $buttontext caption for the start attempt button. If this is null, show no /** @var string $buttontext caption for the start attempt button. If this is null, show no
* button, or if it is '' show a back to the course button. */ * button, or if it is '' show a back to the course button. */
public $buttontext; public $buttontext;
/** @var string $startattemptwarning alert to show the user before starting an attempt. */ /** @var string $startattemptwarning alert to show the user before starting an attempt. */
public $startattemptwarning; public $startattemptwarning;
/** @var moodle_url $startattempturl URL to start an attempt. */ /** @var moodle_url $startattempturl URL to start an attempt. */
public $startattempturl; public $startattempturl;
/** @var moodle_url $startattempturl URL for any Back to the course button. */ /** @var moodle_url $startattempturl URL for any Back to the course button. */
public $backtocourseurl; public $backtocourseurl;
/** @var bool $showbacktocourse should we show a back to the course button? */ /** @var bool $showbacktocourse should we show a back to the course button? */
public $showbacktocourse; public $showbacktocourse;
/** @var bool whether the attempt must take place in a popup window. */ /** @var bool whether the attempt must take place in a popup window. */
public $popuprequired; public $popuprequired;
/** @var array options to use for the popup window, if required. */ /** @var array options to use for the popup window, if required. */
public $popupoptions; public $popupoptions;
/** @var bool $quizhasquestions whether the quiz has any questions. */ /** @var bool $quizhasquestions whether the quiz has any questions. */
public $quizhasquestions; public $quizhasquestions;
}}
Editor
Original Text
Changed Text