diff --git a/mod/quiz/classes/output/edit_renderer.php b/mod/quiz/classes/output/edit_renderer.php index c1e175eec3d..00afad9314a 100644 --- a/mod/quiz/classes/output/edit_renderer.php +++ b/mod/quiz/classes/output/edit_renderer.php @@ -64,7 +64,7 @@ class edit_renderer extends \plugin_renderer_base { $output .= $this->total_marks($quizobj->get_quiz()); // Show the questions organised into sections and pages. - $output .= $this->start_section_list(); + $output .= $this->start_section_list($structure); foreach ($structure->get_sections() as $section) { $output .= $this->start_section($structure, $section); @@ -254,10 +254,15 @@ class edit_renderer extends \plugin_renderer_base { /** * Generate the starting container html for the start of a list of sections + * @param structure $structure the structure of the quiz being edited. * @return string HTML to output. */ - protected function start_section_list() { - return html_writer::start_tag('ul', array('class' => 'slots')); + protected function start_section_list(structure $structure) { + $class = 'slots'; + if ($structure->get_section_count() == 1) { + $class .= ' only-one-section'; + } + return html_writer::start_tag('ul', array('class' => $class)); } /** diff --git a/mod/quiz/classes/structure.php b/mod/quiz/classes/structure.php index 36c34998de1..a9c4fe2164d 100644 --- a/mod/quiz/classes/structure.php +++ b/mod/quiz/classes/structure.php @@ -470,6 +470,14 @@ class structure { return $this->sections[$sectionid]; } + /** + * Get the number of questions in the quiz. + * @return int the number of questions in the quiz. + */ + public function get_section_count() { + return count($this->sections); + } + /** * Get the overall quiz grade formatted for display. * @return string the maximum grade for this quiz. @@ -876,7 +884,7 @@ class structure { $this->check_can_be_edited(); - if ($this->is_only_slot_in_section($slotnumber)) { + if ($this->is_only_slot_in_section($slotnumber) && $this->get_section_count() > 1) { throw new \coding_exception('You cannot remove the last slot in a section.'); } diff --git a/mod/quiz/styles.css b/mod/quiz/styles.css index ecc0cf71e47..90bdadea77b 100644 --- a/mod/quiz/styles.css +++ b/mod/quiz/styles.css @@ -724,6 +724,9 @@ table.quizreviewsummary td.cell { #page-mod-quiz-edit ul.slots li.section.only-has-one-slot li.activity .editing_delete { visibility: hidden; } +#page-mod-quiz-edit ul.slots.only-one-section li.section.only-has-one-slot li.activity .editing_delete { + visibility: visible; +} #page-mod-quiz-edit ul.slots li.section li.activity .question_dependency_wrapper { position: absolute; diff --git a/mod/quiz/tests/behat/editing_remove_question.feature b/mod/quiz/tests/behat/editing_remove_question.feature index 21d2b24bd4b..cc02d514184 100644 --- a/mod/quiz/tests/behat/editing_remove_question.feature +++ b/mod/quiz/tests/behat/editing_remove_question.feature @@ -64,3 +64,36 @@ Feature: Edit quiz page - remove questions And I should not see "Question A" on quiz page "2" And the "Remove" page break icon after question "Question B" should not exist And I should see "Total of marks: 1.00" + + @javascript + Scenario: Cannot delete the last question in a section. + Given the following "questions" exist: + | questioncategory | qtype | name | questiontext | + | Test questions | truefalse | Question A | This is question 01 | + | Test questions | truefalse | Question B | This is question 02 | + | Test questions | truefalse | Question C | This is question 03 | + And quiz "Quiz 1" contains the following questions: + | question | page | + | Question A | 1 | + | Question B | 1 | + | Question C | 2 | + And quiz "Quiz 1" contains the following sections: + | heading | firstslot | shuffle | + | Heading 1 | 1 | 1 | + | Heading 2 | 2 | 1 | + When I follow "Edit quiz" + Then "Delete" "link" in the "Question A" "list_item" should not be visible + Then "Delete" "link" in the "Question B" "list_item" should be visible + Then "Delete" "link" in the "Question C" "list_item" should be visible + + @javascript + Scenario: Can delete the last question in a quiz. + Given the following "questions" exist: + | questioncategory | qtype | name | questiontext | + | Test questions | truefalse | Question A | This is question 01 | + And quiz "Quiz 1" contains the following questions: + | question | page | + | Question A | 1 | + When I follow "Edit quiz" + And I delete "Question A" in the quiz by clicking the delete icon + Then I should see "Questions: 0" diff --git a/mod/quiz/tests/structure_test.php b/mod/quiz/tests/structure_test.php index 7dfeb95dcc1..6210f81288f 100644 --- a/mod/quiz/tests/structure_test.php +++ b/mod/quiz/tests/structure_test.php @@ -153,10 +153,10 @@ class mod_quiz_structure_testcase extends advanced_testcase { } else { list($name, $page, $qtype) = $item; $question = $structure->get_question_in_slot($slot); - $this->assertEquals($slot, $question->slot); $this->assertEquals($name, $question->name); - $this->assertEquals($qtype, $question->qtype); - $this->assertEquals($page, $question->page); + $this->assertEquals($slot, $question->slot, 'Slot number wrong for question ' . $name); + $this->assertEquals($qtype, $question->qtype, 'Question type wrong for question ' . $name); + $this->assertEquals($page, $question->page, 'Page number wrong for question ' . $name); $slot += 1; } @@ -624,6 +624,29 @@ class mod_quiz_structure_testcase extends advanced_testcase { $structure->remove_slot(3); } + public function test_can_remove_last_question_in_a_quiz() { + $quizobj = $this->create_test_quiz(array( + 'Heading 1', + array('TF1', 1, 'truefalse'), + )); + $structure = \mod_quiz\structure::create_for_quiz($quizobj); + + $structure->remove_slot(1); + + $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $questiongenerator->create_question_category(); + $q = $questiongenerator->create_question('truefalse', null, + array('name' => 'TF2', 'category' => $cat->id)); + + quiz_add_quiz_question($q->id, $quizobj->get_quiz(), 0); + $structure = \mod_quiz\structure::create_for_quiz($quizobj); + + $this->assert_quiz_layout(array( + 'Heading 1', + array('TF2', 1, 'truefalse'), + ), $structure); + } + public function test_add_question_updates_headings() { $quizobj = $this->create_test_quiz(array( array('TF1', 1, 'truefalse'), @@ -648,7 +671,7 @@ class mod_quiz_structure_testcase extends advanced_testcase { ), $structure); } - public function test_add_question_and_end_does_not_update_headings() { + public function test_add_question_at_end_does_not_update_headings() { $quizobj = $this->create_test_quiz(array( array('TF1', 1, 'truefalse'), 'Heading 2', diff --git a/mod/quiz/upgrade.txt b/mod/quiz/upgrade.txt index 2c395e86287..5421f092a96 100644 --- a/mod/quiz/upgrade.txt +++ b/mod/quiz/upgrade.txt @@ -1,5 +1,12 @@ This files describes API changes in the quiz code. +=== 2.9.5. === + +* mod_quiz\output\edit_renderer::start_section_list now takes $structure as an + argument. If you have overridden this method (it's hard to believe anyone ever + would) you will need to update your renderer. + + === 2.9 === * There have been changes in classes/output/edit_renderer.php for MDL-40990.