From dbc014b2a6798349983a2da9523488244b44f279 Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Fri, 19 Feb 2021 10:19:04 +0800 Subject: [PATCH] MDL-70196 theme_boost: New navbar renderer for navbar alterations - Part of: MDL-69588 --- theme/boost/classes/boostnavbar.php | 179 +++++++++++++++++++ theme/boost/classes/output/core_renderer.php | 9 + theme/boost/version.php | 2 +- 3 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 theme/boost/classes/boostnavbar.php diff --git a/theme/boost/classes/boostnavbar.php b/theme/boost/classes/boostnavbar.php new file mode 100644 index 00000000000..19507ba8eb8 --- /dev/null +++ b/theme/boost/classes/boostnavbar.php @@ -0,0 +1,179 @@ +. + +namespace theme_boost; + +/** + * Creates a navbar for boost that allows easy control of the navbar items. + * + * @package theme_boost + * @copyright 2021 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class boostnavbar implements \renderable { + + /** @var array The individual items of the navbar. */ + protected $items = []; + + /** + * Takes a navbar object and picks the necessary parts for display. + * + * @param \navbar $navbar The navigation bar. + */ + public function __construct(\navbar $navbar) { + foreach ($navbar->get_items() as $item) { + $this->items[] = $item; + } + $this->prepare_nodes_for_boost(); + } + + /** + * Prepares the navigation nodes for use with boost. + */ + protected function prepare_nodes_for_boost(): void { + // Don't display the navbar if we are in the site navigation. + if (!is_null($this->get_item('root'))) { + $this->clear_items(); + return; + } + + $this->remove('myhome'); // Dashboard. + $this->remove('home'); + + // Set the designated one path for courses. + $mycoursesnode = $this->get_item('mycourses'); + if (!is_null($mycoursesnode)) { + $url = new \moodle_url('/mycourses/'); + $mycoursesnode->action = $url; + $mycoursesnode->text = get_string('courses'); + } + + $this->remove_no_link_items(); + + // Don't display the navbar if there is only one item. Apparently this is bad UX design. + if ($this->item_count() <= 1) { + $this->clear_items(); + return; + } + + // Make sure that the last item is not a link. Not sure if this is always a good idea. + $this->remove_last_item_action(); + } + + /** + * Get all the boostnavbaritem elements. + * + * @return boostnavbaritem[] Boost navbar items. + */ + public function get_items(): array { + return $this->items; + } + + /** + * Removes all navigation items out of this boost navbar + */ + protected function clear_items(): void { + $this->items = []; + } + + /** + * Retrieve a single navbar item. + * + * @param string|int $key The identifier of the navbar item to return. + * @return \breadcrumb_navigation_node|null The navbar item. + */ + protected function get_item($key): ?\breadcrumb_navigation_node { + foreach ($this->items as $item) { + if ($key === $item->key) { + return $item; + } + } + return null; + } + + /** + * Counts all of the navbar items. + * + * @return int How many navbar items there are. + */ + protected function item_count(): int { + return count($this->items); + } + + /** + * Remove a boostnavbaritem from the boost navbar. + * + * @param string|int $itemkey An identifier for the boostnavbaritem + */ + protected function remove($itemkey): void { + + $itemfound = false; + foreach ($this->items as $key => $item) { + if ($item->key === $itemkey) { + unset($this->items[$key]); + $itemfound = true; + break; + } + } + if (!$itemfound) { + return; + } + + $itemcount = $this->item_count(); + if ($itemcount <= 0) { + return; + } + + $this->items = array_values($this->items); + // Set the last item to last item if it is not. + $lastitem = $this->items[$itemcount - 1]; + if (!$lastitem->is_last()) { + $lastitem->set_last(true); + } + } + + /** + * Removes the action from the last item of the boostnavbaritem. + */ + protected function remove_last_item_action(): void { + $item = end($this->items); + $item->action = null; + reset($this->items); + } + + /** + * Returns the second last navbar item. This is for use in the mobile view where we are showing just the second + * last item in the breadcrumb navbar. + * + * @return breakcrumb_navigation_node|null The second last navigation node. + */ + public function get_penultimate_item(): ?\breadcrumb_navigation_node { + $number = $this->item_count() - 2; + return ($number >= 0) ? $this->items[$number] : null; + } + + /** + * Remove items that are categories or have no actions associated with them. + */ + protected function remove_no_link_items(): void { + foreach ($this->items as $key => $value) { + if (!$value->has_action() || $value->type == \navigation_node::TYPE_SECTION) { + unset($this->items[$key]); + } + } + $this->items = array_values($this->items); + } +} diff --git a/theme/boost/classes/output/core_renderer.php b/theme/boost/classes/output/core_renderer.php index 05c2ef8c68e..480aadabcd8 100644 --- a/theme/boost/classes/output/core_renderer.php +++ b/theme/boost/classes/output/core_renderer.php @@ -42,4 +42,13 @@ class core_renderer extends \core_renderer { return $this->render_single_button($button); } + /** + * Renders the "breadcrumb" for all pages in boost. + * + * @return string the HTML for the navbar. + */ + public function navbar(): string { + $newnav = new \theme_boost\boostnavbar($this->page->navbar); + return $this->render_from_template('core/navbar', $newnav); + } } diff --git a/theme/boost/version.php b/theme/boost/version.php index 4284349dd4c..d3acb13b9b1 100644 --- a/theme/boost/version.php +++ b/theme/boost/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021052500; +$plugin->version = 2021052503; $plugin->requires = 2021052500; $plugin->component = 'theme_boost';