Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
   1  <?php
   2  // This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
  16  
  17  namespace core\hook\navigation;
  18  
  19  /**
  20   * Test hook for primary navigation.
  21   *
  22   * @coversDefaultClass \core\hook\navigation\primary_extend
  23   *
  24   * @package   core
  25   * @author    Petr Skoda
  26   * @copyright 2023 Open LMS
  27   * @license   https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28   */
  29  class primary_extend_test extends \advanced_testcase {
  30      /**
  31       * Test stoppable_trait.
  32       * @covers ::stop_propagation
  33       */
  34      public function test_stop_propagation() {
  35          global $PAGE;
  36          $this->resetAfterTest();
  37  
  38          $PAGE = new \moodle_page();
  39          $PAGE->set_url('/');
  40          $primarynav = new \core\navigation\views\primary($PAGE);
  41  
  42          $hook = new primary_extend($primarynav);
  43          $this->assertInstanceOf('Psr\EventDispatcher\StoppableEventInterface', $hook);
  44          $this->assertFalse($hook->isPropagationStopped());
  45  
  46          $hook->stop_propagation();
  47          $this->assertTrue($hook->isPropagationStopped());
  48      }
  49  
  50      /**
  51       * Test hook is triggered when initialising primary navigation menu.
  52       * @covers \core\navigation\views\primary::initialise
  53       */
  54      public function test_trigggering() {
  55          global $PAGE;
  56          $this->resetAfterTest();
  57  
  58          $PAGE = new \moodle_page();
  59          $PAGE->set_url('/');
  60  
  61          $count = 0;
  62          $receivedhook = null;
  63          $testcallback = function(primary_extend $hook) use (&$receivedhook, &$count): void {
  64              $count++;
  65              $receivedhook = $hook;
  66          };
  67          $this->redirectHook(primary_extend::class, $testcallback);
  68  
  69          $primarynav = new \core\navigation\views\primary($PAGE);
  70          $this->assertSame(0, $count);
  71          $this->assertNull($receivedhook);
  72  
  73          $primarynav->initialise();
  74          $this->assertSame(1, $count);
  75          $this->assertInstanceOf(primary_extend::class, $receivedhook);
  76      }
  77  
  78      /**
  79       * Verify that nothing except this hook modifies the primary menu.
  80       * @covers \core\navigation\views\primary::initialise
  81       */
  82      public function test_unsupported_hacks() {
  83          global $PAGE;
  84          $this->resetAfterTest();
  85  
  86          $PAGE = new \moodle_page();
  87          $PAGE->set_url('/');
  88  
  89          $testcallback = function(primary_extend $hook): void {
  90              // Nothing to do, propagation is stopped by hook redirection.
  91          };
  92          $this->redirectHook(primary_extend::class, $testcallback);
  93  
  94          $primarynav = new \core\navigation\views\primary($PAGE);
  95          $primarynav->initialise();
  96          $this->assertSame(['home'], $primarynav->get_children_key_list(),
  97              'Unsupported primary menu modification detected, use new primary_extend hook instead.');
  98  
  99          $this->setAdminUser();
 100          $primarynav = new \core\navigation\views\primary($PAGE);
 101          $primarynav->initialise();
 102          $this->assertSame(['home', 'myhome', 'mycourses'], $primarynav->get_children_key_list(),
 103              'Unsupported primary menu modification detected, use new primary_extend hook instead.');
 104      }
 105  
 106      /**
 107       * Test adding of primary menu items via hook.
 108       * @covers \core\navigation\views\primary::initialise
 109       */
 110      public function test_primary_menu_extending() {
 111          global $PAGE;
 112          $this->resetAfterTest();
 113  
 114          $PAGE = new \moodle_page();
 115          $PAGE->set_url('/');
 116  
 117          $testcallback = function(primary_extend $hook): void {
 118              $primaryview = $hook->get_primaryview();
 119              $primaryview->add('Pokus', null);
 120          };
 121          $this->redirectHook(primary_extend::class, $testcallback);
 122  
 123          $primarynav = new \core\navigation\views\primary($PAGE);
 124          $primarynav->initialise();
 125          $keys = $primarynav->get_children_key_list();
 126          $this->assertCount(2, $keys);
 127          $firstkey = array_shift($keys);
 128          $this->assertSame('home', $firstkey);
 129          $secondkey = array_shift($keys);
 130          /** @var \navigation_node $pokus */
 131          $pokus = $primarynav->get($secondkey);
 132          $this->assertInstanceOf(\navigation_node::class, $pokus);
 133          $this->assertSame('Pokus', $pokus->text);
 134      }
 135  
 136      /**
 137       * Test replacing of the whole primary menu.
 138       * @covers \core\navigation\views\primary::initialise
 139       */
 140      public function test_primary_menu_replacing() {
 141          global $PAGE;
 142          $this->resetAfterTest();
 143  
 144          $PAGE = new \moodle_page();
 145          $PAGE->set_url('/');
 146  
 147          $testcallback = function(primary_extend $hook): void {
 148              $primaryview = $hook->get_primaryview();
 149              $keys = $primaryview->get_children_key_list();
 150              foreach ($keys as $key) {
 151                  $item = $primaryview->get($key);
 152                  $item->remove();
 153              }
 154              $primaryview->add('Pokus', null);
 155              // Technically we do not need to stop because observers are overridden,
 156              // but this can be used as an example for plugin that wants to stop
 157              // adding of primary menu items from plugins.
 158              $hook->stop_propagation();
 159          };
 160          $this->redirectHook(primary_extend::class, $testcallback);
 161  
 162          $primarynav = new \core\navigation\views\primary($PAGE);
 163          $primarynav->initialise();
 164          $keys = $primarynav->get_children_key_list();
 165          $this->assertCount(1, $keys);
 166          $firstkey = array_shift($keys);
 167          /** @var \navigation_node $pokus */
 168          $pokus = $primarynav->get($firstkey);
 169          $this->assertInstanceOf(\navigation_node::class, $pokus);
 170          $this->assertSame('Pokus', $pokus->text);
 171      }
 172  }