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 310 and 401] [Versions 39 and 401] [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  /**
  18   * Unit tests.
  19   *
  20   * @package filter_glossary
  21   * @category test
  22   * @copyright 2013 The Open University
  23   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  namespace filter_glossary;
  27  
  28  /**
  29   * Test case for glossary.
  30   */
  31  class filter_test extends \advanced_testcase {
  32  
  33      public function test_link_to_entry_with_alias() {
  34          global $CFG;
  35          $this->resetAfterTest(true);
  36  
  37          // Enable glossary filter at top level.
  38          filter_set_global_state('glossary', TEXTFILTER_ON);
  39          $CFG->glossary_linkentries = 1;
  40  
  41          // Create a test course.
  42          $course = $this->getDataGenerator()->create_course();
  43          $context = \context_course::instance($course->id);
  44  
  45          // Create a glossary.
  46          $glossary = $this->getDataGenerator()->create_module('glossary',
  47                  array('course' => $course->id, 'mainglossary' => 1));
  48  
  49          // Create two entries with ampersands and one normal entry.
  50          $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
  51          $normal = $generator->create_content($glossary, array('concept' => 'entry name'),
  52                  array('first alias', 'second alias'));
  53  
  54          // Format text with all three entries in HTML.
  55          $html = '<p>First we have entry name, then we have it twp aliases first alias and second alias.</p>';
  56          $filtered = format_text($html, FORMAT_HTML, array('context' => $context));
  57  
  58          // Find all the glossary links in the result.
  59          $matches = array();
  60          preg_match_all('~eid=([0-9]+).*?title="(.*?)"~', $filtered, $matches);
  61  
  62          // There should be 3 glossary links.
  63          $this->assertEquals(3, count($matches[1]));
  64          $this->assertEquals($normal->id, $matches[1][0]);
  65          $this->assertEquals($normal->id, $matches[1][1]);
  66          $this->assertEquals($normal->id, $matches[1][2]);
  67  
  68          // Check text of title attribute.
  69          $this->assertEquals($glossary->name . ': entry name',   $matches[2][0]);
  70          $this->assertEquals($glossary->name . ': first alias',  $matches[2][1]);
  71          $this->assertEquals($glossary->name . ': second alias', $matches[2][2]);
  72      }
  73  
  74      public function test_longest_link_used() {
  75          global $CFG;
  76          $this->resetAfterTest(true);
  77  
  78          // Enable glossary filter at top level.
  79          filter_set_global_state('glossary', TEXTFILTER_ON);
  80          $CFG->glossary_linkentries = 1;
  81  
  82          // Create a test course.
  83          $course = $this->getDataGenerator()->create_course();
  84          $context = \context_course::instance($course->id);
  85  
  86          // Create a glossary.
  87          $glossary = $this->getDataGenerator()->create_module('glossary',
  88                  array('course' => $course->id, 'mainglossary' => 1));
  89  
  90          // Create two entries with ampersands and one normal entry.
  91          $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
  92          $shorter = $generator->create_content($glossary, array('concept' => 'Tim'));
  93          $longer = $generator->create_content($glossary, array('concept' => 'Time'));
  94  
  95          // Format text with all three entries in HTML.
  96          $html = '<p>Time will tell</p>';
  97          $filtered = format_text($html, FORMAT_HTML, array('context' => $context));
  98  
  99          // Find all the glossary links in the result.
 100          $matches = array();
 101          preg_match_all('~eid=([0-9]+).*?title="(.*?)"~', $filtered, $matches);
 102  
 103          // There should be 1 glossary link to Time, not Tim.
 104          $this->assertEquals(1, count($matches[1]));
 105          $this->assertEquals($longer->id, $matches[1][0]);
 106  
 107          // Check text of title attribute.
 108          $this->assertEquals($glossary->name . ': Time',   $matches[2][0]);
 109      }
 110  
 111      public function test_link_to_category() {
 112          global $CFG;
 113          $this->resetAfterTest(true);
 114  
 115          // Enable glossary filter at top level.
 116          filter_set_global_state('glossary', TEXTFILTER_ON);
 117          $CFG->glossary_linkentries = 1;
 118  
 119          // Create a test course.
 120          $course = $this->getDataGenerator()->create_course();
 121          $context = \context_course::instance($course->id);
 122  
 123          // Create a glossary.
 124          $glossary = $this->getDataGenerator()->create_module('glossary',
 125                  array('course' => $course->id, 'mainglossary' => 1));
 126  
 127          // Create two entries with ampersands and one normal entry.
 128          /** @var mod_glossary_generator $generator */
 129          $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 130          $category = $generator->create_category($glossary, array('name' => 'My category', 'usedynalink' => 1));
 131  
 132          // Format text with all three entries in HTML.
 133          $html = '<p>This is My category you know.</p>';
 134          $filtered = format_text($html, FORMAT_HTML, array('context' => $context));
 135  
 136          // Find all the glossary links in the result.
 137          $matches = array();
 138          preg_match_all('~hook=([0-9]+).*?title="(.*?)"~', $filtered, $matches);
 139  
 140          // There should be 1 glossary link.
 141          $this->assertEquals(1, count($matches[1]));
 142          $this->assertEquals($category->id, $matches[1][0]);
 143          $this->assertEquals($glossary->name . ': Category My category', $matches[2][0]);
 144      }
 145  
 146      /**
 147       * Test ampersands.
 148       */
 149      public function test_ampersands() {
 150          global $CFG;
 151          $this->resetAfterTest(true);
 152  
 153          // Enable glossary filter at top level.
 154          filter_set_global_state('glossary', TEXTFILTER_ON);
 155          $CFG->glossary_linkentries = 1;
 156  
 157          // Create a test course.
 158          $course = $this->getDataGenerator()->create_course();
 159          $context = \context_course::instance($course->id);
 160  
 161          // Create a glossary.
 162          $glossary = $this->getDataGenerator()->create_module('glossary',
 163                  array('course' => $course->id, 'mainglossary' => 1));
 164  
 165          // Create two entries with ampersands and one normal entry.
 166          /** @var mod_glossary_generator $generator */
 167          $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 168          $normal = $generator->create_content($glossary, array('concept' => 'normal'));
 169          $amp1 = $generator->create_content($glossary, array('concept' => 'A&B'));
 170          $amp2 = $generator->create_content($glossary, array('concept' => 'C&amp;D'));
 171  
 172          // Format text with all three entries in HTML.
 173          $html = '<p>A&amp;B C&amp;D normal</p>';
 174          $filtered = format_text($html, FORMAT_HTML, array('context' => $context));
 175  
 176          // Find all the glossary links in the result.
 177          $matches = array();
 178          preg_match_all('~eid=([0-9]+).*?title="(.*?)"~', $filtered, $matches);
 179  
 180          // There should be 3 glossary links.
 181          $this->assertEquals(3, count($matches[1]));
 182          $this->assertEquals($amp1->id, $matches[1][0]);
 183          $this->assertEquals($amp2->id, $matches[1][1]);
 184          $this->assertEquals($normal->id, $matches[1][2]);
 185  
 186          // Check text and escaping of title attribute.
 187          $this->assertEquals($glossary->name . ': A&amp;B', $matches[2][0]);
 188          $this->assertEquals($glossary->name . ': C&amp;D', $matches[2][1]);
 189          $this->assertEquals($glossary->name . ': normal', $matches[2][2]);
 190      }
 191  
 192      /**
 193       * Test brackets.
 194       */
 195      public function test_brackets() {
 196          global $CFG;
 197          $this->resetAfterTest(true);
 198  
 199          // Enable glossary filter at top level.
 200          filter_set_global_state('glossary', TEXTFILTER_ON);
 201          $CFG->glossary_linkentries = 1;
 202  
 203          // Create a test course.
 204          $course = $this->getDataGenerator()->create_course();
 205          $context = \context_course::instance($course->id);
 206  
 207          // Create a glossary.
 208          $glossary = $this->getDataGenerator()->create_module('glossary',
 209                  array('course' => $course->id, 'mainglossary' => 1));
 210  
 211          // Create two entries with ampersands and one normal entry.
 212          /** @var mod_glossary_generator $generator */
 213          $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 214          $simple = $generator->create_content($glossary, array('concept' => 'simple'));
 215          $withbrackets = $generator->create_content($glossary, array('concept' => 'more complex (perhaps)'));
 216          $test2 = $generator->create_content($glossary, array('concept' => 'Test (2)'));
 217  
 218          // Format text with all three entries in HTML.
 219          $html = '<p>Some thigns are simple. Others are more complex (perhaps). Test (2).</p>';
 220          $filtered = format_text($html, FORMAT_HTML, array('context' => $context));
 221  
 222          // Find all the glossary links in the result.
 223          $matches = array();
 224          preg_match_all('~eid=([0-9]+).*?title="(.*?)"~', $filtered, $matches);
 225  
 226          // There should be 3 glossary links.
 227          $this->assertEquals(3, count($matches[1]));
 228          $this->assertEquals($simple->id, $matches[1][0]);
 229          $this->assertEquals($withbrackets->id, $matches[1][1]);
 230          $this->assertEquals($test2->id, $matches[1][2]);
 231  
 232          // Check text and escaping of title attribute.
 233          $this->assertEquals($glossary->name . ': simple', $matches[2][0]);
 234          $this->assertEquals($glossary->name . ': more complex (perhaps)', $matches[2][1]);
 235          $this->assertEquals($glossary->name . ': Test (2)', $matches[2][2]);
 236      }
 237  
 238      public function test_exclude_excludes_link_to_entry_with_alias() {
 239          global $CFG, $GLOSSARY_EXCLUDEENTRY;
 240  
 241          $this->resetAfterTest(true);
 242  
 243          // Enable glossary filter at top level.
 244          filter_set_global_state('glossary', TEXTFILTER_ON);
 245          $CFG->glossary_linkentries = 1;
 246  
 247          // Create a test course.
 248          $course = $this->getDataGenerator()->create_course();
 249          $context = \context_course::instance($course->id);
 250  
 251          // Create a glossary.
 252          $glossary = $this->getDataGenerator()->create_module('glossary',
 253                  array('course' => $course->id, 'mainglossary' => 1));
 254  
 255          // Create two entries with ampersands and one normal entry.
 256          $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 257          $tobeexcluded = $generator->create_content($glossary, array('concept' => 'entry name'),
 258                  array('first alias', 'second alias'));
 259          $normal = $generator->create_content($glossary, array('concept' => 'other entry'));
 260  
 261          // Format text with all three entries in HTML.
 262          $html = '<p>First we have entry name, then we have it twp aliases first alias and second alias. ' .
 263                  'In this case, those should not be linked, but this other entry should be.</p>';
 264          $GLOSSARY_EXCLUDEENTRY = $tobeexcluded->id;
 265          $filtered = format_text($html, FORMAT_HTML, array('context' => $context));
 266          $GLOSSARY_EXCLUDEENTRY = null;
 267  
 268          // Find all the glossary links in the result.
 269          $matches = array();
 270          preg_match_all('~eid=([0-9]+).*?title="(.*?)"~', $filtered, $matches);
 271  
 272          // There should be 1 glossary links.
 273          $this->assertEquals(1, count($matches[1]));
 274          $this->assertEquals($normal->id, $matches[1][0]);
 275          $this->assertEquals($glossary->name . ': other entry', $matches[2][0]);
 276      }
 277  
 278      public function test_exclude_does_not_exclude_categories() {
 279          global $CFG, $GLOSSARY_EXCLUDEENTRY;
 280          $this->resetAfterTest(true);
 281  
 282          // Enable glossary filter at top level.
 283          filter_set_global_state('glossary', TEXTFILTER_ON);
 284          $CFG->glossary_linkentries = 1;
 285  
 286          // Create a test course.
 287          $course = $this->getDataGenerator()->create_course();
 288          $context = \context_course::instance($course->id);
 289  
 290          // Create a glossary.
 291          $glossary = $this->getDataGenerator()->create_module('glossary',
 292                  array('course' => $course->id, 'mainglossary' => 1));
 293  
 294          // Create two entries with ampersands and one normal entry.
 295          /** @var mod_glossary_generator $generator */
 296          $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 297          $category = $generator->create_category($glossary, array('name' => 'My category', 'usedynalink' => 1));
 298  
 299          // Format text with all three entries in HTML.
 300          $html = '<p>This is My category you know.</p>';
 301          $GLOSSARY_EXCLUDEENTRY = $category->id;
 302          $filtered = format_text($html, FORMAT_HTML, array('context' => $context));
 303          $GLOSSARY_EXCLUDEENTRY = null;
 304  
 305          // Find all the glossary links in the result.
 306          $matches = array();
 307          preg_match_all('~hook=([0-9]+).*?title="(.*?)"~', $filtered, $matches);
 308  
 309          // There should be 1 glossary link.
 310          $this->assertEquals(1, count($matches[1]));
 311          $this->assertEquals($category->id, $matches[1][0]);
 312          $this->assertEquals($glossary->name . ': Category My category', $matches[2][0]);
 313      }
 314  }