Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 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 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 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   * Tests for the parts of ../filterlib.php that involve loading the configuration
  19   * from, and saving the configuration to, the database.
  20   *
  21   * @package   core_filter
  22   * @category  phpunit
  23   * @copyright 2009 Tim Hunt
  24   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  global $CFG;
  30  require_once($CFG->libdir . '/filterlib.php');
  31  
  32  /**
  33   * Test filters.
  34   */
  35  class core_filterlib_testcase extends advanced_testcase {
  36  
  37      private function assert_only_one_filter_globally($filter, $state) {
  38          global $DB;
  39          $recs = $DB->get_records('filter_active');
  40          $this->assertCount(1, $recs);
  41          $rec = reset($recs);
  42          unset($rec->id);
  43          $expectedrec = new stdClass();
  44          $expectedrec->filter = $filter;
  45          $expectedrec->contextid = context_system::instance()->id;
  46          $expectedrec->active = $state;
  47          $expectedrec->sortorder = 1;
  48          $this->assertEquals($expectedrec, $rec);
  49      }
  50  
  51      private function assert_global_sort_order($filters) {
  52          global $DB;
  53  
  54          $sortedfilters = $DB->get_records_menu('filter_active',
  55              array('contextid' => context_system::instance()->id), 'sortorder', 'sortorder,filter');
  56          $testarray = array();
  57          $index = 1;
  58          foreach ($filters as $filter) {
  59              $testarray[$index++] = $filter;
  60          }
  61          $this->assertEquals($testarray, $sortedfilters);
  62      }
  63  
  64      public function test_set_filter_globally_on() {
  65          $this->resetAfterTest();
  66          $this->remove_all_filters_from_config(); // Remove all filters.
  67          // Setup fixture.
  68          // Exercise SUT.
  69          filter_set_global_state('name', TEXTFILTER_ON);
  70          // Validate.
  71          $this->assert_only_one_filter_globally('name', TEXTFILTER_ON);
  72      }
  73  
  74      public function test_set_filter_globally_off() {
  75          $this->resetAfterTest();
  76          $this->remove_all_filters_from_config(); // Remove all filters.
  77          // Setup fixture.
  78          // Exercise SUT.
  79          filter_set_global_state('name', TEXTFILTER_OFF);
  80          // Validate.
  81          $this->assert_only_one_filter_globally('name', TEXTFILTER_OFF);
  82      }
  83  
  84      public function test_set_filter_globally_disabled() {
  85          $this->resetAfterTest();
  86          $this->remove_all_filters_from_config(); // Remove all filters.
  87          // Setup fixture.
  88          // Exercise SUT.
  89          filter_set_global_state('name', TEXTFILTER_DISABLED);
  90          // Validate.
  91          $this->assert_only_one_filter_globally('name', TEXTFILTER_DISABLED);
  92      }
  93  
  94      /**
  95       * @expectedException coding_exception
  96       */
  97      public function test_global_config_exception_on_invalid_state() {
  98          $this->resetAfterTest();
  99          filter_set_global_state('name', 0);
 100      }
 101  
 102      public function test_auto_sort_order() {
 103          $this->resetAfterTest();
 104          $this->remove_all_filters_from_config(); // Remove all filters.
 105          // Setup fixture.
 106          // Exercise SUT.
 107          filter_set_global_state('one', TEXTFILTER_DISABLED);
 108          filter_set_global_state('two', TEXTFILTER_DISABLED);
 109          // Validate.
 110          $this->assert_global_sort_order(array('one', 'two'));
 111      }
 112  
 113      public function test_auto_sort_order_enabled() {
 114          $this->resetAfterTest();
 115          $this->remove_all_filters_from_config(); // Remove all filters.
 116          // Setup fixture.
 117          // Exercise SUT.
 118          filter_set_global_state('one', TEXTFILTER_ON);
 119          filter_set_global_state('two', TEXTFILTER_OFF);
 120          // Validate.
 121          $this->assert_global_sort_order(array('one', 'two'));
 122      }
 123  
 124      public function test_update_existing_dont_duplicate() {
 125          $this->resetAfterTest();
 126          $this->remove_all_filters_from_config(); // Remove all filters.
 127          // Setup fixture.
 128          // Exercise SUT.
 129          filter_set_global_state('name', TEXTFILTER_ON);
 130          filter_set_global_state('name', TEXTFILTER_OFF);
 131          // Validate.
 132          $this->assert_only_one_filter_globally('name', TEXTFILTER_OFF);
 133      }
 134  
 135      public function test_update_reorder_down() {
 136          $this->resetAfterTest();
 137          $this->remove_all_filters_from_config(); // Remove all filters.
 138          // Setup fixture.
 139          filter_set_global_state('one', TEXTFILTER_ON);
 140          filter_set_global_state('two', TEXTFILTER_ON);
 141          filter_set_global_state('three', TEXTFILTER_ON);
 142          // Exercise SUT.
 143          filter_set_global_state('two', TEXTFILTER_ON, -1);
 144          // Validate.
 145          $this->assert_global_sort_order(array('two', 'one', 'three'));
 146      }
 147  
 148      public function test_update_reorder_up() {
 149          $this->resetAfterTest();
 150          $this->remove_all_filters_from_config(); // Remove all filters.
 151          // Setup fixture.
 152          filter_set_global_state('one', TEXTFILTER_ON);
 153          filter_set_global_state('two', TEXTFILTER_ON);
 154          filter_set_global_state('three', TEXTFILTER_ON);
 155          filter_set_global_state('four', TEXTFILTER_ON);
 156          // Exercise SUT.
 157          filter_set_global_state('two', TEXTFILTER_ON, 1);
 158          // Validate.
 159          $this->assert_global_sort_order(array('one', 'three', 'two', 'four'));
 160      }
 161  
 162      public function test_auto_sort_order_change_to_enabled() {
 163          $this->resetAfterTest();
 164          $this->remove_all_filters_from_config(); // Remove all filters.
 165          // Setup fixture.
 166          filter_set_global_state('one', TEXTFILTER_ON);
 167          filter_set_global_state('two', TEXTFILTER_DISABLED);
 168          filter_set_global_state('three', TEXTFILTER_DISABLED);
 169          // Exercise SUT.
 170          filter_set_global_state('three', TEXTFILTER_ON);
 171          // Validate.
 172          $this->assert_global_sort_order(array('one', 'three', 'two'));
 173      }
 174  
 175      public function test_auto_sort_order_change_to_disabled() {
 176          $this->resetAfterTest();
 177          $this->remove_all_filters_from_config(); // Remove all filters.
 178          // Setup fixture.
 179          filter_set_global_state('one', TEXTFILTER_ON);
 180          filter_set_global_state('two', TEXTFILTER_ON);
 181          filter_set_global_state('three', TEXTFILTER_DISABLED);
 182          // Exercise SUT.
 183          filter_set_global_state('one', TEXTFILTER_DISABLED);
 184          // Validate.
 185          $this->assert_global_sort_order(array('two', 'one', 'three'));
 186      }
 187  
 188      public function test_filter_get_global_states() {
 189          $this->resetAfterTest();
 190          $this->remove_all_filters_from_config(); // Remove all filters.
 191          // Setup fixture.
 192          filter_set_global_state('one', TEXTFILTER_ON);
 193          filter_set_global_state('two', TEXTFILTER_OFF);
 194          filter_set_global_state('three', TEXTFILTER_DISABLED);
 195          // Exercise SUT.
 196          $filters = filter_get_global_states();
 197          // Validate.
 198          $this->assertEquals(array(
 199              'one' => (object) array('filter' => 'one', 'active' => TEXTFILTER_ON, 'sortorder' => 1),
 200              'two' => (object) array('filter' => 'two', 'active' => TEXTFILTER_OFF, 'sortorder' => 2),
 201              'three' => (object) array('filter' => 'three', 'active' => TEXTFILTER_DISABLED, 'sortorder' => 3)
 202          ), $filters);
 203      }
 204  
 205      private function assert_only_one_local_setting($filter, $contextid, $state) {
 206          global $DB;
 207          $recs = $DB->get_records('filter_active');
 208          $this->assertEquals(1, count($recs), 'More than one record returned %s.');
 209          $rec = reset($recs);
 210          unset($rec->id);
 211          unset($rec->sortorder);
 212          $expectedrec = new stdClass();
 213          $expectedrec->filter = $filter;
 214          $expectedrec->contextid = $contextid;
 215          $expectedrec->active = $state;
 216          $this->assertEquals($expectedrec, $rec);
 217      }
 218  
 219      private function assert_no_local_setting() {
 220          global $DB;
 221          $this->assertEquals(0, $DB->count_records('filter_active'));
 222      }
 223  
 224      public function test_local_on() {
 225          $this->resetAfterTest();
 226          $this->remove_all_filters_from_config(); // Remove all filters.
 227          // Exercise SUT.
 228          filter_set_local_state('name', 123, TEXTFILTER_ON);
 229          // Validate.
 230          $this->assert_only_one_local_setting('name', 123, TEXTFILTER_ON);
 231      }
 232  
 233      public function test_local_off() {
 234          $this->resetAfterTest();
 235          $this->remove_all_filters_from_config(); // Remove all filters.
 236          // Exercise SUT.
 237          filter_set_local_state('name', 123, TEXTFILTER_OFF);
 238          // Validate.
 239          $this->assert_only_one_local_setting('name', 123, TEXTFILTER_OFF);
 240      }
 241  
 242      public function test_local_inherit() {
 243          $this->resetAfterTest();
 244          $this->remove_all_filters_from_config(); // Remove all filters.
 245          // Exercise SUT.
 246          filter_set_local_state('name', 123, TEXTFILTER_INHERIT);
 247          // Validate.
 248          $this->assert_no_local_setting();
 249      }
 250  
 251      /**
 252       * @expectedException coding_exception
 253       */
 254      public function test_local_invalid_state_throws_exception() {
 255          $this->resetAfterTest();
 256          // Exercise SUT.
 257          filter_set_local_state('name', 123, -9999);
 258      }
 259  
 260      /**
 261       * @expectedException coding_exception
 262       */
 263      public function test_throws_exception_when_setting_global() {
 264          $this->resetAfterTest();
 265          // Exercise SUT.
 266          filter_set_local_state('name', context_system::instance()->id, TEXTFILTER_INHERIT);
 267      }
 268  
 269      public function test_local_inherit_deletes_existing() {
 270          $this->resetAfterTest();
 271          $this->remove_all_filters_from_config(); // Remove all filters.
 272          // Setup fixture.
 273          filter_set_local_state('name', 123, TEXTFILTER_INHERIT);
 274          // Exercise SUT.
 275          filter_set_local_state('name', 123, TEXTFILTER_INHERIT);
 276          // Validate.
 277          $this->assert_no_local_setting();
 278      }
 279  
 280      private function assert_only_one_config($filter, $context, $name, $value) {
 281          global $DB;
 282          $recs = $DB->get_records('filter_config');
 283          $this->assertEquals(1, count($recs), 'More than one record returned %s.');
 284          $rec = reset($recs);
 285          unset($rec->id);
 286          $expectedrec = new stdClass();
 287          $expectedrec->filter = $filter;
 288          $expectedrec->contextid = $context;
 289          $expectedrec->name = $name;
 290          $expectedrec->value = $value;
 291          $this->assertEquals($expectedrec, $rec);
 292      }
 293  
 294      public function test_set_new_config() {
 295          $this->resetAfterTest();
 296          $this->remove_all_filters_from_config(); // Remove all filters.
 297          // Exercise SUT.
 298          filter_set_local_config('name', 123, 'settingname', 'An arbitrary value');
 299          // Validate.
 300          $this->assert_only_one_config('name', 123, 'settingname', 'An arbitrary value');
 301      }
 302  
 303      public function test_update_existing_config() {
 304          $this->resetAfterTest();
 305          $this->remove_all_filters_from_config(); // Remove all filters.
 306          // Setup fixture.
 307          filter_set_local_config('name', 123, 'settingname', 'An arbitrary value');
 308          // Exercise SUT.
 309          filter_set_local_config('name', 123, 'settingname', 'A changed value');
 310          // Validate.
 311          $this->assert_only_one_config('name', 123, 'settingname', 'A changed value');
 312      }
 313  
 314      public function test_filter_get_local_config() {
 315          $this->resetAfterTest();
 316          // Setup fixture.
 317          filter_set_local_config('name', 123, 'setting1', 'An arbitrary value');
 318          filter_set_local_config('name', 123, 'setting2', 'Another arbitrary value');
 319          filter_set_local_config('name', 122, 'settingname', 'Value from another context');
 320          filter_set_local_config('other', 123, 'settingname', 'Someone else\'s value');
 321          // Exercise SUT.
 322          $config = filter_get_local_config('name', 123);
 323          // Validate.
 324          $this->assertEquals(array('setting1' => 'An arbitrary value', 'setting2' => 'Another arbitrary value'), $config);
 325      }
 326  
 327      protected function setup_available_in_context_tests() {
 328          $course = $this->getDataGenerator()->create_course(array('category'=>1));
 329  
 330          $childcontext = context_coursecat::instance(1);
 331          $childcontext2 = context_course::instance($course->id);
 332          $syscontext = context_system::instance();
 333  
 334          return [
 335              'syscontext' => $syscontext,
 336              'childcontext' => $childcontext,
 337              'childcontext2' => $childcontext2
 338          ];
 339      }
 340  
 341      protected function remove_all_filters_from_config() {
 342          global $DB;
 343          $DB->delete_records('filter_active', array());
 344          $DB->delete_records('filter_config', array());
 345      }
 346  
 347      private function assert_filter_list($expectedfilters, $filters) {
 348          $this->assertEquals($expectedfilters, array_keys($filters), '', 0, 10, true);
 349      }
 350  
 351      public function test_globally_on_is_returned() {
 352          $this->resetAfterTest();
 353          $this->remove_all_filters_from_config(); // Remove all filters.
 354          [
 355              'syscontext' => $syscontext
 356          ] = $this->setup_available_in_context_tests();
 357          // Setup fixture.
 358          filter_set_global_state('name', TEXTFILTER_ON);
 359          // Exercise SUT.
 360          $filters = filter_get_active_in_context($syscontext);
 361          // Validate.
 362          $this->assert_filter_list(array('name'), $filters);
 363          // Check no config returned correctly.
 364          $this->assertEquals(array(), $filters['name']);
 365      }
 366  
 367      public function test_globally_off_not_returned() {
 368          $this->resetAfterTest();
 369          $this->remove_all_filters_from_config(); // Remove all filters.
 370          [
 371              'childcontext2' => $childcontext2
 372          ] = $this->setup_available_in_context_tests();
 373          // Setup fixture.
 374          filter_set_global_state('name', TEXTFILTER_OFF);
 375          // Exercise SUT.
 376          $filters = filter_get_active_in_context($childcontext2);
 377          // Validate.
 378          $this->assert_filter_list(array(), $filters);
 379      }
 380  
 381      public function test_globally_off_overridden() {
 382          $this->resetAfterTest();
 383          $this->remove_all_filters_from_config(); // Remove all filters.
 384          [
 385              'childcontext' => $childcontext,
 386              'childcontext2' => $childcontext2
 387          ] = $this->setup_available_in_context_tests();
 388          // Setup fixture.
 389          filter_set_global_state('name', TEXTFILTER_OFF);
 390          filter_set_local_state('name', $childcontext->id, TEXTFILTER_ON);
 391          // Exercise SUT.
 392          $filters = filter_get_active_in_context($childcontext2);
 393          // Validate.
 394          $this->assert_filter_list(array('name'), $filters);
 395      }
 396  
 397      public function test_globally_on_overridden() {
 398          $this->resetAfterTest();
 399          $this->remove_all_filters_from_config(); // Remove all filters.
 400          [
 401              'childcontext' => $childcontext,
 402              'childcontext2' => $childcontext2
 403          ] = $this->setup_available_in_context_tests();
 404          // Setup fixture.
 405          filter_set_global_state('name', TEXTFILTER_ON);
 406          filter_set_local_state('name', $childcontext->id, TEXTFILTER_OFF);
 407          // Exercise SUT.
 408          $filters = filter_get_active_in_context($childcontext2);
 409          // Validate.
 410          $this->assert_filter_list(array(), $filters);
 411      }
 412  
 413      public function test_globally_disabled_not_overridden() {
 414          $this->resetAfterTest();
 415          $this->remove_all_filters_from_config(); // Remove all filters.
 416          [
 417              'syscontext' => $syscontext,
 418              'childcontext' => $childcontext
 419          ] = $this->setup_available_in_context_tests();
 420          // Setup fixture.
 421          filter_set_global_state('name', TEXTFILTER_DISABLED);
 422          filter_set_local_state('name', $childcontext->id, TEXTFILTER_ON);
 423          // Exercise SUT.
 424          $filters = filter_get_active_in_context($syscontext);
 425          // Validate.
 426          $this->assert_filter_list(array(), $filters);
 427      }
 428  
 429      public function test_single_config_returned() {
 430          $this->resetAfterTest();
 431          [
 432              'childcontext' => $childcontext
 433          ] = $this->setup_available_in_context_tests();
 434          // Setup fixture.
 435          filter_set_global_state('name', TEXTFILTER_ON);
 436          filter_set_local_config('name', $childcontext->id, 'settingname', 'A value');
 437          // Exercise SUT.
 438          $filters = filter_get_active_in_context($childcontext);
 439          // Validate.
 440          $this->assertEquals(array('settingname' => 'A value'), $filters['name']);
 441      }
 442  
 443      public function test_multi_config_returned() {
 444          $this->resetAfterTest();
 445          [
 446              'childcontext' => $childcontext
 447          ] = $this->setup_available_in_context_tests();
 448          // Setup fixture.
 449          filter_set_global_state('name', TEXTFILTER_ON);
 450          filter_set_local_config('name', $childcontext->id, 'settingname', 'A value');
 451          filter_set_local_config('name', $childcontext->id, 'anothersettingname', 'Another value');
 452          // Exercise SUT.
 453          $filters = filter_get_active_in_context($childcontext);
 454          // Validate.
 455          $this->assertEquals(array('settingname' => 'A value', 'anothersettingname' => 'Another value'), $filters['name']);
 456      }
 457  
 458      public function test_config_from_other_context_not_returned() {
 459          $this->resetAfterTest();
 460          [
 461              'childcontext' => $childcontext,
 462              'childcontext2' => $childcontext2
 463          ] = $this->setup_available_in_context_tests();
 464          // Setup fixture.
 465          filter_set_global_state('name', TEXTFILTER_ON);
 466          filter_set_local_config('name', $childcontext->id, 'settingname', 'A value');
 467          filter_set_local_config('name', $childcontext2->id, 'anothersettingname', 'Another value');
 468          // Exercise SUT.
 469          $filters = filter_get_active_in_context($childcontext2);
 470          // Validate.
 471          $this->assertEquals(array('anothersettingname' => 'Another value'), $filters['name']);
 472      }
 473  
 474      public function test_config_from_other_filter_not_returned() {
 475          $this->resetAfterTest();
 476          [
 477              'childcontext' => $childcontext
 478          ] = $this->setup_available_in_context_tests();
 479          // Setup fixture.
 480          filter_set_global_state('name', TEXTFILTER_ON);
 481          filter_set_local_config('name', $childcontext->id, 'settingname', 'A value');
 482          filter_set_local_config('other', $childcontext->id, 'anothersettingname', 'Another value');
 483          // Exercise SUT.
 484          $filters = filter_get_active_in_context($childcontext);
 485          // Validate.
 486          $this->assertEquals(array('settingname' => 'A value'), $filters['name']);
 487      }
 488  
 489      protected function assert_one_available_filter($filter, $localstate, $inheritedstate, $filters) {
 490          $this->assertEquals(1, count($filters), 'More than one record returned %s.');
 491          $rec = $filters[$filter];
 492          unset($rec->id);
 493          $expectedrec = new stdClass();
 494          $expectedrec->filter = $filter;
 495          $expectedrec->localstate = $localstate;
 496          $expectedrec->inheritedstate = $inheritedstate;
 497          $this->assertEquals($expectedrec, $rec);
 498      }
 499  
 500      public function test_available_in_context_localoverride() {
 501          $this->resetAfterTest();
 502          $this->remove_all_filters_from_config(); // Remove all filters.
 503          [
 504              'childcontext' => $childcontext
 505          ] = $this->setup_available_in_context_tests();
 506          // Setup fixture.
 507          filter_set_global_state('name', TEXTFILTER_ON);
 508          filter_set_local_state('name', $childcontext->id, TEXTFILTER_OFF);
 509          // Exercise SUT.
 510          $filters = filter_get_available_in_context($childcontext);
 511          // Validate.
 512          $this->assert_one_available_filter('name', TEXTFILTER_OFF, TEXTFILTER_ON, $filters);
 513      }
 514  
 515      public function test_available_in_context_nolocaloverride() {
 516          $this->resetAfterTest();
 517          $this->remove_all_filters_from_config(); // Remove all filters.
 518          [
 519              'childcontext' => $childcontext,
 520              'childcontext2' => $childcontext2
 521          ] = $this->setup_available_in_context_tests();
 522          // Setup fixture.
 523          filter_set_global_state('name', TEXTFILTER_ON);
 524          filter_set_local_state('name', $childcontext->id, TEXTFILTER_OFF);
 525          // Exercise SUT.
 526          $filters = filter_get_available_in_context($childcontext2);
 527          // Validate.
 528          $this->assert_one_available_filter('name', TEXTFILTER_INHERIT, TEXTFILTER_OFF, $filters);
 529      }
 530  
 531      public function test_available_in_context_disabled_not_returned() {
 532          $this->resetAfterTest();
 533          $this->remove_all_filters_from_config(); // Remove all filters.
 534          [
 535              'childcontext' => $childcontext
 536          ] = $this->setup_available_in_context_tests();
 537          // Setup fixture.
 538          filter_set_global_state('name', TEXTFILTER_DISABLED);
 539          filter_set_local_state('name', $childcontext->id, TEXTFILTER_ON);
 540          // Exercise SUT.
 541          $filters = filter_get_available_in_context($childcontext);
 542          // Validate.
 543          $this->assertEquals(array(), $filters);
 544      }
 545  
 546      /**
 547       * @expectedException coding_exception
 548       */
 549      public function test_available_in_context_exception_with_syscontext() {
 550          $this->resetAfterTest();
 551          [
 552              'syscontext' => $syscontext
 553          ] = $this->setup_available_in_context_tests();
 554          // Exercise SUT.
 555          filter_get_available_in_context($syscontext);
 556      }
 557  
 558      protected function setup_preload_activities_test() {
 559          $syscontext = context_system::instance();
 560          $catcontext = context_coursecat::instance(1);
 561          $course = $this->getDataGenerator()->create_course(array('category' => 1));
 562          $coursecontext = context_course::instance($course->id);
 563          $page1 = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
 564          $activity1context = context_module::instance($page1->cmid);
 565          $page2 = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
 566          $activity2context = context_module::instance($page2->cmid);
 567          return [
 568              'syscontext' => $syscontext,
 569              'catcontext' => $catcontext,
 570              'course' => $course,
 571              'coursecontext' => $coursecontext,
 572              'activity1context' => $activity1context,
 573              'activity2context' => $activity2context
 574           ];
 575      }
 576  
 577      private function assert_matches($modinfo, $activity1context, $activity2context) {
 578          global $FILTERLIB_PRIVATE, $DB;
 579  
 580          // Use preload cache...
 581          $FILTERLIB_PRIVATE = new stdClass();
 582          filter_preload_activities($modinfo);
 583  
 584          // Get data and check no queries are made.
 585          $before = $DB->perf_get_reads();
 586          $plfilters1 = filter_get_active_in_context($activity1context);
 587          $plfilters2 = filter_get_active_in_context($activity2context);
 588          $after = $DB->perf_get_reads();
 589          $this->assertEquals($before, $after);
 590  
 591          // Repeat without cache and check it makes queries now.
 592          $FILTERLIB_PRIVATE = new stdClass;
 593          $before = $DB->perf_get_reads();
 594          $filters1 = filter_get_active_in_context($activity1context);
 595          $filters2 = filter_get_active_in_context($activity2context);
 596          $after = $DB->perf_get_reads();
 597          $this->assertTrue($after > $before);
 598  
 599          // Check they match.
 600          $this->assertEquals($plfilters1, $filters1);
 601          $this->assertEquals($plfilters2, $filters2);
 602      }
 603  
 604      public function test_preload() {
 605          $this->resetAfterTest();
 606          [
 607              'catcontext' => $catcontext,
 608              'course' => $course,
 609              'coursecontext' => $coursecontext,
 610              'activity1context' => $activity1context,
 611              'activity2context' => $activity2context
 612           ] = $this->setup_preload_activities_test();
 613          // Get course and modinfo.
 614          $modinfo = new course_modinfo($course, 2);
 615  
 616          // Note: All the tests in this function check that the result from the
 617          // preloaded cache is the same as the result from calling the standard
 618          // function without preloading.
 619  
 620          // Initially, check with no filters enabled.
 621          $this->assert_matches($modinfo, $activity1context, $activity2context);
 622  
 623          // Enable filter globally, check.
 624          filter_set_global_state('name', TEXTFILTER_ON);
 625          $this->assert_matches($modinfo, $activity1context, $activity2context);
 626  
 627          // Disable for activity 2.
 628          filter_set_local_state('name', $activity2context->id, TEXTFILTER_OFF);
 629          $this->assert_matches($modinfo, $activity1context, $activity2context);
 630  
 631          // Disable at category.
 632          filter_set_local_state('name', $catcontext->id, TEXTFILTER_OFF);
 633          $this->assert_matches($modinfo, $activity1context, $activity2context);
 634  
 635          // Enable for activity 1.
 636          filter_set_local_state('name', $activity1context->id, TEXTFILTER_ON);
 637          $this->assert_matches($modinfo, $activity1context, $activity2context);
 638  
 639          // Disable globally.
 640          filter_set_global_state('name', TEXTFILTER_DISABLED);
 641          $this->assert_matches($modinfo, $activity1context, $activity2context);
 642  
 643          // Add another 2 filters.
 644          filter_set_global_state('frog', TEXTFILTER_ON);
 645          filter_set_global_state('zombie', TEXTFILTER_ON);
 646          $this->assert_matches($modinfo, $activity1context, $activity2context);
 647  
 648          // Disable random one of these in each context.
 649          filter_set_local_state('zombie', $activity1context->id, TEXTFILTER_OFF);
 650          filter_set_local_state('frog', $activity2context->id, TEXTFILTER_OFF);
 651          $this->assert_matches($modinfo, $activity1context, $activity2context);
 652  
 653          // Now do some filter options.
 654          filter_set_local_config('name', $activity1context->id, 'a', 'x');
 655          filter_set_local_config('zombie', $activity1context->id, 'a', 'y');
 656          filter_set_local_config('frog', $activity1context->id, 'a', 'z');
 657          // These last two don't do anything as they are not at final level but I
 658          // thought it would be good to have that verified in test.
 659          filter_set_local_config('frog', $coursecontext->id, 'q', 'x');
 660          filter_set_local_config('frog', $catcontext->id, 'q', 'z');
 661          $this->assert_matches($modinfo, $activity1context, $activity2context);
 662      }
 663  
 664      public function test_filter_delete_all_for_filter() {
 665          global $DB;
 666          $this->resetAfterTest();
 667          $this->remove_all_filters_from_config(); // Remove all filters.
 668  
 669          // Setup fixture.
 670          filter_set_global_state('name', TEXTFILTER_ON);
 671          filter_set_global_state('other', TEXTFILTER_ON);
 672          filter_set_local_config('name', context_system::instance()->id, 'settingname', 'A value');
 673          filter_set_local_config('other', context_system::instance()->id, 'settingname', 'Other value');
 674          set_config('configname', 'A config value', 'filter_name');
 675          set_config('configname', 'Other config value', 'filter_other');
 676          // Exercise SUT.
 677          filter_delete_all_for_filter('name');
 678          // Validate.
 679          $this->assertEquals(1, $DB->count_records('filter_active'));
 680          $this->assertTrue($DB->record_exists('filter_active', array('filter' => 'other')));
 681          $this->assertEquals(1, $DB->count_records('filter_config'));
 682          $this->assertTrue($DB->record_exists('filter_config', array('filter' => 'other')));
 683          $expectedconfig = new stdClass;
 684          $expectedconfig->configname = 'Other config value';
 685          $this->assertEquals($expectedconfig, get_config('filter_other'));
 686          $this->assertEquals(get_config('filter_name'), new stdClass());
 687      }
 688  
 689      public function test_filter_delete_all_for_context() {
 690          global $DB;
 691          $this->resetAfterTest();
 692          $this->remove_all_filters_from_config(); // Remove all filters.
 693  
 694          // Setup fixture.
 695          filter_set_global_state('name', TEXTFILTER_ON);
 696          filter_set_local_state('name', 123, TEXTFILTER_OFF);
 697          filter_set_local_config('name', 123, 'settingname', 'A value');
 698          filter_set_local_config('other', 123, 'settingname', 'Other value');
 699          filter_set_local_config('other', 122, 'settingname', 'Other value');
 700          // Exercise SUT.
 701          filter_delete_all_for_context(123);
 702          // Validate.
 703          $this->assertEquals(1, $DB->count_records('filter_active'));
 704          $this->assertTrue($DB->record_exists('filter_active', array('contextid' => context_system::instance()->id)));
 705          $this->assertEquals(1, $DB->count_records('filter_config'));
 706          $this->assertTrue($DB->record_exists('filter_config', array('filter' => 'other')));
 707      }
 708  
 709      public function test_set() {
 710          global $CFG;
 711          $this->resetAfterTest();
 712  
 713          $this->assertFileExists("$CFG->dirroot/filter/emailprotect"); // Any standard filter.
 714          $this->assertFileExists("$CFG->dirroot/filter/tidy");         // Any standard filter.
 715          $this->assertFileNotExists("$CFG->dirroot/filter/grgrggr");   // Any non-existent filter
 716  
 717          // Setup fixture.
 718          set_config('filterall', 0);
 719          set_config('stringfilters', '');
 720          // Exercise SUT.
 721          filter_set_applies_to_strings('tidy', true);
 722          // Validate.
 723          $this->assertEquals('tidy', $CFG->stringfilters);
 724          $this->assertEquals(1, $CFG->filterall);
 725  
 726          filter_set_applies_to_strings('grgrggr', true);
 727          $this->assertEquals('tidy', $CFG->stringfilters);
 728          $this->assertEquals(1, $CFG->filterall);
 729  
 730          filter_set_applies_to_strings('emailprotect', true);
 731          $this->assertEquals('tidy,emailprotect', $CFG->stringfilters);
 732          $this->assertEquals(1, $CFG->filterall);
 733      }
 734  
 735      public function test_unset_to_empty() {
 736          global $CFG;
 737          $this->resetAfterTest();
 738  
 739          $this->assertFileExists("$CFG->dirroot/filter/tidy"); // Any standard filter.
 740  
 741          // Setup fixture.
 742          set_config('filterall', 1);
 743          set_config('stringfilters', 'tidy');
 744          // Exercise SUT.
 745          filter_set_applies_to_strings('tidy', false);
 746          // Validate.
 747          $this->assertEquals('', $CFG->stringfilters);
 748          $this->assertEquals('', $CFG->filterall);
 749      }
 750  
 751      public function test_unset_multi() {
 752          global $CFG;
 753          $this->resetAfterTest();
 754  
 755          $this->assertFileExists("$CFG->dirroot/filter/emailprotect"); // Any standard filter.
 756          $this->assertFileExists("$CFG->dirroot/filter/tidy");         // Any standard filter.
 757          $this->assertFileExists("$CFG->dirroot/filter/multilang");    // Any standard filter.
 758  
 759          // Setup fixture.
 760          set_config('filterall', 1);
 761          set_config('stringfilters', 'emailprotect,tidy,multilang');
 762          // Exercise SUT.
 763          filter_set_applies_to_strings('tidy', false);
 764          // Validate.
 765          $this->assertEquals('emailprotect,multilang', $CFG->stringfilters);
 766          $this->assertEquals(1, $CFG->filterall);
 767      }
 768  
 769      public function test_filter_manager_instance() {
 770          $this->resetAfterTest();
 771  
 772          set_config('perfdebug', 7);
 773          filter_manager::reset_caches();
 774          $filterman = filter_manager::instance();
 775          $this->assertInstanceOf('filter_manager', $filterman);
 776          $this->assertNotInstanceOf('performance_measuring_filter_manager', $filterman);
 777  
 778          set_config('perfdebug', 15);
 779          filter_manager::reset_caches();
 780          $filterman = filter_manager::instance();
 781          $this->assertInstanceOf('filter_manager', $filterman);
 782          $this->assertInstanceOf('performance_measuring_filter_manager', $filterman);
 783      }
 784  
 785      public function test_filter_get_active_state_contextid_parameter() {
 786          $this->resetAfterTest();
 787  
 788          filter_set_global_state('glossary', TEXTFILTER_ON);
 789          // Using system context by default.
 790          $active = filter_get_active_state('glossary');
 791          $this->assertEquals($active, TEXTFILTER_ON);
 792  
 793          $systemcontext = context_system::instance();
 794          // Passing $systemcontext object.
 795          $active = filter_get_active_state('glossary', $systemcontext);
 796          $this->assertEquals($active, TEXTFILTER_ON);
 797  
 798          // Passing $systemcontext id.
 799          $active = filter_get_active_state('glossary', $systemcontext->id);
 800          $this->assertEquals($active, TEXTFILTER_ON);
 801  
 802          // Not system context.
 803          filter_set_local_state('glossary', '123', TEXTFILTER_ON);
 804          $active = filter_get_active_state('glossary', '123');
 805          $this->assertEquals($active, TEXTFILTER_ON);
 806      }
 807  
 808      public function test_filter_get_active_state_filtername_parameter() {
 809          $this->resetAfterTest();
 810  
 811          filter_set_global_state('glossary', TEXTFILTER_ON);
 812          // Using full filtername.
 813          $active = filter_get_active_state('filter/glossary');
 814          $this->assertEquals($active, TEXTFILTER_ON);
 815  
 816          // Wrong filtername.
 817          $this->expectException('coding_exception');
 818          $active = filter_get_active_state('mod/glossary');
 819      }
 820  
 821      public function test_filter_get_active_state_after_change() {
 822          $this->resetAfterTest();
 823  
 824          filter_set_global_state('glossary', TEXTFILTER_ON);
 825          $systemcontextid = context_system::instance()->id;
 826          $active = filter_get_active_state('glossary', $systemcontextid);
 827          $this->assertEquals($active, TEXTFILTER_ON);
 828  
 829          filter_set_global_state('glossary', TEXTFILTER_OFF);
 830          $systemcontextid = context_system::instance()->id;
 831          $active = filter_get_active_state('glossary', $systemcontextid);
 832          $this->assertEquals($active, TEXTFILTER_OFF);
 833  
 834          filter_set_global_state('glossary', TEXTFILTER_DISABLED);
 835          $systemcontextid = context_system::instance()->id;
 836          $active = filter_get_active_state('glossary', $systemcontextid);
 837          $this->assertEquals($active, TEXTFILTER_DISABLED);
 838      }
 839  
 840      public function test_filter_get_globally_enabled_default() {
 841          $this->resetAfterTest();
 842          $enabledfilters = filter_get_globally_enabled();
 843          $this->assertArrayNotHasKey('glossary', $enabledfilters);
 844      }
 845  
 846      public function test_filter_get_globally_enabled_after_change() {
 847          $this->resetAfterTest();
 848          filter_set_global_state('glossary', TEXTFILTER_ON);
 849          $enabledfilters = filter_get_globally_enabled();
 850          $this->assertArrayHasKey('glossary', $enabledfilters);
 851      }
 852  
 853      public function test_filter_get_globally_enabled_filters_with_config() {
 854          $this->resetAfterTest();
 855          $this->remove_all_filters_from_config(); // Remove all filters.
 856          [
 857              'syscontext' => $syscontext,
 858              'childcontext' => $childcontext
 859          ] = $this->setup_available_in_context_tests();
 860          $this->remove_all_filters_from_config(); // Remove all filters.
 861  
 862          // Set few filters.
 863          filter_set_global_state('one', TEXTFILTER_ON);
 864          filter_set_global_state('three', TEXTFILTER_OFF, -1);
 865          filter_set_global_state('two', TEXTFILTER_DISABLED);
 866  
 867          // Set global config.
 868          filter_set_local_config('one', $syscontext->id, 'test1a', 'In root');
 869          filter_set_local_config('one', $syscontext->id, 'test1b', 'In root');
 870          filter_set_local_config('two', $syscontext->id, 'test2a', 'In root');
 871          filter_set_local_config('two', $syscontext->id, 'test2b', 'In root');
 872  
 873          // Set child config.
 874          filter_set_local_config('one', $childcontext->id, 'test1a', 'In child');
 875          filter_set_local_config('one', $childcontext->id, 'test1b', 'In child');
 876          filter_set_local_config('two', $childcontext->id, 'test2a', 'In child');
 877          filter_set_local_config('two', $childcontext->id, 'test2b', 'In child');
 878          filter_set_local_config('three', $childcontext->id, 'test3a', 'In child');
 879          filter_set_local_config('three', $childcontext->id, 'test3b', 'In child');
 880  
 881          // Check.
 882          $actual = filter_get_globally_enabled_filters_with_config();
 883          $this->assertCount(2, $actual);
 884          $this->assertEquals(['three', 'one'], array_keys($actual));     // Checks sortorder.
 885          $this->assertArrayHasKey('one', $actual);
 886          $this->assertArrayNotHasKey('two', $actual);
 887          $this->assertArrayHasKey('three', $actual);
 888          $this->assertEquals(['test1a' => 'In root', 'test1b' => 'In root'], $actual['one']);
 889          $this->assertEquals([], $actual['three']);
 890      }
 891  }