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.
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

declare(strict_types=1);

namespace core_group\reportbuilder\datasource;

> use core_customfield_generator;
use core_reportbuilder_generator; use core_reportbuilder_testcase;
< use core_reportbuilder\local\filters\{date, text};
> use core_reportbuilder\local\filters\{boolean_select, date, select, text};
defined('MOODLE_INTERNAL') || die(); global $CFG; require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php"); /** * Unit tests for groups datasource * * @package core_group * @covers \core_group\reportbuilder\datasource\groups * @copyright 2022 Paul Holden <paulh@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class groups_test extends core_reportbuilder_testcase { /** * Test default datasource */ public function test_datasource_default(): void { $this->resetAfterTest(); $course = $this->getDataGenerator()->create_course();
< $user = $this->getDataGenerator()->create_and_enrol($course, 'student');
> $userone = $this->getDataGenerator()->create_and_enrol($course, 'student', ['firstname' => 'Zoe']); > $usertwo = $this->getDataGenerator()->create_and_enrol($course, 'student', ['firstname' => 'Amy']);
< $group = $this->getDataGenerator()->create_group(['courseid' => $course->id]); < $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
> $groupone = $this->getDataGenerator()->create_group(['courseid' => $course->id, 'name' => 'Zebras']); > $grouptwo = $this->getDataGenerator()->create_group(['courseid' => $course->id, 'name' => 'Aardvarks']); > > $this->getDataGenerator()->create_group_member(['groupid' => $groupone->id, 'userid' => $userone->id]); > $this->getDataGenerator()->create_group_member(['groupid' => $groupone->id, 'userid' => $usertwo->id]);
/** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); $report = $generator->create_report(['name' => 'Groups', 'source' => groups::class, 'default' => 1]); $content = $this->get_custom_report_content($report->get('id'));
< $this->assertCount(1, $content);
< $contentrow = array_values(reset($content));
> // Default columns are course, group, user. Sorted by each. > $courseurl = course_get_url($course);
$this->assertEquals([
< "<a href=\"https://www.example.com/moodle/course/view.php?id={$course->id}\">{$course->fullname}</a>", // Course. < $group->name, // Group. < fullname($user), // User. < ], $contentrow);
> ["<a href=\"{$courseurl}\">{$course->fullname}</a>", $grouptwo->name, ''], > ["<a href=\"{$courseurl}\">{$course->fullname}</a>", $groupone->name, fullname($usertwo)], > ["<a href=\"{$courseurl}\">{$course->fullname}</a>", $groupone->name, fullname($userone)], > ], array_map('array_values', $content));
} /** * Test datasource groupings reports */ public function test_datasource_groupings(): void { $this->resetAfterTest(); $course = $this->getDataGenerator()->create_course(); // Create group, add to grouping. $groupone = $this->getDataGenerator()->create_group(['courseid' => $course->id, 'name' => 'Group A']); $grouping = $this->getDataGenerator()->create_grouping(['courseid' => $course->id]); $this->getDataGenerator()->create_grouping_group(['groupingid' => $grouping->id, 'groupid' => $groupone->id]); // Create second group, no grouping. $grouptwo = $this->getDataGenerator()->create_group(['courseid' => $course->id, 'name' => 'Group B']); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); $report = $generator->create_report(['name' => 'Groups', 'source' => groups::class, 'default' => 0]); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'grouping:name']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:name', 'sortenabled' => 1]); $content = $this->get_custom_report_content($report->get('id')); $this->assertCount(2, $content); $this->assertEquals([ [ $course->fullname, $grouping->name, $groupone->name, ], [ $course->fullname, null, $grouptwo->name, ], ], array_map('array_values', $content)); } /** * Test datasource columns that aren't added by default */ public function test_datasource_non_default_columns(): void { $this->resetAfterTest();
> $this->setAdminUser();
$course = $this->getDataGenerator()->create_course(); $user = $this->getDataGenerator()->create_and_enrol($course, 'student');
< $group = $this->getDataGenerator()->create_group(['courseid' => $course->id, 'idnumber' => 'G101', 'enrolmentkey' => 'S', < 'description' => 'My group']);
> /** @var core_customfield_generator $generator */ > $generator = $this->getDataGenerator()->get_plugin_generator('core_customfield'); > > // Create group with custom field, and single group member. > $groupfieldcategory = $generator->create_category(['component' => 'core_group', 'area' => 'group']); > $generator->create_field(['categoryid' => $groupfieldcategory->get('id'), 'shortname' => 'hi']); > > $group = $this->getDataGenerator()->create_group([ > 'courseid' => $course->id, > 'idnumber' => 'G101', > 'enrolmentkey' => 'S', > 'description' => 'My group', > 'customfield_hi' => 'Hello', > ]);
$this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
< $grouping = $this->getDataGenerator()->create_grouping(['courseid' => $course->id, 'idnumber' => 'GR101', < 'description' => 'My grouping']);
> // Create grouping with custom field, and single group. > $groupingfieldcategory = $generator->create_category(['component' => 'core_group', 'area' => 'grouping']); > $generator->create_field(['categoryid' => $groupingfieldcategory->get('id'), 'shortname' => 'bye']); > > $grouping = $this->getDataGenerator()->create_grouping([ > 'courseid' => $course->id, > 'idnumber' => 'GR101', > 'description' => 'My grouping', > 'customfield_bye' => 'Goodbye', > ]);
$this->getDataGenerator()->create_grouping_group(['groupingid' => $grouping->id, 'groupid' => $group->id]); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); $report = $generator->create_report(['name' => 'Groups', 'source' => groups::class, 'default' => 0]); // Course (just to test join). $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:shortname']); // Group. $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:idnumber']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:description']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:enrolmentkey']);
> $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:visibility']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:picture']); > $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:participation']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:timecreated']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:timemodified']);
> $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:customfield_hi']);
// Grouping. $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'grouping:name']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'grouping:idnumber']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'grouping:description']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'grouping:timecreated']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'grouping:timemodified']);
> $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'grouping:customfield_bye']);
// Group member. $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group_member:timeadded']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group_member:component']); // User (just to test join). $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:username']); $content = $this->get_custom_report_content($report->get('id')); $this->assertCount(1, $content); [ $courseshortname, $groupidnumber, $groupdescription, $groupenrolmentkey,
> $groupvisibility, $grouppicture, > $groupparticipation,
$grouptimecreated, $grouptimemodified,
> $groupcustomfield,
$groupingname, $groupingidnumber, $groupingdescription, $groupingtimecreated, $groupingtimemodified,
> $groupingcustomfield,
$groupmembertimeadded, $groupmemebercomponent, $userusername, ] = array_values($content[0]); $this->assertEquals($course->shortname, $courseshortname); $this->assertEquals('G101', $groupidnumber); $this->assertEquals(format_text($group->description), $groupdescription); $this->assertEquals('S', $groupenrolmentkey);
> $this->assertEquals('Visible', $groupvisibility); $this->assertEmpty($grouppicture); > $this->assertEquals('Yes', $groupparticipation);
$this->assertNotEmpty($grouptimecreated); $this->assertNotEmpty($grouptimemodified);
> $this->assertEquals('Hello', $groupcustomfield);
$this->assertEquals($grouping->name, $groupingname); $this->assertEquals('GR101', $groupingidnumber); $this->assertEquals(format_text($grouping->description), $groupingdescription); $this->assertNotEmpty($groupingtimecreated); $this->assertNotEmpty($groupingtimemodified);
> $this->assertEquals('Goodbye', $groupingcustomfield);
$this->assertNotEmpty($groupmembertimeadded); $this->assertEmpty($groupmemebercomponent); $this->assertEquals($user->username, $userusername); } /** * Data provider for {@see test_datasource_filters} * * @return array[] */ public function datasource_filters_provider(): array { return [ // Course (just to test join). 'Filter course name' => ['course:fullname', [ 'course:fullname_operator' => text::IS_EQUAL_TO, 'course:fullname_value' => 'Test course', ], true], 'Filter course name (no match)' => ['course:fullname', [ 'course:fullname_operator' => text::IS_NOT_EQUAL_TO, 'course:fullname_value' => 'Test course', ], false], // Group. 'Filter group name' => ['group:name', [ 'group:name_operator' => text::IS_EQUAL_TO, 'group:name_value' => 'Test group', ], true], 'Filter group name (no match)' => ['group:name', [ 'group:name_operator' => text::IS_NOT_EQUAL_TO, 'group:name_value' => 'Test group', ], false], 'Filter group idnumber' => ['group:idnumber', [ 'group:idnumber_operator' => text::IS_EQUAL_TO, 'group:idnumber_value' => 'G101', ], true], 'Filter group idnumber (no match)' => ['group:idnumber', [ 'group:idnumber_operator' => text::IS_NOT_EQUAL_TO, 'group:idnumber_value' => 'G101',
> ], false], ], false], > 'Filter group visibility' => ['group:visibility', [ 'Filter group time created' => ['group:timecreated', [ > 'group:visibility_operator' => select::EQUAL_TO, 'group:timecreated_operator' => date::DATE_RANGE, > 'group:visibility_value' => 0, // Visible to everyone. 'group:timecreated_from' => 1622502000, > ], true], ], true], > 'Filter group visibility (no match)' => ['group:visibility', [ 'Filter group time created (no match)' => ['group:timecreated', [ > 'group:visibility_operator' => select::EQUAL_TO, 'group:timecreated_operator' => date::DATE_RANGE, > 'group:visibility_value' => 1, // Visible to members only. 'group:timecreated_to' => 1622502000, > ], false], ], false], > 'Filter group participation' => ['group:participation', [ > 'group:participation_operator' => boolean_select::CHECKED, // Grouping. > ], true], 'Filter grouping name' => ['grouping:name', [ > 'Filter group participation (no match)' => ['group:participation', [ 'grouping:name_operator' => text::IS_EQUAL_TO, > 'group:participation_operator' => boolean_select::NOT_CHECKED,
'grouping:name_value' => 'Test grouping', ], true], 'Filter grouping name (no match)' => ['grouping:name', [ 'grouping:name_operator' => text::IS_NOT_EQUAL_TO, 'grouping:name_value' => 'Test grouping', ], false], 'Filter grouping idnumber' => ['grouping:idnumber', [ 'grouping:idnumber_operator' => text::IS_EQUAL_TO, 'grouping:idnumber_value' => 'GR101', ], true], 'Filter grouping idnumber (no match)' => ['grouping:idnumber', [ 'grouping:idnumber_operator' => text::IS_NOT_EQUAL_TO, 'grouping:idnumber_value' => 'GR101', ], false], 'Filter grouping time created' => ['grouping:timecreated', [ 'grouping:timecreated_operator' => date::DATE_RANGE, 'grouping:timecreated_from' => 1622502000, ], true], 'Filter grouping time created (no match)' => ['grouping:timecreated', [ 'grouping:timecreated_operator' => date::DATE_RANGE, 'grouping:timecreated_to' => 1622502000, ], false], // Group member. 'Filter group member time added' => ['group_member:timeadded', [ 'group_member:timeadded_operator' => date::DATE_RANGE, 'group_member:timeadded_from' => 1622502000, ], true], 'Filter group member time added (no match)' => ['group_member:timeadded', [ 'group_member:timeadded_operator' => date::DATE_RANGE, 'group_member:timeadded_to' => 1622502000, ], false], // User (just to test join). 'Filter user username' => ['user:username', [ 'user:username_operator' => text::IS_EQUAL_TO, 'user:username_value' => 'testuser', ], true], 'Filter user username (no match)' => ['user:username', [ 'user:username_operator' => text::IS_NOT_EQUAL_TO, 'user:username_value' => 'testuser', ], false], ]; } /** * Test datasource filters * * @param string $filtername * @param array $filtervalues * @param bool $expectmatch * * @dataProvider datasource_filters_provider */ public function test_datasource_filters( string $filtername, array $filtervalues, bool $expectmatch ): void { $this->resetAfterTest(); $course = $this->getDataGenerator()->create_course(['fullname' => 'Test course']); $user = $this->getDataGenerator()->create_and_enrol($course, 'student', ['username' => 'testuser']); $group = $this->getDataGenerator()->create_group(['courseid' => $course->id, 'idnumber' => 'G101', 'name' => 'Test group']); $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]); $grouping = $this->getDataGenerator()->create_grouping(['courseid' => $course->id, 'idnumber' => 'GR101', 'name' => 'Test grouping']); $this->getDataGenerator()->create_grouping_group(['groupingid' => $grouping->id, 'groupid' => $group->id]); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); // Create report containing single column, and given filter. $report = $generator->create_report(['name' => 'Tasks', 'source' => groups::class, 'default' => 0]); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'group:idnumber']); // Add filter, set it's values. $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]); $content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues); if ($expectmatch) { $this->assertCount(1, $content); $this->assertEquals('G101', reset($content[0])); } else { $this->assertEmpty($content); } } /** * Stress test datasource * * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php */ public function test_stress_datasource(): void { if (!PHPUNIT_LONGTEST) { $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); } $this->resetAfterTest(); $course = $this->getDataGenerator()->create_course(['fullname' => 'Test course']); $user = $this->getDataGenerator()->create_and_enrol($course, 'student', ['username' => 'testuser']); $group = $this->getDataGenerator()->create_group(['courseid' => $course->id, 'idnumber' => 'G101', 'name' => 'Test group']); $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]); $grouping = $this->getDataGenerator()->create_grouping(['courseid' => $course->id, 'idnumber' => 'GR101', 'name' => 'Test grouping']); $this->getDataGenerator()->create_grouping_group(['groupingid' => $grouping->id, 'groupid' => $group->id]); $this->datasource_stress_test_columns(groups::class); $this->datasource_stress_test_columns_aggregation(groups::class); $this->datasource_stress_test_conditions(groups::class, 'group:idnumber'); } }