diff --git a/lang/en/question.php b/lang/en/question.php index dbde0c3e292..13e17ec6b8e 100644 --- a/lang/en/question.php +++ b/lang/en/question.php @@ -114,6 +114,7 @@ $string['editcategories_link'] = 'question/category'; $string['editcategory'] = 'Edit category'; $string['editingcategory'] = 'Editing a category'; $string['editingquestion'] = 'Editing a question'; +$string['editquestion'] = 'Edit question'; $string['editthiscategory'] = 'Edit this category'; $string['emptyxml'] = 'Unkown error - empty imsmanifest.xml'; $string['enabled'] = 'Enabled'; diff --git a/mod/quiz/attemptlib.php b/mod/quiz/attemptlib.php index 6f7b5416226..adf11823875 100644 --- a/mod/quiz/attemptlib.php +++ b/mod/quiz/attemptlib.php @@ -283,19 +283,27 @@ class quiz { /** * @param int $attemptid the id of an attempt. + * @param int $page optional page number to go to in the attempt. * @return string the URL of that attempt. */ - public function attempt_url($attemptid) { + public function attempt_url($attemptid, $page = 0) { global $CFG; - return $CFG->wwwroot . '/mod/quiz/attempt.php?attempt=' . $attemptid; + $url = $CFG->wwwroot . '/mod/quiz/attempt.php?attempt=' . $attemptid; + if ($page) { + $url .= '&page=' . $page; + } + return $url; } /** * @return string the URL of this quiz's edit page. Needs to be POSTed to with a cmid parameter. */ - public function start_attempt_url() { - return new moodle_url('/mod/quiz/startattempt.php', - array('cmid' => $this->cm->id, 'sesskey' => sesskey())); + public function start_attempt_url($page = 0) { + $params = array('cmid' => $this->cm->id, 'sesskey' => sesskey()); + if ($page) { + $params['page'] = $page; + } + return new moodle_url('/mod/quiz/startattempt.php', $params); } /** @@ -661,6 +669,40 @@ class quiz_attempt { } } + /** + * Wrapper that the correct mod_quiz_display_options for this quiz at the + * moment. + * + * @param bool $reviewing true for review page, else attempt page. + * @param int $slot which question is being displayed. + * @param moodle_url $thispageurl to return to after the editing form is + * submitted or cancelled. If null, no edit link will be generated. + * + * @return question_display_options the render options for this user on this + * attempt, with extra info to generate an edit link, if applicable. + */ + public function get_display_options_with_edit_link($reviewing, $slot, $thispageurl) { + $options = clone($this->get_display_options($reviewing)); + + if (!$thispageurl) { + return $options; + } + + if (!($reviewing || $this->is_preview())) { + return $options; + } + + $question = $this->quba->get_question($slot); + if (!question_has_capability_on($question, 'edit', $question->category)) { + return $options; + } + + $options->editquestionparams['cmid'] = $this->get_cmid(); + $options->editquestionparams['returnurl'] = $thispageurl; + + return $options; + } + /** * @param int $page page number * @return bool true if this is the last page of the quiz. @@ -802,8 +844,13 @@ class quiz_attempt { /** * @return string the URL of this quiz's edit page. Needs to be POSTed to with a cmid parameter. */ - public function start_attempt_url() { - return $this->quizobj->start_attempt_url(); + public function start_attempt_url($slot = null, $page = -1) { + if ($page == -1 && !is_null($slot)) { + $page = $this->quba->get_question($slot)->_page; + } else { + $page = 0; + } + return $this->quizobj->start_attempt_url($page); } /** @@ -896,12 +943,12 @@ class quiz_attempt { * * @param int $id the id of a question in this quiz attempt. * @param bool $reviewing is the being printed on an attempt or a review page. - * @param string $thispageurl the URL of the page this question is being printed on. + * @param moodle_url $thispageurl the URL of the page this question is being printed on. * @return string HTML for the question in its current state. */ - public function render_question($slot, $reviewing, $thispageurl = '') { + public function render_question($slot, $reviewing, $thispageurl = null) { return $this->quba->render_question($slot, - $this->get_display_options($reviewing), + $this->get_display_options_with_edit_link($reviewing, $slot, $thispageurl), $this->quba->get_question($slot)->_number); } @@ -925,8 +972,6 @@ class quiz_attempt { * Wrapper round print_question from lib/questionlib.php. * * @param int $id the id of a question in this quiz attempt. - * @param bool $reviewing is the being printed on an attempt or a review page. - * @param string $thispageurl the URL of the page this question is being printed on. */ public function render_question_for_commenting($slot) { $options = $this->get_display_options(true); diff --git a/mod/quiz/renderer.php b/mod/quiz/renderer.php index 7f2a99ee1d0..ed5d2da79f8 100644 --- a/mod/quiz/renderer.php +++ b/mod/quiz/renderer.php @@ -77,9 +77,9 @@ class mod_quiz_renderer extends plugin_renderer_base { $output .= $this->review_summary_table($summarydata, 0); if (!is_null($seq)) { - $output .= $attemptobj->render_question_at_step($slot, $seq, true, $this->page->url); + $output .= $attemptobj->render_question_at_step($slot, $seq, true); } else { - $output .= $attemptobj->render_question($slot, true, $this->page->url); + $output .= $attemptobj->render_question($slot, true); } $output .= $this->close_window_button(); diff --git a/mod/quiz/startattempt.php b/mod/quiz/startattempt.php index 23d4a366311..f44ecc54443 100644 --- a/mod/quiz/startattempt.php +++ b/mod/quiz/startattempt.php @@ -31,8 +31,9 @@ require_once(dirname(__FILE__) . '/../../config.php'); require_once($CFG->dirroot . '/mod/quiz/locallib.php'); // Get submitted parameters. -$id = required_param('cmid', PARAM_INT); // Course Module ID +$id = required_param('cmid', PARAM_INT); // Course module id $forcenew = optional_param('forcenew', false, PARAM_BOOL); // Used to force a new preview +$page = optional_param('page', 0, PARAM_INT); // Page to jump to in the attempt. if (!$cm = get_coursemodule_from_id('quiz', $id)) { print_error('invalidcoursemodule'); @@ -84,7 +85,7 @@ $lastattempt = end($attempts); // If an in-progress attempt exists, check password then redirect to it. if ($lastattempt && !$lastattempt->timefinish) { $accessmanager->do_password_check($quizobj->is_preview_user()); - redirect($quizobj->attempt_url($lastattempt->id)); + redirect($quizobj->attempt_url($lastattempt->id, $page)); } // Get number for the next or unfinished attempt @@ -220,4 +221,4 @@ events_trigger('quiz_attempt_started', $eventdata); $transaction->allow_commit(); // Redirect to the attempt page. -redirect($quizobj->attempt_url($attempt->id)); +redirect($quizobj->attempt_url($attempt->id, $page)); diff --git a/question/engine/lib.php b/question/engine/lib.php index b83fa1d3e5b..04612977b25 100644 --- a/question/engine/lib.php +++ b/question/engine/lib.php @@ -505,6 +505,20 @@ class question_display_options { */ public $history = self::HIDDEN; + /** + * If not empty, then a link to edit the question will be included in + * the info box for the question. + * + * If used, this array must contain an element courseid or cmid. + * + * It shoudl also contain a parameter returnurl => moodle_url giving a + * sensible URL to go back to when the editing form is submitted or cancelled. + * + * @var array url parameter for the edit link. id => questiosnid will be + * added automatically. + */ + public $editquestionparams = array(); + /** * @var int the context the attempt being output belongs to. */ diff --git a/question/engine/renderer.php b/question/engine/renderer.php index d68220b7b6b..910bda96585 100644 --- a/question/engine/renderer.php +++ b/question/engine/renderer.php @@ -113,6 +113,7 @@ class core_question_renderer extends plugin_renderer_base { $output .= $this->status($qa, $behaviouroutput, $options); $output .= $this->mark_summary($qa, $options); $output .= $this->question_flag($qa, $options->flags); + $output .= $this->edit_question_link($qa, $options); return $output; } @@ -254,6 +255,28 @@ class core_question_renderer extends plugin_renderer_base { '" alt="' . get_string('flagthisquestion', 'question') . '" />'; } + protected function edit_question_link(question_attempt $qa, + question_display_options $options) { + global $CFG; + + if (empty($options->editquestionparams)) { + return ''; + } + + $params = $options->editquestionparams; + if ($params['returnurl'] instanceof moodle_url) { + $params['returnurl'] = str_replace($CFG->wwwroot, '', + $params['returnurl']->out(false)); + } + $params['id'] = $qa->get_question()->id; + $editurl = new moodle_url('/question/question.php', $params); + + return html_writer::tag('div', html_writer::link( + $editurl, $this->pix_icon('i/edit', get_string('edit')) . + get_string('editquestion', 'question')), + array('class' => 'editquestion')); + } + /** * Generate the display of the formulation part of the question. This is the * area that contains the quetsion text, and the controls for students to diff --git a/theme/base/style/question.css b/theme/base/style/question.css index 1ff8eb16e97..2a0ce677b49 100644 --- a/theme/base/style/question.css +++ b/theme/base/style/question.css @@ -42,7 +42,8 @@ body.jsenabled #qtypechoicecontainer {display: block;} .que h2.no {margin: 0;font-size: 0.8em;line-height: 1;} .que span.qno {font-size: 1.5em;font-weight:bold;} .que .state, -.que .grade {font-size: 0.8em; margin-top: 0.7em;} +.que .grade, +.que .editquestion {font-size: 0.8em; margin-top: 0.7em;} .que .info .questionflag {margin-top: 1em;margin-right: 1em;text-align: center;} .que .content {margin: 0 0 0 7.5em;}