See Release Notes
Long Term Support Release
Differences Between: [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 ReflectionMethod; 20 21 /** 22 * Primary navigation renderable test 23 * 24 * @package core 25 * @category navigation 26 * @copyright 2021 onwards Peter Dias 27 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 */ 29 class primary_test extends \advanced_testcase { 30 /** 31 * Basic setup to make sure the nav objects gets generated without any issues. 32 */ 33 public function setUp(): void { 34 global $PAGE; 35 $this->resetAfterTest(); 36 $pagecourse = $this->getDataGenerator()->create_course(); 37 $assign = $this->getDataGenerator()->create_module('assign', ['course' => $pagecourse->id]); 38 $cm = get_coursemodule_from_id('assign', $assign->cmid); 39 $contextrecord = \context_module::instance($cm->id); 40 $pageurl = new \moodle_url('/mod/assign/view.php', ['id' => $cm->instance]); 41 $PAGE->set_cm($cm); 42 $PAGE->set_url($pageurl); 43 $PAGE->set_course($pagecourse); 44 $PAGE->set_context($contextrecord); 45 } 46 47 /** 48 * Test the primary export to confirm we are getting the nodes 49 * 50 * @dataProvider primary_export_provider 51 * @param bool $withcustom Setup with custom menu 52 * @param bool $withlang Setup with langs 53 * @param string $userloggedin The type of user ('admin' or 'guest') if creating setup with logged in user, 54 * otherwise consider the user as non-logged in 55 * @param array $expecteditems An array of nodes expected with content in them. 56 */ 57 public function test_primary_export(bool $withcustom, bool $withlang, string $userloggedin, array $expecteditems) { 58 global $PAGE, $CFG; 59 if ($withcustom) { 60 $CFG->custommenuitems = "Course search|/course/search.php 61 Google|https://google.com.au/ 62 Netflix|https://netflix.com/au"; 63 } 64 if ($userloggedin === 'admin') { 65 $this->setAdminUser(); 66 } else if ($userloggedin === 'guest') { 67 $this->setGuestUser(); 68 } else { 69 $this->setUser(0); 70 } 71 72 // Mimic multiple langs installed. To trigger responses 'get_list_of_translations'. 73 // Note: The text/title of the nodes generated will be 'English(fr), English(de)' but we don't care about this. 74 // We are testing whether the nodes gets generated when the lang menu is available. 75 if ($withlang) { 76 mkdir("$CFG->dataroot/lang/de", 0777, true); 77 mkdir("$CFG->dataroot/lang/fr", 0777, true); 78 // Ensure the new langs are picked up and not taken from the cache. 79 $stringmanager = get_string_manager(); 80 $stringmanager->reset_caches(true); 81 } 82 83 $primary = new primary($PAGE); 84 $renderer = $PAGE->get_renderer('core'); 85 $data = array_filter($primary->export_for_template($renderer)); 86 87 // Assert that the number of returned menu items equals the expected result. 88 $this->assertCount(count($expecteditems), $data); 89 // Assert that returned menu items match the expected items. 90 foreach ($data as $menutype => $value) { 91 $this->assertTrue(in_array($menutype, $expecteditems)); 92 } 93 // When the user is logged in (excluding guest access), assert that lang menu is included as a part of the 94 // user menu when multiple languages are installed. 95 if (isloggedin() && !isguestuser()) { 96 // Look for a language menu item within the user menu items. 97 $usermenulang = array_filter($data['user']['items'], function($usermenuitem) { 98 return $usermenuitem->itemtype !== 'divider' && $usermenuitem->title === get_string('language'); 99 }); 100 if ($withlang) { // If multiple languages are installed. 101 // Assert that the language menu exists within the user menu. 102 $this->assertNotEmpty($usermenulang); 103 } else { // If the aren't any additional installed languages. 104 $this->assertEmpty($usermenulang); 105 } 106 } else { // Otherwise assert that the user menu does not contain any items. 107 $this->assertArrayNotHasKey('items', $data['user']); 108 } 109 } 110 111 /** 112 * Provider for the test_primary_export function. 113 * 114 * @return array 115 */ 116 public function primary_export_provider(): array { 117 return [ 118 "Export the menu data when: custom menu exists; multiple langs installed; user is not logged in." => [ 119 true, true, '', ['mobileprimarynav', 'moremenu', 'lang', 'user'] 120 ], 121 "Export the menu data when: custom menu exists; langs not installed; user is not logged in." => [ 122 true, false, '', ['mobileprimarynav', 'moremenu', 'user'] 123 ], 124 "Export the menu data when: custom menu exists; multiple langs installed; logged in as admin." => [ 125 true, true, 'admin', ['mobileprimarynav', 'moremenu', 'user'] 126 ], 127 "Export the menu data when: custom menu exists; langs not installed; logged in as admin." => [ 128 true, false, 'admin', ['mobileprimarynav', 'moremenu', 'user'] 129 ], 130 "Export the menu data when: custom menu exists; multiple langs installed; logged in as guest." => [ 131 true, true, 'guest', ['mobileprimarynav', 'moremenu', 'lang', 'user'] 132 ], 133 "Export the menu data when: custom menu exists; langs not installed; logged in as guest." => [ 134 true, false, 'guest', ['mobileprimarynav', 'moremenu', 'user'] 135 ], 136 "Export the menu data when: custom menu does not exist; multiple langs installed; logged in as guest." => [ 137 false, true, 'guest', ['mobileprimarynav', 'moremenu', 'lang', 'user'] 138 ], 139 "Export the menu data when: custom menu does not exist; multiple langs installed; logged in as admin." => [ 140 false, true, 'admin', ['mobileprimarynav', 'moremenu', 'user'] 141 ], 142 "Export the menu data when: custom menu does not exist; langs not installed; user is not logged in." => [ 143 false, false, '', ['mobileprimarynav', 'moremenu', 'user'] 144 ], 145 ]; 146 } 147 148 /** 149 * Test the custom menu getter to confirm the nodes gets generated and are returned correctly. 150 * 151 * @dataProvider custom_menu_provider 152 * @param string $config 153 * @param array $expected 154 */ 155 public function test_get_custom_menu(string $config, array $expected) { 156 global $CFG, $PAGE; 157 $CFG->custommenuitems = $config; 158 $output = new primary($PAGE); 159 $method = new ReflectionMethod('core\navigation\output\primary', 'get_custom_menu'); 160 $method->setAccessible(true); 161 $renderer = $PAGE->get_renderer('core'); 162 163 // We can't assert the value of each menuitem "moremenuid" property (because it's random). 164 $custommenufilter = static function(array $custommenu) use (&$custommenufilter): void { 165 foreach ($custommenu as $menuitem) { 166 unset($menuitem->moremenuid); 167 // Recursively move through child items. 168 $custommenufilter($menuitem->children); 169 } 170 }; 171 172 $actual = $method->invoke($output, $renderer); 173 $custommenufilter($actual); 174 175 $this->assertEquals($expected, $actual); 176 } 177 178 /** 179 * Provider for test_get_custom_menu 180 * 181 * @return array 182 */ 183 public function custom_menu_provider(): array { 184 return [ 185 'Simple custom menu' => [ 186 "Course search|/course/search.php 187 Google|https://google.com.au/ 188 Netflix|https://netflix.com/au", [ 189 (object) [ 190 'text' => 'Course search', 191 'url' => 'https://www.example.com/moodle/course/search.php', 192 'title' => '', 193 'sort' => 1, 194 'children' => [], 195 'haschildren' => false, 196 ], 197 (object) [ 198 'text' => 'Google', 199 'url' => 'https://google.com.au/', 200 'title' => '', 201 'sort' => 2, 202 'children' => [], 203 'haschildren' => false, 204 ], 205 (object) [ 206 'text' => 'Netflix', 207 'url' => 'https://netflix.com/au', 208 'title' => '', 209 'sort' => 3, 210 'children' => [], 211 'haschildren' => false, 212 ], 213 ] 214 ], 215 'Complex, nested custom menu' => [ 216 "Moodle community|http://moodle.org 217 -Moodle free support|http://moodle.org/support 218 -Moodle development|http://moodle.org/development 219 --Moodle Tracker|http://tracker.moodle.org 220 --Moodle Docs|https://docs.moodle.org 221 -Moodle News|http://moodle.org/news 222 Moodle company 223 -Moodle commercial hosting|http://moodle.com/hosting 224 -Moodle commercial support|http://moodle.com/support", [ 225 (object) [ 226 'text' => 'Moodle community', 227 'url' => 'http://moodle.org', 228 'title' => '', 229 'sort' => 1, 230 'children' => [ 231 (object) [ 232 'text' => 'Moodle free support', 233 'url' => 'http://moodle.org/support', 234 'title' => '', 235 'sort' => 2, 236 'children' => [], 237 'haschildren' => false, 238 ], 239 (object) [ 240 'text' => 'Moodle development', 241 'url' => 'http://moodle.org/development', 242 'title' => '', 243 'sort' => 3, 244 'children' => [ 245 (object) [ 246 'text' => 'Moodle Tracker', 247 'url' => 'http://tracker.moodle.org', 248 'title' => '', 249 'sort' => 4, 250 'children' => [], 251 'haschildren' => false, 252 ], 253 (object) [ 254 'text' => 'Moodle Docs', 255 'url' => 'https://docs.moodle.org', 256 'title' => '', 257 'sort' => 5, 258 'children' => [], 259 'haschildren' => false, 260 ], 261 ], 262 'haschildren' => true, 263 ], 264 (object) [ 265 'text' => 'Moodle News', 266 'url' => 'http://moodle.org/news', 267 'title' => '', 268 'sort' => 6, 269 'children' => [], 270 'haschildren' => false, 271 ], 272 ], 273 'haschildren' => true, 274 ], 275 (object) [ 276 'text' => 'Moodle company', 277 'url' => null, 278 'title' => '', 279 'sort' => 7, 280 'children' => [ 281 (object) [ 282 'text' => 'Moodle commercial hosting', 283 'url' => 'http://moodle.com/hosting', 284 'title' => '', 285 'sort' => 8, 286 'children' => [], 287 'haschildren' => false, 288 ], 289 (object) [ 290 'text' => 'Moodle commercial support', 291 'url' => 'http://moodle.com/support', 292 'title' => '', 293 'sort' => 9, 294 'children' => [], 295 'haschildren' => false, 296 ], 297 ], 298 'haschildren' => true, 299 ], 300 ] 301 ] 302 ]; 303 } 304 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body