You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
693 lines
25 KiB
693 lines
25 KiB
<?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 theme_ilb\output;
|
|
|
|
use coding_exception;
|
|
use html_writer;
|
|
use tabobject;
|
|
use tabtree;
|
|
use custom_menu_item;
|
|
use custom_menu;
|
|
use block_contents;
|
|
use navigation_node;
|
|
use action_link;
|
|
use stdClass;
|
|
use moodle_url;
|
|
use preferences_groups;
|
|
use action_menu;
|
|
use help_icon;
|
|
use single_button;
|
|
use context_course;
|
|
use pix_icon;
|
|
|
|
defined('MOODLE_INTERNAL') || die;
|
|
|
|
/**
|
|
* Renderers to align Moodle's HTML with that expected by Bootstrap
|
|
*
|
|
* @package theme_ilb
|
|
* @copyright 2012 Bas Brands, www.basbrands.nl
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
|
|
class core_renderer extends \core_renderer {
|
|
|
|
/** @var custom_menu_item language The language menu if created */
|
|
protected $language = null;
|
|
|
|
/**
|
|
* Outputs the opening section of a box.
|
|
*
|
|
* @param string $classes A space-separated list of CSS classes
|
|
* @param string $id An optional ID
|
|
* @param array $attributes An array of other attributes to give the box.
|
|
* @return string the HTML to output.
|
|
*/
|
|
public function box_start($classes = 'generalbox', $id = null, $attributes = array()) {
|
|
if (is_array($classes)) {
|
|
$classes = implode(' ', $classes);
|
|
}
|
|
return parent::box_start($classes . ' py-3', $id, $attributes);
|
|
}
|
|
|
|
/**
|
|
* Wrapper for header elements.
|
|
*
|
|
* @return string HTML to display the main header.
|
|
*/
|
|
public function full_header() {
|
|
global $PAGE;
|
|
|
|
$header = new stdClass();
|
|
$header->settingsmenu = $this->context_header_settings_menu();
|
|
$header->contextheader = $this->context_header();
|
|
$header->hasnavbar = empty($PAGE->layout_options['nonavbar']);
|
|
$header->navbar = $this->navbar();
|
|
$header->pageheadingbutton = $this->page_heading_button();
|
|
$header->courseheader = $this->course_header();
|
|
return $this->render_from_template('theme_ilb/header', $header);
|
|
}
|
|
|
|
/**
|
|
* The standard tags that should be included in the <head> tag
|
|
* including a meta description for the front page
|
|
*
|
|
* @return string HTML fragment.
|
|
*/
|
|
public function standard_head_html() {
|
|
global $SITE, $PAGE;
|
|
|
|
$output = parent::standard_head_html();
|
|
if ($PAGE->pagelayout == 'frontpage') {
|
|
$summary = s(strip_tags(format_text($SITE->summary, FORMAT_HTML)));
|
|
if (!empty($summary)) {
|
|
$output .= "<meta name=\"description\" content=\"$summary\" />\n";
|
|
}
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
/*
|
|
* This renders the navbar.
|
|
* Uses bootstrap compatible html.
|
|
*/
|
|
public function navbar() {
|
|
return $this->render_from_template('core/navbar', $this->page->navbar);
|
|
}
|
|
|
|
/**
|
|
* We don't like these...
|
|
*
|
|
*/
|
|
public function edit_button(moodle_url $url) {
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Override to inject the logo.
|
|
*
|
|
* @param array $headerinfo The header info.
|
|
* @param int $headinglevel What level the 'h' tag will be.
|
|
* @return string HTML for the header bar.
|
|
*/
|
|
public function context_header($headerinfo = null, $headinglevel = 1) {
|
|
global $SITE;
|
|
|
|
if ($this->should_display_main_logo($headinglevel)) {
|
|
$sitename = format_string($SITE->fullname, true, array('context' => context_course::instance(SITEID)));
|
|
return html_writer::div(html_writer::empty_tag('img', [
|
|
'src' => $this->get_logo_url(null, 150), 'alt' => $sitename, 'class' => 'img-fluid']), 'logo');
|
|
}
|
|
|
|
return parent::context_header($headerinfo, $headinglevel);
|
|
}
|
|
|
|
/**
|
|
* Get the compact logo URL.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_compact_logo_url($maxwidth = 100, $maxheight = 100) {
|
|
return parent::get_compact_logo_url(null, 70);
|
|
}
|
|
|
|
/**
|
|
* Whether we should display the main logo.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function should_display_main_logo($headinglevel = 1) {
|
|
global $PAGE;
|
|
|
|
// Only render the logo if we're on the front page or login page and the we have a logo.
|
|
$logo = $this->get_logo_url();
|
|
if ($headinglevel == 1 && !empty($logo)) {
|
|
if ($PAGE->pagelayout == 'frontpage' || $PAGE->pagelayout == 'login') {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
/**
|
|
* Whether we should display the logo in the navbar.
|
|
*
|
|
* We will when there are no main logos, and we have compact logo.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function should_display_navbar_logo() {
|
|
$logo = $this->get_compact_logo_url();
|
|
return !empty($logo) && !$this->should_display_main_logo();
|
|
}
|
|
|
|
/*
|
|
* Overriding the custom_menu function ensures the custom menu is
|
|
* always shown, even if no menu items are configured in the global
|
|
* theme settings page.
|
|
*/
|
|
public function custom_menu($custommenuitems = '') {
|
|
global $CFG;
|
|
|
|
if (empty($custommenuitems) && !empty($CFG->custommenuitems)) {
|
|
$custommenuitems = $CFG->custommenuitems;
|
|
}
|
|
$custommenu = new custom_menu($custommenuitems, current_language());
|
|
return $this->render_custom_menu($custommenu);
|
|
}
|
|
|
|
/**
|
|
* We want to show the custom menus as a list of links in the footer on small screens.
|
|
* Just return the menu object exported so we can render it differently.
|
|
*/
|
|
public function custom_menu_flat() {
|
|
global $CFG;
|
|
$custommenuitems = '';
|
|
|
|
if (empty($custommenuitems) && !empty($CFG->custommenuitems)) {
|
|
$custommenuitems = $CFG->custommenuitems;
|
|
}
|
|
$custommenu = new custom_menu($custommenuitems, current_language());
|
|
$langs = get_string_manager()->get_list_of_translations();
|
|
$haslangmenu = $this->lang_menu() != '';
|
|
|
|
if ($haslangmenu) {
|
|
$strlang = get_string('language');
|
|
$currentlang = current_language();
|
|
if (isset($langs[$currentlang])) {
|
|
$currentlang = $langs[$currentlang];
|
|
} else {
|
|
$currentlang = $strlang;
|
|
}
|
|
$this->language = $custommenu->add($currentlang, new moodle_url('#'), $strlang, 10000);
|
|
foreach ($langs as $langtype => $langname) {
|
|
$this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
|
|
}
|
|
}
|
|
|
|
return $custommenu->export_for_template($this);
|
|
}
|
|
|
|
/*
|
|
* This renders the bootstrap top menu.
|
|
*
|
|
* This renderer is needed to enable the Bootstrap style navigation.
|
|
*/
|
|
protected function render_custom_menu(custom_menu $menu) {
|
|
global $CFG;
|
|
|
|
$langs = get_string_manager()->get_list_of_translations();
|
|
$haslangmenu = $this->lang_menu() != '';
|
|
|
|
if (!$menu->has_children() && !$haslangmenu) {
|
|
return '';
|
|
}
|
|
|
|
if ($haslangmenu) {
|
|
$strlang = get_string('language');
|
|
$currentlang = current_language();
|
|
if (isset($langs[$currentlang])) {
|
|
$currentlang = $langs[$currentlang];
|
|
} else {
|
|
$currentlang = $strlang;
|
|
}
|
|
$this->language = $menu->add($currentlang, new moodle_url('#'), $strlang, 10000);
|
|
foreach ($langs as $langtype => $langname) {
|
|
$this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
|
|
}
|
|
}
|
|
|
|
$content = '';
|
|
foreach ($menu->get_children() as $item) {
|
|
$context = $item->export_for_template($this);
|
|
$content .= $this->render_from_template('core/custom_menu_item', $context);
|
|
}
|
|
|
|
return $content;
|
|
}
|
|
|
|
/**
|
|
* This code renders the navbar button to control the display of the custom menu
|
|
* on smaller screens.
|
|
*
|
|
* Do not display the button if the menu is empty.
|
|
*
|
|
* @return string HTML fragment
|
|
*/
|
|
public function navbar_button() {
|
|
global $CFG;
|
|
|
|
if (empty($CFG->custommenuitems) && $this->lang_menu() == '') {
|
|
return '';
|
|
}
|
|
|
|
$iconbar = html_writer::tag('span', '', array('class' => 'icon-bar'));
|
|
$button = html_writer::tag('a', $iconbar . "\n" . $iconbar. "\n" . $iconbar, array(
|
|
'class' => 'btn btn-navbar',
|
|
'data-toggle' => 'collapse',
|
|
'data-target' => '.nav-collapse'
|
|
));
|
|
return $button;
|
|
}
|
|
|
|
/**
|
|
* Renders tabtree
|
|
*
|
|
* @param tabtree $tabtree
|
|
* @return string
|
|
*/
|
|
protected function render_tabtree(tabtree $tabtree) {
|
|
if (empty($tabtree->subtree)) {
|
|
return '';
|
|
}
|
|
$data = $tabtree->export_for_template($this);
|
|
return $this->render_from_template('core/tabtree', $data);
|
|
}
|
|
|
|
/**
|
|
* Renders tabobject (part of tabtree)
|
|
*
|
|
* This function is called from {@link core_renderer::render_tabtree()}
|
|
* and also it calls itself when printing the $tabobject subtree recursively.
|
|
*
|
|
* @param tabobject $tabobject
|
|
* @return string HTML fragment
|
|
*/
|
|
protected function render_tabobject(tabobject $tab) {
|
|
throw new coding_exception('Tab objects should not be directly rendered.');
|
|
}
|
|
|
|
/**
|
|
* Prints a nice side block with an optional header.
|
|
*
|
|
* @param block_contents $bc HTML for the content
|
|
* @param string $region the region the block is appearing in.
|
|
* @return string the HTML to be output.
|
|
*/
|
|
public function block(block_contents $bc, $region) {
|
|
$bc = clone($bc); // Avoid messing up the object passed in.
|
|
if (empty($bc->blockinstanceid) || !strip_tags($bc->title)) {
|
|
$bc->collapsible = block_contents::NOT_HIDEABLE;
|
|
}
|
|
|
|
$id = !empty($bc->attributes['id']) ? $bc->attributes['id'] : uniqid('block-');
|
|
$context = new stdClass();
|
|
$context->skipid = $bc->skipid;
|
|
$context->blockinstanceid = $bc->blockinstanceid;
|
|
$context->dockable = $bc->dockable;
|
|
$context->id = $id;
|
|
$context->hidden = $bc->collapsible == block_contents::HIDDEN;
|
|
$context->skiptitle = strip_tags($bc->title);
|
|
$context->showskiplink = !empty($context->skiptitle);
|
|
$context->arialabel = $bc->arialabel;
|
|
$context->ariarole = !empty($bc->attributes['role']) ? $bc->attributes['role'] : 'complementary';
|
|
$context->type = $bc->attributes['data-block'];
|
|
$context->title = $bc->title;
|
|
$context->content = $bc->content;
|
|
$context->annotation = $bc->annotation;
|
|
$context->footer = $bc->footer;
|
|
$context->hascontrols = !empty($bc->controls);
|
|
if ($context->hascontrols) {
|
|
$context->controls = $this->block_controls($bc->controls, $id);
|
|
}
|
|
|
|
return $this->render_from_template('core/block', $context);
|
|
}
|
|
|
|
/**
|
|
* Returns the CSS classes to apply to the body tag.
|
|
*
|
|
* @since Moodle 2.5.1 2.6
|
|
* @param array $additionalclasses Any additional classes to apply.
|
|
* @return string
|
|
*/
|
|
public function body_css_classes(array $additionalclasses = array()) {
|
|
return $this->page->bodyclasses . ' ' . implode(' ', $additionalclasses);
|
|
}
|
|
|
|
/**
|
|
* Renders preferences groups.
|
|
*
|
|
* @param preferences_groups $renderable The renderable
|
|
* @return string The output.
|
|
*/
|
|
public function render_preferences_groups(preferences_groups $renderable) {
|
|
return $this->render_from_template('core/preferences_groups', $renderable);
|
|
}
|
|
|
|
/**
|
|
* Renders an action menu component.
|
|
*
|
|
* @param action_menu $menu
|
|
* @return string HTML
|
|
*/
|
|
public function render_action_menu(action_menu $menu) {
|
|
|
|
// We don't want the class icon there!
|
|
foreach ($menu->get_secondary_actions() as $action) {
|
|
if ($action instanceof \action_menu_link && $action->has_class('icon')) {
|
|
$action->attributes['class'] = preg_replace('/(^|\s+)icon(\s+|$)/i', '', $action->attributes['class']);
|
|
}
|
|
}
|
|
|
|
if ($menu->is_empty()) {
|
|
return '';
|
|
}
|
|
$context = $menu->export_for_template($this);
|
|
|
|
return $this->render_from_template('core/action_menu', $context);
|
|
}
|
|
|
|
/**
|
|
* Implementation of user image rendering.
|
|
*
|
|
* @param help_icon $helpicon A help icon instance
|
|
* @return string HTML fragment
|
|
*/
|
|
protected function render_help_icon(help_icon $helpicon) {
|
|
$context = $helpicon->export_for_template($this);
|
|
return $this->render_from_template('core/help_icon', $context);
|
|
}
|
|
|
|
/**
|
|
* Renders a single button widget.
|
|
*
|
|
* This will return HTML to display a form containing a single button.
|
|
*
|
|
* @param single_button $button
|
|
* @return string HTML fragment
|
|
*/
|
|
protected function render_single_button(single_button $button) {
|
|
return $this->render_from_template('core/single_button', $button->export_for_template($this));
|
|
}
|
|
|
|
/**
|
|
* Renders the login form.
|
|
*
|
|
* @param \core_auth\output\login $form The renderable.
|
|
* @return string
|
|
*/
|
|
public function render_login(\core_auth\output\login $form) {
|
|
global $CFG, $SITE;
|
|
|
|
$context = $form->export_for_template($this);
|
|
|
|
// Override because rendering is not supported in template yet.
|
|
if ($CFG->rememberusername == 0) {
|
|
$context->cookieshelpiconformatted = $this->help_icon('cookiesenabledonlysession');
|
|
} else {
|
|
$context->cookieshelpiconformatted = $this->help_icon('cookiesenabled');
|
|
}
|
|
$context->errorformatted = $this->error_text($context->error);
|
|
$url = $this->get_logo_url();
|
|
if ($url) {
|
|
$url = $url->out(false);
|
|
}
|
|
$context->logourl = $url;
|
|
$context->sitename = format_string($SITE->fullname, true,
|
|
['context' => context_course::instance(SITEID), "escape" => false]);
|
|
|
|
return $this->render_from_template('core/loginform', $context);
|
|
}
|
|
|
|
/**
|
|
* Render the login signup form into a nice template for the theme.
|
|
*
|
|
* @param mform $form
|
|
* @return string
|
|
*/
|
|
public function render_login_signup_form($form) {
|
|
global $SITE;
|
|
|
|
$context = $form->export_for_template($this);
|
|
$url = $this->get_logo_url();
|
|
if ($url) {
|
|
$url = $url->out(false);
|
|
}
|
|
$context['logourl'] = $url;
|
|
$context['sitename'] = format_string($SITE->fullname, true,
|
|
['context' => context_course::instance(SITEID), "escape" => false]);
|
|
|
|
return $this->render_from_template('core/signup_form_layout', $context);
|
|
}
|
|
|
|
/**
|
|
* This is an optional menu that can be added to a layout by a theme. It contains the
|
|
* menu for the course administration, only on the course main page.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function context_header_settings_menu() {
|
|
$context = $this->page->context;
|
|
$menu = new action_menu();
|
|
|
|
$items = $this->page->navbar->get_items();
|
|
$currentnode = end($items);
|
|
|
|
$showcoursemenu = false;
|
|
$showfrontpagemenu = false;
|
|
$showusermenu = false;
|
|
|
|
// We are on the course home page.
|
|
if (($context->contextlevel == CONTEXT_COURSE) &&
|
|
!empty($currentnode) &&
|
|
($currentnode->type == navigation_node::TYPE_COURSE || $currentnode->type == navigation_node::TYPE_SECTION)) {
|
|
$showcoursemenu = true;
|
|
}
|
|
|
|
$courseformat = course_get_format($this->page->course);
|
|
// This is a single activity course format, always show the course menu on the activity main page.
|
|
if ($context->contextlevel == CONTEXT_MODULE &&
|
|
!$courseformat->has_view_page()) {
|
|
|
|
$this->page->navigation->initialise();
|
|
$activenode = $this->page->navigation->find_active_node();
|
|
// If the settings menu has been forced then show the menu.
|
|
if ($this->page->is_settings_menu_forced()) {
|
|
$showcoursemenu = true;
|
|
} else if (!empty($activenode) && ($activenode->type == navigation_node::TYPE_ACTIVITY ||
|
|
$activenode->type == navigation_node::TYPE_RESOURCE)) {
|
|
|
|
// We only want to show the menu on the first page of the activity. This means
|
|
// the breadcrumb has no additional nodes.
|
|
if ($currentnode && ($currentnode->key == $activenode->key && $currentnode->type == $activenode->type)) {
|
|
$showcoursemenu = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This is the site front page.
|
|
if ($context->contextlevel == CONTEXT_COURSE &&
|
|
!empty($currentnode) &&
|
|
$currentnode->key === 'home') {
|
|
$showfrontpagemenu = true;
|
|
}
|
|
|
|
// This is the user profile page.
|
|
if ($context->contextlevel == CONTEXT_USER &&
|
|
!empty($currentnode) &&
|
|
($currentnode->key === 'myprofile')) {
|
|
$showusermenu = true;
|
|
}
|
|
|
|
if ($showfrontpagemenu) {
|
|
$settingsnode = $this->page->settingsnav->find('frontpage', navigation_node::TYPE_SETTING);
|
|
if ($settingsnode) {
|
|
// Build an action menu based on the visible nodes from this navigation tree.
|
|
$skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
|
|
|
|
// We only add a list to the full settings menu if we didn't include every node in the short menu.
|
|
if ($skipped) {
|
|
$text = get_string('morenavigationlinks');
|
|
$url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
|
|
$link = new action_link($url, $text, null, null, new pix_icon('t/edit', ''));
|
|
$menu->add_secondary_action($link);
|
|
}
|
|
}
|
|
} else if ($showcoursemenu) {
|
|
$settingsnode = $this->page->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE);
|
|
if ($settingsnode) {
|
|
// Build an action menu based on the visible nodes from this navigation tree.
|
|
$skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
|
|
|
|
// We only add a list to the full settings menu if we didn't include every node in the short menu.
|
|
if ($skipped) {
|
|
$text = get_string('morenavigationlinks');
|
|
$url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
|
|
$link = new action_link($url, $text, null, null, new pix_icon('t/edit', ''));
|
|
$menu->add_secondary_action($link);
|
|
}
|
|
}
|
|
} else if ($showusermenu) {
|
|
// Get the course admin node from the settings navigation.
|
|
$settingsnode = $this->page->settingsnav->find('useraccount', navigation_node::TYPE_CONTAINER);
|
|
if ($settingsnode) {
|
|
// Build an action menu based on the visible nodes from this navigation tree.
|
|
$this->build_action_menu_from_navigation($menu, $settingsnode);
|
|
}
|
|
}
|
|
|
|
return $this->render($menu);
|
|
}
|
|
|
|
/**
|
|
* This is an optional menu that can be added to a layout by a theme. It contains the
|
|
* menu for the most specific thing from the settings block. E.g. Module administration.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function region_main_settings_menu() {
|
|
$context = $this->page->context;
|
|
$menu = new action_menu();
|
|
|
|
if ($context->contextlevel == CONTEXT_MODULE) {
|
|
|
|
$this->page->navigation->initialise();
|
|
$node = $this->page->navigation->find_active_node();
|
|
$buildmenu = false;
|
|
// If the settings menu has been forced then show the menu.
|
|
if ($this->page->is_settings_menu_forced()) {
|
|
$buildmenu = true;
|
|
} else if (!empty($node) && ($node->type == navigation_node::TYPE_ACTIVITY ||
|
|
$node->type == navigation_node::TYPE_RESOURCE)) {
|
|
|
|
$items = $this->page->navbar->get_items();
|
|
$navbarnode = end($items);
|
|
// We only want to show the menu on the first page of the activity. This means
|
|
// the breadcrumb has no additional nodes.
|
|
if ($navbarnode && ($navbarnode->key === $node->key && $navbarnode->type == $node->type)) {
|
|
$buildmenu = true;
|
|
}
|
|
}
|
|
if ($buildmenu) {
|
|
// Get the course admin node from the settings navigation.
|
|
$node = $this->page->settingsnav->find('modulesettings', navigation_node::TYPE_SETTING);
|
|
if ($node) {
|
|
// Build an action menu based on the visible nodes from this navigation tree.
|
|
$this->build_action_menu_from_navigation($menu, $node);
|
|
}
|
|
}
|
|
|
|
} else if ($context->contextlevel == CONTEXT_COURSECAT) {
|
|
// For course category context, show category settings menu, if we're on the course category page.
|
|
if ($this->page->pagetype === 'course-index-category') {
|
|
$node = $this->page->settingsnav->find('categorysettings', navigation_node::TYPE_CONTAINER);
|
|
if ($node) {
|
|
// Build an action menu based on the visible nodes from this navigation tree.
|
|
$this->build_action_menu_from_navigation($menu, $node);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
$items = $this->page->navbar->get_items();
|
|
$navbarnode = end($items);
|
|
|
|
if ($navbarnode && ($navbarnode->key === 'participants')) {
|
|
$node = $this->page->settingsnav->find('users', navigation_node::TYPE_CONTAINER);
|
|
if ($node) {
|
|
// Build an action menu based on the visible nodes from this navigation tree.
|
|
$this->build_action_menu_from_navigation($menu, $node);
|
|
}
|
|
|
|
}
|
|
}
|
|
return $this->render($menu);
|
|
}
|
|
|
|
/**
|
|
* Take a node in the nav tree and make an action menu out of it.
|
|
* The links are injected in the action menu.
|
|
*
|
|
* @param action_menu $menu
|
|
* @param navigation_node $node
|
|
* @param boolean $indent
|
|
* @param boolean $onlytopleafnodes
|
|
* @return boolean nodesskipped - True if nodes were skipped in building the menu
|
|
*/
|
|
protected function build_action_menu_from_navigation(action_menu $menu,
|
|
navigation_node $node,
|
|
$indent = false,
|
|
$onlytopleafnodes = false) {
|
|
$skipped = false;
|
|
// Build an action menu based on the visible nodes from this navigation tree.
|
|
foreach ($node->children as $menuitem) {
|
|
if ($menuitem->display) {
|
|
if ($onlytopleafnodes && $menuitem->children->count()) {
|
|
$skipped = true;
|
|
continue;
|
|
}
|
|
if ($menuitem->action) {
|
|
if ($menuitem->action instanceof action_link) {
|
|
$link = $menuitem->action;
|
|
// Give preference to setting icon over action icon.
|
|
if (!empty($menuitem->icon)) {
|
|
$link->icon = $menuitem->icon;
|
|
}
|
|
} else {
|
|
$link = new action_link($menuitem->action, $menuitem->text, null, null, $menuitem->icon);
|
|
}
|
|
} else {
|
|
if ($onlytopleafnodes) {
|
|
$skipped = true;
|
|
continue;
|
|
}
|
|
$link = new action_link(new moodle_url('#'), $menuitem->text, null, ['disabled' => true], $menuitem->icon);
|
|
}
|
|
if ($indent) {
|
|
$link->add_class('ml-4');
|
|
}
|
|
if (!empty($menuitem->classes)) {
|
|
$link->add_class(implode(" ", $menuitem->classes));
|
|
}
|
|
|
|
$menu->add_secondary_action($link);
|
|
$skipped = $skipped || $this->build_action_menu_from_navigation($menu, $menuitem, true);
|
|
}
|
|
}
|
|
return $skipped;
|
|
}
|
|
|
|
/**
|
|
* Secure login info.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function secure_login_info() {
|
|
return $this->login_info(false);
|
|
}
|
|
}
|
|
|