Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 400 and 403] [Versions 401 and 403] [Versions 402 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  declare(strict_types=1);
  18  
  19  namespace core_cohort\reportbuilder\datasource;
  20  
  21  use context_coursecat;
  22  use context_system;
  23  use core_customfield_generator;
  24  use core_reportbuilder_generator;
  25  use core_reportbuilder_testcase;
  26  use core_reportbuilder\local\filters\{date, select, text};
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  global $CFG;
  31  require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php");
  32  
  33  /**
  34   * Unit tests for cohorts datasource
  35   *
  36   * @package     core_cohort
  37   * @covers      \core_cohort\reportbuilder\datasource\cohorts
  38   * @copyright   2021 Paul Holden <paulh@moodle.com>
  39   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  40   */
  41  class cohorts_test extends core_reportbuilder_testcase {
  42  
  43      /**
  44       * Test default datasource
  45       */
  46      public function test_datasource_default(): void {
  47          $this->resetAfterTest();
  48  
  49          // Test subject.
  50          $contextsystem = context_system::instance();
  51          $cohortone = $this->getDataGenerator()->create_cohort([
  52              'contextid' => $contextsystem->id,
  53              'name' => 'Legends',
  54              'idnumber' => 'C101',
  55              'description' => 'Cohort for the legends',
  56          ]);
  57  
  58          $category = $this->getDataGenerator()->create_category();
  59          $contextcategory = context_coursecat::instance($category->id);
  60          $cohorttwo = $this->getDataGenerator()->create_cohort([
  61              'contextid' => $contextcategory->id,
  62              'name' => 'Category cohort',
  63              'description' => 'This is my category cohort',
  64          ]);
  65  
  66          /** @var core_reportbuilder_generator $generator */
  67          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
  68          $report = $generator->create_report(['name' => 'Cohorts', 'source' => cohorts::class, 'default' => 1]);
  69  
  70          $content = $this->get_custom_report_content($report->get('id'));
  71  
  72          // Default columns are name, context, idnumber, description. Sorted by name.
  73          $this->assertEquals([
  74              [$cohorttwo->name, $contextcategory->get_context_name(false), $cohorttwo->idnumber,
  75                  format_text($cohorttwo->description)],
  76              [$cohortone->name, $contextsystem->get_context_name(false), $cohortone->idnumber,
  77                  format_text($cohortone->description)],
  78          ], array_map('array_values', $content));
  79      }
  80  
  81      /**
  82       * Test datasource columns that aren't added by default
  83       */
  84      public function test_datasource_non_default_columns(): void {
  85          $this->resetAfterTest();
  86          $this->setAdminUser();
  87  
  88          /** @var core_customfield_generator $generator */
  89          $generator = $this->getDataGenerator()->get_plugin_generator('core_customfield');
  90  
  91          $fieldcategory = $generator->create_category(['component' => 'core_cohort', 'area' => 'cohort']);
  92          $field = $generator->create_field(['categoryid' => $fieldcategory->get('id'), 'shortname' => 'hi']);
  93  
  94          // Test subject.
  95          $cohort = $this->getDataGenerator()->create_cohort([
  96              'name' => 'Legends',
  97              'idnumber' => 'C101',
  98              'description' => 'Cohort for the legends',
  99              'customfield_hi' => 'Hello',
 100          ]);
 101  
 102          $user = $this->getDataGenerator()->create_user(['firstname' => 'Lionel', 'lastname' => 'Richards']);
 103          cohort_add_member($cohort->id, $user->id);
 104  
 105          /** @var core_reportbuilder_generator $generator */
 106          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
 107          $report = $generator->create_report(['name' => 'Cohorts', 'source' => cohorts::class, 'default' => 0]);
 108  
 109          $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:visible']);
 110          $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:timecreated']);
 111          $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:timemodified']);
 112          $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:component']);
 113          $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:theme']);
 114          $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:customfield_hi']);
 115          $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort_member:timeadded']);
 116          $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullname']);
 117  
 118          $content = $this->get_custom_report_content($report->get('id'));
 119          $this->assertCount(1, $content);
 120  
 121          [$visible, $timecreated, $timemodified, $component, $theme, $custom, $timeadded, $fullname] = array_values($content[0]);
 122  
 123          $this->assertEquals('Yes', $visible);
 124          $this->assertNotEmpty($timecreated);
 125          $this->assertNotEmpty($timemodified);
 126          $this->assertEquals('Created manually', $component);
 127          $this->assertEmpty($theme);
 128          $this->assertEquals('Hello', $custom);
 129          $this->assertNotEmpty($timeadded);
 130          $this->assertEquals(fullname($user), $fullname);
 131      }
 132  
 133      /**
 134       * Data provider for {@see test_datasource_filters}
 135       *
 136       * @return array[]
 137       */
 138      public function datasource_filters_provider(): array {
 139          return [
 140              // Cohort.
 141              'Filter context' => ['cohort:context', [
 142                  'cohort:context_operator' => select::EQUAL_TO,
 143                  'cohort:context_value' => context_system::instance()->id,
 144              ], true],
 145              'Filter content (no match)' => ['cohort:context', [
 146                  'cohort:context_operator' => select::EQUAL_TO,
 147                  'cohort:context_value' => -1,
 148              ], false],
 149              'Filter name' => ['cohort:name', [
 150                  'cohort:name_operator' => text::IS_EQUAL_TO,
 151                  'cohort:name_value' => 'Legends',
 152              ], true],
 153              'Filter name (no match)' => ['cohort:name', [
 154                  'cohort:name_operator' => text::IS_EQUAL_TO,
 155                  'cohort:name_value' => 'Dancing',
 156              ], false],
 157              'Filter idnumber' => ['cohort:idnumber', [
 158                  'cohort:idnumber_operator' => text::IS_EQUAL_TO,
 159                  'cohort:idnumber_value' => 'C101',
 160              ], true],
 161              'Filter idnumber (no match)' => ['cohort:idnumber', [
 162                  'cohort:idnumber_operator' => text::IS_EQUAL_TO,
 163                  'cohort:idnumber_value' => 'C102',
 164              ], false],
 165              'Filter time created' => ['cohort:timecreated', [
 166                  'cohort:timecreated_operator' => date::DATE_RANGE,
 167                  'cohort:timecreated_from' => 1622502000,
 168              ], true],
 169              'Filter time created (no match)' => ['cohort:timecreated', [
 170                  'cohort:timecreated_operator' => date::DATE_RANGE,
 171                  'cohort:timecreated_to' => 1622502000,
 172              ], false],
 173              'Filter description' => ['cohort:description', [
 174                  'cohort:description_operator' => text::CONTAINS,
 175                  'cohort:description_value' => 'legends',
 176              ], true],
 177              'Filter description (no match)' => ['cohort:description', [
 178                  'cohort:description_operator' => text::IS_EMPTY,
 179              ], false],
 180  
 181              // Cohort member.
 182              'Filter time added' => ['cohort_member:timeadded', [
 183                  'cohort_member:timeadded_operator' => date::DATE_RANGE,
 184                  'cohort_member:timeadded_from' => 1622502000,
 185              ], true],
 186              'Filter time added (no match)' => ['cohort_member:timeadded', [
 187                  'cohort_member:timeadded_operator' => date::DATE_RANGE,
 188                  'cohort_member:timeadded_to' => 1622502000,
 189              ], false],
 190  
 191              // User.
 192              'Filter user' => ['user:username', [
 193                  'user:username_operator' => text::IS_EQUAL_TO,
 194                  'user:username_value' => 'lionel',
 195              ], true],
 196              'Filter user (no match)' => ['user:username', [
 197                  'user:username_operator' => text::IS_EQUAL_TO,
 198                  'user:username_value' => 'rick',
 199              ], false],
 200          ];
 201      }
 202  
 203      /**
 204       * Test datasource filters
 205       *
 206       * @param string $filtername
 207       * @param array $filtervalues
 208       * @param bool $expectmatch
 209       *
 210       * @dataProvider datasource_filters_provider
 211       */
 212      public function test_datasource_filters(string $filtername, array $filtervalues, bool $expectmatch): void {
 213          $this->resetAfterTest();
 214  
 215          // Test subject.
 216          $cohort = $this->getDataGenerator()->create_cohort([
 217              'name' => 'Legends',
 218              'idnumber' => 'C101',
 219              'description' => 'Cohort for the legends',
 220          ]);
 221  
 222          $user = $this->getDataGenerator()->create_user(['username' => 'lionel']);
 223          cohort_add_member($cohort->id, $user->id);
 224  
 225          /** @var core_reportbuilder_generator $generator */
 226          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
 227  
 228          // Create report containing single column, and given filter.
 229          $report = $generator->create_report(['name' => 'Cohorts', 'source' => cohorts::class, 'default' => 0]);
 230          $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:name']);
 231  
 232          // Add filter, set it's values.
 233          $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]);
 234          $content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues);
 235  
 236          if ($expectmatch) {
 237              $this->assertCount(1, $content);
 238              $this->assertEquals('Legends', reset($content[0]));
 239          } else {
 240              $this->assertEmpty($content);
 241          }
 242      }
 243  
 244      /**
 245       * Stress test datasource
 246       *
 247       * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php
 248       */
 249      public function test_stress_datasource(): void {
 250          if (!PHPUNIT_LONGTEST) {
 251              $this->markTestSkipped('PHPUNIT_LONGTEST is not defined');
 252          }
 253  
 254          $this->resetAfterTest();
 255  
 256          $cohort = $this->getDataGenerator()->create_cohort();
 257          $user = $this->getDataGenerator()->create_user();
 258          cohort_add_member($cohort->id, $user->id);
 259  
 260          $this->datasource_stress_test_columns(cohorts::class);
 261          $this->datasource_stress_test_columns_aggregation(cohorts::class);
 262          $this->datasource_stress_test_conditions(cohorts::class, 'cohort:name');
 263      }
 264  }