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] [Versions 39 and 310]

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