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}}
+
+ {{/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'];
+ }
}