diff --git a/badges/classes/output/base_action_bar.php b/badges/classes/output/base_action_bar.php index 6b89d331338..2cc11b6a686 100644 --- a/badges/classes/output/base_action_bar.php +++ b/badges/classes/output/base_action_bar.php @@ -17,8 +17,10 @@ namespace core_badges\output; use renderable; -use templatable; +use renderer_base; use moodle_page; +use navigation_node; +use templatable; /** * Abstract class for the badges tertiary navigation. The class initialises the page and type class variables. @@ -50,4 +52,52 @@ abstract class base_action_bar implements renderable, templatable { * @return string */ abstract public function get_template(): string; + + /** + * Gets additional third party navigation nodes for display. + * + * @param renderer_base $output The output + * @return array All that sweet third party navigation action. + */ + public function get_third_party_nav_action(renderer_base $output): array { + $badgenode = $this->page->settingsnav->find('coursebadges', navigation_node::TYPE_CONTAINER); + if (!$badgenode) { + return []; + } + $leftovernodes = []; + foreach ($badgenode->children as $key => $value) { + if (array_search($value->key, $this->expected_items()) === false) { + $leftovernodes[] = $value; + } + } + $result = \core\navigation\views\secondary::create_menu_element($leftovernodes); + + if ($result == false) { + return []; + } else { + $data ['thirdpartybutton'] = true; + if (count($result) == 1) { + // Return a button. + $link = key($result); + $text = current($result); + $data['thirdpartynodes'] = ['link' => $link, 'text' => $text]; + } else { + // Return a url_select. + $selectobject = new \url_select($result, $this->page->url, get_string('othernavigation', 'badges')); + $data['thirdpartynodes'] = $selectobject->export_for_template($output); + $data['thirdpartybutton'] = false; + } + } + + return $data; + } + + /** + * Expected navigation node keys for badges. + * + * @return array default badge navigation node keys. + */ + protected function expected_items(): array { + return ['coursebadges', 'newbadge']; + } } diff --git a/badges/classes/output/manage_badge_action_bar.php b/badges/classes/output/manage_badge_action_bar.php index 5cc712b5237..7344b72d47d 100644 --- a/badges/classes/output/manage_badge_action_bar.php +++ b/badges/classes/output/manage_badge_action_bar.php @@ -71,6 +71,8 @@ class manage_badge_action_bar extends base_action_bar { foreach ($elements as $key => $element) { $elements[$key] = $element->export_for_template($output); } + $additional = $this->get_third_party_nav_action($output); + $elements += $additional ?: []; return $elements; } diff --git a/badges/classes/output/recipients_action_bar.php b/badges/classes/output/recipients_action_bar.php index 6720aff31cd..cae5ba7ce91 100644 --- a/badges/classes/output/recipients_action_bar.php +++ b/badges/classes/output/recipients_action_bar.php @@ -53,6 +53,8 @@ class recipients_action_bar extends manage_badge_action_bar { $button = new single_button($url, get_string('award', 'badges'), 'post', true); $elements['awardbutton'] = $button->export_for_template($output); } + $thirdpartynav = $this->get_third_party_nav_action($output); + $elements += $thirdpartynav ?: []; return $elements; } diff --git a/badges/classes/output/standard_action_bar.php b/badges/classes/output/standard_action_bar.php index 951d91e24cf..93026a087b2 100644 --- a/badges/classes/output/standard_action_bar.php +++ b/badges/classes/output/standard_action_bar.php @@ -96,6 +96,10 @@ class standard_action_bar extends base_action_bar { $buttons[$key] = $button->export_for_template($output); } - return ['buttons' => $buttons]; + $data = ['buttons' => $buttons]; + $additional = $this->get_third_party_nav_action($output); + $data += $additional ?: []; + + return $data; } } diff --git a/badges/templates/award_badge.mustache b/badges/templates/award_badge.mustache index 7e2ab5e50cb..bdae5a7c451 100644 --- a/badges/templates/award_badge.mustache +++ b/badges/templates/award_badge.mustache @@ -103,5 +103,6 @@ {{> core/single_button }} {{/awardbutton}} + {{> core_badges/badge_more_nav }} diff --git a/badges/templates/badge_more_nav.mustache b/badges/templates/badge_more_nav.mustache new file mode 100644 index 00000000000..622d5a57e31 --- /dev/null +++ b/badges/templates/badge_more_nav.mustache @@ -0,0 +1,37 @@ +{{! + This file is part of Moodle - http://moodle.org/ + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core_badges/badge_more_nav + + Example context (json): + { + "thirdpartybutton": true, + "thirdpartynodes": { + "link": "http://example.org/help", + "text": "Example text" + } + } +}} +{{#thirdpartybutton}} + {{#thirdpartynodes}} +
+ {{text}} +
+ {{/thirdpartynodes}} +{{/thirdpartybutton}} +{{^thirdpartybutton}} + {{#thirdpartynodes}} + {{> core/url_select}} + {{/thirdpartynodes}} +{{/thirdpartybutton}} diff --git a/badges/templates/manage_badge.mustache b/badges/templates/manage_badge.mustache index 04803875cc1..081c3eeb45b 100644 --- a/badges/templates/manage_badge.mustache +++ b/badges/templates/manage_badge.mustache @@ -83,5 +83,6 @@ {{> core/url_select }} {{/urlselect}} + {{> core_badges/badge_more_nav }} diff --git a/badges/templates/manage_badges.mustache b/badges/templates/manage_badges.mustache index 4fe4c3c56e3..7c4c4b8143d 100644 --- a/badges/templates/manage_badges.mustache +++ b/badges/templates/manage_badges.mustache @@ -59,5 +59,6 @@ {{> core/single_button }} {{/buttons}} + {{> core_badges/badge_more_nav }} diff --git a/grade/grading/lib.php b/grade/grading/lib.php index 7af2811ea0f..3615e98e8ae 100644 --- a/grade/grading/lib.php +++ b/grade/grading/lib.php @@ -453,33 +453,13 @@ class grading_manager { // no money, no funny return; - } else if (count($areas) == 1) { + } else { // make just a single node for the management screen $areatitle = reset($areas); $areaname = key($areas); $this->set_area($areaname); - $method = $this->get_active_method(); $managementnode = $modulenode->add(get_string('gradingmanagement', 'core_grading'), $this->get_management_url(), settings_navigation::TYPE_CUSTOM, null, 'advgrading'); - if ($method) { - $controller = $this->get_controller($method); - $controller->extend_settings_navigation($settingsnav, $managementnode); - } - - } else { - // make management screen node for each area - $managementnode = $modulenode->add(get_string('gradingmanagement', 'core_grading'), - null, settings_navigation::TYPE_CUSTOM, null, 'advgrading'); - foreach ($areas as $areaname => $areatitle) { - $this->set_area($areaname); - $method = $this->get_active_method(); - $node = $managementnode->add($areatitle, - $this->get_management_url(), settings_navigation::TYPE_CUSTOM); - if ($method) { - $controller = $this->get_controller($method); - $controller->extend_settings_navigation($settingsnav, $node); - } - } } } diff --git a/lang/en/badges.php b/lang/en/badges.php index 499d1ed47b6..35313af6957 100644 --- a/lang/en/badges.php +++ b/lang/en/badges.php @@ -456,6 +456,7 @@ $string['oauth2issuer'] = 'OAuth 2 services'; $string['openbadgesv1'] = 'Open Badges v1.0'; $string['openbadgesv2'] = 'Open Badges v2.0'; $string['openbadgesv2p1'] = 'Open Badges v2.1'; +$string['othernavigation'] = 'Other navigation ...'; $string['potentialrecipients'] = 'Potential badge recipients'; $string['preferences'] = 'Badge preferences'; $string['privacy:metadata:backpack'] = 'A record of user\'s backpacks'; diff --git a/lib/classes/navigation/views/secondary.php b/lib/classes/navigation/views/secondary.php index 5e15666ebcc..8da27ce0c78 100644 --- a/lib/classes/navigation/views/secondary.php +++ b/lib/classes/navigation/views/secondary.php @@ -215,65 +215,6 @@ class secondary extends view { $this->initialised = true; } - /** - * Recursively goes and gets all children nodes. - * - * @param navigation_node $node The node to get the children of. - * @return array The additional child nodes. - */ - protected function get_additional_child_nodes(navigation_node $node): array { - $nodes = []; - foreach ($node->children as $child) { - if ($child->has_action()) { - $nodes[$child->action->out()] = $child->text; - } - if ($child->has_children()) { - $childnodes = $this->get_additional_child_nodes($child); - $nodes = array_merge($nodes, $childnodes); - } - } - return $nodes; - } - - /** - * Returns an array of sections, actions, and text for a url select menu. - * - * @param navigation_node $node The node to use for a url select menu. - * @return array The menu array. - */ - protected function get_menu_array(navigation_node $node): array { - $urldata = []; - - // Check that children have children. - $additionalchildren = false; - $initialchildren = []; - if ($node->has_action()) { - $initialchildren[$node->action->out()] = $node->text; - } - foreach ($node->children as $child) { - $additionalnode = []; - if ($child->has_action()) { - $additionalnode[$child->action->out()] = $child->text; - } - - if ($child->has_children()) { - $additionalchildren = true; - $text = (is_a($child->text, 'lang_string')) ? $child->text->out() : $child->text; - $urldata[][$text] = $additionalnode + $this->get_additional_child_nodes($child); - } else { - $initialchildren += $additionalnode; - } - } - if ($additionalchildren) { - $text = (is_a($node->text, 'lang_string')) ? $node->text->out() : $node->text; - $urldata[][$text] = $initialchildren; - } else { - $urldata = $initialchildren; - } - - return $urldata; - } - /** * Returns a node with the action being from the first found child node that has an action (Recursive). * @@ -492,6 +433,11 @@ class secondary extends view { * @return url_select|null The overflow menu data. */ public function get_overflow_menu_data(): ?url_select { + + if (!$this->page->get_navigation_overflow_state()) { + return null; + } + $activenode = $this->find_active_node(); $incourseadmin = false; @@ -514,7 +460,7 @@ class secondary extends view { if (is_null($courseoverflownode)) { return null; } - $menuarray = $this->get_menu_array($courseoverflownode); + $menuarray = static::create_menu_element([$courseoverflownode]); if ($activenode->key != 'courseadmin') { $inmenu = false; foreach ($menuarray as $key => $value) { @@ -576,9 +522,9 @@ class secondary extends view { if (!isset($menunode) || !$menunode->has_children()) { return null; } - $selectdata = $this->get_menu_array($menunode); - $urlselect = new url_select($selectdata, $matchednode->action->out(), null); - $urlselect->set_label(get_string('browsesettingindex', 'course'), ['class' => 'sr_only']); + $selectdata = static::create_menu_element([$menunode], false); + $urlselect = new url_select($selectdata, $matchednode->action->out(false), null); + $urlselect->set_label(get_string('browsesettingindex', 'course'), ['class' => 'sr-only']); return $urlselect; } @@ -751,4 +697,185 @@ class secondary extends view { } } } + + /** + * Takes the given navigation nodes and searches for children and formats it all into an array in a format to be used by a + * url_select element. + * + * @param navigation_node[] $navigationnodes Navigation nodes to format into a menu. + * @param bool $forceheadings Whether the returned array should be forced to use headings. + * @return array|null A url select element for navigating through the navigation nodes. + */ + public static function create_menu_element(array $navigationnodes, bool $forceheadings = false): ?array { + if (empty($navigationnodes)) { + return null; + } + + // If one item, do we put this into a url_select? + if (count($navigationnodes) < 2) { + // Check if there are children. + $navnode = array_shift($navigationnodes); + $menudata = []; + if (!$navnode->has_children()) { + // Just one item. + if (!$navnode->has_action()) { + return null; + } + $menudata[$navnode->action->out(false)] = static::format_node_text($navnode); + } else { + if (static::does_menu_need_headings($navnode) || $forceheadings) { + // Let's do headings. + $menudata = static::get_headings_nav_array($navnode); + } else { + // Simple flat nav. + $menudata = static::get_flat_nav_array($navnode); + } + } + return $menudata; + } else { + // We have more than one navigation node to handle. Put each node in it's own heading. + $menudata = []; + $titledata = []; + foreach ($navigationnodes as $navigationnode) { + if ($navigationnode->has_children()) { + $menuarray = []; + // Add a heading and flatten out everything else. + if ($navigationnode->has_action()) { + $menuarray[static::format_node_text($navigationnode)][$navigationnode->action->out(false)] = + static::format_node_text($navigationnode); + $menuarray[static::format_node_text($navigationnode)] += static::get_whole_tree_flat($navigationnode); + } else { + $menuarray[static::format_node_text($navigationnode)] = static::get_whole_tree_flat($navigationnode); + } + + $titledata += $menuarray; + } else { + // Add with no heading. + if (!$navigationnode->has_action()) { + return null; + } + $menudata[$navigationnode->action->out(false)] = static::format_node_text($navigationnode); + } + } + $menudata += [$titledata]; + return $menudata; + } + } + + /** + * Recursively goes through the provided navigation node and returns a flat version. + * + * @param navigation_node $navigationnode The navigationnode. + * @return array The whole tree flat. + */ + protected static function get_whole_tree_flat(navigation_node $navigationnode): array { + $nodes = []; + foreach ($navigationnode->children as $child) { + if ($child->has_action()) { + $nodes[$child->action->out()] = $child->text; + } + if ($child->has_children()) { + $childnodes = static::get_whole_tree_flat($child); + $nodes = array_merge($nodes, $childnodes); + } + } + return $nodes; + } + + /** + * Checks to see if the provided navigation node has children and determines if we want headings for a url select element. + * + * @param navigation_node $navigationnode The navigation node we are checking. + * @return bool Whether we want headings or not. + */ + protected static function does_menu_need_headings(navigation_node $navigationnode): bool { + if (!$navigationnode->has_children()) { + return false; + } + foreach ($navigationnode->children as $child) { + if ($child->has_children()) { + return true; + } + } + return false; + } + + /** + * Takes the navigation node and returns it in a flat fashion. This is not recursive. + * + * @param navigation_node $navigationnode The navigation node that we want to format into an array in a flat structure. + * @return array The flat navigation array. + */ + protected static function get_flat_nav_array(navigation_node $navigationnode): array { + $menuarray = []; + if ($navigationnode->has_action()) { + $menuarray[$navigationnode->action->out(false)] = static::format_node_text($navigationnode); + } + + foreach ($navigationnode->children as $child) { + if ($child->has_action()) { + $menuarray[$child->action->out(false)] = static::format_node_text($child); + } + } + return $menuarray; + } + + /** + * For any navigation node that we have determined needs headings we return a more tree like array structure. + * + * @param navigation_node $navigationnode The navigation node to use for the formatted array structure. + * @return array The headings navigation array structure. + */ + protected static function get_headings_nav_array(navigation_node $navigationnode): array { + $menublock = []; + // We know that this single node has headings, so grab this for the first heading. + $firstheading = []; + if ($navigationnode->has_action()) { + $firstheading[static::format_node_text($navigationnode)][$navigationnode->action->out(false)] = + static::format_node_text($navigationnode); + $firstheading[static::format_node_text($navigationnode)] += static::get_more_child_nodes($navigationnode, $menublock); + } else { + $firstheading[static::format_node_text($navigationnode)] = static::get_more_child_nodes($navigationnode, $menublock); + } + return [$firstheading + $menublock]; + } + + /** + * Recursively goes and gets all children nodes. + * + * @param navigation_node $node The node to get the children of. + * @param array $menublock Used to put all child nodes in its own container. + * @return array The additional child nodes. + */ + protected static function get_more_child_nodes(navigation_node $node, array &$menublock): array { + $nodes = []; + foreach ($node->children as $child) { + if (!$child->has_children()) { + if (!$child->has_action()) { + continue; + } + $nodes[$child->action->out(false)] = static::format_node_text($child); + } else { + $newarray = []; + if ($child->has_action()) { + $newarray[static::format_node_text($child)][$child->action->out(false)] = static::format_node_text($child); + $newarray[static::format_node_text($child)] += static::get_more_child_nodes($child, $menublock); + } else { + $newarray[static::format_node_text($child)] = static::get_more_child_nodes($child, $menublock); + } + $menublock += $newarray; + } + } + return $nodes; + } + + /** + * Returns the navigation node text in a string. + * + * @param navigation_node $navigationnode The navigationnode to return the text string of. + * @return string The navigation node text string. + */ + protected static function format_node_text(navigation_node $navigationnode): string { + return (is_a($navigationnode->text, 'lang_string')) ? $navigationnode->text->out() : $navigationnode->text; + } } diff --git a/lib/classes/output/participants_action_bar.php b/lib/classes/output/participants_action_bar.php index 045c4eb93ff..a16482f2c3a 100644 --- a/lib/classes/output/participants_action_bar.php +++ b/lib/classes/output/participants_action_bar.php @@ -110,10 +110,31 @@ class participants_action_bar implements \renderable { } } - // TODO: Implement MDL-72930. + // Need to do some funky code here to find out if we have added third party navigation nodes. + $thirdpartynodearray = $this->get_thirdparty_node_array() ?: []; + $formattedcontent = array_merge($formattedcontent, $thirdpartynodearray); return $formattedcontent; } + /** + * Gets an array of third party navigation nodes in an array formatted for a url_select element. + * + * @return array|null The thirdparty node array. + */ + protected function get_thirdparty_node_array(): ?array { + $results = []; + + $flatnodes = array_merge(...(array_values($this->get_ordered_nodes()))); + + foreach ($this->node->children as $child) { + if (array_search($child->key, $flatnodes) === false) { + $results[] = $child; + } + } + + return \core\navigation\views\secondary::create_menu_element($results, true); + } + /** * Recursively tries to find a matching url * @param array $urlcontent The content for the url_select diff --git a/lib/classes/report_helper.php b/lib/classes/report_helper.php index 10cdaeafefc..e66d47c0f36 100644 --- a/lib/classes/report_helper.php +++ b/lib/classes/report_helper.php @@ -45,26 +45,41 @@ class report_helper { global $OUTPUT, $PAGE; if ($reportnode = $PAGE->settingsnav->find('coursereports', \navigation_node::TYPE_CONTAINER)) { - if ($children = $reportnode->children) { - // Menu to select report pages to navigate. - $activeurl = ''; - foreach ($children as $key => $node) { - $name = $node->text; - $url = $node->action()->out(false); - $menu[$url] = $name; - if ($name === $pluginname) { - $activeurl = $url; + $menuarray = \core\navigation\views\secondary::create_menu_element([$reportnode]); + if (empty($menuarray)) { + return; + } + + $coursereports = get_string('reports'); + $activeurl = ''; + if (isset($menuarray[0])) { + // Remove the reports entry. + $result = array_search($coursereports, $menuarray[0][$coursereports]); + unset($menuarray[0][$coursereports][$result]); + + // Find the active node. + foreach ($menuarray[0] as $key => $value) { + $check = array_search($pluginname, $value); + if ($check !== false) { + $activeurl = $check; } } + } else { + $result = array_search($coursereports, $menuarray); + unset($menuarray[$result]); + + $check = array_search($pluginname, $menuarray); + if ($check !== false) { + $activeurl = $check; + } + } - if (!empty($menu)) { - $select = new url_select($menu, $activeurl, null, 'choosecoursereport'); - $select->set_label(get_string('reporttype'), ['class' => 'accesshide']); - $select->class .= " mb-3"; - echo $OUTPUT->render($select); - } + $select = new url_select($menuarray, $activeurl, null, 'choosecoursereport'); + $select->set_label(get_string('reporttype'), ['class' => 'accesshide']); + $select->class .= " mb-3"; + echo $OUTPUT->render($select); } } diff --git a/lib/pagelib.php b/lib/pagelib.php index eb7a00117f0..98801ad2237 100644 --- a/lib/pagelib.php +++ b/lib/pagelib.php @@ -408,6 +408,11 @@ class moodle_page { */ protected $_activityheader; + /** + * @var bool The value of displaying the navigation overflow. + */ + protected $_navigationoverflow = true; + /** * Force the settings menu to be displayed on this page. This will only force the * settings menu on an activity / resource page that is being displayed on a theme that @@ -2258,4 +2263,23 @@ class moodle_page { public function get_primary_activate_tab(): ?string { return $this->_activenodeprimary; } + + /** + * Sets the navigation overflow state. This allows developers to turn off the overflow menu if they perhaps are using + * some other navigation to show settings. + * + * @param bool $state The state of whether to show the navigation overflow. + */ + public function set_navigation_overflow_state(bool $state): void { + $this->_navigationoverflow = $state; + } + + /** + * Gets the navigation overflow state. + * + * @return bool The navigation overflow state. + */ + public function get_navigation_overflow_state(): bool { + return $this->_navigationoverflow; + } } diff --git a/lib/tests/navigation/views/secondary_test.php b/lib/tests/navigation/views/secondary_test.php index a2d5d34288a..7ce4d1ede78 100644 --- a/lib/tests/navigation/views/secondary_test.php +++ b/lib/tests/navigation/views/secondary_test.php @@ -514,9 +514,7 @@ class secondary_test extends \advanced_testcase { $secondary = new secondary($PAGE); $secondary->add_node($this->generate_node_tree_construct($structure, 'primarynode')); $selectednode = $secondary->find($selected, null); - $method = new ReflectionMethod('core\navigation\views\secondary', 'get_menu_array'); - $method->setAccessible(true); - $response = $method->invoke($secondary, $selectednode); + $response = \core\navigation\views\secondary::create_menu_element([$selectednode]); $this->assertSame($expected, $response); } @@ -544,7 +542,7 @@ class secondary_test extends \advanced_testcase { "Fetch information from a node with children" => [ 'child2', [ - 'https://www.example.com/moodle/test.php' => 'child2', + 'https://www.example.com/moodle/test.php' => 'child2.3', 'https://www.example.com/moodle/view/course.php?child=2' => 'child2.1', 'https://www.example.com/moodle/view/admin.php?child=2' => 'child2.2' ], @@ -557,22 +555,18 @@ class secondary_test extends \advanced_testcase { 'parentnode1', [ [ + 'parentnode1' => [ + 'https://www.example.com/moodle/my' => 'child1' + ], 'child2' => [ 'https://www.example.com/moodle/test.php' => 'child2', 'https://www.example.com/moodle/view/course.php?child=2' => 'child2.1', 'https://www.example.com/moodle/view/admin.php?child=2' => 'child2.2', - ] - ], - [ + ], 'child3' => [ 'https://www.example.com/moodle/view/course.php?child=3' => 'child3.1', 'https://www.example.com/moodle/view/admin.php?child=3' => 'child3.2' ] - ], - [ - 'parentnode1' => [ - 'https://www.example.com/moodle/my' => 'child1' - ] ] ], ], @@ -657,78 +651,6 @@ class secondary_test extends \advanced_testcase { ]; } - /** - * Test for get_additional_child_nodes - * - * @param string $selectedkey - * @param array $expected - * @dataProvider test_get_additional_child_nodes_provider - */ - public function test_get_additional_child_nodes(string $selectedkey, array $expected) { - global $PAGE; - $structure = [ - 'parentnode1' => [ - 'child1' => '/my', - 'child2' => [ - 'action' => '/test.php', - 'children' => [ - 'child2.1' => '/view/course.php?child=2', - 'child2.2' => '/view/admin.php?child=2', - ] - ], - 'child3' => [ - 'child3.1' => '/view/course.php?child=3', - 'child3.2' => '/view/admin.php?child=3', - ] - ], - 'parentnode2' => "/view/module.php" - ]; - - $secondary = new secondary($PAGE); - $nodes = $this->generate_node_tree_construct($structure, 'primarynode'); - $selectednode = $nodes->find($selectedkey, null); - $method = new ReflectionMethod('core\navigation\views\secondary', 'get_additional_child_nodes'); - $method->setAccessible(true); - $response = $method->invoke($secondary, $selectednode); - - $this->assertSame($expected, $response); - } - - /** - * Provider for test_get_additional_child_nodes - * - * @return array[] - */ - public function test_get_additional_child_nodes_provider(): array { - return [ - "Get nodes with deep nested children" => [ - "parentnode1", - [ - 'https://www.example.com/moodle/my' => 'child1', - 'https://www.example.com/moodle/test.php' => 'child2', - 'https://www.example.com/moodle/view/course.php?child=2' => 'child2.1', - 'https://www.example.com/moodle/view/admin.php?child=2' => 'child2.2', - 'https://www.example.com/moodle/view/course.php?child=3' => 'child3.1', - 'https://www.example.com/moodle/view/admin.php?child=3' => 'child3.2', - ] - ], - "Get children from parent without action " => [ - "child3", - [ - 'https://www.example.com/moodle/view/course.php?child=3' => 'child3.1', - 'https://www.example.com/moodle/view/admin.php?child=3' => 'child3.2' - ] - ], - "Get children from parent with action " => [ - "child2", - [ - 'https://www.example.com/moodle/view/course.php?child=2' => 'child2.1', - 'https://www.example.com/moodle/view/admin.php?child=2' => 'child2.2' - ] - ], - ]; - } - /** * Test the get_overflow_menu_data function * diff --git a/mod/data/lib.php b/mod/data/lib.php index 34ba3d45d13..5364e0d136d 100644 --- a/mod/data/lib.php +++ b/mod/data/lib.php @@ -3633,14 +3633,8 @@ function data_extend_settings_navigation(settings_navigation $settings, navigati $datanode->add(get_string('fields', 'data'), new moodle_url('/mod/data/field.php', array('d' => $data->id))); - $templates = $datanode->add(get_string('templates', 'data'), + $datanode->add(get_string('templates', 'data'), new moodle_url('/mod/data/templates.php', array('d' => $data->id))); - - $templatelist = array ('listtemplate', 'singletemplate', 'asearchtemplate', 'addtemplate', 'rsstemplate', 'csstemplate', 'jstemplate'); - foreach ($templatelist as $template) { - $templates->add(get_string($template, 'data'), new moodle_url('/mod/data/templates.php', array('d'=>$data->id,'mode'=>$template))); - } - $datanode->add(get_string('presets', 'data'), new moodle_url('/mod/data/preset.php', array('d' => $data->id))); } diff --git a/mod/quiz/classes/output/resultsaction.php b/mod/quiz/classes/output/resultsaction.php deleted file mode 100644 index 02e330270cb..00000000000 --- a/mod/quiz/classes/output/resultsaction.php +++ /dev/null @@ -1,73 +0,0 @@ -. - -namespace mod_quiz\output; - -use templatable; -use renderable; -use renderer_base; -use moodle_url; -use url_select; - -/** - * Render results action - * - * @package mod_quiz - * @copyright 2021 Sujith Haridasan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class resultsaction implements templatable, renderable { - /** @var int */ - private $id; - - /** - * resultsaction constructor. - * - * @param int $id The course module id. - */ - public function __construct(int $id) { - $this->id = $id; - } - - /** - * Provide data for the template - * - * @param renderer_base $output renderer_base object. - * @return array data for template. - */ - public function export_for_template(renderer_base $output): array { - global $PAGE; - - $gradeslink = new moodle_url('/mod/quiz/report.php', ['id' => $this->id, 'mode' => 'overview']); - $responseslink = new moodle_url('/mod/quiz/report.php', ['id' => $this->id, 'mode' => 'responses']); - $statisticslink = new moodle_url('/mod/quiz/report.php', ['id' => $this->id, 'mode' => 'statistics']); - $manualgrading = new moodle_url('/mod/quiz/report.php', ['id' => $this->id, 'mode' => 'grading']); - - $menu = [ - $gradeslink->out(false) => get_string('grades', 'grades'), - $responseslink->out(false) => get_string('responses', 'quiz_responses'), - $statisticslink->out(false) => get_string('statistics', 'quiz_statistics'), - $manualgrading->out(false) => get_string('grading', 'quiz_grading') - ]; - - $urlselect = new url_select($menu, $PAGE->url->out(false), null, 'quizresults'); - - $data = [ - 'resultaction' => $urlselect->export_for_template($output) - ]; - return $data; - } -} diff --git a/mod/quiz/renderer.php b/mod/quiz/renderer.php index dcf2126abb7..2e5a41c76db 100644 --- a/mod/quiz/renderer.php +++ b/mod/quiz/renderer.php @@ -1398,16 +1398,6 @@ class mod_quiz_renderer extends plugin_renderer_base { return $this->render_from_template('mod_quiz/quiz_edit_action', $overwriteedit->export_for_template($this)); } - /** - * Get rendered HTML for the action area of the results page. - * - * @param \mod_quiz\output\resultsaction $resultsaction resultsaction object. - * @return string rendered HTML string from the template. - */ - public function get_results_action(\mod_quiz\output\resultsaction $resultsaction): string { - return $this->render_from_template('mod_quiz/quiz_results_action', $resultsaction->export_for_template($this)); - } - /** * Get rendered HTML for the action area of the overrides page. * diff --git a/mod/quiz/report/default.php b/mod/quiz/report/default.php index 6b45bfdd08e..03725fbd31f 100644 --- a/mod/quiz/report/default.php +++ b/mod/quiz/report/default.php @@ -71,9 +71,6 @@ abstract class quiz_default_report { if (!$PAGE->has_secondary_navigation()) { echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context))); } - $resultsaction = new \mod_quiz\output\resultsaction($cm->id); - $renderer = $PAGE->get_renderer('mod_quiz'); - echo $renderer->get_results_action($resultsaction); if (!empty($CFG->enableplagiarism)) { require_once($CFG->libdir . '/plagiarismlib.php'); echo plagiarism_update_status($course, $cm); diff --git a/mod/quiz/templates/quiz_results_action.mustache b/mod/quiz/templates/quiz_results_action.mustache deleted file mode 100644 index 8caa96ff6b4..00000000000 --- a/mod/quiz/templates/quiz_results_action.mustache +++ /dev/null @@ -1,58 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template mod_quiz/quiz_results_action - Actions bar at the top of the report page UI. - Classes required for JS: - * none - Data attributes required for JS: - * none - Context variables required for this template: - * see mod/quiz/classes/output/resultsaction.php - Example context (json): - { - "resultaction": { - "id": "url_select_test", - "options": [{ - "name": "Grades", - "value": "/mod/quiz/report.php?id=4&mode=overview" - }, - { - "name": "Responses", - "value": "/mod/quiz/report.php?id=4&mode=responses" - }, - { - "name": "Statistics", - "value": "/mod/quiz/report.php?id=4&mode=statistics" - }, - { - "name": "Manual grading", - "value": "/mod/quiz/report.php?id=4&mode=grading" - } - ] - } - } -}} -
-
-
- {{#resultaction}} - {{>core/url_select}} - {{/resultaction}} -
-
-
diff --git a/question/classes/output/qbank_actionbar.php b/question/classes/output/qbank_actionbar.php index 7933b562fdb..58646b4c9ac 100644 --- a/question/classes/output/qbank_actionbar.php +++ b/question/classes/output/qbank_actionbar.php @@ -65,10 +65,39 @@ class qbank_actionbar implements templatable, renderable { } $menu[$importlink->out(false)] = get_string('import', 'question'); $menu[$exportlink->out(false)] = get_string('export', 'question'); + $additional = $this->get_additional_menu_elements(); + $menu += $additional ?: []; $urlselect = new url_select($menu, $this->currenturl, null, 'questionbankaction'); $urlselect->set_label('questionbankactionselect', ['class' => 'accesshide']); return ['questionbankselect' => $urlselect->export_for_template($output)]; } + + /** + * Gets the additional third party navigation nodes. + * + * @return array|null The additional menu elements. + */ + protected function get_additional_menu_elements(): ?array { + global $PAGE; + $qbnode = $PAGE->settingsnav->find('questionbank', \navigation_node::TYPE_CONTAINER); + $othernodes = []; + foreach ($qbnode->children as $key => $value) { + if (array_search($value->key, $this->expected_nodes()) === false) { + $othernodes[] = $value; + } + } + $result = \core\navigation\views\secondary::create_menu_element($othernodes, true); + return $result; + } + + /** + * Returns a list of expected child navigation nodes for 'questionbank'. + * + * @return array The expected nodes + */ + protected function expected_nodes(): array { + return ['questions', 'categories', 'import', 'export']; + } }