diff --git a/mod/quiz/classes/output/attempt_summary_information.php b/mod/quiz/classes/output/attempt_summary_information.php index f271005ddb2..d5b66856731 100644 --- a/mod/quiz/classes/output/attempt_summary_information.php +++ b/mod/quiz/classes/output/attempt_summary_information.php @@ -61,6 +61,84 @@ class attempt_summary_information implements renderable, named_templatable { ]; } + /** + * Add an item to the summary just before the given item. + * + * If that item is not present, then add as the first item. + * + * @param string $shortname unique identifier of this item (not displayed). + * @param string|renderable $title the title of this item. + * @param string|renderable $content the content of this item. + * @param string $addbefore identifier of the other item to add this before. + */ + public function add_item_before( + string $shortname, + string|renderable $title, + string|renderable $content, + string $addbefore, + ): void { + $position = array_search($addbefore, array_keys($this->summarydata)); + if ($position !== false) { + $this->insert_new_item_at_position($shortname, $title, $content, $position); + } else { + $this->insert_new_item_at_position($shortname, $title, $content, 0); + } + } + + /** + * Add an item to the summary just after the given item. + * + * If that item is not present, then just add at the end. + * + * @param string $shortname unique identifier of this item (not displayed). + * @param string|renderable $title the title of this item. + * @param string|renderable $content the content of this item. + * @param string $addafter identifier of the other item to add this before. + */ + public function add_item_after( + string $shortname, + string|renderable $title, + string|renderable $content, + string $addafter, + ): void { + $position = array_search($addafter, array_keys($this->summarydata)); + if ($position !== false) { + $this->insert_new_item_at_position($shortname, $title, $content, $position + 1); + } else { + $this->add_item($shortname, $title, $content); + } + } + + /** + * Add an item to the summary just before the given position. + * + * @param string $shortname unique identifier of this item (not displayed). + * @param string|renderable $title the title of this item. + * @param string|renderable $content the content of this item. + * @param int $position Numerical position to insert the item at. 0 means first. + */ + protected function insert_new_item_at_position( + string $shortname, + string|renderable $title, + string|renderable $content, + int $position, + ) { + $this->summarydata = array_merge( + array_slice($this->summarydata, 0, $position), + [$shortname => ['title' => $title, 'content' => $content]], + array_slice($this->summarydata, $position, count($this->summarydata)), + ); + } + + /** + * Remove an item, if present. + * + * @param string $shortname + */ + public function remove_item(string $shortname): void { + unset($this->summarydata[$shortname]); + } + /** * Filter the data held, to keep only the information with the given shortnames. * diff --git a/mod/quiz/tests/output/attempt_summary_information_test.php b/mod/quiz/tests/output/attempt_summary_information_test.php new file mode 100644 index 00000000000..232058218af --- /dev/null +++ b/mod/quiz/tests/output/attempt_summary_information_test.php @@ -0,0 +1,193 @@ +. + +namespace mod_quiz\output; + +use advanced_testcase; + +/** + * Tests for {@see attempt_summary_information}. + * + * @package mod_quiz + * @copyright The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @covers \mod_quiz\output\attempt_summary_information + */ +final class attempt_summary_information_test extends advanced_testcase { + + public function test_add_item(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + $summary->add_item('test', 'Test name', 'Test value'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'Test name', 'content' => 'Test value'], + ], $data['items']); + } + + public function test_add_item_before_start(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + $summary->add_item('test', 'Test name', 'Test value'); + + $summary->add_item_before('newitem', 'New name', 'New value', 'test'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'New name', 'content' => 'New value'], + (object) ['title' => 'Test name', 'content' => 'Test value'], + ], $data['items']); + } + + public function test_add_item_before_middle(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + $summary->add_item('item1', 'Existing 1', 'One'); + $summary->add_item('item2', 'Existing 2', 'Two'); + + $summary->add_item_before('newitem', 'New name', 'New value', 'item2'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'Existing 1', 'content' => 'One'], + (object) ['title' => 'New name', 'content' => 'New value'], + (object) ['title' => 'Existing 2', 'content' => 'Two'], + ], $data['items']); + } + + public function test_add_item_before_no_match(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + $summary->add_item('test', 'Test name', 'Test value'); + + $summary->add_item_before('newitem', 'New name', 'New value', 'unknown'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'New name', 'content' => 'New value'], + (object) ['title' => 'Test name', 'content' => 'Test value'], + ], $data['items']); + } + + public function test_add_item_before_empty(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + + $summary->add_item_before('newitem', 'New name', 'New value', 'unknown'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'New name', 'content' => 'New value'], + ], $data['items']); + } + + public function test_add_item_after_end(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + $summary->add_item('test', 'Test name', 'Test value'); + + $summary->add_item_after('newitem', 'New name', 'New value', 'test'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'Test name', 'content' => 'Test value'], + (object) ['title' => 'New name', 'content' => 'New value'], + ], $data['items']); + } + + public function test_add_item_after_middle(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + $summary->add_item('item1', 'Existing 1', 'One'); + $summary->add_item('item2', 'Existing 2', 'Two'); + + $summary->add_item_after('newitem', 'New name', 'New value', 'item1'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'Existing 1', 'content' => 'One'], + (object) ['title' => 'New name', 'content' => 'New value'], + (object) ['title' => 'Existing 2', 'content' => 'Two'], + ], $data['items']); + } + + public function test_add_item_after_no_match(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + $summary->add_item('test', 'Test name', 'Test value'); + + $summary->add_item_after('newitem', 'New name', 'New value', 'unknown'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'Test name', 'content' => 'Test value'], + (object) ['title' => 'New name', 'content' => 'New value'], + ], $data['items']); + } + + public function test_add_item_after_empty(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + + $summary->add_item_after('newitem', 'New name', 'New value', 'unknown'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'New name', 'content' => 'New value'], + ], $data['items']); + } + + public function test_remove_item(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + $summary->add_item('item1', 'Existing 1', 'One'); + $summary->add_item('item2', 'Existing 2', 'Two'); + + $summary->remove_item('item1'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'Existing 2', 'content' => 'Two'], + ], $data['items']); + } + + public function test_remove_item_not_present(): void { + global $PAGE; + + $summary = new attempt_summary_information(); + $summary->add_item('item1', 'Existing 1', 'One'); + $summary->add_item('item2', 'Existing 2', 'Two'); + + $summary->remove_item('item3'); + + $data = $summary->export_for_template($PAGE->get_renderer('mod_quiz')); + $this->assertEquals([ + (object) ['title' => 'Existing 1', 'content' => 'One'], + (object) ['title' => 'Existing 2', 'content' => 'Two'], + ], $data['items']); + } +}