mirror of
https://github.com/moodle/moodle.git
synced 2025-03-19 23:20:09 +01:00
Merge branch 'MDL-75345-401' of https://github.com/paulholden/moodle into MOODLE_401_STABLE
This commit is contained in:
commit
3ef9c4c5d0
@ -21,7 +21,11 @@ namespace core_course\reportbuilder\datasource;
|
||||
use core_customfield_generator;
|
||||
use core_reportbuilder_testcase;
|
||||
use core_reportbuilder_generator;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\tags;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
@ -60,12 +64,13 @@ class courses_test extends core_reportbuilder_testcase {
|
||||
$content = $this->get_custom_report_content($report->get('id'));
|
||||
$this->assertCount(1, $content);
|
||||
|
||||
$contentrow = array_values(reset($content));
|
||||
$contentrow = array_values($content[0]);
|
||||
|
||||
$this->assertEquals([
|
||||
'My cats', // Category name.
|
||||
'C101', // Course shortname.
|
||||
'All about cats', // Course fullname.
|
||||
'CAT101', // Course ID number.
|
||||
$category->get_formatted_name(),
|
||||
$course->shortname,
|
||||
$course->fullname,
|
||||
$course->idnumber,
|
||||
], $contentrow);
|
||||
}
|
||||
|
||||
@ -75,17 +80,44 @@ class courses_test extends core_reportbuilder_testcase {
|
||||
public function test_datasource_non_default_columns(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course(['tags' => ['Horses']]);
|
||||
$category = $this->getDataGenerator()->create_category([
|
||||
'name' => 'Animals',
|
||||
'idnumber' => 'CAT101',
|
||||
'description' => 'Category description',
|
||||
]);
|
||||
$course = $this->getDataGenerator()->create_course([
|
||||
'category' => $category->id,
|
||||
'fullname' => 'Cats',
|
||||
'summary' => 'Course description',
|
||||
'tags' => ['Horses'],
|
||||
]);
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
$report = $generator->create_report(['name' => 'Courses', 'source' => courses::class, 'default' => 0]);
|
||||
|
||||
// Category.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:namewithlink']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:path']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:idnumber']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:description']);
|
||||
|
||||
// Course.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:coursefullnamewithlink']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:courseshortnamewithlink']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:courseidnumberewithlink']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:summary']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:format']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:startdate']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:enddate']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:visible']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:groupmode']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:groupmodeforce']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:lang']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:calendartype']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:theme']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:enablecompletion']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:downloadcontent']);
|
||||
|
||||
// Tags.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'tag:name']);
|
||||
@ -95,10 +127,33 @@ class courses_test extends core_reportbuilder_testcase {
|
||||
$this->assertCount(1, $content);
|
||||
|
||||
$courserow = array_values($content[0]);
|
||||
$this->assertEquals('Category 1', $courserow[0]);
|
||||
$this->assertEquals($course->fullname, $courserow[1]);
|
||||
$this->assertEquals('Horses', $courserow[2]);
|
||||
$this->assertStringContainsString('Horses', $courserow[3]);
|
||||
|
||||
// Category.
|
||||
$this->assertStringContainsString($category->get_formatted_name(), $courserow[0]);
|
||||
$this->assertEquals($category->get_nested_name(false), $courserow[1]);
|
||||
$this->assertEquals($category->idnumber, $courserow[2]);
|
||||
$this->assertEquals(format_text($category->description, $category->descriptionformat), $courserow[3]);
|
||||
|
||||
// Course.
|
||||
$this->assertStringContainsString($course->fullname, $courserow[4]);
|
||||
$this->assertStringContainsString($course->shortname, $courserow[5]);
|
||||
$this->assertStringContainsString($course->idnumber, $courserow[6]);
|
||||
$this->assertEquals(format_text($course->summary, $course->summaryformat), $courserow[7]);
|
||||
$this->assertEquals('Topics format', $courserow[8]);
|
||||
$this->assertEquals(userdate($course->startdate), $courserow[9]);
|
||||
$this->assertEmpty($courserow[10]);
|
||||
$this->assertEquals('Yes', $courserow[11]);
|
||||
$this->assertEquals('No groups', $courserow[12]);
|
||||
$this->assertEquals('No', $courserow[13]);
|
||||
$this->assertEmpty($courserow[14]);
|
||||
$this->assertEmpty($courserow[15]);
|
||||
$this->assertEmpty($courserow[16]);
|
||||
$this->assertEquals('No', $courserow[17]);
|
||||
$this->assertEmpty($courserow[18]);
|
||||
|
||||
// Tags.
|
||||
$this->assertEquals('Horses', $courserow[19]);
|
||||
$this->assertStringContainsString('Horses', $courserow[20]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,6 +201,142 @@ class courses_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
public function datasource_filters_provider(): array {
|
||||
return [
|
||||
// Category.
|
||||
'Filter category' => ['course_category:name', [
|
||||
'course_category:name_value' => -1,
|
||||
], false],
|
||||
'Filter category name' => ['course_category:text', [
|
||||
'course_category:text_operator' => text::IS_EQUAL_TO,
|
||||
'course_category:text_value' => 'Animals',
|
||||
], true],
|
||||
'Filter category name (no match)' => ['course_category:text', [
|
||||
'course_category:text_operator' => text::IS_EQUAL_TO,
|
||||
'course_category:text_value' => 'Fruit',
|
||||
], false],
|
||||
'Filter category idnumber' => ['course_category:idnumber', [
|
||||
'course_category:idnumber_operator' => text::IS_EQUAL_TO,
|
||||
'course_category:idnumber_value' => 'CAT101',
|
||||
], true],
|
||||
'Filter category idnumber (no match)' => ['course_category:idnumber', [
|
||||
'course_category:idnumber_operator' => text::CONTAINS,
|
||||
'course_category:idnumber_value' => 'FRUIT',
|
||||
], false],
|
||||
|
||||
// Course.
|
||||
'Filter course' => ['course:courseselector', [
|
||||
'course:courseselector_values' => [-1],
|
||||
], false],
|
||||
'Filter course fullname' => ['course:fullname', [
|
||||
'course:fullname_operator' => text::IS_EQUAL_TO,
|
||||
'course:fullname_value' => 'Equine',
|
||||
], true],
|
||||
'Filter course fullname (no match)' => ['course:fullname', [
|
||||
'course:fullname_operator' => text::IS_EQUAL_TO,
|
||||
'course:fullname_value' => 'Foxes',
|
||||
], false],
|
||||
'Filter course shortname' => ['course:shortname', [
|
||||
'course:shortname_operator' => text::IS_EQUAL_TO,
|
||||
'course:shortname_value' => 'EQ101',
|
||||
], true],
|
||||
'Filter course shortname (no match)' => ['course:shortname', [
|
||||
'course:shortname_operator' => text::IS_EQUAL_TO,
|
||||
'course:shortname_value' => 'FX101',
|
||||
], false],
|
||||
'Filter course idnumber' => ['course:idnumber', [
|
||||
'course:idnumber_operator' => text::IS_EQUAL_TO,
|
||||
'course:idnumber_value' => 'E-101AB',
|
||||
], true],
|
||||
'Filter course idnumber (no match)' => ['course:idnumber', [
|
||||
'course:idnumber_operator' => text::IS_EQUAL_TO,
|
||||
'course:idnumber_value' => 'F-101XT',
|
||||
], false],
|
||||
'Filter course summary' => ['course:summary', [
|
||||
'course:summary_operator' => text::CONTAINS,
|
||||
'course:summary_value' => 'Lorem ipsum',
|
||||
], true],
|
||||
'Filter course summary (no match)' => ['course:summary', [
|
||||
'course:summary_operator' => text::IS_EQUAL_TO,
|
||||
'course:summary_value' => 'Fiat',
|
||||
], false],
|
||||
'Filter course format' => ['course:format', [
|
||||
'course:format_operator' => select::EQUAL_TO,
|
||||
'course:format_value' => 'topics',
|
||||
], true],
|
||||
'Filter course format (no match)' => ['course:format', [
|
||||
'course:format_operator' => select::EQUAL_TO,
|
||||
'course:format_value' => 'weekly',
|
||||
], false],
|
||||
'Filter course startdate' => ['course:startdate', [
|
||||
'course:startdate_operator' => date::DATE_RANGE,
|
||||
'course:startdate_from' => 1622502000,
|
||||
], true],
|
||||
'Filter course startdate (no match)' => ['course:startdate', [
|
||||
'course:startdate_operator' => date::DATE_RANGE,
|
||||
'course:startdate_to' => 1622502000,
|
||||
], false],
|
||||
'Filter course enddate' => ['course:enddate', [
|
||||
'course:enddate_operator' => date::DATE_EMPTY,
|
||||
], true],
|
||||
'Filter course enddate (no match)' => ['course:enddate', [
|
||||
'course:enddate_operator' => date::DATE_NOT_EMPTY,
|
||||
], false],
|
||||
'Filter course visible' => ['course:visible', [
|
||||
'course:visible_operator' => boolean_select::CHECKED,
|
||||
], true],
|
||||
'Filter course visible (no match)' => ['course:visible', [
|
||||
'course:visible_operator' => boolean_select::NOT_CHECKED,
|
||||
], false],
|
||||
'Filter course groupmode' => ['course:groupmode', [
|
||||
'course:groupmode_operator' => select::EQUAL_TO,
|
||||
'course:groupmode_value' => 0, // No groups.
|
||||
], true],
|
||||
'Filter course groupmode (no match)' => ['course:groupmode', [
|
||||
'course:groupmode_operator' => select::EQUAL_TO,
|
||||
'course:groupmode_value' => 1, // Separate groups.
|
||||
], false],
|
||||
'Filter course groupmodeforce' => ['course:groupmodeforce', [
|
||||
'course:groupmodeforce_operator' => boolean_select::NOT_CHECKED,
|
||||
], true],
|
||||
'Filter course groupmodeforce (no match)' => ['course:groupmodeforce', [
|
||||
'course:groupmodeforce_operator' => boolean_select::CHECKED,
|
||||
], false],
|
||||
'Filter course lang' => ['course:lang', [
|
||||
'course:lang_operator' => select::EQUAL_TO,
|
||||
'course:lang_value' => 'en',
|
||||
], true],
|
||||
'Filter course lang (no match)' => ['course:lang', [
|
||||
'course:lang_operator' => select::EQUAL_TO,
|
||||
'course:lang_value' => 'de',
|
||||
], false],
|
||||
'Filter course calendartype' => ['course:calendartype', [
|
||||
'course:calendartype_operator' => select::EQUAL_TO,
|
||||
'course:calendartype_value' => 'gregorian',
|
||||
], true],
|
||||
'Filter course calendartype (no match)' => ['course:calendartype', [
|
||||
'course:calendartype_operator' => select::EQUAL_TO,
|
||||
'course:calendartype_value' => 'hijri',
|
||||
], false],
|
||||
'Filter course theme' => ['course:theme', [
|
||||
'course:theme_operator' => select::EQUAL_TO,
|
||||
'course:theme_value' => 'boost',
|
||||
], true],
|
||||
'Filter course theme (no match)' => ['course:theme', [
|
||||
'course:theme_operator' => select::EQUAL_TO,
|
||||
'course:theme_value' => 'classic',
|
||||
], false],
|
||||
'Filter course enablecompletion' => ['course:enablecompletion', [
|
||||
'course:enablecompletion_operator' => boolean_select::NOT_CHECKED,
|
||||
], true],
|
||||
'Filter course enablecompletion (no match)' => ['course:enablecompletion', [
|
||||
'course:enablecompletion_operator' => boolean_select::CHECKED,
|
||||
], false],
|
||||
'Filter course downloadcontent' => ['course:downloadcontent', [
|
||||
'course:downloadcontent_operator' => boolean_select::CHECKED,
|
||||
], true],
|
||||
'Filter course downloadcontent (no match)' => ['course:downloadcontent', [
|
||||
'course:downloadcontent_operator' => boolean_select::NOT_CHECKED,
|
||||
], false],
|
||||
|
||||
// Tags.
|
||||
'Filter tag name' => ['tag:name', [
|
||||
'tag:name_operator' => tags::EQUAL_TO,
|
||||
@ -166,14 +357,21 @@ class courses_test extends core_reportbuilder_testcase {
|
||||
*
|
||||
* @dataProvider datasource_filters_provider
|
||||
*/
|
||||
public function test_datasource_filters(
|
||||
string $filtername,
|
||||
array $filtervalues,
|
||||
bool $expectmatch
|
||||
): void {
|
||||
public function test_datasource_filters(string $filtername, array $filtervalues, bool $expectmatch): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course(['tags' => ['Horses']]);
|
||||
$category = $this->getDataGenerator()->create_category(['name' => 'Animals', 'idnumber' => 'CAT101']);
|
||||
$course = $this->getDataGenerator()->create_course([
|
||||
'category' => $category->id,
|
||||
'fullname' => 'Equine',
|
||||
'shortname' => 'EQ101',
|
||||
'idnumber' => 'E-101AB',
|
||||
'lang' => 'en',
|
||||
'calendartype' => 'gregorian',
|
||||
'theme' => 'boost',
|
||||
'downloadcontent' => 1,
|
||||
'tags' => ['Horses'],
|
||||
]);
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
|
@ -193,7 +193,7 @@ class user_profile_fields {
|
||||
break;
|
||||
case 'datetime':
|
||||
$classname = date::class;
|
||||
$fieldsql = $DB->sql_cast_char2int($field);
|
||||
$fieldsql = $DB->sql_cast_char2int($field, true);
|
||||
break;
|
||||
case 'menu':
|
||||
$classname = select::class;
|
||||
|
@ -1,76 +0,0 @@
|
||||
<?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_reportbuilder;
|
||||
|
||||
use core_reportbuilder\local\entities\course;
|
||||
use core_reportbuilder\local\helpers\database;
|
||||
|
||||
/**
|
||||
* Testable system report fixture for testing the course entity
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class course_entity_report extends system_report {
|
||||
|
||||
/**
|
||||
* Initialise the report
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
$entity = new course();
|
||||
$coursetablealias = $entity->get_table_alias('course');
|
||||
$param = database::generate_param_name();
|
||||
|
||||
$this->set_main_table('course', $coursetablealias);
|
||||
$this->add_entity($entity);
|
||||
// Add a base condition to hide the site course.
|
||||
$this->add_base_condition_sql("$coursetablealias.id <> :$param", [$param => SITEID]);
|
||||
|
||||
$columns = [];
|
||||
foreach ($entity->get_columns() as $column) {
|
||||
$columns[] = $column->get_unique_identifier();
|
||||
}
|
||||
$this->add_columns_from_entities($columns);
|
||||
|
||||
$filters = [];
|
||||
foreach ($entity->get_filters() as $filter) {
|
||||
$filters[] = $filter->get_unique_identifier();
|
||||
}
|
||||
$this->add_filters_from_entities($filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can view the report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function can_view(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly set availability of report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_available(): bool {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
<?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_reportbuilder;
|
||||
|
||||
use core_reportbuilder\local\entities\user;
|
||||
|
||||
/**
|
||||
* Testable system report fixture for testing the user entity
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class user_entity_report extends system_report {
|
||||
|
||||
/**
|
||||
* Initialise the report
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
$entity = new user();
|
||||
|
||||
$this->set_main_table('user', $entity->get_table_alias('user'));
|
||||
$this->add_entity($entity);
|
||||
|
||||
$columns = [];
|
||||
foreach ($entity->get_columns() as $column) {
|
||||
$columns[] = $column->get_unique_identifier();
|
||||
}
|
||||
$this->add_columns_from_entities($columns);
|
||||
|
||||
$filters = [];
|
||||
foreach ($entity->get_filters() as $filter) {
|
||||
$filters[] = $filter->get_unique_identifier();
|
||||
}
|
||||
$this->add_filters_from_entities($filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can view the report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function can_view(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly set availability of report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_available(): bool {
|
||||
return true;
|
||||
}
|
||||
}
|
349
reportbuilder/tests/local/entities/base_test.php
Normal file
349
reportbuilder/tests/local/entities/base_test.php
Normal file
@ -0,0 +1,349 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for base entity
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\local\entities;
|
||||
|
||||
use advanced_testcase;
|
||||
use coding_exception;
|
||||
use lang_string;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\report\column;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Unit tests for base entity
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @covers \core_reportbuilder\local\entities\base
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class base_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test entity table alias
|
||||
*/
|
||||
public function test_get_table_alias(): void {
|
||||
$entity = new base_test_entity();
|
||||
$this->assertEquals('m', $entity->get_table_alias('mytable'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for invalid get table alias
|
||||
*/
|
||||
public function test_get_table_alias_invalid(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: ' .
|
||||
'Invalid table name (nonexistingalias)');
|
||||
$entity->get_table_alias('nonexistingalias');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting table alias
|
||||
*/
|
||||
public function test_set_table_alias(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$entity->set_table_alias('mytable', 'newalias');
|
||||
$this->assertEquals('newalias', $entity->get_table_alias('mytable'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test invalid entity set table alias
|
||||
*/
|
||||
public function test_set_table_alias_invalid(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: Invalid table name (nonexistent)');
|
||||
$entity->set_table_alias('nonexistent', 'newalias');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting multiple table aliases
|
||||
*/
|
||||
public function test_set_table_aliases(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$entity->set_table_aliases([
|
||||
'mytable' => 'newalias',
|
||||
'myothertable' => 'newalias2',
|
||||
]);
|
||||
$this->assertEquals('newalias', $entity->get_table_alias('mytable'));
|
||||
$this->assertEquals('newalias2', $entity->get_table_alias('myothertable'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting multiple table aliases, containing an invalid table
|
||||
*/
|
||||
public function test_set_table_aliases_invalid(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: Invalid table name (nonexistent)');
|
||||
$entity->set_table_aliases([
|
||||
'mytable' => 'newalias',
|
||||
'nonexistent' => 'newalias2',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test entity name
|
||||
*/
|
||||
public function test_set_entity_name(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$this->assertEquals('base_test_entity', $entity->get_entity_name());
|
||||
|
||||
$entity->set_entity_name('newentityname');
|
||||
$this->assertEquals('newentityname', $entity->get_entity_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test invalid entity name
|
||||
*/
|
||||
public function test_set_entity_name_invalid(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Entity name must be comprised of alphanumeric character, underscore or dash');
|
||||
$entity->set_entity_name('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test entity title
|
||||
*/
|
||||
public function test_set_entity_title(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$this->assertEquals(new lang_string('yes'), $entity->get_entity_title());
|
||||
|
||||
$newtitle = new lang_string('fullname');
|
||||
$entity->set_entity_title($newtitle);
|
||||
$this->assertEquals($newtitle, $entity->get_entity_title());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test adding single join
|
||||
*/
|
||||
public function test_add_join(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$tablejoin = "JOIN {course} c2 ON c2.id = c1.id";
|
||||
$entity->add_join($tablejoin);
|
||||
|
||||
$this->assertEquals([$tablejoin], $entity->get_joins());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test adding multiple joins
|
||||
*/
|
||||
public function test_add_joins(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$tablejoins = [
|
||||
"JOIN {course} c2 ON c2.id = c1.id",
|
||||
"JOIN {course} c3 ON c3.id = c1.id",
|
||||
];
|
||||
$entity->add_joins($tablejoins);
|
||||
|
||||
$this->assertEquals($tablejoins, $entity->get_joins());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test adding duplicate joins
|
||||
*/
|
||||
public function test_add_duplicate_joins(): void {
|
||||
$entity = new base_test_entity();
|
||||
|
||||
$tablejoins = [
|
||||
"JOIN {course} c2 ON c2.id = c1.id",
|
||||
"JOIN {course} c3 ON c3.id = c1.id",
|
||||
];
|
||||
$entity
|
||||
->add_joins($tablejoins)
|
||||
->add_joins($tablejoins);
|
||||
|
||||
$this->assertEquals($tablejoins, $entity->get_joins());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting column
|
||||
*/
|
||||
public function test_get_column(): void {
|
||||
$entity = (new base_test_entity())->initialise();
|
||||
|
||||
$column = $entity->get_column('test');
|
||||
$this->assertEquals('base_test_entity:test', $column->get_unique_identifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for invalid get column
|
||||
*/
|
||||
public function test_get_column_invalid(): void {
|
||||
$entity = (new base_test_entity())->initialise();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: ' .
|
||||
'Invalid column name (nonexistingcolumn)');
|
||||
$entity->get_column('nonexistingcolumn');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting columns
|
||||
*/
|
||||
public function test_get_columns(): void {
|
||||
$entity = (new base_test_entity())->initialise();
|
||||
|
||||
$columns = $entity->get_columns();
|
||||
$this->assertCount(1, $columns);
|
||||
$this->assertContainsOnlyInstancesOf(column::class, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting filter
|
||||
*/
|
||||
public function test_get_filter(): void {
|
||||
$entity = (new base_test_entity())->initialise();
|
||||
|
||||
$filter = $entity->get_filter('test');
|
||||
$this->assertEquals('base_test_entity:test', $filter->get_unique_identifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for invalid get filter
|
||||
*/
|
||||
public function test_get_filter_invalid(): void {
|
||||
$entity = (new base_test_entity())->initialise();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: ' .
|
||||
'Invalid filter name (nonexistingfilter)');
|
||||
$entity->get_filter('nonexistingfilter');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting filters
|
||||
*/
|
||||
public function test_get_filters(): void {
|
||||
$entity = (new base_test_entity())->initialise();
|
||||
|
||||
$filters = $entity->get_filters();
|
||||
$this->assertCount(1, $filters);
|
||||
$this->assertContainsOnlyInstancesOf(filter::class, $filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting condition
|
||||
*/
|
||||
public function test_get_condition(): void {
|
||||
$entity = (new base_test_entity())->initialise();
|
||||
|
||||
$condition = $entity->get_condition('test');
|
||||
$this->assertEquals('base_test_entity:test', $condition->get_unique_identifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for invalid get condition
|
||||
*/
|
||||
public function test_get_condition_invalid(): void {
|
||||
$entity = (new base_test_entity())->initialise();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: ' .
|
||||
'Invalid condition name (nonexistingcondition)');
|
||||
$entity->get_condition('nonexistingcondition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting conditions
|
||||
*/
|
||||
public function test_get_conditions(): void {
|
||||
$entity = (new base_test_entity())->initialise();
|
||||
|
||||
$conditions = $entity->get_conditions();
|
||||
$this->assertCount(1, $conditions);
|
||||
$this->assertContainsOnlyInstancesOf(filter::class, $conditions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple implementation of the base entity
|
||||
*/
|
||||
class base_test_entity extends base {
|
||||
|
||||
/**
|
||||
* Table aliases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_default_table_aliases(): array {
|
||||
return [
|
||||
'mytable' => 'm',
|
||||
'myothertable' => 'o',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Entity title
|
||||
*
|
||||
* @return lang_string
|
||||
*/
|
||||
protected function get_default_entity_title(): lang_string {
|
||||
return new lang_string('yes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise entity
|
||||
*
|
||||
* @return base
|
||||
*/
|
||||
public function initialise(): base {
|
||||
$column = (new column(
|
||||
'test',
|
||||
new lang_string('no'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_field('no');
|
||||
|
||||
$filter = (new filter(
|
||||
text::class,
|
||||
'test',
|
||||
new lang_string('no'),
|
||||
$this->get_entity_name(),
|
||||
))
|
||||
->set_field_sql('no');
|
||||
|
||||
return $this
|
||||
->add_column($column)
|
||||
->add_filter($filter)
|
||||
->add_condition($filter);
|
||||
}
|
||||
}
|
@ -1,515 +0,0 @@
|
||||
<?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_reportbuilder\local\entities;
|
||||
|
||||
use advanced_testcase;
|
||||
use coding_exception;
|
||||
use context_system;
|
||||
use lang_string;
|
||||
use core_reportbuilder\course_entity_report;
|
||||
use core_reportbuilder\manager;
|
||||
use core_reportbuilder\testable_system_report_table;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\tags;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\helpers\user_filter_manager;
|
||||
|
||||
/**
|
||||
* Unit tests for course entity
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @covers \core_reportbuilder\local\entities\base
|
||||
* @covers \core_reportbuilder\local\entities\course
|
||||
* @covers \core_reportbuilder\local\helpers\custom_fields
|
||||
* @covers \core_reportbuilder\local\report\base
|
||||
* @covers \core_reportbuilder\system_report
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class course_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Load required classes
|
||||
*/
|
||||
public static function setUpBeforeClass(): void {
|
||||
global $CFG;
|
||||
|
||||
require_once("{$CFG->dirroot}/course/lib.php");
|
||||
require_once("{$CFG->dirroot}/reportbuilder/tests/fixtures/testable_system_report_table.php");
|
||||
require_once("{$CFG->dirroot}/reportbuilder/tests/fixtures/course_entity_report.php");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate courses for the tests
|
||||
*/
|
||||
public function generate_courses(): array {
|
||||
$coursecategory1 = $this->getDataGenerator()->create_category();
|
||||
$course1 = $this->getDataGenerator()->create_course([
|
||||
'fullname' => 'Course 1',
|
||||
'shortname' => 'C1',
|
||||
'idnumber' => 'IDNumber1',
|
||||
'visible' => 1,
|
||||
'startdate' => 289308600,
|
||||
'enddate' => 3445023600,
|
||||
'category' => $coursecategory1->id,
|
||||
'groupmode' => NOGROUPS,
|
||||
'enablecompletion' => 1,
|
||||
'downloadcontent' => DOWNLOAD_COURSE_CONTENT_DISABLED,
|
||||
'format' => 'topics',
|
||||
'calendartype' => 'Gregorian',
|
||||
'theme' => 'afterburner',
|
||||
'lang' => 'en',
|
||||
'tags' => ['dancing'],
|
||||
]);
|
||||
|
||||
$coursecategory2 = $this->getDataGenerator()->create_category();
|
||||
$course2 = $this->getDataGenerator()->create_course([
|
||||
'fullname' => 'Course 2',
|
||||
'shortname' => 'C2',
|
||||
'idnumber' => 'IDNumber2',
|
||||
'visible' => 0,
|
||||
'startdate' => 1614726000,
|
||||
'enddate' => 1961881200,
|
||||
'category' => $coursecategory2->id,
|
||||
'groupmode' => SEPARATEGROUPS,
|
||||
'enablecompletion' => 0,
|
||||
'downloadcontent' => DOWNLOAD_COURSE_CONTENT_ENABLED,
|
||||
'format' => 'topics',
|
||||
'calendartype' => 'Gregorian',
|
||||
'theme' => 'afterburner',
|
||||
'lang' => 'es',
|
||||
]);
|
||||
|
||||
return [$coursecategory1, $course1, $coursecategory2, $course2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test callbacks are correctly applied for those columns using them
|
||||
*/
|
||||
public function test_get_columns_with_callbacks(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
[$coursecategory1, $course1] = $this->generate_courses();
|
||||
$testdate = time();
|
||||
|
||||
// Add some customfields to the course.
|
||||
$cfgenerator = self::getDataGenerator()->get_plugin_generator('core_customfield');
|
||||
$params = [
|
||||
'component' => 'core_course',
|
||||
'area' => 'course',
|
||||
'itemid' => 0,
|
||||
'contextid' => context_system::instance()->id
|
||||
];
|
||||
$category = $cfgenerator->create_category($params);
|
||||
$field1 = $cfgenerator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'text', 'name' => 'Customfield text 1', 'shortname' => 'cf1']);
|
||||
$cfgenerator->add_instance_data($field1, (int)$course1->id, 'Do. Or do not. There is no try');
|
||||
$field2 = $cfgenerator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'text', 'name' => 'Customfield text 2', 'shortname' => 'cf2']);
|
||||
$cfgenerator->add_instance_data($field2, (int)$course1->id, 'Chewie, we are home');
|
||||
$field3 = $cfgenerator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'checkbox', 'name' => 'Customfield checkbox', 'shortname' => 'cf3']);
|
||||
$cfgenerator->add_instance_data($field3, (int)$course1->id, 1);
|
||||
$field4 = $cfgenerator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'date', 'name' => 'Customfield date', 'shortname' => 'cf4']);
|
||||
$cfgenerator->add_instance_data($field4, (int)$course1->id, $testdate);
|
||||
$field5 = $cfgenerator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'select', 'name' => 'Customfield menu', 'shortname' => 'cf5',
|
||||
'configdata' => ['defaultvalue' => 'Option A', 'options' => "Option A\nOption B\nOption C"]]);
|
||||
// Select option C for course1 (options are counted starting from one).
|
||||
$cfgenerator->add_instance_data($field5, (int)$course1->id, 3);
|
||||
|
||||
$tablerows = $this->get_report_table_rows();
|
||||
$courserows = array_filter($tablerows, static function(array $row) use ($course1): bool {
|
||||
return $row['shortname'] === $course1->shortname;
|
||||
});
|
||||
$courserow = reset($courserows);
|
||||
|
||||
$this->assertEquals('Course 1', $courserow['fullname']);
|
||||
$this->assertEquals('C1', $courserow['shortname']);
|
||||
$this->assertEquals('IDNumber1', $courserow['idnumber']);
|
||||
$this->assertEquals('Yes', $courserow['visible']);
|
||||
$this->assertEquals(userdate(289308600), $courserow['startdate']);
|
||||
$this->assertEquals(userdate(3445023600), $courserow['enddate']);
|
||||
$this->assertEquals('No groups', $courserow['groupmode']);
|
||||
$this->assertEquals('Yes', $courserow['enablecompletion']);
|
||||
$this->assertEquals('No', $courserow['downloadcontent']);
|
||||
$this->assertEquals('Topics format', $courserow['format']);
|
||||
$this->assertEquals('Gregorian', $courserow['calendartype']);
|
||||
$this->assertEquals('afterburner', $courserow['theme']);
|
||||
$this->assertEquals(get_string_manager()->get_list_of_translations()['en'], $courserow['lang']);
|
||||
$expected = '<a href="https://www.example.com/moodle/course/view.php?id=' . $course1->id . '">Course 1</a>';
|
||||
$this->assertEquals($expected, $courserow['coursefullnamewithlink']);
|
||||
$expected = '<a href="https://www.example.com/moodle/course/view.php?id=' . $course1->id . '">C1</a>';
|
||||
$this->assertEquals($expected, $courserow['courseshortnamewithlink']);
|
||||
$expected = '<a href="https://www.example.com/moodle/course/view.php?id=' . $course1->id . '">IDNumber1</a>';
|
||||
$this->assertEquals($expected, $courserow['courseidnumberewithlink']);
|
||||
$this->assertEquals('Do. Or do not. There is no try', $courserow['customfield_cf1']);
|
||||
$this->assertEquals('Chewie, we are home', $courserow['customfield_cf2']);
|
||||
$this->assertEquals('Yes', $courserow['customfield_cf3']);
|
||||
$this->assertEquals(userdate($testdate), $courserow['customfield_cf4']);
|
||||
$this->assertEquals('Option C', $courserow['customfield_cf5']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filtering report by course fields
|
||||
*/
|
||||
public function test_filters(): void {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
[$coursecategory1] = $this->generate_courses();
|
||||
|
||||
// Filter by fullname field.
|
||||
$filtervalues = [
|
||||
'course:fullname_operator' => text::IS_EQUAL_TO,
|
||||
'course:fullname_value' => 'Course 1',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Course 1',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by shortname field.
|
||||
$filtervalues = [
|
||||
'course:shortname_operator' => text::IS_EQUAL_TO,
|
||||
'course:shortname_value' => 'C1',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Course 1',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by idnumber field.
|
||||
$filtervalues = [
|
||||
'course:idnumber_operator' => text::IS_EQUAL_TO,
|
||||
'course:idnumber_value' => 'IDNumber2',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Course 2',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by visible field.
|
||||
$filtervalues = [
|
||||
'course:visible_operator' => boolean_select::NOT_CHECKED,
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Course 2',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by startdate field.
|
||||
$filtervalues = [
|
||||
'course:startdate_operator' => date::DATE_RANGE,
|
||||
'course:startdate_from' => 289135800,
|
||||
'course:startdate_to' => 289740600,
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Course 1',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by group mode field.
|
||||
$filtervalues = [
|
||||
'course:groupmode_operator' => select::EQUAL_TO,
|
||||
'course:groupmode_value' => SEPARATEGROUPS,
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Course 2',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by enable completion field.
|
||||
$filtervalues = [
|
||||
'course:enablecompletion_operator' => boolean_select::CHECKED,
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Course 1',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filtering report by course customfield
|
||||
*/
|
||||
public function test_customfield_text_filter(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course1 = $this->getDataGenerator()->create_course([
|
||||
'fullname' => 'Philosophy and Superheroes',
|
||||
'shortname' => 'PS1',
|
||||
]);
|
||||
$course2 = $this->getDataGenerator()->create_course([
|
||||
'fullname' => 'The game of Mathematics',
|
||||
'shortname' => 'GM1',
|
||||
]);
|
||||
|
||||
// Add some customfields to the course.
|
||||
$cfgenerator = self::getDataGenerator()->get_plugin_generator('core_customfield');
|
||||
$params = [
|
||||
'component' => 'core_course',
|
||||
'area' => 'course',
|
||||
'itemid' => 0,
|
||||
'contextid' => context_system::instance()->id
|
||||
];
|
||||
$category = $cfgenerator->create_category($params);
|
||||
$field = $cfgenerator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'text', 'name' => 'Customfield text 1', 'shortname' => 'cf']);
|
||||
$cfgenerator->add_instance_data($field, (int)$course1->id, 'Leia Organa');
|
||||
$cfgenerator->add_instance_data($field, (int)$course2->id, 'Han Solo');
|
||||
$field5 = $cfgenerator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'select', 'name' => 'Customfield menu', 'shortname' => 'cf5',
|
||||
'configdata' => ['defaultvalue' => 'Option A', 'options' => "Option A\nOption B\nOption C"]]);
|
||||
$cfgenerator->add_instance_data($field5, (int)$course1->id, 3);
|
||||
$cfgenerator->add_instance_data($field5, (int)$course2->id, 2);
|
||||
|
||||
$filtervalues = [
|
||||
'course:customfield_cf_operator' => text::IS_EQUAL_TO,
|
||||
'course:customfield_cf_value' => 'Leia Organa',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Philosophy and Superheroes',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
$filtervalues = [
|
||||
'course:customfield_cf_operator' => text::IS_EQUAL_TO,
|
||||
'course:customfield_cf_value' => 'Han Solo',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'The game of Mathematics',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by menu customfield.
|
||||
$filtervalues = [
|
||||
'course:customfield_cf5_operator' => select::EQUAL_TO,
|
||||
'course:customfield_cf5_value' => 3, // Option C.
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Philosophy and Superheroes',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by course customfield that doesn't exist.
|
||||
$filtervalues = [
|
||||
'course:customfield_cf_operator' => text::IS_EQUAL_TO,
|
||||
'course:customfield_cf_value' => 'Luke Skywalker',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEmpty($tablerows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create the report, and return it's rows
|
||||
*
|
||||
* @param array $filtervalues
|
||||
* @return array
|
||||
*/
|
||||
private function get_report_table_rows(array $filtervalues = []): array {
|
||||
$report = manager::create_report_persistent((object) [
|
||||
'type' => course_entity_report::TYPE_SYSTEM_REPORT,
|
||||
'source' => course_entity_report::class,
|
||||
]);
|
||||
|
||||
user_filter_manager::set($report->get('id'), $filtervalues);
|
||||
|
||||
return testable_system_report_table::create($report->get('id'), [])->get_table_rows();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test entity table alias
|
||||
*/
|
||||
public function test_get_table_alias(): void {
|
||||
$courseentity = new course();
|
||||
$this->assertEquals('c', $courseentity->get_table_alias('course'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for invalid get table alias
|
||||
*/
|
||||
public function test_get_table_alias_invalid(): void {
|
||||
$courseentity = new course();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: ' .
|
||||
'Invalid table name (nonexistingalias)');
|
||||
$courseentity->get_table_alias('nonexistingalias');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting table alias
|
||||
*/
|
||||
public function test_set_table_alias(): void {
|
||||
$courseentity = new course();
|
||||
|
||||
$courseentity->set_table_alias('course', 'newalias');
|
||||
$this->assertEquals('newalias', $courseentity->get_table_alias('course'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test invalid entity set table alias
|
||||
*/
|
||||
public function test_set_table_alias_invalid(): void {
|
||||
$courseentity = new course();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: Invalid table name (nonexistent)');
|
||||
$courseentity->set_table_alias('nonexistent', 'newalias');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting multiple table aliases
|
||||
*/
|
||||
public function test_set_table_aliases(): void {
|
||||
$courseentity = new course();
|
||||
|
||||
$courseentity->set_table_aliases([
|
||||
'course' => 'newalias',
|
||||
'context' => 'newalias2',
|
||||
]);
|
||||
$this->assertEquals('newalias', $courseentity->get_table_alias('course'));
|
||||
$this->assertEquals('newalias2', $courseentity->get_table_alias('context'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting multiple table aliases, containing an invalid table
|
||||
*/
|
||||
public function test_set_table_aliases_invalid(): void {
|
||||
$courseentity = new course();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: Invalid table name (nonexistent)');
|
||||
$courseentity->set_table_aliases([
|
||||
'course' => 'newalias',
|
||||
'nonexistent' => 'newalias2',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test entity name
|
||||
*/
|
||||
public function test_name(): void {
|
||||
$courseentity = new course();
|
||||
|
||||
$this->assertEquals('course', $courseentity->get_entity_name());
|
||||
|
||||
$courseentity->set_entity_name('newentityname');
|
||||
$this->assertEquals('newentityname', $courseentity->get_entity_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test invalid entity name
|
||||
*/
|
||||
public function test_name_invalid(): void {
|
||||
$courseentity = new course();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Entity name must be comprised of alphanumeric character, underscore or dash');
|
||||
$courseentity->set_entity_name('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test entity title
|
||||
*/
|
||||
public function test_title(): void {
|
||||
$courseentity = new course();
|
||||
|
||||
$this->assertEquals(new lang_string('entitycourse', 'core_reportbuilder'), $courseentity->get_entity_title());
|
||||
|
||||
$newtitle = new lang_string('fullname');
|
||||
$courseentity->set_entity_title($newtitle);
|
||||
$this->assertEquals($newtitle, $courseentity->get_entity_title());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test adding single join
|
||||
*/
|
||||
public function test_add_join(): void {
|
||||
$courseentity = (new course())
|
||||
->set_table_alias('course', 'c1');
|
||||
|
||||
$tablejoin = "JOIN {course} c2 ON c2.id = c1.id";
|
||||
$courseentity->add_join($tablejoin);
|
||||
|
||||
$this->assertEquals([$tablejoin], $courseentity->get_joins());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test adding multiple joins
|
||||
*/
|
||||
public function test_add_joins(): void {
|
||||
$courseentity = (new course())
|
||||
->set_table_alias('course', 'c1');
|
||||
|
||||
$tablejoins = [
|
||||
"JOIN {course} c2 ON c2.id = c1.id",
|
||||
"JOIN {course} c3 ON c3.id = c1.id",
|
||||
];
|
||||
$courseentity->add_joins($tablejoins);
|
||||
|
||||
$this->assertEquals($tablejoins, $courseentity->get_joins());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test adding duplicate joins
|
||||
*/
|
||||
public function test_add_duplicate_joins(): void {
|
||||
$courseentity = (new course())
|
||||
->set_table_alias('course', 'c1');
|
||||
|
||||
$tablejoins = [
|
||||
"JOIN {course} c2 ON c2.id = c1.id",
|
||||
"JOIN {course} c3 ON c3.id = c1.id",
|
||||
];
|
||||
$courseentity
|
||||
->add_joins($tablejoins)
|
||||
->add_joins($tablejoins);
|
||||
|
||||
$this->assertEquals($tablejoins, $courseentity->get_joins());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for invalid get column
|
||||
*/
|
||||
public function test_get_column_invalid(): void {
|
||||
$courseentity = new course();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: ' .
|
||||
'Invalid column name (nonexistingcolumn)');
|
||||
$courseentity->get_column('nonexistingcolumn');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for invalid get filter
|
||||
*/
|
||||
public function test_get_filter_invalid(): void {
|
||||
$courseentity = new course();
|
||||
|
||||
$this->expectException(coding_exception::class);
|
||||
$this->expectExceptionMessage('Coding error detected, it must be fixed by a programmer: ' .
|
||||
'Invalid filter name (nonexistingfilter)');
|
||||
$courseentity->get_filter('nonexistingfilter');
|
||||
}
|
||||
}
|
@ -19,295 +19,51 @@ declare(strict_types=1);
|
||||
namespace core_reportbuilder\local\entities;
|
||||
|
||||
use advanced_testcase;
|
||||
use moodle_url;
|
||||
use core_reportbuilder\manager;
|
||||
use core_reportbuilder\testable_system_report_table;
|
||||
use core_reportbuilder\user_entity_report;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\tags;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\helpers\user_filter_manager;
|
||||
|
||||
/**
|
||||
* Unit tests for user entity
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @covers \core_reportbuilder\local\entities\base
|
||||
* @covers \core_reportbuilder\local\entities\user
|
||||
* @covers \core_reportbuilder\local\helpers\user_profile_fields
|
||||
* @covers \core_reportbuilder\local\report\base
|
||||
* @covers \core_reportbuilder\system_report
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class user_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Load required classes
|
||||
* Test getting user identity column
|
||||
*/
|
||||
public static function setUpBeforeClass(): void {
|
||||
global $CFG;
|
||||
|
||||
require_once("{$CFG->dirroot}/reportbuilder/tests/fixtures/testable_system_report_table.php");
|
||||
require_once("{$CFG->dirroot}/reportbuilder/tests/fixtures/user_entity_report.php");
|
||||
require_once("{$CFG->dirroot}/user/profile/lib.php");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test callbacks are correctly applied for those columns using them
|
||||
*/
|
||||
public function test_columns_with_callbacks(): void {
|
||||
public function test_get_identity_column(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Add a couple of user profile fields to show on the report.
|
||||
$this->getDataGenerator()->create_custom_profile_field(['datatype' => 'text',
|
||||
'shortname' => 'favcolor', 'name' => 'Favorite color']);
|
||||
$this->getDataGenerator()->create_custom_profile_field(['datatype' => 'text',
|
||||
'shortname' => 'favsuperpower', 'name' => 'Favorite super power']);
|
||||
$this->getDataGenerator()->create_custom_profile_field(['datatype' => 'text', 'name' => 'Hi', 'shortname' => 'hi']);
|
||||
|
||||
$user = $this->getDataGenerator()->create_user([
|
||||
'suspended' => 1,
|
||||
'confirmed' => 0,
|
||||
'country' => 'ES',
|
||||
'interests' => ['dancing'],
|
||||
'profile_field_favcolor' => 'Blue',
|
||||
'profile_field_favsuperpower' => 'Time travel',
|
||||
]);
|
||||
$user = new user();
|
||||
$user->initialise();
|
||||
|
||||
$tablerows = $this->get_report_table_rows();
|
||||
$userrows = array_filter($tablerows, static function(array $row) use ($user): bool {
|
||||
return $row['username'] === $user->username;
|
||||
});
|
||||
$userrow = reset($userrows);
|
||||
$columnusername = $user->get_identity_column('username');
|
||||
$this->assertEquals('user:username', $columnusername->get_unique_identifier());
|
||||
|
||||
$this->assertEquals('Yes', $userrow['suspended']);
|
||||
$this->assertEquals('No', $userrow['confirmed']);
|
||||
$this->assertEquals('Spain', $userrow['country']);
|
||||
$this->assertEquals('Blue', $userrow['profilefield_favcolor']);
|
||||
$this->assertEquals('Time travel', $userrow['profilefield_favsuperpower']);
|
||||
$columnprofilefield = $user->get_identity_column('profile_field_hi');
|
||||
$this->assertEquals('user:profilefield_hi', $columnprofilefield->get_unique_identifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the formatted user fullname columns
|
||||
* Test getting user identity filter
|
||||
*/
|
||||
public function test_fullname_columns(): void {
|
||||
global $OUTPUT;
|
||||
|
||||
public function test_get_identity_filter(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$user = $this->getDataGenerator()->create_user([]);
|
||||
$this->getDataGenerator()->create_custom_profile_field(['datatype' => 'text', 'name' => 'Hi', 'shortname' => 'hi']);
|
||||
|
||||
$tablerows = $this->get_report_table_rows();
|
||||
$userrows = array_filter($tablerows, static function(array $row) use ($user): bool {
|
||||
return $row['username'] === $user->username;
|
||||
});
|
||||
$userrow = reset($userrows);
|
||||
$user = new user();
|
||||
$user->initialise();
|
||||
|
||||
$userfullname = fullname($user);
|
||||
$userprofile = (new moodle_url('/user/profile.php', ['id' => $user->id]))->out();
|
||||
$userpicture = $OUTPUT->user_picture($user, ['link' => false, 'alttext' => false]);
|
||||
$filterusername = $user->get_identity_filter('username');
|
||||
$this->assertEquals('user:username', $filterusername->get_unique_identifier());
|
||||
|
||||
$this->assertEquals($userfullname, $userrow['fullname']);
|
||||
$this->assertEquals('<a href="' . $userprofile . '">' . $userfullname . '</a>', $userrow['fullnamewithlink']);
|
||||
$this->assertEquals($userpicture . $userfullname, $userrow['fullnamewithpicture']);
|
||||
$this->assertEquals('<a href="' . $userprofile . '">' . $userpicture . $userfullname . '</a>',
|
||||
$userrow['fullnamewithpicturelink']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test picture column callback
|
||||
*/
|
||||
public function test_picture_column(): void {
|
||||
global $OUTPUT;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$user = $this->getDataGenerator()->create_user([]);
|
||||
|
||||
$tablerows = $this->get_report_table_rows();
|
||||
$userrows = array_filter($tablerows, static function(array $row) use ($user): bool {
|
||||
return $row['username'] === $user->username;
|
||||
});
|
||||
$userrow = reset($userrows);
|
||||
|
||||
$userpicture = $OUTPUT->user_picture($user, ['link' => false, 'alttext' => false]);
|
||||
$this->assertEquals($userpicture, $userrow['picture']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filtering report by user fields
|
||||
*/
|
||||
public function test_filters(): void {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->getDataGenerator()->create_user(['firstname' => 'Daffy', 'lastname' => 'Duck', 'email' => 'daffy@test.com',
|
||||
'city' => 'LA', 'lastaccess' => time() - YEARSECS, 'suspended' => 1, 'interests' => ['dancing']]);
|
||||
$this->getDataGenerator()->create_user(['firstname' => 'Donald', 'lastname' => 'Duck', 'email' => 'donald@test.com',
|
||||
'city' => 'Chicago', 'lastaccess' => time(), 'suspended' => 0]);
|
||||
|
||||
// Filter by fullname field.
|
||||
$filtervalues = [
|
||||
'user:fullname_operator' => text::IS_EQUAL_TO,
|
||||
'user:fullname_value' => 'Daffy Duck',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Daffy Duck',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by firstname field.
|
||||
$filtervalues = [
|
||||
'user:firstname_operator' => text::CONTAINS,
|
||||
'user:firstname_value' => 'Donald',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Donald Duck',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by lastname field.
|
||||
$filtervalues = [
|
||||
'user:lastname_operator' => text::CONTAINS,
|
||||
'user:lastname_value' => 'Duck',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEqualsCanonicalizing([
|
||||
'Donald Duck',
|
||||
'Daffy Duck',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by email field.
|
||||
$filtervalues = [
|
||||
'user:email_operator' => text::IS_EQUAL_TO,
|
||||
'user:email_value' => 'donald@test.com',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Donald Duck',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by city field.
|
||||
$filtervalues = [
|
||||
'user:city_operator' => text::IS_EQUAL_TO,
|
||||
'user:city_value' => 'Chicago',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Donald Duck',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by city field.
|
||||
$filtervalues = [
|
||||
'user:city_operator' => text::IS_EQUAL_TO,
|
||||
'user:city_value' => 'Chicago',
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Donald Duck',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by lastaccess field.
|
||||
$filtervalues = [
|
||||
'user:lastaccess_operator' => date::DATE_RANGE,
|
||||
'user:lastaccess_from' => time() - YEARSECS - 100,
|
||||
'user:lastaccess_to' => time() - YEARSECS + 100,
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Daffy Duck',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by suspened field.
|
||||
$filtervalues = [
|
||||
'user:suspended_operator' => boolean_select::CHECKED,
|
||||
];
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Daffy Duck',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filtering report by a user profile field
|
||||
*/
|
||||
public function test_userprofilefield_filter(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Add a user profile field to show on the report.
|
||||
$this->getDataGenerator()->create_custom_profile_field(['datatype' => 'text',
|
||||
'shortname' => 'favcolor', 'name' => 'Favorite color']);
|
||||
|
||||
$this->getDataGenerator()->create_user(['firstname' => 'Daffy', 'lastname' => 'Duck', 'profile_field_favcolor' => 'Blue']);
|
||||
$this->getDataGenerator()->create_user(['firstname' => 'Donald', 'lastname' => 'Duck',
|
||||
'profile_field_favcolor' => 'Green']);
|
||||
|
||||
$filtervalues = [
|
||||
'user:profilefield_favcolor_operator' => text::IS_EQUAL_TO,
|
||||
'user:profilefield_favcolor_value' => 'Green',
|
||||
];
|
||||
|
||||
$tablerows = $this->get_report_table_rows($filtervalues);
|
||||
$this->assertEquals([
|
||||
'Donald Duck',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for {@see test_userprofilefield_filter_empty}
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function userprofilefield_filter_empty_provider(): array {
|
||||
return [
|
||||
['checkbox', 1, boolean_select::NOT_CHECKED],
|
||||
['text', 'Hello', text::IS_EMPTY],
|
||||
['text', 'Hello', text::IS_NOT_EQUAL_TO],
|
||||
['text', 'Hello', text::DOES_NOT_CONTAIN],
|
||||
['menu', 'one', select::NOT_EQUAL_TO, "one\ntwo"],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filtering report by a user profile field with negated operators (contains the "empty" value appropriate to the field
|
||||
* type, or is not set/null)
|
||||
*
|
||||
* @param string $datatype
|
||||
* @param mixed $userfieldvalue
|
||||
* @param int $operator
|
||||
* @param string $datatypeparam1
|
||||
*
|
||||
* @dataProvider userprofilefield_filter_empty_provider
|
||||
*/
|
||||
public function test_userprofilefield_filter_empty(string $datatype, $userfieldvalue, int $operator,
|
||||
string $datatypeparam1 = ''): void {
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->getDataGenerator()->create_custom_profile_field([
|
||||
'datatype' => $datatype,
|
||||
'shortname' => 'test',
|
||||
'name' => 'My test field',
|
||||
'param1' => $datatypeparam1,
|
||||
]);
|
||||
|
||||
// At this point, the custom profile field was created after the admin account, so the value will be not set/null.
|
||||
$filtervalues = [
|
||||
'user:profilefield_test_operator' => $operator,
|
||||
'user:profilefield_test_value' => $userfieldvalue,
|
||||
];
|
||||
|
||||
// Create a user who does have the field set.
|
||||
$user = $this->getDataGenerator()->create_user(['profile_field_test' => $userfieldvalue]);
|
||||
|
||||
$rows = $this->get_report_table_rows($filtervalues);
|
||||
|
||||
$usernames = array_column($rows, 'username');
|
||||
$this->assertContains('admin', $usernames);
|
||||
$this->assertNotContains($user->username, $usernames);
|
||||
$filterprofilefield = $user->get_identity_filter('profile_field_hi');
|
||||
$this->assertEquals('user:profilefield_hi', $filterprofilefield->get_unique_identifier());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,21 +100,4 @@ class user_test extends advanced_testcase {
|
||||
// Ensure we received back all name fields.
|
||||
$this->assertEquals($expecteduserfields, array_keys((array) $user));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create the report, and return it's rows
|
||||
*
|
||||
* @param array $filtervalues
|
||||
* @return array
|
||||
*/
|
||||
private function get_report_table_rows(array $filtervalues = []): array {
|
||||
$report = manager::create_report_persistent((object) [
|
||||
'type' => user_entity_report::TYPE_SYSTEM_REPORT,
|
||||
'source' => user_entity_report::class,
|
||||
]);
|
||||
|
||||
user_filter_manager::set($report->get('id'), $filtervalues);
|
||||
|
||||
return testable_system_report_table::create($report->get('id'), [])->get_table_rows();
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\local\helpers;
|
||||
|
||||
use advanced_testcase;
|
||||
use core_customfield_generator;
|
||||
use core_reportbuilder_generator;
|
||||
use core_reportbuilder_testcase;
|
||||
use core_reportbuilder\local\entities\course;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\report\column;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
use core_course\reportbuilder\datasource\courses;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php");
|
||||
|
||||
/**
|
||||
* Unit tests for custom fields helper
|
||||
@ -31,29 +43,36 @@ use core_reportbuilder\local\report\filter;
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class custom_fields_test extends advanced_testcase {
|
||||
class custom_fields_test extends core_reportbuilder_testcase {
|
||||
|
||||
/**
|
||||
* Generate a course with customfields
|
||||
* Generate custom fields, one of each type
|
||||
*
|
||||
* @return custom_fields
|
||||
*/
|
||||
public function generate_course_with_customfields(): custom_fields {
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
private function generate_customfields(): custom_fields {
|
||||
|
||||
// Add some customfields to the course.
|
||||
$cfgenerator = self::getDataGenerator()->get_plugin_generator('core_customfield');
|
||||
$params = [
|
||||
/** @var core_customfield_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_customfield');
|
||||
$category = $generator->create_category([
|
||||
'component' => 'core_course',
|
||||
'area' => 'course',
|
||||
'itemid' => 0,
|
||||
'contextid' => \context_system::instance()->id
|
||||
];
|
||||
$category = $cfgenerator->create_category($params);
|
||||
$field1 = $cfgenerator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'text', 'name' => 'Customfield text 1', 'shortname' => 'cf1']);
|
||||
$cfgenerator->add_instance_data($field1, (int)$course->id, 'C-3PO');
|
||||
$field2 = $cfgenerator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'text', 'name' => 'Customfield text 2', 'shortname' => 'cf2']);
|
||||
$cfgenerator->add_instance_data($field2, (int)$course->id, 'R2-D2');
|
||||
]);
|
||||
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'text', 'name' => 'Text', 'shortname' => 'text']);
|
||||
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'checkbox', 'name' => 'Checkbox', 'shortname' => 'checkbox']);
|
||||
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'date', 'name' => 'Date', 'shortname' => 'date']);
|
||||
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'select', 'name' => 'Select', 'shortname' => 'select',
|
||||
'configdata' => ['options' => "Cat\nDog", 'defaultvalue' => 'Cat']]);
|
||||
|
||||
$courseentity = new course();
|
||||
$coursealias = $courseentity->get_table_alias('course');
|
||||
@ -69,14 +88,16 @@ class custom_fields_test extends advanced_testcase {
|
||||
public function test_get_columns(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$customfields = $this->generate_course_with_customfields();
|
||||
$customfields = $this->generate_customfields();
|
||||
$columns = $customfields->get_columns();
|
||||
$this->assertCount(2, $columns);
|
||||
[$column0, $column1] = $columns;
|
||||
$this->assertInstanceOf(column::class, $column0);
|
||||
$this->assertInstanceOf(column::class, $column1);
|
||||
$this->assertEqualsCanonicalizing(['Customfield text 1', 'Customfield text 2'],
|
||||
[$column0->get_title(), $column1->get_title()]);
|
||||
|
||||
$this->assertCount(4, $columns);
|
||||
$this->assertContainsOnlyInstancesOf(column::class, $columns);
|
||||
|
||||
[$column0, $column1, $column2, $column3] = $columns;
|
||||
$this->assertEqualsCanonicalizing(['Text', 'Checkbox', 'Date', 'Select'],
|
||||
[$column0->get_title(), $column1->get_title(), $column2->get_title(), $column3->get_title()]);
|
||||
|
||||
$this->assertEquals(column::TYPE_TEXT, $column0->get_type());
|
||||
$this->assertEquals('course', $column0->get_entity_name());
|
||||
$this->assertStringStartsWith('LEFT JOIN {customfield_data}', $column0->get_joins()[0]);
|
||||
@ -90,7 +111,7 @@ class custom_fields_test extends advanced_testcase {
|
||||
public function test_add_join(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$customfields = $this->generate_course_with_customfields();
|
||||
$customfields = $this->generate_customfields();
|
||||
$columns = $customfields->get_columns();
|
||||
$this->assertCount(1, ($columns[0])->get_joins());
|
||||
|
||||
@ -105,7 +126,7 @@ class custom_fields_test extends advanced_testcase {
|
||||
public function test_add_joins(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$customfields = $this->generate_course_with_customfields();
|
||||
$customfields = $this->generate_customfields();
|
||||
$columns = $customfields->get_columns();
|
||||
$this->assertCount(1, ($columns[0])->get_joins());
|
||||
|
||||
@ -120,14 +141,132 @@ class custom_fields_test extends advanced_testcase {
|
||||
public function test_get_filters(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$customfields = $this->generate_course_with_customfields();
|
||||
$customfields = $this->generate_customfields();
|
||||
$filters = $customfields->get_filters();
|
||||
$this->assertCount(2, $filters);
|
||||
[$filter0, $filter1] = $filters;
|
||||
$this->assertInstanceOf(filter::class, $filter0);
|
||||
$this->assertInstanceOf(filter::class, $filter1);
|
||||
$this->assertEqualsCanonicalizing(['Customfield text 1', 'Customfield text 2'],
|
||||
[$filter0->get_header(), $filter1->get_header()]);
|
||||
|
||||
$this->assertCount(4, $filters);
|
||||
$this->assertContainsOnlyInstancesOf(filter::class, $filters);
|
||||
|
||||
[$filter0, $filter1, $filter2, $filter3] = $filters;
|
||||
$this->assertEqualsCanonicalizing(['Text', 'Checkbox', 'Date', 'Select'],
|
||||
[$filter0->get_header(), $filter1->get_header(), $filter2->get_header(), $filter3->get_header()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that adding custom field columns to a report returns expected values
|
||||
*/
|
||||
public function test_custom_report_content(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->generate_customfields();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course(['customfields' => [
|
||||
['shortname' => 'text', 'value' => 'Hello'],
|
||||
['shortname' => 'checkbox', 'value' => true],
|
||||
['shortname' => 'date', 'value' => 1669852800],
|
||||
['shortname' => 'select', 'value' => 2],
|
||||
]]);
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
$report = $generator->create_report(['name' => 'Courses', 'source' => courses::class, 'default' => 0]);
|
||||
|
||||
// Add user profile field columns to the report.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_text']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_checkbox']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_date']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_select']);
|
||||
|
||||
$content = $this->get_custom_report_content($report->get('id'));
|
||||
|
||||
$this->assertEquals([
|
||||
$course->fullname,
|
||||
'Hello',
|
||||
'Yes',
|
||||
userdate(1669852800),
|
||||
'Dog'
|
||||
], array_values($content[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for {@see test_custom_report_filter}
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function custom_report_filter_provider(): array {
|
||||
return [
|
||||
'Filter by text custom field' => ['course:customfield_text', [
|
||||
'course:customfield_text_operator' => text::IS_EQUAL_TO,
|
||||
'course:customfield_text_value' => 'Hello',
|
||||
], true],
|
||||
'Filter by text custom field (no match)' => ['course:customfield_text', [
|
||||
'course:customfield_text_operator' => text::IS_EQUAL_TO,
|
||||
'course:customfield_text_value' => 'Goodbye',
|
||||
], false],
|
||||
'Filter by checkbox custom field' => ['course:customfield_checkbox', [
|
||||
'course:customfield_checkbox_operator' => boolean_select::CHECKED,
|
||||
], true],
|
||||
'Filter by checkbox custom field (no match)' => ['course:customfield_checkbox', [
|
||||
'course:customfield_checkbox_operator' => boolean_select::NOT_CHECKED,
|
||||
], false],
|
||||
'Filter by date custom field' => ['course:customfield_date', [
|
||||
'course:customfield_date_operator' => date::DATE_RANGE,
|
||||
'course:customfield_date_from' => 1622502000,
|
||||
], true],
|
||||
'Filter by date custom field (no match)' => ['course:customfield_date', [
|
||||
'course:customfield_date_operator' => date::DATE_RANGE,
|
||||
'course:customfield_date_to' => 1622502000,
|
||||
], false],
|
||||
'Filter by select custom field' => ['course:customfield_select', [
|
||||
'course:customfield_select_operator' => select::EQUAL_TO,
|
||||
'course:customfield_select_value' => 2,
|
||||
], true],
|
||||
'Filter by select custom field (no match)' => ['course:customfield_select', [
|
||||
'course:customfield_select_operator' => select::EQUAL_TO,
|
||||
'course:customfield_select_value' => 1,
|
||||
], false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filtering report by custom fields
|
||||
*
|
||||
* @param string $filtername
|
||||
* @param array $filtervalues
|
||||
* @param bool $expectmatch
|
||||
*
|
||||
* @dataProvider custom_report_filter_provider
|
||||
*/
|
||||
public function test_custom_report_filter(string $filtername, array $filtervalues, bool $expectmatch): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->generate_customfields();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course(['customfields' => [
|
||||
['shortname' => 'text', 'value' => 'Hello'],
|
||||
['shortname' => 'checkbox', 'value' => true],
|
||||
['shortname' => 'date', 'value' => 1669852800],
|
||||
['shortname' => 'select', 'value' => 2],
|
||||
]]);
|
||||
|
||||
/** @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' => 'Users', 'source' => courses::class, 'default' => 0]);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']);
|
||||
|
||||
// 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($course->fullname, reset($content[0]));
|
||||
} else {
|
||||
$this->assertEmpty($content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,10 @@ namespace core_reportbuilder\local\helpers;
|
||||
use core_reportbuilder_generator;
|
||||
use core_reportbuilder_testcase;
|
||||
use core_reportbuilder\local\entities\user;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\report\column;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
use core_user\reportbuilder\datasource\users;
|
||||
@ -223,4 +227,98 @@ class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
],
|
||||
], $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for {@see test_custom_report_filter}
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function custom_report_filter_provider(): array {
|
||||
return [
|
||||
'Filter by checkbox profile field' => ['user:profilefield_checkbox', [
|
||||
'user:profilefield_checkbox_operator' => boolean_select::CHECKED,
|
||||
], 'testuser'],
|
||||
'Filter by checkbox profile field (empty)' => ['user:profilefield_checkbox', [
|
||||
'user:profilefield_checkbox_operator' => boolean_select::NOT_CHECKED,
|
||||
], 'admin'],
|
||||
'Filter by datetime profile field' => ['user:profilefield_datetime', [
|
||||
'user:profilefield_datetime_operator' => date::DATE_RANGE,
|
||||
'user:profilefield_datetime_from' => 1622502000,
|
||||
], 'testuser'],
|
||||
'Filter by datetime profile field (empty)' => ['user:profilefield_datetime', [
|
||||
'user:profilefield_datetime_operator' => date::DATE_EMPTY,
|
||||
], 'admin'],
|
||||
'Filter by menu profile field' => ['user:profilefield_menu', [
|
||||
'user:profilefield_menu_operator' => select::EQUAL_TO,
|
||||
'user:profilefield_menu_value' => 'Dog',
|
||||
], 'testuser'],
|
||||
'Filter by menu profile field (empty)' => ['user:profilefield_menu', [
|
||||
'user:profilefield_menu_operator' => select::NOT_EQUAL_TO,
|
||||
'user:profilefield_menu_value' => 'Dog',
|
||||
], 'admin'],
|
||||
'Filter by social profile field' => ['user:profilefield_social', [
|
||||
'user:profilefield_social_operator' => text::IS_EQUAL_TO,
|
||||
'user:profilefield_social_value' => '12345',
|
||||
], 'testuser'],
|
||||
'Filter by social profile field (empty)' => ['user:profilefield_social', [
|
||||
'user:profilefield_social_operator' => text::IS_EMPTY,
|
||||
], 'admin'],
|
||||
'Filter by text profile field' => ['user:profilefield_text', [
|
||||
'user:profilefield_text_operator' => text::IS_EQUAL_TO,
|
||||
'user:profilefield_text_value' => 'Hello',
|
||||
], 'testuser'],
|
||||
'Filter by text profile field (empty)' => ['user:profilefield_text', [
|
||||
'user:profilefield_text_operator' => text::IS_NOT_EQUAL_TO,
|
||||
'user:profilefield_text_value' => 'Hello',
|
||||
], 'admin'],
|
||||
'Filter by textarea profile field' => ['user:profilefield_textarea', [
|
||||
'user:profilefield_textarea_operator' => text::IS_EQUAL_TO,
|
||||
'user:profilefield_textarea_value' => 'Goodbye',
|
||||
], 'testuser'],
|
||||
'Filter by textarea profile field (empty)' => ['user:profilefield_textarea', [
|
||||
'user:profilefield_textarea_operator' => text::DOES_NOT_CONTAIN,
|
||||
'user:profilefield_textarea_value' => 'Goodbye',
|
||||
], 'admin'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filtering report by custom profile fields
|
||||
*
|
||||
* @param string $filtername
|
||||
* @param array $filtervalues
|
||||
* @param string $expectmatchuser
|
||||
*
|
||||
* @dataProvider custom_report_filter_provider
|
||||
*/
|
||||
public function test_custom_report_filter(string $filtername, array $filtervalues, string $expectmatchuser): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$userprofilefields = $this->generate_userprofilefields();
|
||||
|
||||
// Create test subject with user profile fields content.
|
||||
$user = $this->getDataGenerator()->create_user([
|
||||
'username' => 'testuser',
|
||||
'profile_field_checkbox' => true,
|
||||
'profile_field_datetime' => '2021-12-09',
|
||||
'profile_field_menu' => 'Dog',
|
||||
'profile_field_Social' => '12345',
|
||||
'profile_field_text' => 'Hello',
|
||||
'profile_field_textarea' => 'Goodbye',
|
||||
]);
|
||||
|
||||
/** @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' => 'Users', 'source' => users::class, 'default' => 0]);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:username']);
|
||||
|
||||
// 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);
|
||||
|
||||
$this->assertCount(1, $content);
|
||||
$this->assertEquals($expectmatchuser, reset($content[0]));
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,12 @@ namespace core_user\reportbuilder\datasource;
|
||||
use core_collator;
|
||||
use core_reportbuilder_testcase;
|
||||
use core_reportbuilder_generator;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\tags;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\filters\user as user_filter;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
@ -68,14 +73,43 @@ class users_test extends core_reportbuilder_testcase {
|
||||
public function test_datasource_non_default_columns(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$user = $this->getDataGenerator()->create_user(['firstname' => 'Zoe', 'interests' => ['Horses']]);
|
||||
$user = $this->getDataGenerator()->create_user([
|
||||
'firstname' => 'Zoe',
|
||||
'idnumber' => 'U0001',
|
||||
'city' => 'London',
|
||||
'country' => 'GB',
|
||||
'interests' => ['Horses'],
|
||||
]);
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
$report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]);
|
||||
|
||||
// User.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullnamewithlink']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullnamewithpicture']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullnamewithpicturelink']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:picture']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:lastname']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:city']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:country']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:description']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstnamephonetic']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:lastnamephonetic']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:middlename']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:alternatename']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:idnumber']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:institution']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:department']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:phone1']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:phone2']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:address']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:lastaccess']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:suspended']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:confirmed']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:moodlenetprofile']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:timecreated']);
|
||||
|
||||
// Tags.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'tag:name']);
|
||||
@ -85,18 +119,44 @@ class users_test extends core_reportbuilder_testcase {
|
||||
$this->assertCount(2, $content);
|
||||
|
||||
// Consistent order by firstname, just in case.
|
||||
core_collator::asort_array_of_arrays_by_key($content, 'c0_firstname');
|
||||
core_collator::asort_array_of_arrays_by_key($content, 'c4_firstname');
|
||||
$content = array_values($content);
|
||||
|
||||
[$adminrow, $userrow] = array_map('array_values', $content);
|
||||
|
||||
$this->assertEquals('Admin', $adminrow[0]);
|
||||
$this->assertEmpty($adminrow[1]);
|
||||
$this->assertEmpty($adminrow[2]);
|
||||
$this->assertStringContainsString('Admin User', $adminrow[0]);
|
||||
$this->assertStringContainsString('Admin User', $adminrow[1]);
|
||||
$this->assertStringContainsString('Admin User', $adminrow[2]);
|
||||
$this->assertNotEmpty($adminrow[3]);
|
||||
$this->assertEquals('Admin', $adminrow[4]);
|
||||
$this->assertEquals('User', $adminrow[5]);
|
||||
|
||||
$this->assertEquals('Zoe', $userrow[0]);
|
||||
$this->assertEquals('Horses', $userrow[1]);
|
||||
$this->assertStringContainsString('Horses', $userrow[2]);
|
||||
$this->assertStringContainsString(fullname($user), $userrow[0]);
|
||||
$this->assertStringContainsString(fullname($user), $userrow[1]);
|
||||
$this->assertStringContainsString(fullname($user), $userrow[2]);
|
||||
$this->assertNotEmpty($userrow[3]);
|
||||
$this->assertEquals($user->firstname, $userrow[4]);
|
||||
$this->assertEquals($user->lastname, $userrow[5]);
|
||||
$this->assertEquals($user->city, $userrow[6]);
|
||||
$this->assertEquals('United Kingdom', $userrow[7]);
|
||||
$this->assertEquals($user->description, $userrow[8]);
|
||||
$this->assertEquals($user->firstnamephonetic, $userrow[9]);
|
||||
$this->assertEquals($user->lastnamephonetic, $userrow[10]);
|
||||
$this->assertEquals($user->middlename, $userrow[11]);
|
||||
$this->assertEquals($user->alternatename, $userrow[12]);
|
||||
$this->assertEquals($user->idnumber, $userrow[13]);
|
||||
$this->assertEquals($user->institution, $userrow[14]);
|
||||
$this->assertEquals($user->department, $userrow[15]);
|
||||
$this->assertEquals($user->phone1, $userrow[16]);
|
||||
$this->assertEquals($user->phone2, $userrow[17]);
|
||||
$this->assertEquals($user->address, $userrow[18]);
|
||||
$this->assertEmpty($userrow[19]);
|
||||
$this->assertEquals('No', $userrow[20]);
|
||||
$this->assertEquals('Yes', $userrow[21]);
|
||||
$this->assertEquals($user->moodlenetprofile, $userrow[22]);
|
||||
$this->assertNotEmpty($userrow[23]);
|
||||
$this->assertEquals('Horses', $userrow[24]);
|
||||
$this->assertStringContainsString('Horses', $userrow[25]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,6 +166,202 @@ class users_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
public function datasource_filters_provider(): array {
|
||||
return [
|
||||
// User.
|
||||
'Filter user' => ['user:userselect', [
|
||||
'user:userselect_operator' => user_filter::USER_SELECT,
|
||||
'user:userselect_value' => [-1],
|
||||
], false],
|
||||
'Filter fullname' => ['user:fullname', [
|
||||
'user:fullname_operator' => text::CONTAINS,
|
||||
'user:fullname_value' => 'Zoe',
|
||||
], true],
|
||||
'Filter fullname (no match)' => ['user:fullname', [
|
||||
'user:fullname_operator' => text::CONTAINS,
|
||||
'user:fullname_value' => 'Alfie',
|
||||
], false],
|
||||
'Filter firstname' => ['user:firstname', [
|
||||
'user:firstname_operator' => text::IS_EQUAL_TO,
|
||||
'user:firstname_value' => 'Zoe',
|
||||
], true],
|
||||
'Filter firstname (no match)' => ['user:firstname', [
|
||||
'user:firstname_operator' => text::IS_EQUAL_TO,
|
||||
'user:firstname_value' => 'Alfie',
|
||||
], false],
|
||||
'Filter middlename' => ['user:middlename', [
|
||||
'user:middlename_operator' => text::IS_EQUAL_TO,
|
||||
'user:middlename_value' => 'Zebediah',
|
||||
], true],
|
||||
'Filter middlename (no match)' => ['user:middlename', [
|
||||
'user:middlename_operator' => text::IS_EQUAL_TO,
|
||||
'user:middlename_value' => 'Aardvark',
|
||||
], false],
|
||||
'Filter lastname' => ['user:lastname', [
|
||||
'user:lastname_operator' => text::IS_EQUAL_TO,
|
||||
'user:lastname_value' => 'Zebra',
|
||||
], true],
|
||||
'Filter lastname (no match)' => ['user:lastname', [
|
||||
'user:lastname_operator' => text::IS_EQUAL_TO,
|
||||
'user:lastname_value' => 'Aardvark',
|
||||
], false],
|
||||
'Filter firstnamephonetic' => ['user:firstnamephonetic', [
|
||||
'user:firstnamephonetic_operator' => text::IS_EQUAL_TO,
|
||||
'user:firstnamephonetic_value' => 'Eoz',
|
||||
], true],
|
||||
'Filter firstnamephonetic (no match)' => ['user:firstnamephonetic', [
|
||||
'user:firstnamephonetic_operator' => text::IS_EQUAL_TO,
|
||||
'user:firstnamephonetic_value' => 'Alfie',
|
||||
], false],
|
||||
'Filter lastnamephonetic' => ['user:lastnamephonetic', [
|
||||
'user:lastnamephonetic_operator' => text::IS_EQUAL_TO,
|
||||
'user:lastnamephonetic_value' => 'Arbez',
|
||||
], true],
|
||||
'Filter lastnamephonetic (no match)' => ['user:lastnamephonetic', [
|
||||
'user:lastnamephonetic_operator' => text::IS_EQUAL_TO,
|
||||
'user:lastnamephonetic_value' => 'Aardvark',
|
||||
], false],
|
||||
'Filter alternatename' => ['user:alternatename', [
|
||||
'user:alternatename_operator' => text::IS_EQUAL_TO,
|
||||
'user:alternatename_value' => 'Zee',
|
||||
], true],
|
||||
'Filter alternatename (no match)' => ['user:alternatename', [
|
||||
'user:alternatename_operator' => text::IS_EQUAL_TO,
|
||||
'user:alternatename_value' => 'Aardvark',
|
||||
], false],
|
||||
'Filter email' => ['user:email', [
|
||||
'user:email_operator' => text::CONTAINS,
|
||||
'user:email_value' => 'zoe1',
|
||||
], true],
|
||||
'Filter email (no match)' => ['user:email', [
|
||||
'user:email_operator' => text::CONTAINS,
|
||||
'user:email_value' => 'alfie1',
|
||||
], false],
|
||||
'Filter phone1' => ['user:phone1', [
|
||||
'user:phone1_operator' => text::IS_EQUAL_TO,
|
||||
'user:phone1_value' => '111',
|
||||
], true],
|
||||
'Filter phone1 (no match)' => ['user:phone1', [
|
||||
'user:phone1_operator' => text::IS_EQUAL_TO,
|
||||
'user:phone1_value' => '119',
|
||||
], false],
|
||||
'Filter phone2' => ['user:phone2', [
|
||||
'user:phone2_operator' => text::IS_EQUAL_TO,
|
||||
'user:phone2_value' => '222',
|
||||
], true],
|
||||
'Filter phone2 (no match)' => ['user:phone2', [
|
||||
'user:phone2_operator' => text::IS_EQUAL_TO,
|
||||
'user:phone2_value' => '229',
|
||||
], false],
|
||||
'Filter address' => ['user:address', [
|
||||
'user:address_operator' => text::IS_EQUAL_TO,
|
||||
'user:address_value' => 'Big Farm',
|
||||
], true],
|
||||
'Filter address (no match)' => ['user:address', [
|
||||
'user:address_operator' => text::IS_EQUAL_TO,
|
||||
'user:address_value' => 'Small Farm',
|
||||
], false],
|
||||
|
||||
'Filter city' => ['user:city', [
|
||||
'user:city_operator' => text::IS_EQUAL_TO,
|
||||
'user:city_value' => 'Barcelona',
|
||||
], true],
|
||||
'Filter city (no match)' => ['user:city', [
|
||||
'user:city_operator' => text::IS_EQUAL_TO,
|
||||
'user:city_value' => 'Perth',
|
||||
], false],
|
||||
'Filter country' => ['user:country', [
|
||||
'user:country_operator' => select::EQUAL_TO,
|
||||
'user:country_value' => 'ES',
|
||||
], true],
|
||||
'Filter country (no match)' => ['user:country', [
|
||||
'user:country_operator' => select::EQUAL_TO,
|
||||
'user:country_value' => 'AU',
|
||||
], false],
|
||||
'Filter description' => ['user:description', [
|
||||
'user:description_operator' => text::CONTAINS,
|
||||
'user:description_value' => 'Hello there',
|
||||
], true],
|
||||
'Filter description (no match)' => ['user:description', [
|
||||
'user:description_operator' => text::CONTAINS,
|
||||
'user:description_value' => 'Goodbye',
|
||||
], false],
|
||||
'Filter auth' => ['user:auth', [
|
||||
'user:auth_operator' => select::EQUAL_TO,
|
||||
'user:auth_value' => 'manual',
|
||||
], true],
|
||||
'Filter auth (no match)' => ['user:auth', [
|
||||
'user:auth_operator' => select::EQUAL_TO,
|
||||
'user:auth_value' => 'ldap',
|
||||
], false],
|
||||
'Filter username' => ['user:username', [
|
||||
'user:username_operator' => text::IS_EQUAL_TO,
|
||||
'user:username_value' => 'zoe1',
|
||||
], true],
|
||||
'Filter username (no match)' => ['user:username', [
|
||||
'user:username_operator' => text::IS_EQUAL_TO,
|
||||
'user:username_value' => 'alfie1',
|
||||
], false],
|
||||
'Filter idnumber' => ['user:idnumber', [
|
||||
'user:idnumber_operator' => text::IS_EQUAL_TO,
|
||||
'user:idnumber_value' => 'Z0001',
|
||||
], true],
|
||||
'Filter idnumber (no match)' => ['user:idnumber', [
|
||||
'user:idnumber_operator' => text::IS_EQUAL_TO,
|
||||
'user:idnumber_value' => 'A0001',
|
||||
], false],
|
||||
'Filter institution' => ['user:institution', [
|
||||
'user:institution_operator' => text::IS_EQUAL_TO,
|
||||
'user:institution_value' => 'Farm',
|
||||
], true],
|
||||
'Filter institution (no match)' => ['user:institution', [
|
||||
'user:institution_operator' => text::IS_EQUAL_TO,
|
||||
'user:institution_value' => 'University',
|
||||
], false],
|
||||
'Filter department' => ['user:department', [
|
||||
'user:department_operator' => text::IS_EQUAL_TO,
|
||||
'user:department_value' => 'Stable',
|
||||
], true],
|
||||
'Filter department (no match)' => ['user:department', [
|
||||
'user:department_operator' => text::IS_EQUAL_TO,
|
||||
'user:department_value' => 'Office',
|
||||
], false],
|
||||
'Filter moodlenetprofile' => ['user:moodlenetprofile', [
|
||||
'user:moodlenetprofile_operator' => text::IS_EQUAL_TO,
|
||||
'user:moodlenetprofile_value' => '@zoe1@example.com',
|
||||
], true],
|
||||
'Filter moodlenetprofile (no match)' => ['user:moodlenetprofile', [
|
||||
'user:moodlenetprofile_operator' => text::IS_EQUAL_TO,
|
||||
'user:moodlenetprofile_value' => '@alfie1@example.com',
|
||||
], false],
|
||||
'Filter suspended' => ['user:suspended', [
|
||||
'user:suspended_operator' => boolean_select::NOT_CHECKED,
|
||||
], true],
|
||||
'Filter suspended (no match)' => ['user:suspended', [
|
||||
'user:suspended_operator' => boolean_select::CHECKED,
|
||||
], false],
|
||||
'Filter confirmed' => ['user:confirmed', [
|
||||
'user:confirmed_operator' => boolean_select::CHECKED,
|
||||
], true],
|
||||
'Filter confirmed (no match)' => ['user:confirmed', [
|
||||
'user:confirmed_operator' => boolean_select::NOT_CHECKED,
|
||||
], false],
|
||||
'Filter timecreated' => ['user:timecreated', [
|
||||
'user:timecreated_operator' => date::DATE_RANGE,
|
||||
'user:timecreated_from' => 1622502000,
|
||||
], true],
|
||||
'Filter timecreated (no match)' => ['user:timecreated', [
|
||||
'user:timecreated_operator' => date::DATE_RANGE,
|
||||
'user:timecreated_from' => 1619823600,
|
||||
'user:timecreated_to' => 1622502000,
|
||||
], false],
|
||||
'Filter lastaccess' => ['user:lastaccess', [
|
||||
'user:lastaccess_operator' => date::DATE_EMPTY,
|
||||
], true],
|
||||
'Filter lastaccess (no match)' => ['user:lastaccess', [
|
||||
'user:lastaccess_operator' => date::DATE_RANGE,
|
||||
'user:lastaccess_from' => 1619823600,
|
||||
'user:lastaccess_to' => 1622502000,
|
||||
], false],
|
||||
|
||||
// Tags.
|
||||
'Filter tag name' => ['tag:name', [
|
||||
'tag:name_operator' => tags::EQUAL_TO,
|
||||
@ -126,14 +382,30 @@ class users_test extends core_reportbuilder_testcase {
|
||||
*
|
||||
* @dataProvider datasource_filters_provider
|
||||
*/
|
||||
public function test_datasource_filters(
|
||||
string $filtername,
|
||||
array $filtervalues,
|
||||
bool $expectmatch
|
||||
): void {
|
||||
public function test_datasource_filters(string $filtername, array $filtervalues, bool $expectmatch): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$user = $this->getDataGenerator()->create_user(['interests' => ['Horses']]);
|
||||
$user = $this->getDataGenerator()->create_user([
|
||||
'username' => 'zoe1',
|
||||
'email' => 'zoe1@example.com',
|
||||
'firstname' => 'Zoe',
|
||||
'middlename' => 'Zebediah',
|
||||
'lastname' => 'Zebra',
|
||||
'firstnamephonetic' => 'Eoz',
|
||||
'lastnamephonetic' => 'Arbez',
|
||||
'alternatename' => 'Zee',
|
||||
'idnumber' => 'Z0001',
|
||||
'institution' => 'Farm',
|
||||
'department' => 'Stable',
|
||||
'phone1' => '111',
|
||||
'phone2' => '222',
|
||||
'address' => 'Big Farm',
|
||||
'city' => 'Barcelona',
|
||||
'country' => 'ES',
|
||||
'description' => 'Hello there',
|
||||
'moodlenetprofile' => '@zoe1@example.com',
|
||||
'interests' => ['Horses'],
|
||||
]);
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
@ -147,8 +419,11 @@ class users_test extends core_reportbuilder_testcase {
|
||||
$content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues);
|
||||
|
||||
if ($expectmatch) {
|
||||
$this->assertCount(1, $content);
|
||||
$this->assertEquals($user->username, reset($content[0]));
|
||||
$this->assertNotEmpty($content);
|
||||
|
||||
// Merge report usernames into easily traversable array.
|
||||
$usernames = array_merge(...array_map('array_values', $content));
|
||||
$this->assertContains($user->username, $usernames);
|
||||
} else {
|
||||
$this->assertEmpty($content);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user