Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   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  declare(strict_types=1);
  18  
  19  namespace core_reportbuilder\local\report;
  20  
  21  use advanced_testcase;
  22  use lang_string;
  23  use moodle_exception;
  24  use core_reportbuilder\local\filters\text;
  25  
  26  /**
  27   * Unit tests for a report filter
  28   *
  29   * @package     core_reportbuilder
  30   * @covers      \core_reportbuilder\local\report\filter
  31   * @copyright   2021 Paul Holden <paulh@moodle.com>
  32   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class filter_test extends advanced_testcase {
  35  
  36      /**
  37       * Test getting filter class
  38       */
  39      public function test_get_filter_class(): void {
  40          $filter = $this->create_filter('username');
  41          $this->assertEquals(text::class, $filter->get_filter_class());
  42      }
  43  
  44      /**
  45       * Test specifying invalid filter class
  46       */
  47      public function test_invalid_filter_class(): void {
  48          $this->expectException(moodle_exception::class);
  49          $this->expectExceptionMessage('Invalid filter (sillyclass)');
  50          new filter('sillyclass', 'username', new lang_string('username'), 'filter_testcase');
  51      }
  52  
  53      /**
  54       * Test getting name
  55       */
  56      public function test_get_name(): void {
  57          $filter = $this->create_filter('username');
  58          $this->assertEquals('username', $filter->get_name());
  59      }
  60  
  61      /**
  62       * Test getting header
  63       */
  64      public function test_get_header(): void {
  65          $filter = $this->create_filter('username');
  66          $this->assertEquals('Username', $filter->get_header());
  67      }
  68  
  69      /**
  70       * Test setting header
  71       */
  72      public function test_set_header(): void {
  73          $filter = $this->create_filter('username')
  74              ->set_header(new lang_string('firstname'));
  75  
  76          $this->assertEquals('First name', $filter->get_header());
  77      }
  78  
  79      /**
  80       * Test getting entity name
  81       */
  82      public function test_get_entity_name(): void {
  83          $filter = $this->create_filter('username');
  84          $this->assertEquals('filter_testcase', $filter->get_entity_name());
  85      }
  86  
  87      /**
  88       * Test getting unique identifier
  89       */
  90      public function test_get_unique_identifier(): void {
  91          $filter = $this->create_filter('username');
  92          $this->assertEquals('filter_testcase:username', $filter->get_unique_identifier());
  93      }
  94  
  95      /**
  96       * Test getting field SQL
  97       */
  98      public function test_get_field_sql(): void {
  99          $filter = $this->create_filter('username', 'u.username');
 100          $this->assertEquals('u.username', $filter->get_field_sql());
 101      }
 102  
 103      /**
 104       * Test getting field params
 105       */
 106      public function test_get_field_params(): void {
 107          $filter = $this->create_filter('username', 'u.username = :foo', ['foo' => 'bar']);
 108          $this->assertEquals(['foo' => 'bar'], $filter->get_field_params());
 109      }
 110  
 111      /**
 112       * Test getting field SQL and params, while providing index for uniqueness
 113       */
 114      public function test_get_field_sql_and_params(): void {
 115          $filter = $this->create_filter('username', 'u.username = :username AND u.idnumber = :idnumber',
 116              ['username' => 'test', 'idnumber' => 'bar']);
 117  
 118          [$sql, $params] = $filter->get_field_sql_and_params(1);
 119          $this->assertEquals('u.username = :username_1 AND u.idnumber = :idnumber_1', $sql);
 120          $this->assertEquals(['username_1' => 'test', 'idnumber_1' => 'bar'], $params);
 121      }
 122  
 123      /**
 124       * Test adding single join
 125       */
 126      public function test_add_join(): void {
 127          $filter = $this->create_filter('username', 'u.username');
 128          $this->assertEquals([], $filter->get_joins());
 129  
 130          $filter->add_join('JOIN {user} u ON u.id = table.userid');
 131          $this->assertEquals(['JOIN {user} u ON u.id = table.userid'], $filter->get_joins());
 132      }
 133  
 134      /**
 135       * Test adding multiple joins
 136       */
 137      public function test_add_joins(): void {
 138          $tablejoins = [
 139              "JOIN {course} c2 ON c2.id = c1.id",
 140              "JOIN {course} c3 ON c3.id = c1.id",
 141          ];
 142  
 143          $filter = $this->create_filter('username', 'u.username')
 144              ->add_joins($tablejoins);
 145  
 146          $this->assertEquals($tablejoins, $filter->get_joins());
 147      }
 148  
 149      /**
 150       * Test is available
 151       */
 152      public function test_is_available(): void {
 153          $filter = $this->create_filter('username', 'u.username');
 154          $this->assertTrue($filter->get_is_available());
 155  
 156          $filter->set_is_available(true);
 157          $this->assertTrue($filter->get_is_available());
 158      }
 159  
 160      /**
 161       * Test setting filter options
 162       */
 163      public function test_set_options(): void {
 164          $filter = $this->create_filter('username', 'u.username')
 165              ->set_options([1, 2, 3]);
 166  
 167          $this->assertEquals([1, 2, 3], $filter->get_options());
 168      }
 169  
 170      /**
 171       * Test setting filter options via callback
 172       */
 173      public function test_set_options_callback(): void {
 174          $filter = $this->create_filter('username', 'u.username')
 175              ->set_options_callback(static function() {
 176                  return 10 * 5;
 177              });
 178  
 179          $this->assertEquals(50, $filter->get_options());
 180      }
 181  
 182      /**
 183       * Test restricting filter operators
 184       */
 185      public function test_limited_operators(): void {
 186          $filter = $this->create_filter('username', 'u.username')
 187              ->set_limited_operators([
 188                  text::IS_EQUAL_TO,
 189                  text::IS_NOT_EQUAL_TO,
 190              ]);
 191  
 192          $limitedoperators = $filter->restrict_limited_operators([
 193              text::CONTAINS => 'Contains',
 194              text::DOES_NOT_CONTAIN => 'Does not contain',
 195              text::IS_EQUAL_TO => 'Is equal to',
 196              text::IS_NOT_EQUAL_TO => 'Is not equal to',
 197          ]);
 198  
 199          $this->assertEquals([
 200              text::IS_EQUAL_TO => 'Is equal to',
 201              text::IS_NOT_EQUAL_TO => 'Is not equal to',
 202          ], $limitedoperators);
 203      }
 204  
 205      /**
 206       * Test not restricting filter operators
 207       */
 208      public function test_unlimited_operators(): void {
 209          $filter = $this->create_filter('username', 'u.username');
 210  
 211          $operators = [
 212              text::CONTAINS => 'Contains',
 213              text::DOES_NOT_CONTAIN => 'Does not contain',
 214          ];
 215  
 216          // If no operator limit has been set for the filter, then all available operators should be present.
 217          $this->assertEquals($operators, $filter->restrict_limited_operators($operators));
 218      }
 219  
 220      /**
 221       * Helper method to create a filter instance
 222       *
 223       * @param string $name
 224       * @param string $fieldsql
 225       * @param array $fieldparams
 226       * @return filter
 227       */
 228      private function create_filter(string $name, string $fieldsql = '', array $fieldparams = []): filter {
 229          return new filter(text::class, $name, new lang_string($name), 'filter_testcase', $fieldsql, $fieldparams);
 230      }
 231  }