See Release Notes
Long Term Support Release
Differences Between: [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core\navigation\output; 18 19 use renderable; 20 use renderer_base; 21 use templatable; 22 use custom_menu; 23 24 /** 25 * Primary navigation renderable 26 * 27 * This file combines primary nav, custom menu, lang menu and 28 * usermenu into a standardized format for the frontend 29 * 30 * @package core 31 * @category navigation 32 * @copyright 2021 onwards Peter Dias 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 */ 35 class primary implements renderable, templatable { 36 /** @var moodle_page $page the moodle page that the navigation belongs to */ 37 private $page = null; 38 39 /** 40 * primary constructor. 41 * @param \moodle_page $page 42 */ 43 public function __construct($page) { 44 $this->page = $page; 45 } 46 47 /** 48 * Combine the various menus into a standardized output. 49 * 50 * @param renderer_base|null $output 51 * @return array 52 */ 53 public function export_for_template(?renderer_base $output = null): array { 54 if (!$output) { 55 $output = $this->page->get_renderer('core'); 56 } 57 58 $menudata = (object) array_merge($this->get_primary_nav(), $this->get_custom_menu($output)); 59 $moremenu = new \core\navigation\output\more_menu($menudata, 'navbar-nav', false); 60 $mobileprimarynav = array_merge($this->get_primary_nav(), $this->get_custom_menu($output)); 61 62 $languagemenu = new \core\output\language_menu($this->page); 63 64 return [ 65 'mobileprimarynav' => $mobileprimarynav, 66 'moremenu' => $moremenu->export_for_template($output), 67 'lang' => !isloggedin() || isguestuser() ? $languagemenu->export_for_template($output) : [], 68 'user' => $this->get_user_menu($output), 69 ]; 70 } 71 72 /** 73 * Get the primary nav object and standardize the output 74 * 75 * @return array 76 */ 77 protected function get_primary_nav(): array { 78 $nodes = []; 79 foreach ($this->page->primarynav->children as $node) { 80 $nodes[] = [ 81 'title' => $node->get_title(), 82 'url' => $node->action(), 83 'text' => $node->text, 84 'icon' => $node->icon, 85 'isactive' => $node->isactive, 86 'key' => $node->key, 87 ]; 88 } 89 90 return $nodes; 91 } 92 93 /** 94 * Custom menu items reside on the same level as the original nodes. 95 * Fetch and convert the nodes to a standardised array. 96 * 97 * @param renderer_base $output 98 * @return array 99 */ 100 protected function get_custom_menu(renderer_base $output): array { 101 global $CFG; 102 103 // Early return if a custom menu does not exists. 104 if (empty($CFG->custommenuitems)) { 105 return []; 106 } 107 108 $custommenuitems = $CFG->custommenuitems; 109 $currentlang = current_language(); 110 $custommenunodes = custom_menu::convert_text_to_menu_nodes($custommenuitems, $currentlang); 111 $nodes = []; 112 foreach ($custommenunodes as $node) { 113 $nodes[] = $node->export_for_template($output); 114 } 115 116 return $nodes; 117 } 118 119 /** 120 * Get/Generate the user menu. 121 * 122 * This is leveraging the data from user_get_user_navigation_info and the logic in $OUTPUT->user_menu() 123 * 124 * @param renderer_base $output 125 * @return array 126 */ 127 public function get_user_menu(renderer_base $output): array { 128 global $CFG, $USER, $PAGE; 129 require_once($CFG->dirroot . '/user/lib.php'); 130 131 $usermenudata = []; 132 $submenusdata = []; 133 $info = user_get_user_navigation_info($USER, $PAGE); 134 if (isset($info->unauthenticateduser)) { 135 $info->unauthenticateduser['content'] = get_string($info->unauthenticateduser['content']); 136 $info->unauthenticateduser['url'] = get_login_url(); 137 return (array) $info; 138 } 139 // Gather all the avatar data to be displayed in the user menu. 140 $usermenudata['avatardata'][] = [ 141 'content' => $info->metadata['useravatar'], 142 'classes' => 'current' 143 ]; 144 $usermenudata['userfullname'] = $info->metadata['realuserfullname'] ?? $info->metadata['userfullname']; 145 146 // Logged in as someone else. 147 if ($info->metadata['asotheruser']) { 148 $usermenudata['avatardata'][] = [ 149 'content' => $info->metadata['realuseravatar'], 150 'classes' => 'realuser' 151 ]; 152 $usermenudata['metadata'][] = [ 153 'content' => get_string('loggedinas', 'moodle', $info->metadata['userfullname']), 154 'classes' => 'viewingas' 155 ]; 156 } 157 158 // Gather all the meta data to be displayed in the user menu. 159 $metadata = [ 160 'asotherrole' => [ 161 'value' => 'rolename', 162 'class' => 'role role-##GENERATEDCLASS##', 163 ], 164 'userloginfail' => [ 165 'value' => 'userloginfail', 166 'class' => 'loginfailures', 167 ], 168 'asmnetuser' => [ 169 'value' => 'mnetidprovidername', 170 'class' => 'mnet mnet-##GENERATEDCLASS##', 171 ], 172 ]; 173 foreach ($metadata as $key => $value) { 174 if (!empty($info->metadata[$key])) { 175 $content = $info->metadata[$value['value']] ?? ''; 176 $generatedclass = strtolower(preg_replace('#[ ]+#', '-', trim($content))); 177 $customclass = str_replace('##GENERATEDCLASS##', $generatedclass, ($value['class'] ?? '')); 178 $usermenudata['metadata'][] = [ 179 'content' => $content, 180 'classes' => $customclass 181 ]; 182 } 183 } 184 185 $modifiedarray = array_map(function($value) { 186 $value->divider = $value->itemtype == 'divider'; 187 $value->link = $value->itemtype == 'link'; 188 if (isset($value->pix) && !empty($value->pix)) { 189 $value->pixicon = $value->pix; 190 unset($value->pix); 191 } 192 return $value; 193 }, $info->navitems); 194 195 // Include the language menu as a submenu within the user menu. 196 $languagemenu = new \core\output\language_menu($this->page); 197 $langmenu = $languagemenu->export_for_template($output); 198 if (!empty($langmenu)) { 199 $languageitems = $langmenu['items']; 200 // If there are available languages, generate the data for the the language selector submenu. 201 if (!empty($languageitems)) { 202 $langsubmenuid = uniqid(); 203 // Generate the data for the link to language selector submenu. 204 $language = (object) [ 205 'itemtype' => 'submenu-link', 206 'submenuid' => $langsubmenuid, 207 'title' => get_string('language'), 208 'divider' => false, 209 'submenulink' => true, 210 ]; 211 212 // Place the link before the 'Log out' menu item which is either the last item in the menu or 213 // second to last when 'Switch roles' is available. 214 $menuposition = count($modifiedarray) - 1; 215 if (has_capability('moodle/role:switchroles', $PAGE->context)) { 216 $menuposition = count($modifiedarray) - 2; 217 } 218 array_splice($modifiedarray, $menuposition, 0, [$language]); 219 220 // Generate the data for the language selector submenu. 221 $submenusdata[] = (object)[ 222 'id' => $langsubmenuid, 223 'title' => get_string('languageselector'), 224 'items' => $languageitems, 225 ]; 226 } 227 } 228 229 // Add divider before the last item. 230 $modifiedarray[count($modifiedarray) - 2]->divider = true; 231 $usermenudata['items'] = $modifiedarray; 232 $usermenudata['submenus'] = array_values($submenusdata); 233 234 return $usermenudata; 235 } 236 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body