mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 12:32:08 +02:00
MDL-70198 core_navigation: Implement secondary nav and curate nodes
Implement the new secondary nav and curate the nodes from flatnav and settingsnav
This commit is contained in:
parent
23bb8a21c1
commit
683e7b2aaf
@ -460,7 +460,7 @@ class grading_manager {
|
||||
$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);
|
||||
$this->get_management_url(), settings_navigation::TYPE_CUSTOM, null, 'advgrading');
|
||||
if ($method) {
|
||||
$controller = $this->get_controller($method);
|
||||
$controller->extend_settings_navigation($settingsnav, $managementnode);
|
||||
@ -469,7 +469,7 @@ class grading_manager {
|
||||
} else {
|
||||
// make management screen node for each area
|
||||
$managementnode = $modulenode->add(get_string('gradingmanagement', 'core_grading'),
|
||||
null, settings_navigation::TYPE_CUSTOM);
|
||||
null, settings_navigation::TYPE_CUSTOM, null, 'advgrading');
|
||||
foreach ($areas as $areaname => $areatitle) {
|
||||
$this->set_area($areaname);
|
||||
$method = $this->get_active_method();
|
||||
|
@ -419,6 +419,7 @@ $string['courselistshortnames'] = 'Display extended course names';
|
||||
$string['courselistshortnames_desc'] = 'If enabled, course short names will be displayed in addition to full names in course lists. If required, extended course names may be customised by editing the \'courseextendednamedisplay\' language string using the language customisation feature.';
|
||||
$string['coursemgmt'] = 'Manage courses and categories';
|
||||
$string['courseoverview'] = 'Course overview';
|
||||
$string['coursepage'] = 'Course Page';
|
||||
$string['courserequestnotify'] = 'Course request notification';
|
||||
$string['courserequestnotifyemail'] = 'User {$a->user} requested a new course at {$a->link}';
|
||||
$string['courserequests'] = 'Course requests';
|
||||
|
249
lib/classes/navigation/views/secondary.php
Normal file
249
lib/classes/navigation/views/secondary.php
Normal file
@ -0,0 +1,249 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core\navigation\views;
|
||||
|
||||
use navigation_node;
|
||||
|
||||
/**
|
||||
* Class secondary_navigation_view.
|
||||
*
|
||||
* The secondary navigation view is a stripped down tweaked version of the
|
||||
* settings_navigation/navigation
|
||||
*
|
||||
* @package core
|
||||
* @category navigation
|
||||
* @copyright 2021 onwards Peter Dias
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class secondary extends view {
|
||||
/**
|
||||
* Defines the default structure for the secondary nav in a course context.
|
||||
*
|
||||
* In a course context, we are curating nodes from the settingsnav and navigation objects.
|
||||
* The following mapping construct specifies which object we are fetching it from, the type of the node, the key
|
||||
* and in what order we want the node - defined as per the mockups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_default_course_mapping(): array {
|
||||
$nodes = [];
|
||||
$nodes['settings'] = [
|
||||
self::TYPE_CONTAINER => [
|
||||
'coursereports' => 3,
|
||||
'questionbank' => 4,
|
||||
],
|
||||
self::TYPE_SETTING => [
|
||||
'editsettings' => 0,
|
||||
'gradebooksetup' => 2.1,
|
||||
'outcomes' => 2.2,
|
||||
'coursecompletion' => 6,
|
||||
],
|
||||
];
|
||||
$nodes['navigation'] = [
|
||||
self::TYPE_CONTAINER => [
|
||||
'participants' => 1,
|
||||
],
|
||||
self::TYPE_SETTING => [
|
||||
'grades' => 2,
|
||||
'badgesview' => 7,
|
||||
'competencies' => 8,
|
||||
],
|
||||
self::TYPE_CUSTOM => [
|
||||
'contentbank' => 5,
|
||||
],
|
||||
];
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the default structure for the secondary nav in a module context.
|
||||
*
|
||||
* In a module context, we are curating nodes from the settingsnav object.
|
||||
* The following mapping construct specifies the type of the node, the key
|
||||
* and in what order we want the node - defined as per the mockups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_default_module_mapping(): array {
|
||||
return [
|
||||
self::TYPE_SETTING => [
|
||||
'modedit' => 1,
|
||||
'roleoverride' => 3,
|
||||
'rolecheck' => 3.1,
|
||||
'logreport' => 4,
|
||||
"mod_{$this->page->activityname}_useroverrides" => 5, // Overrides are module specific.
|
||||
"mod_{$this->page->activityname}_groupoverrides" => 6,
|
||||
'roleassign' => 7,
|
||||
'filtermanage' => 8,
|
||||
'backup' => 9,
|
||||
'restore' => 10,
|
||||
'competencybreakdown' => 11,
|
||||
],
|
||||
self::TYPE_CUSTOM => [
|
||||
'advgrading' => 2,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the view based navigation based on the current context.
|
||||
*
|
||||
* As part of the initial restructure, the secondary nav is only considered for the following pages:
|
||||
* 1 - Site admin settings
|
||||
* 2 - Course page - Does not include front_page which has the same context.
|
||||
* 3 - Module page
|
||||
*/
|
||||
public function initialise(): void {
|
||||
global $SITE;
|
||||
|
||||
if (during_initial_install() || $this->initialised) {
|
||||
return;
|
||||
}
|
||||
$this->id = 'secondary_navigation';
|
||||
$context = $this->context;
|
||||
|
||||
switch ($context->contextlevel) {
|
||||
case CONTEXT_COURSE:
|
||||
if ($this->page->course->id != $SITE->id) {
|
||||
$this->load_course_navigation();
|
||||
}
|
||||
break;
|
||||
case CONTEXT_MODULE:
|
||||
$this->load_module_navigation();
|
||||
break;
|
||||
case CONTEXT_SYSTEM:
|
||||
$this->load_admin_navigation();
|
||||
break;
|
||||
}
|
||||
|
||||
// Search and set the active node.
|
||||
$this->scan_for_active_node($this);
|
||||
$this->initialised = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the course secondary navigation. Since we are sourcing all the info from existing objects that already do
|
||||
* the relevant checks, we don't do it again here.
|
||||
*/
|
||||
protected function load_course_navigation(): void {
|
||||
$course = $this->page->course;
|
||||
|
||||
// Initialise the main navigation and settings nav.
|
||||
// It is important that this is done before we try anything.
|
||||
$settingsnav = $this->page->settingsnav;
|
||||
$navigation = $this->page->navigation;
|
||||
|
||||
$url = new \moodle_url('/course/view.php', ['id' => $course->id, 'sesskey' => sesskey()]);
|
||||
$this->add(get_string('coursepage', 'admin'), $url, self::TYPE_COURSE, null, 'coursehome');
|
||||
|
||||
$nodes = $this->get_default_course_mapping();
|
||||
$nodesordered = $this->get_leaf_nodes($settingsnav, $nodes['settings']);
|
||||
$nodesordered += $this->get_leaf_nodes($navigation, $nodes['navigation']);
|
||||
$this->add_ordered_nodes($nodesordered);
|
||||
|
||||
// All additional nodes will be available under the 'Course admin' page.
|
||||
$text = get_string('courseadministration');
|
||||
$url = new \moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
|
||||
$this->add($text, $url, null, null, 'courseadmin', new \pix_icon('t/edit', $text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the module's secondary navigation. This is based on settings_nav and would include plugin nodes added via
|
||||
* '_extend_settings_navigation'.
|
||||
* It populates the tree based on the nav mockup
|
||||
*
|
||||
* If nodes change, we will have to explicitly call the callback again.
|
||||
*/
|
||||
protected function load_module_navigation(): void {
|
||||
$settingsnav = $this->page->settingsnav;
|
||||
$mainnode = $settingsnav->find('modulesettings', self::TYPE_SETTING);
|
||||
$nodes = $this->get_default_module_mapping();
|
||||
|
||||
if ($mainnode) {
|
||||
$this->add(get_string('module', 'course'), $this->page->url, null, null, 'modulepage');
|
||||
// Add the initial nodes.
|
||||
$nodesordered = $this->get_leaf_nodes($mainnode, $nodes);
|
||||
$this->add_ordered_nodes($nodesordered);
|
||||
|
||||
// We have finished inserting the initial structure.
|
||||
// Populate the menu with the rest of the nodes available.
|
||||
$this->load_remaining_nodes($mainnode, $nodes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the site admin navigation
|
||||
*/
|
||||
protected function load_admin_navigation(): void {
|
||||
$settingsnav = $this->page->settingsnav;
|
||||
$node = $settingsnav->find('root', self::TYPE_SITE_ADMIN);
|
||||
if ($node) {
|
||||
$siteadminnode = $this->add($node->text, "#link$node->key", null, null, 'siteadminnode');
|
||||
foreach ($node->children as $child) {
|
||||
if ($child->display && !$child->is_short_branch()) {
|
||||
$this->add_node($child);
|
||||
} else {
|
||||
$siteadminnode->add_node($child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the indexed nodes to the current view. The key should indicate it's position in the tree. Any sub nodes
|
||||
* needs to be numbered appropriately, e.g. 3.1 would make the identified node be listed under #3 node.
|
||||
*
|
||||
* @param array $nodes An array of navigation nodes to be added.
|
||||
*/
|
||||
protected function add_ordered_nodes(array $nodes): void {
|
||||
ksort($nodes);
|
||||
foreach ($nodes as $key => $node) {
|
||||
// If the key is a string then we are assuming this is a nested element.
|
||||
if (is_string($key)) {
|
||||
$parentnode = $nodes[floor($key)] ?? null;
|
||||
if ($parentnode) {
|
||||
$parentnode->add_node($node);
|
||||
}
|
||||
} else {
|
||||
$this->add_node($node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the remaining nodes that need to be loaded into secondary based on the current context
|
||||
*
|
||||
* @param navigation_node $completenode The original node that we are sourcing information from
|
||||
* @param array $nodesmap The map used to populate secondary nav in the given context
|
||||
*/
|
||||
protected function load_remaining_nodes(navigation_node $completenode, array $nodesmap): void {
|
||||
$flattenednodes = [];
|
||||
foreach ($nodesmap as $nodecontainer) {
|
||||
$flattenednodes = array_merge(array_keys($nodecontainer), $flattenednodes);
|
||||
}
|
||||
|
||||
$populatedkeys = $this->get_children_key_list();
|
||||
$existingkeys = $completenode->get_children_key_list();
|
||||
$leftover = array_diff($existingkeys, $populatedkeys);
|
||||
foreach ($leftover as $key) {
|
||||
if (!in_array($key, $flattenednodes) && $leftovernode = $completenode->get($key)) {
|
||||
$this->add_node($leftovernode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4470,7 +4470,7 @@ class settings_navigation extends navigation_node {
|
||||
if ($adminoptions->editcompletion) {
|
||||
// Add the course completion settings link
|
||||
$url = new moodle_url('/course/completion.php', array('id' => $course->id));
|
||||
$coursenode->add(get_string('coursecompletion', 'completion'), $url, self::TYPE_SETTING, null, null,
|
||||
$coursenode->add(get_string('coursecompletion', 'completion'), $url, self::TYPE_SETTING, null, 'coursecompletion',
|
||||
new pix_icon('i/settings', ''));
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use core\navigation\views\secondary;
|
||||
|
||||
/**
|
||||
* $PAGE is a central store of information about the current page we are
|
||||
@ -79,6 +80,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @property-read array $layout_options An arrays with options for the layout file.
|
||||
* @property-read array $legacythemeinuse True if the legacy browser theme is in use.
|
||||
* @property-read navbar $navbar The navbar object used to display the navbar
|
||||
* @property-read secondary $secondarynav The secondary navigation object
|
||||
* used to display the secondarynav in boost
|
||||
* @property-read global_navigation $navigation The navigation structure for this page.
|
||||
* @property-read xhtml_container_stack $opencontainers Tracks XHTML tags on this page that have been opened but not closed.
|
||||
* mainly for internal use by the rendering code.
|
||||
@ -294,6 +297,12 @@ class moodle_page {
|
||||
*/
|
||||
protected $_flatnav = null;
|
||||
|
||||
/**
|
||||
* @var secondary Contains the nav nodes that will appear
|
||||
* in the secondary navigation.
|
||||
*/
|
||||
protected $_secondarynav = null;
|
||||
|
||||
/**
|
||||
* @var navbar Contains the navbar structure.
|
||||
*/
|
||||
@ -783,6 +792,18 @@ class moodle_page {
|
||||
return $this->_flatnav;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secondary navigation object
|
||||
* @return secondary
|
||||
*/
|
||||
protected function magic_get_secondarynav() {
|
||||
if ($this->_secondarynav === null) {
|
||||
$this->_secondarynav = new secondary($this);
|
||||
$this->_secondarynav->initialise();
|
||||
}
|
||||
return $this->_secondarynav;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns request IP address.
|
||||
*
|
||||
|
@ -33,6 +33,10 @@ information provided here is intended especially for developers.
|
||||
* New DML driver method `$DB->sql_group_concat` for performing group concatenation of a field within a SQL query
|
||||
* Added new class, AMD modules and WS that allow displaying forms in modal popups or load and submit in AJAX requests.
|
||||
See https://docs.moodle.org/dev/Modal_and_AJAX_forms for more details.
|
||||
* New navigation classes to mimic the new navigation project. The existing navigation callbacks are still available and
|
||||
will be called. The following behaviour will be the new standard for nodes added via callbacks:
|
||||
- Module nodes added will be appended to the end and will appear within the hamburger option.
|
||||
- Course nodes added will also be appended and appear within the 'More' option/page.
|
||||
|
||||
=== 3.10 ===
|
||||
* PHPUnit has been upgraded to 8.5. That comes with a few changes:
|
||||
|
@ -60,6 +60,6 @@ function report_competency_extend_navigation_module($navigation, $cm) {
|
||||
context_course::instance($cm->course))) {
|
||||
$url = new moodle_url('/report/competency/index.php', array('id' => $cm->course, 'mod' => $cm->id));
|
||||
$name = get_string('pluginname', 'report_competency');
|
||||
$navigation->add($name, $url, navigation_node::TYPE_SETTING, null, null);
|
||||
$navigation->add($name, $url, navigation_node::TYPE_SETTING, null, 'competencybreakdown');
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user