MDL-29627 quiz_access_manager move all output code to the renderer.
authorTim Hunt <T.J.Hunt@open.ac.uk>
Wed, 5 Oct 2011 19:58:38 +0000 (20:58 +0100)
committerTim Hunt <T.J.Hunt@open.ac.uk>
Thu, 13 Oct 2011 10:13:12 +0000 (11:13 +0100)
This achieves a massive clean-up. It simplifies comples code in a number
of places. It allows some methods and functions to be moved to a more
appropriate home (for example cannot_review_message to the quiz class).
It moves more logic out of the renderer.

17 files changed:
mod/quiz/accessmanager.php
mod/quiz/accessrule/accessrulebase.php
mod/quiz/accessrule/password/rule.php
mod/quiz/accessrule/safebrowser/rule.php
mod/quiz/accessrule/securewindow/rule.php
mod/quiz/attempt.php
mod/quiz/attemptlib.php
mod/quiz/locallib.php
mod/quiz/module.js
mod/quiz/renderer.php
mod/quiz/report/reportlib.php
mod/quiz/review.php
mod/quiz/reviewquestion.php
mod/quiz/simpletest/testquizobj.php [moved from mod/quiz/simpletest/testaccessmanager.php with 72% similarity]
mod/quiz/startattempt.php
mod/quiz/summary.php
mod/quiz/view.php

index 2d2cd3c..2e0c84e 100644 (file)
@@ -285,17 +285,27 @@ class quiz_access_manager {
     }
 
     /**
-     * Do the printheader call, etc. required for a secure page, including the necessary JS.
+     * Sets up the attempt (review or summary) page with any properties required
+     * by the access rules.
      *
-     * @param string $title HTML title tag content, passed to printheader.
-     * @param string $headtags extra stuff to go in the HTML head tag, passed to printheader.
+     * @param moodle_page $page the page object to initialise.
      */
