MDL-82159 core: Migrate navigation classes to new dirs

This commit is contained in:
Andrew Nicols
2025-09-01 15:09:23 +02:00
parent a1a8af4ca0
commit afc3ef7bb4
14 changed files with 6523 additions and 6322 deletions
@@ -0,0 +1,66 @@
<?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/>.
/**
* Subclass of navigation_node allowing different rendering for the breadcrumbs
* in particular adding extra metadata for search engine robots to leverage.
*
* @package core
* @category navigation
* @copyright 2015 Brendan Heywood
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class breadcrumb_navigation_node extends navigation_node {
/** @var $last boolean A flag indicating this is the last item in the list of breadcrumbs. */
private $last = false;
/**
* A proxy constructor
*
* @param mixed $navnode A navigation_node or an array
*/
public function __construct($navnode) {
if (is_array($navnode)) {
parent::__construct($navnode);
} else if ($navnode instanceof navigation_node) {
// Just clone everything.
$objvalues = get_object_vars($navnode);
foreach ($objvalues as $key => $value) {
$this->$key = $value;
}
} else {
throw new coding_exception('Not a valid breadcrumb_navigation_node');
}
}
/**
* Getter for "last"
* @return boolean
*/
public function is_last() {
return $this->last;
}
/**
* Setter for "last"
* @param $val boolean
*/
public function set_last($val) {
$this->last = $val;
}
}
@@ -0,0 +1,156 @@
<?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/>.
/**
* Class used to generate a collection of navigation nodes most closely related
* to the current page.
*
* @deprecated since Moodle 4.0 - do not use any more. Leverage secondary/tertiary navigation concepts
* @package core
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class flat_navigation extends navigation_node_collection {
/** @var moodle_page the moodle page that the navigation belongs to */
protected $page;
/**
* Constructor.
*
* @param moodle_page $page
*/
public function __construct(moodle_page &$page) {
if (during_initial_install()) {
return;
}
debugging("Flat navigation has been deprecated in favour of primary/secondary navigation concepts");
$this->page = $page;
}
/**
* Build the list of navigation nodes based on the current navigation and settings trees.
*
*/
public function initialise() {
global $PAGE, $USER, $OUTPUT, $CFG;
if (during_initial_install()) {
return;
}
$current = false;
$course = $PAGE->course;
$this->page->navigation->initialise();
// First walk the nav tree looking for "flat_navigation" nodes.
if ($course->id > 1) {
// It's a real course.
$url = new moodle_url('/course/view.php', array('id' => $course->id));
$coursecontext = context_course::instance($course->id, MUST_EXIST);
$displaycontext = \context_helper::get_navigation_filter_context($coursecontext);
// This is the name that will be shown for the course.
$coursename = empty($CFG->navshowfullcoursenames) ?
format_string($course->shortname, true, ['context' => $displaycontext]) :
format_string($course->fullname, true, ['context' => $displaycontext]);
$flat = new flat_navigation_node(navigation_node::create($coursename, $url), 0);
$flat->set_collectionlabel($coursename);
$flat->key = 'coursehome';
$flat->icon = new pix_icon('i/course', '');
$courseformat = course_get_format($course);
$coursenode = $PAGE->navigation->find_active_node();
$targettype = navigation_node::TYPE_COURSE;
// Single activity format has no course node - the course node is swapped for the activity node.
if (!$courseformat->has_view_page()) {
$targettype = navigation_node::TYPE_ACTIVITY;
}
while (!empty($coursenode) && ($coursenode->type != $targettype)) {
$coursenode = $coursenode->parent;
}
// There is one very strange page in mod/feedback/view.php which thinks it is both site and course
// context at the same time. That page is broken but we need to handle it (hence the SITEID).
if ($coursenode && $coursenode->key != SITEID) {
$this->add($flat);
foreach ($coursenode->children as $child) {
if ($child->action) {
$flat = new flat_navigation_node($child, 0);
$this->add($flat);
}
}
}
$this->page->navigation->build_flat_navigation_list($this, true, get_string('site'));
} else {
$this->page->navigation->build_flat_navigation_list($this, false, get_string('site'));
}
$admin = $PAGE->settingsnav->find('siteadministration', navigation_node::TYPE_SITE_ADMIN);
if (!$admin) {
// Try again - crazy nav tree!
$admin = $PAGE->settingsnav->find('root', navigation_node::TYPE_SITE_ADMIN);
}
if ($admin) {
$flat = new flat_navigation_node($admin, 0);
$flat->set_showdivider(true, get_string('sitesettings'));
$flat->key = 'sitesettings';
$flat->icon = new pix_icon('t/preferences', '');
$this->add($flat);
}
// Add-a-block in editing mode.
if (isset($this->page->theme->addblockposition) &&
$this->page->theme->addblockposition == BLOCK_ADDBLOCK_POSITION_FLATNAV &&
$PAGE->user_is_editing() && $PAGE->user_can_edit_blocks()) {
$url = new moodle_url($PAGE->url, ['bui_addblock' => '', 'sesskey' => sesskey()]);
$addablock = navigation_node::create(get_string('addblock'), $url);
$flat = new flat_navigation_node($addablock, 0);
$flat->set_showdivider(true, get_string('blocksaddedit'));
$flat->key = 'addblock';
$flat->icon = new pix_icon('i/addblock', '');
$this->add($flat);
$addblockurl = "?{$url->get_query_string(false)}";
$PAGE->requires->js_call_amd('core_block/add_modal', 'init',
[$addblockurl, $this->page->get_edited_page_hash()]);
}
}
/**
* Override the parent so we can set a label for this collection if it has not been set yet.
*
* @param navigation_node $node Node to add
* @param string $beforekey If specified, adds before a node with this key,
* otherwise adds at end
* @return navigation_node Added node
*/
public function add(navigation_node $node, $beforekey=null) {
$result = parent::add($node, $beforekey);
// Extend the parent to get a name for the collection of nodes if required.
if (empty($this->collectionlabel)) {
if ($node instanceof flat_navigation_node) {
$this->set_collectionlabel($node->get_collectionlabel());
}
}
return $result;
}
}
@@ -0,0 +1,151 @@
<?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/>.
/**
* Subclass of navigation_node allowing different rendering for the flat navigation
* in particular allowing dividers and indents.
*
* @deprecated since Moodle 4.0 - do not use any more. Leverage secondary/tertiary navigation concepts
* @package core
* @category navigation
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class flat_navigation_node extends navigation_node {
/** @var $indent integer The indent level */
private $indent = 0;
/** @var $showdivider bool Show a divider before this element */
private $showdivider = false;
/** @var $collectionlabel string Label for a group of nodes */
private $collectionlabel = '';
/**
* A proxy constructor
*
* @param mixed $navnode A navigation_node or an array
*/
public function __construct($navnode, $indent) {
debugging("Flat nav has been deprecated in favour of primary/secondary navigation concepts");
if (is_array($navnode)) {
parent::__construct($navnode);
} else if ($navnode instanceof navigation_node) {
// Just clone everything.
$objvalues = get_object_vars($navnode);
foreach ($objvalues as $key => $value) {
$this->$key = $value;
}
} else {
throw new coding_exception('Not a valid flat_navigation_node');
}
$this->indent = $indent;
}
/**
* Setter, a label is required for a flat navigation node that shows a divider.
*
* @param string $label
*/
public function set_collectionlabel($label) {
$this->collectionlabel = $label;
}
/**
* Getter, get the label for this flat_navigation node, or it's parent if it doesn't have one.
*
* @return string
*/
public function get_collectionlabel() {
if (!empty($this->collectionlabel)) {
return $this->collectionlabel;
}
if ($this->parent && ($this->parent instanceof flat_navigation_node || $this->parent instanceof flat_navigation)) {
return $this->parent->get_collectionlabel();
}
debugging('Navigation region requires a label', DEBUG_DEVELOPER);
return '';
}
/**
* Does this node represent a course section link.
* @return boolean
*/
public function is_section() {
return $this->type == navigation_node::TYPE_SECTION;
}
/**
* In flat navigation - sections are active if we are looking at activities in the section.
* @return boolean
*/
public function isactive() {
global $PAGE;
if ($this->is_section()) {
$active = $PAGE->navigation->find_active_node();
if ($active) {
while ($active = $active->parent) {
if ($active->key == $this->key && $active->type == $this->type) {
return true;
}
}
}
}
return $this->isactive;
}
/**
* Getter for "showdivider"
* @return boolean
*/
public function showdivider() {
return $this->showdivider;
}
/**
* Setter for "showdivider"
* @param $val boolean
* @param $label string Label for the group of nodes
*/
public function set_showdivider($val, $label = '') {
$this->showdivider = $val;
if ($this->showdivider && empty($label)) {
debugging('Navigation region requires a label', DEBUG_DEVELOPER);
} else {
$this->set_collectionlabel($label);
}
}
/**
* Getter for "indent"
* @return boolean
*/
public function get_indent() {
return $this->indent;
}
/**
* Setter for "indent"
* @param $val boolean
*/
public function set_indent($val) {
$this->indent = $val;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,278 @@
<?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/>.
/**
* The global navigation class used especially for AJAX requests.
*
* The primary methods that are used in the global navigation class have been overriden
* to ensure that only the relevant branch is generated at the root of the tree.
* This can be done because AJAX is only used when the backwards structure for the
* requested branch exists.
* This has been done only because it shortens the amounts of information that is generated
* which of course will speed up the response time.. because no one likes laggy AJAX.
*
* @package core
* @category navigation
* @copyright 2009 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class global_navigation_for_ajax extends global_navigation {
/** @var int used for determining what type of navigation_node::TYPE_* is being used */
protected $branchtype;
/** @var int the instance id */
protected $instanceid;
/** @var array Holds an array of expandable nodes */
protected $expandable = array();
/**
* Constructs the navigation for use in an AJAX request
*
* @param moodle_page $page moodle_page object
* @param int $branchtype
* @param int $id
*/
public function __construct($page, $branchtype, $id) {
$this->page = $page;
$this->cache = new navigation_cache(NAVIGATION_CACHE_NAME);
$this->children = new navigation_node_collection();
$this->branchtype = $branchtype;
$this->instanceid = $id;
$this->initialise();
}
/**
* Initialise the navigation given the type and id for the branch to expand.
*
* @return array An array of the expandable nodes
*/
public function initialise() {
global $DB, $SITE;
if ($this->initialised || during_initial_install()) {
return $this->expandable;
}
$this->initialised = true;
$this->rootnodes = array();
$this->rootnodes['site'] = $this->add_course($SITE);
$this->rootnodes['mycourses'] = $this->add(
get_string('mycourses'),
new moodle_url('/my/courses.php'),
self::TYPE_ROOTNODE,
null,
'mycourses'
);
$this->rootnodes['courses'] = $this->add(get_string('courses'), null, self::TYPE_ROOTNODE, null, 'courses');
// The courses branch is always displayed, and is always expandable (although may be empty).
// This mimicks what is done during {@link global_navigation::initialise()}.
$this->rootnodes['courses']->isexpandable = true;
// Branchtype will be one of navigation_node::TYPE_*
switch ($this->branchtype) {
case 0:
if ($this->instanceid === 'mycourses') {
$this->load_courses_enrolled();
} else if ($this->instanceid === 'courses') {
$this->load_courses_other();
}
break;
case self::TYPE_CATEGORY :
$this->load_category($this->instanceid);
break;
case self::TYPE_MY_CATEGORY :
$this->load_category($this->instanceid, self::TYPE_MY_CATEGORY);
break;
case self::TYPE_COURSE :
$course = $DB->get_record('course', array('id' => $this->instanceid), '*', MUST_EXIST);
if (!can_access_course($course, null, '', true)) {
// Thats OK all courses are expandable by default. We don't need to actually expand it we can just
// add the course node and break. This leads to an empty node.
$this->add_course($course);
break;
}
require_course_login($course, true, null, false, true);
$this->page->set_context(context_course::instance($course->id));
$coursenode = $this->add_course($course, false, self::COURSE_CURRENT);
$this->add_course_essentials($coursenode, $course);
$this->load_course_sections($course, $coursenode);
break;
case self::TYPE_SECTION :
$sql = 'SELECT c.*, cs.section AS sectionnumber
FROM {course} c
LEFT JOIN {course_sections} cs ON cs.course = c.id
WHERE cs.id = ?';
$course = $DB->get_record_sql($sql, array($this->instanceid), MUST_EXIST);
require_course_login($course, true, null, false, true);
$this->page->set_context(context_course::instance($course->id));
$coursenode = $this->add_course($course, false, self::COURSE_CURRENT);
$this->add_course_essentials($coursenode, $course);
$this->load_course_sections($course, $coursenode, $course->sectionnumber);
break;
case self::TYPE_ACTIVITY :
$sql = "SELECT c.*
FROM {course} c
JOIN {course_modules} cm ON cm.course = c.id
WHERE cm.id = :cmid";
$params = array('cmid' => $this->instanceid);
$course = $DB->get_record_sql($sql, $params, MUST_EXIST);
$modinfo = get_fast_modinfo($course);
$cm = $modinfo->get_cm($this->instanceid);
require_course_login($course, true, $cm, false, true);
$this->page->set_context(context_module::instance($cm->id));
$coursenode = $this->add_course($course, false, self::COURSE_CURRENT);
$this->load_course_sections($course, $coursenode, null, $cm);
$activitynode = $coursenode->find($cm->id, self::TYPE_ACTIVITY);
if ($activitynode) {
$modulenode = $this->load_activity($cm, $course, $activitynode);
}
break;
default:
throw new Exception('Unknown type');
return $this->expandable;
}
if ($this->page->context->contextlevel == CONTEXT_COURSE && $this->page->context->instanceid != $SITE->id) {
$this->load_for_user(null, true);
}
// Give the local plugins a chance to include some navigation if they want.
$this->load_local_plugin_navigation();
$this->find_expandable($this->expandable);
return $this->expandable;
}
/**
* They've expanded the general 'courses' branch.
*/
protected function load_courses_other() {
$this->load_all_courses();
}
/**
* Loads a single category into the AJAX navigation.
*
* This function is special in that it doesn't concern itself with the parent of
* the requested category or its siblings.
* This is because with the AJAX navigation we know exactly what is wanted and only need to
* request that.
*
* @global moodle_database $DB
* @param int $categoryid id of category to load in navigation.
* @param int $nodetype type of node, if category is under MyHome then it's TYPE_MY_CATEGORY
* @return void.
*/
protected function load_category($categoryid, $nodetype = self::TYPE_CATEGORY) {
global $CFG, $DB;
$limit = 20;
if (!empty($CFG->navcourselimit)) {
$limit = (int)$CFG->navcourselimit;
}
$catcontextsql = context_helper::get_preload_record_columns_sql('ctx');
$sql = "SELECT cc.*, $catcontextsql
FROM {course_categories} cc
JOIN {context} ctx ON cc.id = ctx.instanceid
WHERE ctx.contextlevel = ".CONTEXT_COURSECAT." AND
(cc.id = :categoryid1 OR cc.parent = :categoryid2)
ORDER BY cc.depth ASC, cc.sortorder ASC, cc.id ASC";
$params = array('categoryid1' => $categoryid, 'categoryid2' => $categoryid);
$categories = $DB->get_recordset_sql($sql, $params, 0, $limit);
$categorylist = array();
$subcategories = array();
$basecategory = null;
foreach ($categories as $category) {
$categorylist[] = $category->id;
context_helper::preload_from_record($category);
if ($category->id == $categoryid) {
$this->add_category($category, $this, $nodetype);
$basecategory = $this->addedcategories[$category->id];
} else {
$subcategories[$category->id] = $category;
}
}
$categories->close();
// If category is shown in MyHome then only show enrolled courses and hide empty subcategories,
// else show all courses.
if ($nodetype === self::TYPE_MY_CATEGORY) {
$courses = enrol_get_my_courses('*');
$categoryids = array();
// Only search for categories if basecategory was found.
if (!is_null($basecategory)) {
// Get course parent category ids.
foreach ($courses as $course) {
$categoryids[] = $course->category;
}
// Get a unique list of category ids which a part of the path
// to user's courses.
$coursesubcategories = array();
$addedsubcategories = array();
list($sql, $params) = $DB->get_in_or_equal($categoryids);
$categories = $DB->get_recordset_select('course_categories', 'id '.$sql, $params, 'sortorder, id', 'id, path');
foreach ($categories as $category){
$coursesubcategories = array_merge($coursesubcategories, explode('/', trim($category->path, "/")));
}
$categories->close();
$coursesubcategories = array_unique($coursesubcategories);
// Only add a subcategory if it is part of the path to user's course and
// wasn't already added.
foreach ($subcategories as $subid => $subcategory) {
if (in_array($subid, $coursesubcategories) &&
!in_array($subid, $addedsubcategories)) {
$this->add_category($subcategory, $basecategory, $nodetype);
$addedsubcategories[] = $subid;
}
}
}
foreach ($courses as $course) {
// Add course if it's in category.
if (in_array($course->category, $categorylist)) {
$this->add_course($course, true, self::COURSE_MY);
}
}
} else {
if (!is_null($basecategory)) {
foreach ($subcategories as $key=>$category) {
$this->add_category($category, $basecategory, $nodetype);
}
}
$courses = $DB->get_recordset('course', array('category' => $categoryid), 'sortorder', '*' , 0, $limit);
foreach ($courses as $course) {
$this->add_course($course);
}
$courses->close();
}
}
/**
* Returns an array of expandable nodes
* @return array
*/
public function get_expandable() {
return $this->expandable;
}
}
+371
View File
@@ -0,0 +1,371 @@
<?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/>.
/**
* Navbar class
*
* This class is used to manage the navbar, which is initialised from the navigation
* object held by PAGE
*
* @package core
* @category navigation
* @copyright 2009 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class navbar extends navigation_node {
/** @var bool A switch for whether the navbar is initialised or not */
protected $initialised = false;
/** @var mixed keys used to reference the nodes on the navbar */
protected $keys = array();
/** @var null|string content of the navbar */
protected $content = null;
/** @var moodle_page object the moodle page that this navbar belongs to */
protected $page;
/** @var bool A switch for whether to ignore the active navigation information */
protected $ignoreactive = false;
/** @var bool A switch to let us know if we are in the middle of an install */
protected $duringinstall = false;
/** @var bool A switch for whether the navbar has items */
protected $hasitems = false;
/** @var array An array of navigation nodes for the navbar */
protected $items;
/** @var array An array of child node objects */
public $children = array();
/** @var bool A switch for whether we want to include the root node in the navbar */
public $includesettingsbase = false;
/** @var breadcrumb_navigation_node[] $prependchildren */
protected $prependchildren = array();
/**
* The almighty constructor
*
* @param moodle_page $page
*/
public function __construct(moodle_page $page) {
global $CFG;
if (during_initial_install()) {
$this->duringinstall = true;
return;
}
$this->page = $page;
$this->text = get_string('home');
$this->shorttext = get_string('home');
$this->action = new moodle_url($CFG->wwwroot);
$this->nodetype = self::NODETYPE_BRANCH;
$this->type = self::TYPE_SYSTEM;
}
/**
* Quick check to see if the navbar will have items in.
*
* @return bool Returns true if the navbar will have items, false otherwise
*/
public function has_items() {
if ($this->duringinstall) {
return false;
} else if ($this->hasitems !== false) {
return true;
}
$outcome = false;
if (count($this->children) > 0 || count($this->prependchildren) > 0) {
// There have been manually added items - there are definitely items.
$outcome = true;
} else if (!$this->ignoreactive) {
// We will need to initialise the navigation structure to check if there are active items.
$this->page->navigation->initialise($this->page);
$outcome = ($this->page->navigation->contains_active_node() || $this->page->settingsnav->contains_active_node());
}
$this->hasitems = $outcome;
return $outcome;
}
/**
* Turn on/off ignore active
*
* @param bool $setting
*/
public function ignore_active($setting=true) {
$this->ignoreactive = ($setting);
}
/**
* Gets a navigation node
*
* @param string|int $key for referencing the navbar nodes
* @param int $type breadcrumb_navigation_node::TYPE_*
* @return breadcrumb_navigation_node|bool
*/
public function get($key, $type = null) {
foreach ($this->children as &$child) {
if ($child->key === $key && ($type == null || $type == $child->type)) {
return $child;
}
}
foreach ($this->prependchildren as &$child) {
if ($child->key === $key && ($type == null || $type == $child->type)) {
return $child;
}
}
return false;
}
/**
* Returns an array of breadcrumb_navigation_nodes that make up the navbar.
*
* @return array
*/
public function get_items() {
global $CFG;
$items = array();
// Make sure that navigation is initialised
if (!$this->has_items()) {
return $items;
}
if ($this->items !== null) {
return $this->items;
}
if (count($this->children) > 0) {
// Add the custom children.
$items = array_reverse($this->children);
}
// Check if navigation contains the active node
if (!$this->ignoreactive) {
// We will need to ensure the navigation has been initialised.
$this->page->navigation->initialise($this->page);
// Now find the active nodes on both the navigation and settings.
$navigationactivenode = $this->page->navigation->find_active_node();
$settingsactivenode = $this->page->settingsnav->find_active_node();
if ($navigationactivenode && $settingsactivenode) {
// Parse a combined navigation tree
while ($settingsactivenode && $settingsactivenode->parent !== null) {
if (!$settingsactivenode->mainnavonly) {
$items[] = new breadcrumb_navigation_node($settingsactivenode);
}
$settingsactivenode = $settingsactivenode->parent;
}
if (!$this->includesettingsbase) {
// Removes the first node from the settings (root node) from the list
array_pop($items);
}
while ($navigationactivenode && $navigationactivenode->parent !== null) {
if (!$navigationactivenode->mainnavonly) {
$items[] = new breadcrumb_navigation_node($navigationactivenode);
}
if (!empty($CFG->navshowcategories) &&
$navigationactivenode->type === self::TYPE_COURSE &&
$navigationactivenode->parent->key === 'currentcourse') {
foreach ($this->get_course_categories() as $item) {
$items[] = new breadcrumb_navigation_node($item);
}
}
$navigationactivenode = $navigationactivenode->parent;
}
} else if ($navigationactivenode) {
// Parse the navigation tree to get the active node
while ($navigationactivenode && $navigationactivenode->parent !== null) {
if (!$navigationactivenode->mainnavonly) {
$items[] = new breadcrumb_navigation_node($navigationactivenode);
}
if (!empty($CFG->navshowcategories) &&
$navigationactivenode->type === self::TYPE_COURSE &&
$navigationactivenode->parent->key === 'currentcourse') {
foreach ($this->get_course_categories() as $item) {
$items[] = new breadcrumb_navigation_node($item);
}
}
$navigationactivenode = $navigationactivenode->parent;
}
} else if ($settingsactivenode) {
// Parse the settings navigation to get the active node
while ($settingsactivenode && $settingsactivenode->parent !== null) {
if (!$settingsactivenode->mainnavonly) {
$items[] = new breadcrumb_navigation_node($settingsactivenode);
}
$settingsactivenode = $settingsactivenode->parent;
}
}
}
$items[] = new breadcrumb_navigation_node(array(
'text' => $this->page->navigation->text,
'shorttext' => $this->page->navigation->shorttext,
'key' => $this->page->navigation->key,
'action' => $this->page->navigation->action
));
if (count($this->prependchildren) > 0) {
// Add the custom children
$items = array_merge($items, array_reverse($this->prependchildren));
}
$last = reset($items);
if ($last) {
$last->set_last(true);
}
$this->items = array_reverse($items);
return $this->items;
}
/**
* Get the list of categories leading to this course.
*
* This function is used by {@link navbar::get_items()} to add back the "courses"
* node and category chain leading to the current course. Note that this is only ever
* called for the current course, so we don't need to bother taking in any parameters.
*
* @return array
*/
private function get_course_categories() {
global $CFG;
require_once($CFG->dirroot.'/course/lib.php');
$categories = array();
$cap = 'moodle/category:viewhiddencategories';
$showcategories = !core_course_category::is_simple_site();
if ($showcategories) {
foreach ($this->page->categories as $category) {
$context = context_coursecat::instance($category->id);
if (!core_course_category::can_view_category($category)) {
continue;
}
$displaycontext = \context_helper::get_navigation_filter_context($context);
$url = new moodle_url('/course/index.php', ['categoryid' => $category->id]);
$name = format_string($category->name, true, ['context' => $displaycontext]);
$categorynode = breadcrumb_navigation_node::create($name, $url, self::TYPE_CATEGORY, null, $category->id);
if (!$category->visible) {
$categorynode->hidden = true;
}
$categories[] = $categorynode;
}
}
// Don't show the 'course' node if enrolled in this course.
$coursecontext = context_course::instance($this->page->course->id);
if (!is_enrolled($coursecontext, null, '', true)) {
$courses = $this->page->navigation->get('courses');
if (!$courses) {
// Courses node may not be present.
$courses = breadcrumb_navigation_node::create(
get_string('courses'),
new moodle_url('/course/index.php'),
self::TYPE_CONTAINER
);
}
$categories[] = $courses;
}
return $categories;
}
/**
* Add a new breadcrumb_navigation_node to the navbar, overrides parent::add
*
* This function overrides {@link breadcrumb_navigation_node::add()} so that we can change
* the way nodes get added to allow us to simply call add and have the node added to the
* end of the navbar
*
* @param string $text
* @param string|moodle_url|action_link $action An action to associate with this node.
* @param int $type One of navigation_node::TYPE_*
* @param string $shorttext
* @param string|int $key A key to identify this node with. Key + type is unique to a parent.
* @param pix_icon $icon An optional icon to use for this node.
* @return navigation_node
*/
public function add($text, $action=null, $type=self::TYPE_CUSTOM, $shorttext=null, $key=null, ?pix_icon $icon=null) {
if ($this->content !== null) {
debugging('Nav bar items must be printed before $OUTPUT->header() has been called', DEBUG_DEVELOPER);
}
// Properties array used when creating the new navigation node
$itemarray = array(
'text' => $text,
'type' => $type
);
// Set the action if one was provided
if ($action!==null) {
$itemarray['action'] = $action;
}
// Set the shorttext if one was provided
if ($shorttext!==null) {
$itemarray['shorttext'] = $shorttext;
}
// Set the icon if one was provided
if ($icon!==null) {
$itemarray['icon'] = $icon;
}
// Default the key to the number of children if not provided
if ($key === null) {
$key = count($this->children);
}
// Set the key
$itemarray['key'] = $key;
// Set the parent to this node
$itemarray['parent'] = $this;
// Add the child using the navigation_node_collections add method
$this->children[] = new breadcrumb_navigation_node($itemarray);
return $this;
}
/**
* Prepends a new navigation_node to the start of the navbar
*
* @param string $text
* @param string|moodle_url|action_link $action An action to associate with this node.
* @param int $type One of navigation_node::TYPE_*
* @param string $shorttext
* @param string|int $key A key to identify this node with. Key + type is unique to a parent.
* @param pix_icon $icon An optional icon to use for this node.
* @return navigation_node
*/
public function prepend($text, $action=null, $type=self::TYPE_CUSTOM, $shorttext=null, $key=null, ?pix_icon $icon=null) {
if ($this->content !== null) {
debugging('Nav bar items must be printed before $OUTPUT->header() has been called', DEBUG_DEVELOPER);
}
// Properties array used when creating the new navigation node.
$itemarray = array(
'text' => $text,
'type' => $type
);
// Set the action if one was provided.
if ($action!==null) {
$itemarray['action'] = $action;
}
// Set the shorttext if one was provided.
if ($shorttext!==null) {
$itemarray['shorttext'] = $shorttext;
}
// Set the icon if one was provided.
if ($icon!==null) {
$itemarray['icon'] = $icon;
}
// Default the key to the number of children if not provided.
if ($key === null) {
$key = count($this->children);
}
// Set the key.
$itemarray['key'] = $key;
// Set the parent to this node.
$itemarray['parent'] = $this;
// Add the child node to the prepend list.
$this->prependchildren[] = new breadcrumb_navigation_node($itemarray);
return $this;
}
}
@@ -0,0 +1,204 @@
<?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/>.
/**
* Class navigation_cache
*
* @package core
* @copyright 2025 Andrew Lyons <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* The navigation_cache class is used for global and settings navigation data.
*
* It provides an easy access to the session cache with TTL of 1800 seconds.
*
* Example use:
* <code php>
* if (!$cache->viewdiscussion()) {
* // Code to do stuff and produce cachable content
* $cache->viewdiscussion = has_capability('mod/forum:viewdiscussion', $coursecontext);
* }
* $content = $cache->viewdiscussion;
* </code>
*
* @package core
* @category navigation
* @copyright 2009 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class navigation_cache {
/** @var cache_session The session cache instance */
protected $cache;
/** @var array The current cache area data */
protected $session = [];
/**
* @var string A unique string to segregate this particular cache.
* It can either be unique to start a fresh cache or shared to use an existing cache.
*/
protected $area;
/** @var int cache time information */
#[\core\attribute\deprecated(null, since: '4.5', reason: 'This constant is no longer needed.', mdl: 'MDL-79628')]
const CACHETIME = 0;
/** @var int cache user id */
#[\core\attribute\deprecated(null, since: '4.5', reason: 'This constant is no longer needed.', mdl: 'MDL-79628')]
const CACHEUSERID = 1;
/** @var int cache value */
const CACHEVALUE = 2;
/** @var null|array An array of cache areas to expire on shutdown */
public static $volatilecaches = null;
/**
* Contructor for the cache. Requires a area string be passed in.
*
* @param string $area The unique string to segregate this particular cache.
* @param int $timeout Deprecated since Moodle 4.5. The number of seconds to time the information out after
*/
public function __construct($area, $timeout = null) {
if ($timeout !== null) {
debugging(
'The timeout argument has been deprecated. Please remove it from your method calls.',
DEBUG_DEVELOPER,
);
}
global $USER;
$this->area = "user_{$USER->id}_{$area}";
$this->cache = cache::make('core', 'navigation_cache');
}
/**
* Ensure the navigation cache is initialised
*
* This is called for each access and ensures that no data is put into the cache before it is required.
*/
protected function ensure_navigation_cache_initialised() {
if (empty($this->session)) {
$this->session = $this->cache->get($this->area);
if (!is_array($this->session)) {
$this->session = [];
}
}
}
/**
* Magic Method to retrieve a cached item by simply calling using = cache->key
*
* @param mixed $key The identifier for the cached information
* @return mixed|void The cached information or void if not found
*/
public function __get($key) {
if (!$this->cached($key)) {
return;
}
return unserialize($this->session[$key][self::CACHEVALUE]);
}
/**
* Magic method that simply uses {@see navigation_cache::set()} to store an item in the cache
*
* @param string|int $key The key to store the information against
* @param mixed $information The information to cache
*/
public function __set($key, $information) {
$this->set($key, $information);
}
/**
* Sets some information in the session cache for later retrieval
*
* @param string|int $key
* @param mixed $information
*/
public function set($key, $information) {
$this->ensure_navigation_cache_initialised();
$information = serialize($information);
$this->session[$key] = [self::CACHEVALUE => $information];
$this->cache->set($this->area, $this->session);
}
/**
* Check the existence of the identifier in the cache
*
* @param string|int $key The identifier to check
* @return bool True if the item exists in the cache, false otherwise
*/
public function cached($key) {
$this->ensure_navigation_cache_initialised();
return isset($this->session[$key]) &&
is_array($this->session[$key]);
}
/**
* Compare something to it's equivilant in the cache
*
* @param string $key The key to check
* @param mixed $value The value to compare
* @param bool $serialise Whether to serialise the value before comparison
* this should only be set to false if the value is already
* serialised
* @return bool True if the value is the same as the cached one, false otherwise
*/
public function compare($key, $value, $serialise = true) {
if ($this->cached($key)) {
if ($serialise) {
$value = serialize($value);
}
return $this->session[$key][self::CACHEVALUE] === $value;
}
return false;
}
/**
* Deletes the entire cache area, forcing a fresh cache to be created
*/
public function clear() {
$this->cache->delete($this->area);
$this->session = [];
}
/**
* Marks the cache as volatile (likely to change)
*
* Any caches marked as volatile will be destroyed on shutdown by {@see navigation_node::destroy_volatile_caches()}
*
* @param bool $setting True to mark the cache as volatile, false to remove the volatile flag
*/
public function volatile($setting = true) {
if (self::$volatilecaches === null) {
self::$volatilecaches = [];
core_shutdown_manager::register_function(['navigation_cache', 'destroy_volatile_caches']);
}
if ($setting) {
self::$volatilecaches[$this->area] = $this->area;
} else if (array_key_exists($this->area, self::$volatilecaches)) {
unset(self::$volatilecaches[$this->area]);
}
}
/**
* Destroys all caches marked as volatile
*
* This function is static and works with the static volatilecaches property of navigation cache.
* It manually resets the cached areas back to an empty array.
*/
public static function destroy_volatile_caches() {
if (is_array(self::$volatilecaches) && count(self::$volatilecaches) > 0) {
$cache = cache::make('core', 'navigation_cache');
foreach (self::$volatilecaches as $area) {
$cache->delete($area);
}
self::$volatilecaches = null;
}
}
}
@@ -0,0 +1,121 @@
<?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/>.
/**
* Simple class used to output a navigation branch in XML
*
* @package core
* @category navigation
* @copyright 2009 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class navigation_json {
/** @var array An array of different node types */
protected $nodetype = array('node','branch');
/** @var array An array of node keys and types */
protected $expandable = array();
/**
* Turns a branch and all of its children into XML
*
* @param navigation_node $branch
* @return string XML string
*/
public function convert($branch) {
$xml = $this->convert_child($branch);
return $xml;
}
/**
* Set the expandable items in the array so that we have enough information
* to attach AJAX events
* @param array $expandable
*/
public function set_expandable($expandable) {
foreach ($expandable as $node) {
$this->expandable[$node['key'].':'.$node['type']] = $node;
}
}
/**
* Recusively converts a child node and its children to XML for output
*
* @param navigation_node $child The child to convert
* @param int $depth Pointlessly used to track the depth of the XML structure
* @return string JSON
*/
protected function convert_child($child, $depth=1) {
if (!$child->display) {
return '';
}
$attributes = array();
$attributes['id'] = $child->id;
$attributes['name'] = (string)$child->text; // This can be lang_string object so typecast it.
$attributes['type'] = $child->type;
$attributes['key'] = $child->key;
$attributes['class'] = $child->get_css_type();
$attributes['requiresajaxloading'] = $child->requiresajaxloading;
if ($child->icon instanceof pix_icon) {
$attributes['icon'] = array(
'component' => $child->icon->component,
'pix' => $child->icon->pix,
);
foreach ($child->icon->attributes as $key=>$value) {
if ($key == 'class') {
$attributes['icon']['classes'] = explode(' ', $value);
} else if (!array_key_exists($key, $attributes['icon'])) {
$attributes['icon'][$key] = $value;
}
}
} else if (!empty($child->icon)) {
$attributes['icon'] = (string)$child->icon;
}
if ($child->forcetitle || $child->title !== $child->text) {
$attributes['title'] = htmlentities($child->title ?? '', ENT_QUOTES, 'UTF-8');
}
if (array_key_exists($child->key.':'.$child->type, $this->expandable)) {
$attributes['expandable'] = $child->key;
$child->add_class($this->expandable[$child->key.':'.$child->type]['id']);
}
if (count($child->classes)>0) {
$attributes['class'] .= ' '.join(' ',$child->classes);
}
if (is_string($child->action)) {
$attributes['link'] = $child->action;
} else if ($child->action instanceof moodle_url) {
$attributes['link'] = $child->action->out();
} else if ($child->action instanceof action_link) {
$attributes['link'] = $child->action->url->out();
}
$attributes['hidden'] = ($child->hidden);
$attributes['haschildren'] = ($child->children->count()>0 || $child->type == navigation_node::TYPE_CATEGORY);
$attributes['haschildren'] = $attributes['haschildren'] || $child->type == navigation_node::TYPE_MY_CATEGORY;
if ($child->children->count() > 0) {
$attributes['children'] = array();
foreach ($child->children as $subchild) {
$attributes['children'][] = $this->convert_child($subchild, $depth+1);
}
}
if ($depth > 1) {
return $attributes;
} else {
return json_encode($attributes);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,281 @@
<?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/>.
/**
* Navigation node collection
*
* This class is responsible for managing a collection of navigation nodes.
* It is required because a node's unique identifier is a combination of both its
* key and its type.
*
* Originally an array was used with a string key that was a combination of the two
* however it was decided that a better solution would be to use a class that
* implements the standard IteratorAggregate interface.
*
* @package core
* @category navigation
* @copyright 2010 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class navigation_node_collection implements IteratorAggregate, Countable {
/**
* A multidimensional array to where the first key is the type and the second
* key is the nodes key.
* @var array
*/
protected $collection = array();
/**
* An array that contains references to nodes in the same order they were added.
* This is maintained as a progressive array.
* @var array
*/
protected $orderedcollection = array();
/**
* A reference to the last node that was added to the collection
* @var navigation_node
*/
protected $last = null;
/**
* The total number of items added to this array.
* @var int
*/
protected $count = 0;
/**
* Label for collection of nodes.
* @var string
*/
protected $collectionlabel = '';
/**
* Adds a navigation node to the collection
*
* @param navigation_node $node Node to add
* @param string $beforekey If specified, adds before a node with this key,
* otherwise adds at end
* @return navigation_node Added node
*/
public function add(navigation_node $node, $beforekey=null) {
global $CFG;
$key = $node->key;
$type = $node->type;
// First check we have a 2nd dimension for this type
if (!array_key_exists($type, $this->orderedcollection)) {
$this->orderedcollection[$type] = array();
}
// Check for a collision and report if debugging is turned on
if ($CFG->debug && array_key_exists($key, $this->orderedcollection[$type])) {
debugging('Navigation node intersect: Adding a node that already exists '.$key, DEBUG_DEVELOPER);
}
// Find the key to add before
$newindex = $this->count;
$last = true;
if ($beforekey !== null) {
foreach ($this->collection as $index => $othernode) {
if ($othernode->key === $beforekey) {
$newindex = $index;
$last = false;
break;
}
}
if ($newindex === $this->count) {
debugging('Navigation node add_before: Reference node not found ' . $beforekey .
', options: ' . implode(' ', $this->get_key_list()), DEBUG_DEVELOPER);
}
}
// Add the node to the appropriate place in the by-type structure (which
// is not ordered, despite the variable name)
$this->orderedcollection[$type][$key] = $node;
if (!$last) {
// Update existing references in the ordered collection (which is the
// one that isn't called 'ordered') to shuffle them along if required
for ($oldindex = $this->count; $oldindex > $newindex; $oldindex--) {
$this->collection[$oldindex] = $this->collection[$oldindex - 1];
}
}
// Add a reference to the node to the progressive collection.
$this->collection[$newindex] = $this->orderedcollection[$type][$key];
// Update the last property to a reference to this new node.
$this->last = $this->orderedcollection[$type][$key];
// Reorder the array by index if needed
if (!$last) {
ksort($this->collection);
}
$this->count++;
// Return the reference to the now added node
return $node;
}
/**
* Return a list of all the keys of all the nodes.
* @return array the keys.
*/
public function get_key_list() {
$keys = array();
foreach ($this->collection as $node) {
$keys[] = $node->key;
}
return $keys;
}
/**
* Set a label for this collection.
*
* @param string $label
*/
public function set_collectionlabel($label) {
$this->collectionlabel = $label;
}
/**
* Return a label for this collection.
*
* @return string
*/
public function get_collectionlabel() {
return $this->collectionlabel;
}
/**
* Fetches a node from this collection.
*
* @param string|int $key The key of the node we want to find.
* @param int $type One of navigation_node::TYPE_*.
* @return navigation_node|null|false
*/
public function get($key, $type=null) {
if ($type !== null) {
// If the type is known then we can simply check and fetch
if (!empty($this->orderedcollection[$type][$key])) {
return $this->orderedcollection[$type][$key];
}
} else {
// Because we don't know the type we look in the progressive array
foreach ($this->collection as $node) {
if ($node->key === $key) {
return $node;
}
}
}
return false;
}
/**
* Searches for a node with matching key and type.
*
* This function searches both the nodes in this collection and all of
* the nodes in each collection belonging to the nodes in this collection.
*
* Recursive.
*
* @param string|int $key The key of the node we want to find.
* @param int $type One of navigation_node::TYPE_*.
* @return navigation_node|false
*/
public function find($key, $type=null) {
if ($type !== null && array_key_exists($type, $this->orderedcollection) && array_key_exists($key, $this->orderedcollection[$type])) {
return $this->orderedcollection[$type][$key];
} else {
$nodes = $this->getIterator();
// Search immediate children first
foreach ($nodes as &$node) {
if ($node->key === $key && ($type === null || $type === $node->type)) {
return $node;
}
}
// Now search each childs children
foreach ($nodes as &$node) {
$result = $node->children->find($key, $type);
if ($result !== false) {
return $result;
}
}
}
return false;
}
/**
* Fetches the last node that was added to this collection
*
* @return navigation_node
*/
public function last() {
return $this->last;
}
/**
* Fetches all nodes of a given type from this collection
*
* @param string|int $type node type being searched for.
* @return array ordered collection
*/
public function type($type) {
if (!array_key_exists($type, $this->orderedcollection)) {
$this->orderedcollection[$type] = array();
}
return $this->orderedcollection[$type];
}
/**
* Removes the node with the given key and type from the collection
*
* @param string|int $key The key of the node we want to find.
* @param int $type
* @return bool
*/
public function remove($key, $type=null) {
$child = $this->get($key, $type);
if ($child !== false) {
foreach ($this->collection as $colkey => $node) {
if ($node->key === $key && (is_null($type) || $node->type == $type)) {
unset($this->collection[$colkey]);
$this->collection = array_values($this->collection);
break;
}
}
unset($this->orderedcollection[$child->type][$child->key]);
$this->count--;
return true;
}
return false;
}
/**
* Gets the number of nodes in this collection
*
* This option uses an internal count rather than counting the actual options to avoid
* a performance hit through the count function.
*
* @return int
*/
public function count(): int {
return $this->count;
}
/**
* Gets an array iterator for the collection.
*
* This is required by the IteratorAggregator interface and is used by routines
* such as the foreach loop.
*
* @return ArrayIterator
*/
public function getIterator(): Traversable {
return new ArrayIterator($this->collection);
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,54 @@
<?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/>.
/**
* Class used to populate site admin navigation for ajax.
*
* @package core
* @category navigation
* @copyright 2013 Rajesh Taneja <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class settings_navigation_ajax extends settings_navigation {
/**
* Constructs the navigation for use in an AJAX request
*
* @param moodle_page $page
*/
public function __construct(moodle_page &$page) {
$this->page = $page;
$this->cache = new navigation_cache(NAVIGATION_CACHE_NAME);
$this->children = new navigation_node_collection();
$this->initialise();
}
/**
* Initialise the site admin navigation.
*/
public function initialise() {
if ($this->initialised || during_initial_install()) {
return false;
}
$this->context = $this->page->context;
$this->load_administration_settings();
// Check if local plugins is adding node to site admin.
$this->load_local_plugin_settings();
$this->initialised = true;
}
}
+14
View File
@@ -188,6 +188,20 @@ $legacyclasses = [
'form/cachestore_addinstance_form.php',
],
// Navigation API.
\breadcrumb_navigation_node::class => 'navigation/breadcrumb_navigation_node.php',
\flat_navigation::class => 'navigation/flat_navigation.php',
\flat_navigation_node::class => 'navigation/flat_navigation_node.php',
\global_navigation::class => 'navigation/global_navigation.php',
\global_navigation_for_ajax::class => 'navigation/global_navigation_for_ajax.php',
\navbar::class => 'navigation/navbar.php',
\navigation_cache::class => 'navigation/navigation_cache.php',
\navigation_json::class => 'navigation/navigation_json.php',
\navigation_node::class => 'navigation/navigation_node.php',
\navigation_node_collection::class => 'navigation/navigation_node_collection.php',
\settings_navigation::class => 'navigation/settings_navigation.php',
\settings_navigation_ajax::class => 'navigation/settings_navigation_ajax.php',
// Output API.
\theme_config::class => 'output/theme_config.php',
\xhtml_container_stack::class => 'output/xhtml_container_stack.php',
File diff suppressed because it is too large Load Diff