Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

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  }