Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

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