From c1a2df7f640971e65f22aa1a7b8d2dd597ef7601 Mon Sep 17 00:00:00 2001 From: Sujith Haridasan Date: Wed, 8 Sep 2021 09:04:19 +0530 Subject: [PATCH] MDL-72396 core: Allow setting of active tab Allow easy setting of active tab for the navigation views. --- admin/search.php | 1 + course/index.php | 3 ++ course/management.php | 1 + lib/classes/navigation/views/primary.php | 58 +++++++++++++++++++++++- lib/classes/navigation/views/view.php | 47 +++++++++++-------- lib/pagelib.php | 46 +++++++++++++++++++ my/index.php | 2 + 7 files changed, 139 insertions(+), 19 deletions(-) diff --git a/admin/search.php b/admin/search.php index 648822e60f1..e3c1bb15c7a 100644 --- a/admin/search.php +++ b/admin/search.php @@ -47,6 +47,7 @@ if ($data = data_submitted() and confirm_sesskey() and isset($data->action) and } $PAGE->has_secondary_navigation_setter(false); +$PAGE->set_primary_active_tab('siteadminnode'); // and finally, if we get here, then there are matching settings and we have to print a form // to modify them diff --git a/course/index.php b/course/index.php index 28f66912aa3..6688b5471ff 100644 --- a/course/index.php +++ b/course/index.php @@ -65,6 +65,9 @@ $courserenderer = $PAGE->get_renderer('core', 'course'); $PAGE->set_heading($heading); $content = $courserenderer->course_category($categoryid); +$PAGE->set_primary_active_tab('courses'); +$PAGE->set_secondary_active_tab('categorymain'); + echo $OUTPUT->header(); echo $OUTPUT->skip_link_target(); echo $content; diff --git a/course/management.php b/course/management.php index 94e02aaa951..7bccc1cf7ec 100644 --- a/course/management.php +++ b/course/management.php @@ -108,6 +108,7 @@ $PAGE->set_pagelayout('admin'); $PAGE->set_title($strmanagement); $PAGE->set_heading($pageheading); $PAGE->requires->js_call_amd('core_course/copy_modal', 'init', array($context->id)); +$PAGE->set_secondary_active_tab('managecategory'); // This is a system level page that operates on other contexts. require_login(); diff --git a/lib/classes/navigation/views/primary.php b/lib/classes/navigation/views/primary.php index c30b6780da1..a3e06872d32 100644 --- a/lib/classes/navigation/views/primary.php +++ b/lib/classes/navigation/views/primary.php @@ -16,6 +16,8 @@ namespace core\navigation\views; +use navigation_node; + /** * Class primary. * @@ -63,7 +65,61 @@ class primary extends view { } // Search and set the active node. - $this->search_for_active_node(); + $this->search_and_set_active_node($this); $this->initialised = true; } + + /** + * Searches all children for the matching active node + * + * This method recursively traverse through the node tree to + * find the node to activate/highlight: + * 1. If the user had set primary node key to highlight, it + * tries to match this key with the node(s). Hence it would + * travel all the nodes. + * 2. If no primary key is provided by the dev, then it would + * check for the active node set in the tree. + * + * @param navigation_node $node + * @param array $actionnodes navigation nodes array to set active and inactive. + * @return navigation_node|null + */ + private function search_and_set_active_node(navigation_node $node, + array &$actionnodes = []): ?navigation_node { + global $PAGE; + + $activekey = $PAGE->get_primary_activate_tab(); + if ($activekey) { + if ($node->key && ($activekey === $node->key)) { + return $node; + } + } else if ($node->check_if_active(URL_MATCH_BASE)) { + return $node; + } + + foreach ($node->children as $child) { + $outcome = $this->search_and_set_active_node($child, $actionnodes); + if ($outcome !== null) { + $outcome->make_active(); + $actionnodes['active'] = $outcome; + if ($activekey === null) { + return $actionnodes['active']; + } + } else { + // If the child is active then make it inactive. + if ($child->isactive) { + $actionnodes['set_inactive'][] = $child; + } + } + } + + // If we have successfully found an active node then reset any other nodes to inactive. + if (isset($actionnodes['set_inactive']) && isset($actionnodes['active'])) { + foreach ($actionnodes['set_inactive'] as $inactivenode) { + $inactivenode->make_inactive(); + } + $actionnodes['set_inactive'] = []; + } + return ($actionnodes['active'] ?? null); + } } diff --git a/lib/classes/navigation/views/view.php b/lib/classes/navigation/views/view.php index 428cce91fa3..13a4fc68040 100644 --- a/lib/classes/navigation/views/view.php +++ b/lib/classes/navigation/views/view.php @@ -113,31 +113,42 @@ abstract class view extends navigation_node { * @param int $strictness How stict to be with the scan for the active node. * @return navigation_node|null */ - protected function active_node_scan(navigation_node $node, int $strictness = URL_MATCH_EXACT): ?navigation_node { + protected function active_node_scan(navigation_node $node, + int $strictness = URL_MATCH_EXACT): ?navigation_node { - if ($node->check_if_active($strictness)) { + $result = null; + $activekey = $this->page->get_secondary_active_tab(); + if ($activekey) { + if ($node->key && $activekey === $node->key) { + return $node; + } + } else if ($node->check_if_active($strictness)) { return $node; // No need to continue, exit function. } - if ($node->children->count() > 0) { - foreach ($node->children as $child) { - if ($this->active_node_scan($child, $strictness)) { - // If node is one of the new views then set the active node to the child. - if (!$node instanceof view) { - $node->make_active(); - $child->make_inactive(); - } else { - $child->make_active(); - $this->activenode = $child; - } - - return $node; // We have found the active node, set the parent status, no need to continue. - } else { - // Make sure to reset the active state. + foreach ($node->children as $child) { + if ($this->active_node_scan($child, $strictness)) { + // If node is one of the new views then set the active node to the child. + if (!$node instanceof view) { + $node->make_active(); $child->make_inactive(); + $result = $node; + } else { + $child->make_active(); + $this->activenode = $child; + $result = $child; } + + // If the secondary active tab not set then just return the result (fallback). + if ($activekey === null) { + return $result; + } + } else { + // Make sure to reset the active state. + $child->make_inactive(); } } - return null; + + return $result; } } diff --git a/lib/pagelib.php b/lib/pagelib.php index 02000fdb6a9..5b8e6a3e833 100644 --- a/lib/pagelib.php +++ b/lib/pagelib.php @@ -393,6 +393,16 @@ class moodle_page { */ protected $_hassecondarynavigation = true; + /** + * @var string the key of the secondary node to be activated. + */ + protected $_activekeysecondary = null; + + /** + * @var string the key of the primary node to be activated. + */ + protected $_activenodeprimary = null; + /** * 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 @@ -2189,4 +2199,40 @@ class moodle_page { public function has_secondary_navigation() : bool { return $this->_hassecondarynavigation; } + + /** + * Set the key of the secondary nav node to be activated. + * + * @param string $navkey the key of the secondary nav node to be activated. + */ + public function set_secondary_active_tab(string $navkey) : void { + $this->_activekeysecondary = $navkey; + } + + /** + * The key of secondary nav node to activate. + * + * @return string|null get the key of the secondary node to activate. + */ + public function get_secondary_active_tab(): ?string { + return $this->_activekeysecondary; + } + + /** + * Set the key of the primary nav node to be activated. + * + * @param string $navkey + */ + public function set_primary_active_tab(string $navkey): void { + $this->_activenodeprimary = $navkey; + } + + /** + * The key of the primary nav node to activate. + * + * @return string|null get the key of the primary nav node to activate. + */ + public function get_primary_activate_tab(): ?string { + return $this->_activenodeprimary; + } } diff --git a/my/index.php b/my/index.php index 331954b73c9..83a5c249554 100644 --- a/my/index.php +++ b/my/index.php @@ -90,6 +90,8 @@ $PAGE->set_subpage($currentpage->id); $PAGE->set_title($pagetitle); $PAGE->set_heading($header); +$PAGE->set_primary_active_tab('myhome'); + if (!isguestuser()) { // Skip default home page for guests if (get_home_page() != HOMEPAGE_MY) { if (optional_param('setdefaulthome', false, PARAM_BOOL)) {