-    public function setup_secure_page($title, $headtags = null) {
-        $this->securewindowrule->setup_secure_page($title, $headtags);
+    public function setup_attempt_page($page) {
+        foreach ($this->rules as $rule) {
+            $rule->setup_attempt_page($page);
+        }
     }
 
-    public function show_attempt_timer_if_needed($attempt, $timenow) {
-        global $PAGE;
+    /**
+     * Will cause the attempt time to start counting down after the page has loaded,
+     * if that is necessary.
+     *
+     * @param object $attempt the data from the relevant quiz_attempts row.
+     * @param int $timenow the time to consider as 'now'.
+     * @param mod_quiz_renderer $output the quiz renderer.
+     */
+    public function show_attempt_timer_if_needed($attempt, $timenow, $output) {
+
         $timeleft = false;
         foreach ($this->rules as $rule) {
             $ruletimeleft = $rule->time_left($attempt, $timenow);
@@ -303,134 +313,57 @@ class quiz_access_manager {
                 $timeleft = $ruletimeleft;
             }
         }
+
         if ($timeleft !== false) {
             // 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.
             $timerstartvalue = max($timeleft, 1);
-            $PAGE->requires->js_init_call('M.mod_quiz.timer.init',
-                    array($timerstartvalue), false, quiz_get_js_module());
+            $output->initialise_timer($timerstartvalue);
         }
     }
 
     /**
-     * @return bolean if this quiz should only be shown to students in a secure window.
+     * @return bolean if this quiz should only be shown to students in a popup window.
      */
-    public function securewindow_required($canpreview) {
-        return !$canpreview && !is_null($this->securewindowrule);
-    }
-
-    /**
-     * @return bolean if this quiz should only be shown to students with safe browser.
-     */
-    public function safebrowser_required($canpreview) {
-        return !$canpreview && !is_null($this->safebrowserrule);
+    public function attempt_must_be_in_popup() {
+        foreach ($this->rules as $rule) {
+            if ($rule->attempt_must_be_in_popup()) {
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
-     * Print a button to start a quiz attempt, with an appropriate javascript warning,
-     * depending on the access restrictions. The link will pop up a 'secure' window, if
-     * necessary.
-     *
-     * @param bool $canpreview whether this user can preview. This affects whether they must
-     * use a secure window.
-     * @param string $buttontext the label to put on the button.
-     * @param bool $unfinished whether the button is to continue an existing attempt,
-     * or start a new one. This affects whether a javascript alert is shown.
+     * @return array any options that are required for showing the attempt page
+     *      in a popup window.
      */
-    //TODO: Add this function to renderer
-    public function print_start_attempt_button($canpreview, $buttontext, $unfinished) {
-        global $OUTPUT;
-
-        $url = $this->quizobj->start_attempt_url();
-        $button = new single_button($url, $buttontext);
-        $button->class .= ' quizstartbuttondiv';
-
-        if (!$unfinished) {
-            $strconfirmstartattempt = $this->confirm_start_attempt_message();
-            if ($strconfirmstartattempt) {
-                $button->add_action(new confirm_action($strconfirmstartattempt, null,
-                        get_string('startattempt', 'quiz')));
-            }
-        }
-
-        $warning = '';
-
-        if ($this->securewindow_required($canpreview)) {
-            $button->class .= ' quizsecuremoderequired';
-
-            $button->add_action(new popup_action('click', $url, 'quizpopup',
-                    securewindow_access_rule::$popupoptions));
-
-            $warning = html_writer::tag('noscript',
-                    $OUTPUT->heading(get_string('noscript', 'quiz')));
+    public function get_popup_options() {
+        $options = array();
+        foreach ($this->rules as $rule) {
+            $options += $rule->get_popup_options();
         }
-
-        return $OUTPUT->render($button) . $warning;
+        return $options;
     }
 
     /**
      * Send the user back to the quiz view page. Normally this is just a redirect, but
      * If we were in a secure window, we close this window, and reload the view window we came from.
      *
-     * @param bool $canpreview This affects whether we have to worry about secure window stuff.
-     */
-    public function back_to_view_page($canpreview, $message = '') {
-        global $CFG, $OUTPUT, $PAGE;
-        $url = $this->quizobj->view_url();
-        if ($this->securewindow_required($canpreview)) {
-            $PAGE->set_pagelayout('popup');
-            echo $OUTPUT->header();
-            echo $OUTPUT->box_start();
-            if ($message) {
-                echo '<p>' . $message . '</p><p>' . get_string('windowclosing', 'quiz') . '</p>';
-                $delay = 5;
-            } else {
-                echo '<p>' . get_string('pleaseclose', 'quiz') . '</p>';
-                $delay = 0;
-            }
-            $PAGE->requires->js_function_call('M.mod_quiz.secure_window.close',
-                    array($url, $delay));
-            echo $OUTPUT->box_end();
-            echo $OUTPUT->footer();
-            die();
-        } else {
-            redirect($url, $message);
-        }
-    }
-
-    /**
-     * Print a control to finish the review. Normally this is just a link, but if we are
-     * in a secure window, it needs to be a button that does M.mod_quiz.secure_window.close.
+     * This method does not return;
      *
-     * @param bool $canpreview This affects whether we have to worry about secure window stuff.
+     * @param mod_quiz_renderer $output the quiz renderer.
+     * @param string $message optional message to output while redirecting.
      */
-    public function print_finish_review_link($canpreview, $return = false) {
-        global $CFG;
-        $output = '';
-        $url = $this->quizobj->view_url();
-        $output .= '<div class="finishreview">';
-        if ($this->securewindow_required($canpreview)) {
-            $url = addslashes_js(htmlspecialchars($url));
-            $output .= '<input type="button" value="' . get_string('finishreview', 'quiz') . '" ' .
-                    "onclick=\"M.mod_quiz.secure_window.close('$url', 0)\" />\n";
-        } else {
-            $output .= '<a href="' . $url . '">' . get_string('finishreview', 'quiz') . "</a>\n";
-        }
-        $output .= "</div>\n";
-        if ($return) {
-            return $output;
+    public function back_to_view_page($output, $message = '') {
+        if ($this->attempt_must_be_in_popup()) {
+            echo $output->close_attempt_popup($message, $this->quizobj->view_url());
+            die();
         } else {
-            echo $output;
+            redirect($this->quizobj->view_url(), $message);
         }
     }
 
-    /**
-     * @return bolean if this quiz is password protected.
-     */
-    public function password_required() {
-        return !is_null($this->passwordrule);
-    }
-
     /**
      * Clear the flag in the session that says that the current user is allowed to do this quiz.
      */
@@ -452,22 +385,6 @@ class quiz_access_manager {
         }
     }
 
-    /**
-     * @return string if the quiz policies merit it, return a warning string to be displayed
-     * in a javascript alert on the start attempt button.
-     */
-    public function confirm_start_attempt_message() {
-        $quiz = $this->quizobj->get_quiz();
-        if ($quiz->timelimit && $quiz->attempts) {
-            return get_string('confirmstartattempttimelimit', 'quiz', $quiz->attempts);
-        } else if ($quiz->timelimit) {
-            return get_string('confirmstarttimelimit', 'quiz');
-        } else if ($quiz->attempts) {
-            return get_string('confirmstartattemptlimit', 'quiz', $quiz->attempts);
-        }
-        return '';
-    }
-
     /**
      * Make some text into a link to review the quiz, if that is appropriate.
      *
@@ -476,12 +393,11 @@ class quiz_access_manager {
      * @return string some HTML, the $linktext either unmodified or wrapped in a
      *      link to the review page.
      */
-    public function make_review_link($attempt, $canpreview, $reviewoptions) {
-        global $CFG;
+    public function make_review_link($attempt, $reviewoptions, $output) {
 
         // If review of responses is not allowed, or the attempt is still open, don't link.
         if (!$attempt->timefinish) {
-            return '';
+            return $output->no_review_message('');
         }
 
         $when = quiz_attempt_state($this->quizobj->get_quiz(), $attempt);
@@ -489,52 +405,11 @@ class quiz_access_manager {
                 $this->quizobj->get_quiz(), $when);
 
         if (!$reviewoptions->attempt) {
-            $message = $this->cannot_review_message($when, true);
-            if ($message) {
-                return '<span class="noreviewmessage">' . $message . '</span>';
-            } else {
-                return '';
-            }
-        }
-
-        $linktext = get_string('review', 'quiz');
-
-        // It is OK to link, does it need to be in a secure window?
-        if ($this->securewindow_required($canpreview)) {
-            return $this->securewindowrule->make_review_link($linktext, $attempt->id);
-        } else {
-            return '<a href="' . $this->quizobj->review_url($attempt->id) . '" title="' .
-                    get_string('reviewthisattempt', 'quiz') . '">' . $linktext . '</a>';
-        }
-    }
+            return $output->no_review_message($this->quizobj->cannot_review_message($when, true));
 
-    /**
-     * If $reviewoptions->attempt is false, meaning that students can't review this
-     * attempt at the moment, return an appropriate string explaining why.
-     *
-     * @param int $when One of the mod_quiz_display_options::DURING,
-     *      IMMEDIATELY_AFTER, LATER_WHILE_OPEN or AFTER_CLOSE constants.
-     * @param bool $short if true, return a shorter string.
-     * @return string an appropraite message.
-     */
-    public function cannot_review_message($when, $short = false) {
-        $quiz = $this->quizobj->get_quiz();
-        if ($short) {
-            $langstrsuffix = 'short';
-            $dateformat = get_string('strftimedatetimeshort', 'langconfig');
-        } else {
-            $langstrsuffix = '';
-            $dateformat = '';
-        }
-        if ($when == mod_quiz_display_options::DURING ||
-                $when == mod_quiz_display_options::IMMEDIATELY_AFTER) {
-            return '';
-        } else if ($when == mod_quiz_display_options::LATER_WHILE_OPEN && $quiz->timeclose &&
-                $quiz->reviewattempt & mod_quiz_display_options::AFTER_CLOSE) {
-            return get_string('noreviewuntil' . $langstrsuffix, 'quiz',
-                    userdate($quiz->timeclose, $dateformat));
         } else {
-            return get_string('noreview' . $langstrsuffix, 'quiz');
+            return $output->review_link($this->quizobj->review_url($attempt->id),
+                    $this->attempt_must_be_in_popup(), $this->get_popup_options());
         }
     }
 }
index ca598a6..06e7200 100644 (file)
@@ -40,8 +40,11 @@ defined('MOODLE_INTERNAL') || die();
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 abstract class quiz_access_rule_base {
+    /** @var stdClass the quiz settings. */
     protected $quiz;
+    /** @var quiz the quiz object. */
     protected $quizobj;
+    /** @var int the time to use as 'now'. */
     protected $timenow;
 
     /**
@@ -107,6 +110,33 @@ abstract class quiz_access_rule_base {
         return false;
     }
 
+    /**
+     * @return boolean whether this rule requires that the attemp (and review)
+     *      pages must be displayed in a pop-up window.
+     */
+    public function attempt_must_be_in_popup() {
+        return false;
+    }
+
+    /**
+     * @return array any options that are required for showing the attempt page
+     *      in a popup window.
+     */
+    public function get_popup_options() {
+        return array();
+    }
+
+    /**
+    * Sets up the attempt (review or summary) page with any special extra
+    * properties required by this rule. securewindow rule is an example of where
+    * this is used.
+    *
+    * @param moodle_page $page the page object to initialise.
+    */
+    public function setup_attempt_page($page) {
+        // Do nothing by default.
+    }
+
     /**
      * Add any fields that this rule requires to the quiz settings form. This
      * method is called from {@link mod_quiz_mod_form::definition()}, while the
index f47e4c5..31c9828 100644 (file)
@@ -69,7 +69,7 @@ class quizaccess_password extends quiz_access_rule_base {
 
         // If the user cancelled the password form, send them back to the view page.
         if (optional_param('cancelpassword', false, PARAM_BOOL)) {
-            $accessmanager->back_to_view_page($canpreview);
+            $accessmanager->back_to_view_page($output);
         }
 
         // If they entered the right password, let them in.
@@ -95,16 +95,8 @@ class quizaccess_password extends quiz_access_rule_base {
         $output = '';
 
         // Start the page and print the quiz intro, if any.
-        if ($accessmanager->securewindow_required($canpreview)) {
-            $accessmanager->setup_secure_page($this->quizobj->get_course()->shortname . ': ' .
-            format_string($this->quizobj->get_quiz_name()));
-        } else if ($accessmanager->safebrowser_required($canpreview)) {
-            $PAGE->set_title($this->quizobj->get_course()->shortname . ': ' .
-            format_string($this->quizobj->get_quiz_name()));
-            $PAGE->set_cacheable(false);
-        } else {
-            $PAGE->set_title(format_string($this->quizobj->get_quiz_name()));
-        }
+        $PAGE->set_title(format_string($this->quizobj->get_quiz_name()));
+        $accessmanager->setup_attempt_page($PAGE);
 
         echo $OUTPUT->header();
         if (trim(strip_tags($this->quiz->intro))) {
index 9d65f27..4d0aa73 100644 (file)
@@ -48,6 +48,11 @@ class quizaccess_safebrowser extends quiz_access_rule_base {
         return get_string("safebrowsernotice", "quiz");
     }
 
+    public function setup_attempt_page($page) {
+        $page->set_title($this->quizobj->get_course()->shortname . ': ' . $page->title);
+        $page->set_cacheable(false);
+    }
+
     /**
      * Checks if browser is safe browser
      *
index 258ce3d..00a1543 100644 (file)
@@ -38,7 +38,7 @@ require_once($CFG->dirroot . '/mod/quiz/accessrule/accessrulebase.php');
 */
 class quizaccess_securewindow extends quiz_access_rule_base {
     /** @var array options that should be used for opening the secure popup. */
-    public static $popupoptions = array(
+    protected static $popupoptions = array(
         'left' => 0,
         'top' => 0,
         'fullscreen' => true,
@@ -52,36 +52,21 @@ class quizaccess_securewindow extends quiz_access_rule_base {
         'menubar' => false,
     );
 
-    /**
-     * Make a link to the review page for an attempt.
-     *
-     * @param string $linktext the desired link text.
-     * @param int $attemptid the attempt id.
-     * @return string HTML for the link.
-     */
-    public function make_review_link($linktext, $attemptid) {
-        global $OUTPUT;
-        $url = $this->quizobj->review_url($attemptid);
-        $button = new single_button($url, $linktext);
-        $button->add_action(new popup_action('click', $url, 'quizpopup', self::$popupoptions));
-        return $OUTPUT->render($button);
+    public function attempt_must_be_in_popup() {
+        return true;
     }
 
-    /**
-     * Do the printheader call, etc. required for a secure page, including the necessary JS.
-     *
-     * @param string $title HTML title tag content, passed to printheader.
-     * @param string $headtags extra stuff to go in the HTML head tag, passed to printheader.
-     *                $headtags has been deprectaed since Moodle 2.0
-     */
-    public function setup_secure_page($title, $headtags=null) {
-        global $PAGE;
-        $PAGE->set_popup_notification_allowed(false);//prevent message notifications
-        $PAGE->set_title($title);
-        $PAGE->set_cacheable(false);
-        $PAGE->set_pagelayout('popup');
-        $PAGE->add_body_class('quiz-secure-window');
-        $PAGE->requires->js_init_call('M.mod_quiz.secure_window.init',
+    public function get_popup_options() {
+        return self::$popupoptions;
+    }
+
+    public function setup_attempt_page($page) {
+        $page->set_popup_notification_allowed(false); // Prevent message notifications
+        $page->set_title($this->quizobj->get_course()->shortname . ': ' . $page->title);
+        $page->set_cacheable(false);
+        $page->set_pagelayout('popup');
+        $page->add_body_class('quiz-secure-window');
+        $page->requires->js_init_call('M.mod_quiz.secure_window.init',
                 null, false, quiz_get_js_module());
     }
 }
index 5afa75e..03ba4e3 100644 (file)
@@ -105,19 +105,9 @@ $PAGE->blocks->add_fake_block($navbc, $firstregion);
 
 $title = get_string('attempt', 'quiz', $attemptobj->get_attempt_number());
 $headtags = $attemptobj->get_html_head_contributions($page);
+$PAGE->set_title(format_string($attemptobj->get_quiz_name()));
 $PAGE->set_heading($attemptobj->get_course()->fullname);
-if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
-    $accessmanager->setup_secure_page($attemptobj->get_course()->shortname . ': ' .
-            format_string($attemptobj->get_quiz_name()));
-
-} else if ($accessmanager->safebrowser_required($attemptobj->is_preview_user())) {
-    $PAGE->set_title($attemptobj->get_course()->shortname . ': ' .
-            format_string($attemptobj->get_quiz_name()));
-    $PAGE->set_cacheable(false);
-
-} else {
-    $PAGE->set_title(format_string($attemptobj->get_quiz_name()));
-}
+$accessmanager->setup_attempt_page($PAGE);
 
 if ($attemptobj->is_last_page($page)) {
     $nextpage = -1;
@@ -125,5 +115,5 @@ if ($attemptobj->is_last_page($page)) {
     $nextpage = $page + 1;
 }
 
-$accessmanager->show_attempt_timer_if_needed($attemptobj->get_attempt(), time());
+$accessmanager->show_attempt_timer_if_needed($attemptobj->get_attempt(), time(), $output);
 echo $output->attempt_page($attemptobj, $page, $accessmanager, $messages, $slots, $id, $nextpage);
index af99b63..57c2127 100644 (file)
@@ -316,6 +316,58 @@ class quiz {
 
     // Bits of content =====================================================================
 
+    /**
+     * @param bool $unfinished whether there is currently an unfinished attempt active.
+     * @return string if the quiz policies merit it, return a warning string to
+     *      be displayed in a javascript alert on the start attempt button.
+     */
+    public function confirm_start_attempt_message($unfinished) {
+        if ($unfinished) {
+            return '';
+        }
+
+        if ($this->quiz->timelimit && $this->quiz->attempts) {
+            return get_string('confirmstartattempttimelimit', 'quiz', $this->quiz->attempts);
+        } else if ($this->quiz->timelimit) {
+            return get_string('confirmstarttimelimit', 'quiz');
+        } else if ($this->quiz->attempts) {
+            return get_string('confirmstartattemptlimit', 'quiz', $this->quiz->attempts);
+        }
+
+        return '';
+    }
+
+    /**
+     * If $reviewoptions->attempt is false, meaning that students can't review this
+     * attempt at the moment, return an appropriate string explaining why.
+     *
+     * @param int $when One of the mod_quiz_display_options::DURING,
+     *      IMMEDIATELY_AFTER, LATER_WHILE_OPEN or AFTER_CLOSE constants.
+     * @param bool $short if true, return a shorter string.
+     * @return string an appropraite message.
+     */
+    public function cannot_review_message($when, $short = false) {
+
+        if ($short) {
+            $langstrsuffix = 'short';
+            $dateformat = get_string('strftimedatetimeshort', 'langconfig');
+        } else {
+            $langstrsuffix = '';
+            $dateformat = '';
+        }
+
+        if ($when == mod_quiz_display_options::DURING ||
+                $when == mod_quiz_display_options::IMMEDIATELY_AFTER) {
+            return '';
+        } else if ($when == mod_quiz_display_options::LATER_WHILE_OPEN && $this->quiz->timeclose &&
+                $this->quiz->reviewattempt & mod_quiz_display_options::AFTER_CLOSE) {
+            return get_string('noreviewuntil' . $langstrsuffix, 'quiz',
+                    userdate($this->quiz->timeclose, $dateformat));
+        } else {
+            return get_string('noreview' . $langstrsuffix, 'quiz');
+        }
+    }
+
     /**
      * @param string $title the name of this particular quiz page.
      * @return array the data that needs to be sent to print_header_simple as the $navigation
@@ -897,6 +949,18 @@ class quiz_attempt {
 
     // Bits of content =====================================================================
 
+    /**
+     * If $reviewoptions->attempt is false, meaning that students can't review this
+     * attempt at the moment, return an appropriate string explaining why.
+     *
+     * @param bool $short if true, return a shorter string.
+     * @return string an appropraite message.
+     */
+    public function cannot_review_message($short = false) {
+        return $this->quizobj->cannot_review_message(
+                $this->get_attempt_state(), $short);
+    }
+
     /**
      * Initialise the JS etc. required all the questions on a page..
      * @param mixed $page a page number, or 'all'.
index e5fa7f6..b3d96fe 100644 (file)
@@ -383,19 +383,6 @@ function quiz_has_feedback($quiz) {
     return $cache[$quiz->id];
 }
 
-function quiz_no_questions_message($quiz, $cm, $context) {
-    global $OUTPUT;
-
-    $output = '';
-    $output .= $OUTPUT->notification(get_string('noquestions', 'quiz'));
-    if (has_capability('mod/quiz:manage', $context)) {
-        $output .= $OUTPUT->single_button(new moodle_url('/mod/quiz/edit.php',
-                array('cmid' => $cm->id)), get_string('editquiz', 'quiz'), 'get');
-    }
-
-    return $output;
-}
-
 /**
  * Update the sumgrades field of the quiz. This needs to be called whenever
  * the grading structure of the quiz is changed. For example if a question is
@@ -1293,9 +1280,10 @@ function quiz_get_js_module() {
                 'core_question_engine'),
         'strings' => array(
             array('cancel', 'moodle'),
-            array('timesup', 'quiz'),
-            array('functiondisabledbysecuremode', 'quiz'),
             array('flagged', 'question'),
+            array('functiondisabledbysecuremode', 'quiz'),
+            array('startattempt', 'quiz'),
+            array('timesup', 'quiz'),
         ),
     );
 }
index 4db04d5..ec37234 100644 (file)
@@ -224,6 +224,23 @@ M.mod_quiz.secure_window = {
         e.halt();
     },
 
+    /**
+     * Event handler for the quiz start attempt button.
+     */
+    start_attempt_action: function(e, args) {
+        if (args.startattemptwarning == '') {
+            openpopup(e, args);
+        } else {
+            M.util.show_confirm_dialog(e, {
+                message: args.startattemptwarning,
+                callback: function() {
+                    openpopup(e, args);
+                },
+                continuelabel: M.util.get_string('startattempt', 'quiz')
+            });
+        }
+    },
+
     init_close_button: function(Y, url) {
         Y.on('click', function(e) {
             M.mod_quiz.secure_window.close(url, 0)
index cd8333c..0374d58 100644 (file)
@@ -453,14 +453,50 @@ class mod_quiz_renderer extends plugin_renderer_base {
         return $output;
     }
 
+    /**
+     * Output the JavaScript required to initialise the countdown timer.
+     * @param int $timerstartvalue time remaining, in seconds.
+     */
+    public function initialise_timer($timerstartvalue) {
+        $this->page->requires->js_init_call('M.mod_quiz.timer.init',
+                array($timerstartvalue), false, quiz_get_js_module());
+    }
+
+    /**
+     * Output a page with an optional message, and JavaScript code to close the
+     * current window and redirect the parent window to a new URL.
+     * @param moodle_url $url the URL to redirect the parent window to.
+     * @param string $message message to display before closing the window. (optional)
+     * @return string HTML to output.
+     */
+    public function close_attempt_popup($url, $message = '') {
+        $output = '';
+        $output .= $this->header();
+        $output .= $this->box_start();
+
+        if ($message) {
+            $output .= html_writer('p', $message);
+            $output .= html_writer('p', get_string('windowclosing', 'quiz'));
+            $delay = 5;
+        } else {
+            $output .= html_writer('p', get_string('pleaseclose', 'quiz'));
+            $delay = 0;
+        }
+        $this->page->requires->js_function_call('M.mod_quiz.secure_window.close',
+                array($url, $delay));
+
+        $output .= $this->box_end();
+        $output .= $this->footer();
+        return $output;
+    }
+
     /**
      * Print each message in an array, surrounded by &lt;p>, &lt;/p> tags.
      *
      * @param array $messages the array of message strings.
      * @param bool $return if true, return a string, instead of outputting.
      *
-     * @return mixed, if $return is true, return the string that would have been output, otherwise
-     * return null.
+     * @return string HTML to output.
      */
     public function access_messages($messages) {
         $output = '';
@@ -588,15 +624,104 @@ class mod_quiz_renderer extends plugin_renderer_base {
      * @param array $infomessages further information about why the student cannot
      *      attempt this quiz now, if appicable this quiz
      */
-    public function view_page($course, $quiz, $cm, $context, $infomessages, $viewobj,
-            $buttontext, $preventmessages) {
+    public function view_page($course, $quiz, $cm, $context, $viewobj) {
         $output = '';
-        $output .= $this->view_information($course, $quiz, $cm, $context, $infomessages);
+        $output .= $this->view_information($course, $quiz, $cm, $context, $viewobj->infomessages);
         $output .= $this->view_table($quiz, $context, $viewobj);
         $output .= $this->view_best_score($viewobj);
         $output .= $this->view_result_info($quiz, $context, $cm, $viewobj);
-        $output .= $this->view_attempt_button($course, $quiz, $cm, $context, $viewobj,
-                $buttontext, $preventmessages);
+        $output .= $this->box($this->view_page_buttons($viewobj), 'quizattempt');
+        return $output;
+    }
+
+    /**
+     * Work out, and render, whatever buttons, and surrounding info, should appear
+     * at the end of the review page.
+     * @param mod_quiz_view_object $viewobj the information required to display
+     * the view page.
+     * @return string HTML to output.
+     */
+    public function view_page_buttons(mod_quiz_view_object $viewobj) {
+        $output = '';
+
+        if (!$viewobj->quizhasquestions) {
+            $output .= $this->no_questions_message($viewobj->canedit, $viewobj->editurl);
+        }
+
+        $output .= $this->access_messages($viewobj->preventmessages);
+
+        if ($viewobj->buttontext) {
+            $output .= $this->start_attempt_button($viewobj->buttontext,
+                    $viewobj->startattempturl, $viewobj->startattemptwarning,
+                    $viewobj->popuprequired, $viewobj->popupoptions);
+
+        } else if ($viewobj->buttontext === '') {
+            // We should show a 'back to the course' button.
+            $output .= $this->single_button($viewobj->backtocourseurl,
+                    get_string('backtocourse', 'quiz'), 'get',
+                    array('class' => 'continuebutton'));
+        }
+
+        return $output;
+    }
+
+    /**
+     * Generates the view attempt button
+     *
+     * @param int $course The course ID
+     * @param array $quiz Array containging quiz date
+     * @param int $cm The Course Module ID
+     * @param int $context The page Context ID
+     * @param mod_quiz_view_object $viewobj
+     * @param string $buttontext
+     */
+    public function start_attempt_button($buttontext, moodle_url $url,
+            $startattemptwarning, $popuprequired, $popupoptions) {
+
+        $button = new single_button($url, $buttontext);
+        $button->class .= ' quizstartbuttondiv';
+
+        $warning = '';
+        if ($popuprequired) {
+            $this->page->requires->js_module(quiz_get_js_module());
+            $this->page->requires->js('/mod/quiz/module.js');
+            $popupaction = new popup_action('click', $url, 'quizpopup', $popupoptions);
+
+            $button->class .= ' quizsecuremoderequired';
+            $button->add_action(new component_action('click',
+                    'M.mod_quiz.secure_window.start_attempt_action', array(
+                        'url' => $url->out(false),
+                        'windowname' => 'quizpopup',
+                        'popupoptions' => $popupaction->get_js_options(),
+                        'fullscreen' => true,
+                        'startattemptwarning' => $startattemptwarning,
+                    )));
+
+            $warning = html_writer::tag('noscript', $this->heading(get_string('noscript', 'quiz')));
+
+        } else if ($startattemptwarning) {
+            $button->add_action(new confirm_action($startattemptwarning, null,
+                    get_string('startattempt', 'quiz')));
+        }
+
+        return $this->render($button) . $warning;
+    }
+
+    /**
+     * 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.
+     * @param object $quiz the quiz settings.
+     * @param object $cm the course_module object.
+     * @param object $context the quiz context.
+     * @return string HTML to output.
+     */
+    function no_questions_message($canedit, $editurl) {
+        $output = '';
+        $output .= $this->notification(get_string('noquestions', 'quiz'));
+        if ($canedit) {
+            $output .= $this->single_button($editurl, get_string('editquiz', 'quiz'), 'get');
+        }
+
         return $output;
     }
 
@@ -797,7 +922,7 @@ class mod_quiz_renderer extends plugin_renderer_base {
 
             if ($viewobj->canreviewmine) {
                 $row[] = $viewobj->accessmanager->make_review_link($attempt,
-                        $viewobj->canpreview, $attemptoptions);
+                        $attemptoptions, $this);
             }
 
             if ($viewobj->feedbackcolumn && $attempt->timefinish > 0) {
@@ -893,42 +1018,35 @@ class mod_quiz_renderer extends plugin_renderer_base {
     }
 
     /**
-     * Generates the view attempt button
+     * Output either a link to the review page for an attempt, or a button to
+     * open the review in a popup window.
      *
-     * @param int $course The course ID
-     * @param array $quiz Array containging quiz date
-     * @param int $cm The Course Module ID
-     * @param int $context The page Context ID
-     * @param mod_quiz_view_object $viewobj
-     * @param string $buttontext
+     * @param moodle_url $url of the target page.
+     * @param bool $reviewinpopup whether a pop-up is required.
+     * @param array $popupoptions options to pass to the popup_action constructor.
+     * @return string HTML to output.
      */
-    public function view_attempt_button($course, $quiz, $cm, $context, $viewobj,
-            $buttontext, $preventmessages) {
-        $output = '';
-        // Determine if we should be showing a start/continue attempt button,
-        // or a button to go back to the course page.
-        $output .= $this->box_start('quizattempt');
+    public function review_link($url, $reviewinpopup, $popupoptions) {
+        if ($reviewinpopup) {
+            $button = new single_button($url, get_string('review', 'quiz'));
+            $button->add_action(new popup_action('click', $url, 'quizpopup', $popupoptions));
+            return $this->render($button);
 
-        // Now actually print the appropriate button.
-        if (!quiz_clean_layout($quiz->questions, true)) {
-            $output .= quiz_no_questions_message($quiz, $cm, $context);
-        }
-
-        if ($preventmessages) {
-            $output .= $this->access_messages($preventmessages);
-        }
-
-        if ($buttontext) {
-            $output .= $viewobj->accessmanager->print_start_attempt_button($viewobj->canpreview,
-                    $buttontext, $viewobj->unfinished);
-        } else if ($buttontext === '') {
-            $output .= $this->single_button(new moodle_url('/course/view.php',
-                    array('id' => $course->id)), get_string('backtocourse', 'quiz'), 'get',
-                    array('class' => 'continuebutton'));
+        } else {
+            return html_writer::link($url, get_string('review', 'quiz'),
+                    array('title' => get_string('reviewthisattempt', 'quiz')));
         }
-        $output .= $this->box_end();
+    }
 
-        return $output;
+    /**
+     * Displayed where there might normally be a review link, to explain why the
+     * review is not available at this time.
+     * @param string $message optional message explaining why the review is not possible.
+     * @return string HTML to output.
+     */
+    public function no_review_message($message) {
+        return html_writer::nonempty_tag('span', $message,
+                array('class' => 'noreviewmessage'));
     }
 
     /**
@@ -969,76 +1087,59 @@ class mod_quiz_links_to_other_attempts implements renderable {
 }
 
 class mod_quiz_view_object {
-    /**
-     * @var array $attempt contains all the user's attempts at this quiz.
-     */
+    /** @var array $infomessages of messages with information to display about the quiz. */
+    public $infomessages;
+    /** @var array $attempt contains all the user's attempts at this quiz. */
     public $attempts;
-    /**
-     * @var object $accessmanager contains various access rules.
-     */
+    /** @var quiz_access_manager $accessmanager contains various access rules. */
     public $accessmanager;
-    /**
-     * @var int $canattempt determins capability for attempting a quiz.
-     */
-    public $canattempt;
-    /**
-     * @var int $canpreview determins capability for previewing a quiz.
-     */
-    public $canpreview;
-    /**
-     * @var int $canreviewmine determins capability for reviwing own quiz.
-     */
+    /** @var bool $canreviewmine whether the current user has the capability to review their own attempts. */
     public $canreviewmine;
-    /**
-     * @var int $attemptcolumn contains the number of attempts done.
-     */
+    /** @var bool $canedit whether the current user has the capability to edit the quiz. */
+    public $canedit;
+    /** @var moodle_url $editurl the URL for editing this quiz. */
+    public $editurl;
+    /** @var int $attemptcolumn contains the number of attempts done. */
     public $attemptcolumn;
-    /**
-     * @var int $gradecolumn contains the grades of any attempts.
-     */
+    /** @var int $gradecolumn contains the grades of any attempts. */
     public $gradecolumn;
-    /**
-     * @var int $markcolumn contains the marks of any attempt.
-     */
+    /** @var int $markcolumn contains the marks of any attempt. */
     public $markcolumn;
-    /**
-     * @var int $overallstats contains all marks for any attempt.
-     */
+    /** @var int $overallstats contains all marks for any attempt. */
     public $overallstats;
-    /**
-     * @var string $feedbackcolumn contains any feedback for and attempt.
-     */
+    /** @var string $feedbackcolumn contains any feedback for and attempt. */
     public $feedbackcolumn;
-    /**
-     * @var string $timenow contains a timestamp in string format.
-     */
+    /** @var string $timenow contains a timestamp in string format. */
     public $timenow;
-    /**
-     * @var int $numattempts contains the total number of attempts.
-     */
+    /** @var int $numattempts contains the total number of attempts. */
     public $numattempts;
-    /**
-     * @var int $mygrade contains the current users final grade for a quiz.
-     */
+    /** @var float $mygrade contains the user's final grade for a quiz. */
     public $mygrade;
-    /**
-     * @var int $moreattempts total attempts left.
-     */
+    /** @var bool $moreattempts whether this user is allowed more attempts. */
     public $moreattempts;
-    /**
-     * @var int $mygradeoverridden contains an overriden grade.
-     */
+    /** @var int $mygradeoverridden contains an overriden grade. */
     public $mygradeoverridden;
-    /**
-     * @var string $gradebookfeedback contains any feedback for a gradebook.
-     */
+    /** @var string $gradebookfeedback contains any feedback for a gradebook. */
     public $gradebookfeedback;
-    /**
-     * @var int $unfinished contains 1 if an attempt is unfinished.
-     */
+    /** @var bool $unfinished contains 1 if an attempt is unfinished. */
     public $unfinished;
-    /**
-     * @var int $lastfinishedattempt contains a pointer to the last attempt in the attempts array.
-     */
+    /** @var object $lastfinishedattempt the last attempt from the attempts array. */
     public $lastfinishedattempt;
+    /** @var array $preventmessages of messages telling the user why they can't attempt the quiz now. */
+    public $preventmessages;
+    /** @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. */
+    public $buttontext;
+    /** @var string $startattemptwarning alert to show the user before starting an attempt. */
+    public $startattemptwarning;
+    /** @var moodle_url $startattempturl URL to start an attempt. */
+    public $startattempturl;
+    /** @var moodle_url $startattempturl URL for any Back to the course button. */
+    public $backtocourseurl;
+    /** @var bool whether the attempt must take place in a popup window. */
+    public $popuprequired;
+    /** @var array options to use for the popup window, if required. */
+    public $popupoptions;
+    /** @var bool $quizhasquestions whether the quiz has any questions. */
+    public $quizhasquestions;
 }
index 14a4be8..53fa2b6 100644 (file)
@@ -369,3 +369,24 @@ function quiz_report_download_filename($report, $courseshortname, $quizname) {
 function quiz_report_default_report($context) {
     return reset(quiz_report_list($context));
 }
+
+/**
+ * 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.
+ * @param object $quiz the quiz settings.
+ * @param object $cm the course_module object.
+ * @param object $context the quiz context.
+ * @return string HTML to output.
+ */
+function quiz_no_questions_message($quiz, $cm, $context) {
+    global $OUTPUT;
+
+    $output = '';
+    $output .= $OUTPUT->notification(get_string('noquestions', 'quiz'));
+    if (has_capability('mod/quiz:manage', $context)) {
+        $output .= $OUTPUT->single_button(new moodle_url('/mod/quiz/edit.php',
+        array('cmid' => $cm->id)), get_string('editquiz', 'quiz'), 'get');
+    }
+
+    return $output;
+}
index 46f0470..584e12c 100644 (file)
@@ -58,9 +58,10 @@ $options = $attemptobj->get_display_options(true);
 if ($attemptobj->is_own_attempt()) {
     if (!$attemptobj->is_finished()) {
         redirect($attemptobj->attempt_url(null, $page));
+
     } else if (!$options->attempt) {
-        $accessmanager->back_to_view_page($attemptobj->is_preview_user(),
-                $accessmanager->cannot_review_message($attemptobj->get_attempt_state()));
+        $accessmanager->back_to_view_page($PAGE->get_renderer('mod_quiz'),
+                $attemptobj->cannot_review_message());
     }
 
 } else if (!$attemptobj->is_review_allowed()) {
@@ -100,19 +101,9 @@ if ($attemptobj->is_preview_user() && $attemptobj->is_own_attempt()) {
 
 // Set up the page header
 $headtags = $attemptobj->get_html_head_contributions($page, $showall);
-if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
-    $accessmanager->setup_secure_page($attemptobj->get_course()->shortname.': '.
-            format_string($attemptobj->get_quiz_name()), $headtags);
-} else if ($accessmanager->safebrowser_required($attemptobj->is_preview_user())) {
-    $PAGE->set_title($attemptobj->get_course()->shortname . ': '.
-            format_string($attemptobj->get_quiz_name()));
-    $PAGE->set_heading($attemptobj->get_course()->fullname);
-    $PAGE->set_cacheable(false);
-} else {
-    $PAGE->navbar->add($strreviewtitle);
-    $PAGE->set_title(format_string($attemptobj->get_quiz_name()));
-    $PAGE->set_heading($attemptobj->get_course()->fullname);
-}
+$PAGE->set_title(format_string($attemptobj->get_quiz_name()));
+$PAGE->set_heading($attemptobj->get_course()->fullname);
+$accessmanager->setup_attempt_page($PAGE);
 
 // Summary table start ============================================================================
 
index f0ef55e..0e3e68d 100644 (file)
@@ -59,7 +59,7 @@ if ($attemptobj->is_own_attempt()) {
         die();
     } else if (!$options->attempt) {
         echo $output->review_question_not_allowed(
-                $accessmanager->cannot_review_message($attemptobj->get_review_options()));
+                $attemptobj->cannot_review_message());
         die();
     }
 
similarity index 72%
rename from mod/quiz/simpletest/testaccessmanager.php
rename to mod/quiz/simpletest/testquizobj.php
index bc9887d..625e8d5 100644 (file)
@@ -15,7 +15,7 @@
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Unit tests for the access manager class.
+ * Unit tests for the quiz class.
  *
  * @package    mod
  * @subpackage quiz
@@ -30,12 +30,12 @@ require_once($CFG->dirroot . '/mod/quiz/locallib.php');
 
 
 /**
- * Unit tests for the access manager class
+ * Unit tests for the quiz class
  *
  * @copyright  2008 The Open University
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class quiz_access_manager_test extends UnitTestCase {
+class quiz_class_test extends UnitTestCase {
     public function test_cannot_review_message() {
         $quiz = new stdClass();
         $quiz->reviewattempt = 0x10010;
@@ -48,23 +48,20 @@ class quiz_access_manager_test extends UnitTestCase {
 
         $quizobj = new quiz($quiz, $cm, new stdClass(), false);
 
-        $am = new quiz_access_manager($quizobj, time(), false);
-
         $this->assertEqual('',
-                $am->cannot_review_message(mod_quiz_display_options::DURING));
+                $quizobj->cannot_review_message(mod_quiz_display_options::DURING));
         $this->assertEqual('',
-                $am->cannot_review_message(mod_quiz_display_options::IMMEDIATELY_AFTER));
+                $quizobj->cannot_review_message(mod_quiz_display_options::IMMEDIATELY_AFTER));
         $this->assertEqual(get_string('noreview', 'quiz'),
-                $am->cannot_review_message(mod_quiz_display_options::LATER_WHILE_OPEN));
+                $quizobj->cannot_review_message(mod_quiz_display_options::LATER_WHILE_OPEN));
         $this->assertEqual(get_string('noreview', 'quiz'),
-                $am->cannot_review_message(mod_quiz_display_options::AFTER_CLOSE));
+                $quizobj->cannot_review_message(mod_quiz_display_options::AFTER_CLOSE));
 
         $closetime = time() + 10000;
         $quiz->timeclose = $closetime;
         $quizobj = new quiz($quiz, $cm, new stdClass(), false);
-        $am = new quiz_access_manager($quizobj, time(), false);
 
         $this->assertEqual(get_string('noreviewuntil', 'quiz', userdate($closetime)),
-                $am->cannot_review_message(mod_quiz_display_options::LATER_WHILE_OPEN));
+                $quizobj->cannot_review_message(mod_quiz_display_options::LATER_WHILE_OPEN));
     }
 }
index 1323220..4cf5a92 100644 (file)
@@ -101,6 +101,7 @@ if (!$quizobj->is_preview_user() && $messages) {
     print_error('attempterror', 'quiz', $quizobj->view_url(),
             $output->print_messages($messages));
 }
+
 $accessmanager->do_password_check($quizobj->is_preview_user());
 
 // Delete any previous preview attempts belonging to this user.
index 1cada46..7b0be2b 100644 (file)
@@ -77,21 +77,12 @@ if (empty($attemptobj->get_quiz()->showblocks)) {
     $PAGE->blocks->show_only_fake_blocks();
 }
 
-if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
-    $accessmanager->setup_secure_page($attemptobj->get_course()->shortname . ': ' .
-            format_string($attemptobj->get_quiz_name()), '');
-} else if ($accessmanager->safebrowser_required($attemptobj->is_preview_user())) {
-    $PAGE->set_title($attemptobj->get_course()->shortname . ': ' .
-            format_string($attemptobj->get_quiz_name()));
-    $PAGE->set_heading($attemptobj->get_course()->fullname);
-    $PAGE->set_cacheable(false);
-} else {
-    $PAGE->navbar->add(get_string('summaryofattempt', 'quiz'));
-    $PAGE->set_title(format_string($attemptobj->get_quiz_name()));
-    $PAGE->set_heading($attemptobj->get_course()->fullname);
-}
+$PAGE->navbar->add(get_string('summaryofattempt', 'quiz'));
+$PAGE->set_title(format_string($attemptobj->get_quiz_name()));
+$PAGE->set_heading($attemptobj->get_course()->fullname);
+$accessmanager->setup_attempt_page($PAGE);
 
 // Print heading.
 
-$accessmanager->show_attempt_timer_if_needed($attemptobj->get_attempt(), time());
+$accessmanager->show_attempt_timer_if_needed($attemptobj->get_attempt(), time(), $output);
 echo $output->summary_page($attemptobj, $displayoptions);
index c38b8d5..68c34ac 100644 (file)
@@ -125,8 +125,6 @@ $output = $PAGE->get_renderer('mod_quiz');
 $viewobj = new mod_quiz_view_object();
 $viewobj->attempts = $attempts;
 $viewobj->accessmanager = $accessmanager;
-$viewobj->canattempt = $canattempt;
-$viewobj->canpreview = $canpreview;
 $viewobj->canreviewmine = $canreviewmine;
 
 // Print table with existing attempts
@@ -146,63 +144,68 @@ if ($attempts) {
     $viewobj->attemptcolumn = 1;
 }
 
-$moreattempts = $unfinished || !$accessmanager->is_finished($numattempts, $lastfinishedattempt);
-
 $viewobj->timenow = $timenow;
 $viewobj->numattempts = $numattempts;
 $viewobj->mygrade = $mygrade;
-$viewobj->moreattempts = $moreattempts;
+$viewobj->moreattempts = $unfinished ||
+        !$accessmanager->is_finished($numattempts, $lastfinishedattempt);
 $viewobj->mygradeoverridden = $mygradeoverridden;
 $viewobj->gradebookfeedback = $gradebookfeedback;
-$viewobj->unfinished = $unfinished;
 $viewobj->lastfinishedattempt = $lastfinishedattempt;
+$viewobj->canedit = has_capability('mod/quiz:manage', $context);
+$viewobj->editurl = new moodle_url('/mod/quiz/edit.php', array('cmid' => $cm->id));
+$viewobj->backtocourseurl = new moodle_url('/course/view.php', array('id' => $course->id));
+$viewobj->startattempturl = $quizobj->start_attempt_url();
+$viewobj->startattemptwarning = $quizobj->confirm_start_attempt_message($unfinished);
+$viewobj->popuprequired = $accessmanager->attempt_must_be_in_popup();
+$viewobj->popupoptions = $accessmanager->get_popup_options();
 
 // Display information about this quiz.
-$infomessages = $viewobj->accessmanager->describe_rules();
+$viewobj->infomessages = $viewobj->accessmanager->describe_rules();
 if ($quiz->attempts != 1) {
-    $infomessages[] = get_string('gradingmethod', 'quiz',
+    $viewobj->infomessages[] = get_string('gradingmethod', 'quiz',
             quiz_get_grading_option_name($quiz->grademethod));
 }
 
-// This will be set something if as start/continue attempt button should appear.
-$buttontext = '';
-$preventmessages = array();
-if (!quiz_clean_layout($quiz->questions, true)) {
-    $buttontext = '';
+// Determine wheter a start attempt button should be displayed.
+$viewobj->quizhasquestions = (bool) quiz_clean_layout($quiz->questions, true);
+$viewobj->preventmessages = array();
+if (!$viewobj->quizhasquestions) {
+    $viewobj->buttontext = '';
 
 } else {
-    if ($viewobj->unfinished) {
-        if ($viewobj->canattempt) {
-            $buttontext = get_string('continueattemptquiz', 'quiz');
-        } else if ($viewobj->canpreview) {
-            $buttontext = get_string('continuepreview', 'quiz');
+    if ($unfinished) {
+        if ($canattempt) {
+            $viewobj->buttontext = get_string('continueattemptquiz', 'quiz');
+        } else if ($canpreview) {
+            $viewobj->buttontext = get_string('continuepreview', 'quiz');
         }
 
     } else {
-        if ($viewobj->canattempt) {
-            $preventmessages = $viewobj->accessmanager->prevent_new_attempt($viewobj->numattempts,
-                    $viewobj->lastfinishedattempt);
-            if ($preventmessages) {
-                $buttontext = '';
+        if ($canattempt) {
+            $viewobj->preventmessages = $viewobj->accessmanager->prevent_new_attempt(
+                    $viewobj->numattempts, $viewobj->lastfinishedattempt);
+            if ($viewobj->preventmessages) {
+                $viewobj->buttontext = '';
             } else if ($viewobj->numattempts == 0) {
-                $buttontext = get_string('attemptquiznow', 'quiz');
+                $viewobj->buttontext = get_string('attemptquiznow', 'quiz');
             } else {
-                $buttontext = get_string('reattemptquiz', 'quiz');
+                $viewobj->buttontext = get_string('reattemptquiz', 'quiz');
             }
 
-        } else if ($viewobj->canpreview) {
-            $buttontext = get_string('previewquiznow', 'quiz');
+        } else if ($canpreview) {
+            $viewobj->buttontext = get_string('previewquiznow', 'quiz');
         }
     }
 
     // If, so far, we think a button should be printed, so check if they will be
     // allowed to access it.
-    if ($buttontext) {
+    if ($viewobj->buttontext) {
         if (!$viewobj->moreattempts) {
-            $buttontext = '';
-        } else if ($viewobj->canattempt
-                && $preventmessages = $viewobj->accessmanager->prevent_access()) {
-            $buttontext = '';
+            $viewobj->buttontext = '';
+        } else if ($canattempt
+                && $viewobj->preventmessages = $viewobj->accessmanager->prevent_access()) {
+            $viewobj->buttontext = '';
         }
     }
 }
@@ -212,13 +215,12 @@ echo $OUTPUT->header();
 // Guests can't do a quiz, so offer them a choice of logging in or going back.
 if (isguestuser()) {
     echo $output->view_page_guest($course, $quiz, $cm, $context, $infomessages, $viewobj);
-} else if (!isguestuser() && !($viewobj->canattempt || $viewobj->canpreview
+} else if (!isguestuser() && !($canattempt || $canpreview
           || $viewobj->canreviewmine)) {
     // If they are not enrolled in this course in a good enough role, tell them to enrol.
     echo $output->view_page_notenrolled($course, $quiz, $cm, $context, $infomessages, $viewobj);
 } else {
-    echo $output->view_page($course, $quiz, $cm, $context, $infomessages, $viewobj,
-            $buttontext, $preventmessages);
+    echo $output->view_page($course, $quiz, $cm, $context, $viewobj);
 }
 
 echo $OUTPUT->footer();