mirror of
https://github.com/moodle/moodle.git
synced 2025-04-18 23:15:38 +02:00
MDL-80258 reportbuilder: ensure consistent reporting of entity themes.
Courses, categories, users & cohorts each have a configurable `theme` attribute - ensure reporting on said value is consistent across all the corresponding entities.
This commit is contained in:
parent
a36c27c709
commit
ebcc967d2e
@ -22,6 +22,7 @@ use context;
|
||||
use context_helper;
|
||||
use lang_string;
|
||||
use stdClass;
|
||||
use theme_config;
|
||||
use core_reportbuilder\local\entities\base;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
@ -245,7 +246,14 @@ class cohort extends base {
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_fields("{$tablealias}.theme")
|
||||
->set_is_sortable(true);
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function (?string $theme): string {
|
||||
if ((string) $theme === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return get_string('pluginname', "theme_{$theme}");
|
||||
});
|
||||
|
||||
return $columns;
|
||||
}
|
||||
@ -328,6 +336,22 @@ class cohort extends base {
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Theme filter.
|
||||
$filters[] = (new filter(
|
||||
select::class,
|
||||
'theme',
|
||||
new lang_string('theme'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.theme",
|
||||
))
|
||||
->set_options_callback(static function(): array {
|
||||
return array_map(
|
||||
fn(theme_config $theme) => $theme->get_theme_name(),
|
||||
get_list_of_themes(),
|
||||
);
|
||||
})
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Visible filter.
|
||||
$filters[] = (new filter(
|
||||
boolean_select::class,
|
||||
|
@ -92,6 +92,8 @@ class cohorts_test extends core_reportbuilder_testcase {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
set_config('allowcohortthemes', true);
|
||||
|
||||
/** @var core_customfield_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_customfield');
|
||||
|
||||
@ -103,6 +105,7 @@ class cohorts_test extends core_reportbuilder_testcase {
|
||||
'name' => 'Legends',
|
||||
'idnumber' => 'C101',
|
||||
'description' => 'Cohort for the legends',
|
||||
'theme' => 'boost',
|
||||
'customfield_hi' => 'Hello',
|
||||
]);
|
||||
|
||||
@ -131,7 +134,7 @@ class cohorts_test extends core_reportbuilder_testcase {
|
||||
$this->assertNotEmpty($timecreated);
|
||||
$this->assertNotEmpty($timemodified);
|
||||
$this->assertEquals('Created manually', $component);
|
||||
$this->assertEmpty($theme);
|
||||
$this->assertEquals('Boost', $theme);
|
||||
$this->assertEquals('Hello', $custom);
|
||||
$this->assertNotEmpty($timeadded);
|
||||
$this->assertEquals(fullname($user), $fullname);
|
||||
@ -184,6 +187,14 @@ class cohorts_test extends core_reportbuilder_testcase {
|
||||
'Filter description (no match)' => ['cohort:description', [
|
||||
'cohort:description_operator' => text::IS_EMPTY,
|
||||
], false],
|
||||
'Filter theme' => ['cohort:theme', [
|
||||
'cohort:theme_operator' => select::EQUAL_TO,
|
||||
'cohort:theme_value' => 'boost',
|
||||
], true],
|
||||
'Filter theme (no match)' => ['cohort:theme', [
|
||||
'cohort:theme_operator' => select::EQUAL_TO,
|
||||
'cohort:theme_value' => 'classic',
|
||||
], false],
|
||||
'Filter visible' => ['cohort:visible', [
|
||||
'cohort:visible_operator' => boolean_select::CHECKED,
|
||||
], true],
|
||||
@ -225,11 +236,14 @@ class cohorts_test extends core_reportbuilder_testcase {
|
||||
public function test_datasource_filters(string $filtername, array $filtervalues, bool $expectmatch): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
set_config('allowcohortthemes', true);
|
||||
|
||||
// Test subject.
|
||||
$cohort = $this->getDataGenerator()->create_cohort([
|
||||
'name' => 'Legends',
|
||||
'idnumber' => 'C101',
|
||||
'description' => 'Cohort for the legends',
|
||||
'theme' => 'boost',
|
||||
]);
|
||||
|
||||
$user = $this->getDataGenerator()->create_user(['username' => 'lionel']);
|
||||
|
@ -24,9 +24,10 @@ use html_writer;
|
||||
use lang_string;
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
use theme_config;
|
||||
use core_course_category;
|
||||
use core_reportbuilder\local\entities\base;
|
||||
use core_reportbuilder\local\filters\{category, text};
|
||||
use core_reportbuilder\local\filters\{category, select, text};
|
||||
use core_reportbuilder\local\report\column;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
|
||||
@ -199,6 +200,24 @@ class course_category extends base {
|
||||
return format_text($description, $category->descriptionformat, ['context' => $context->id]);
|
||||
});
|
||||
|
||||
// Theme column.
|
||||
$columns[] = (new column(
|
||||
'theme',
|
||||
new lang_string('theme'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_fields("{$tablealias}.theme")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function (?string $theme): string {
|
||||
if ((string) $theme === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return get_string('pluginname', "theme_{$theme}");
|
||||
});
|
||||
|
||||
// Course count column.
|
||||
$columns[] = (new column(
|
||||
'coursecount',
|
||||
@ -254,6 +273,22 @@ class course_category extends base {
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Theme filter.
|
||||
$filters[] = (new filter(
|
||||
select::class,
|
||||
'theme',
|
||||
new lang_string('theme'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.theme",
|
||||
))
|
||||
->set_options_callback(static function(): array {
|
||||
return array_map(
|
||||
fn(theme_config $theme) => $theme->get_theme_name(),
|
||||
get_list_of_themes(),
|
||||
);
|
||||
})
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
return $filters;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,14 @@ class categories_test extends core_reportbuilder_testcase {
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$category = $this->getDataGenerator()->create_category(['name' => 'Zoo', 'idnumber' => 'Z01', 'description' => 'Animals']);
|
||||
set_config('allowcategorythemes', true);
|
||||
|
||||
$category = $this->getDataGenerator()->create_category([
|
||||
'name' => 'Zoo',
|
||||
'idnumber' => 'Z01',
|
||||
'description' => 'Animals',
|
||||
'theme' => 'boost',
|
||||
]);
|
||||
$course = $this->getDataGenerator()->create_course(['category' => $category->id, 'fullname' => 'Zebra']);
|
||||
|
||||
// Add a cohort.
|
||||
@ -88,6 +95,7 @@ class categories_test extends core_reportbuilder_testcase {
|
||||
'sortenabled' => 1]);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:path']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:description']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:theme']);
|
||||
|
||||
// Add column from each of our entities.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']);
|
||||
@ -98,19 +106,23 @@ class categories_test extends core_reportbuilder_testcase {
|
||||
$content = $this->get_custom_report_content($report->get('id'));
|
||||
$this->assertCount(2, $content);
|
||||
|
||||
[$namewithlink, $path, $description, $coursename, $cohortname, $rolename, $userfullname] = array_values($content[0]);
|
||||
[$namewithlink, $path, $description, $theme, $coursename, $cohortname, $rolename, $userfullname] =
|
||||
array_values($content[0]);
|
||||
$this->assertStringContainsString(get_string('defaultcategoryname'), $namewithlink);
|
||||
$this->assertEquals(get_string('defaultcategoryname'), $path);
|
||||
$this->assertEmpty($description);
|
||||
$this->assertEmpty($theme);
|
||||
$this->assertEmpty($coursename);
|
||||
$this->assertEmpty($cohortname);
|
||||
$this->assertEmpty($rolename);
|
||||
$this->assertEmpty($userfullname);
|
||||
|
||||
[$namewithlink, $path, $description, $coursename, $cohortname, $rolename, $userfullname] = array_values($content[1]);
|
||||
[$namewithlink, $path, $description, $theme, $coursename, $cohortname, $rolename, $userfullname] =
|
||||
array_values($content[1]);
|
||||
$this->assertStringContainsString($category->get_formatted_name(), $namewithlink);
|
||||
$this->assertEquals($category->get_nested_name(false), $path);
|
||||
$this->assertEquals(format_text($category->description, $category->descriptionformat), $description);
|
||||
$this->assertEquals('Boost', $theme);
|
||||
$this->assertEquals($course->fullname, $coursename);
|
||||
$this->assertEquals($cohort->name, $cohortname);
|
||||
$this->assertEquals('Manager', $rolename);
|
||||
@ -151,6 +163,14 @@ class categories_test extends core_reportbuilder_testcase {
|
||||
'course_category:idnumber_operator' => text::IS_EQUAL_TO,
|
||||
'course_category:idnumber_value' => 'P01',
|
||||
], false],
|
||||
'Filter category theme' => ['course_category:theme', [
|
||||
'course_category:theme_operator' => select::EQUAL_TO,
|
||||
'course_category:theme_value' => 'boost',
|
||||
], true],
|
||||
'Filter category theme (no match)' => ['course_category:theme', [
|
||||
'course_category:theme_operator' => select::EQUAL_TO,
|
||||
'course_category:theme_value' => 'classic',
|
||||
], false],
|
||||
|
||||
// Course.
|
||||
'Filter course fullname' => ['course:fullname', [
|
||||
@ -208,8 +228,10 @@ class categories_test extends core_reportbuilder_testcase {
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
set_config('allowcategorythemes', true);
|
||||
|
||||
// Get the default category, modify it so we can filter each value.
|
||||
($category = core_course_category::get_default())->update(['name' => 'Zoo', 'idnumber' => 'Z01']);
|
||||
($category = core_course_category::get_default())->update(['name' => 'Zoo', 'idnumber' => 'Z01', 'theme' => 'boost']);
|
||||
$course = $this->getDataGenerator()->create_course(['category' => $category->id, 'fullname' => 'Zebra']);
|
||||
|
||||
// Add a cohort.
|
||||
|
@ -91,6 +91,7 @@ class courses_test extends core_reportbuilder_testcase {
|
||||
'category' => $category->id,
|
||||
'fullname' => 'Cats',
|
||||
'summary' => 'Course description',
|
||||
'theme' => 'boost',
|
||||
'tags' => ['Horses'],
|
||||
]);
|
||||
|
||||
@ -171,7 +172,7 @@ class courses_test extends core_reportbuilder_testcase {
|
||||
$this->assertEquals('No', $coursegroupmodeforce);
|
||||
$this->assertEmpty($courselang);
|
||||
$this->assertEmpty($coursecalendar);
|
||||
$this->assertEmpty($coursetheme);
|
||||
$this->assertEquals('Boost', $coursetheme);
|
||||
$this->assertEquals('No', $coursecompletion);
|
||||
$this->assertEmpty($coursedownload);
|
||||
$this->assertEquals(userdate($course->timecreated), $coursetimecreated);
|
||||
|
@ -32,6 +32,7 @@ use core_reportbuilder\local\report\filter;
|
||||
use html_writer;
|
||||
use lang_string;
|
||||
use stdClass;
|
||||
use theme_config;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
@ -140,7 +141,7 @@ class course extends base {
|
||||
'groupmodeforce' => new lang_string('groupmodeforce', 'group'),
|
||||
'lang' => new lang_string('forcelanguage'),
|
||||
'calendartype' => new lang_string('forcecalendartype', 'calendar'),
|
||||
'theme' => new lang_string('forcetheme'),
|
||||
'theme' => new lang_string('theme'),
|
||||
'enablecompletion' => new lang_string('enablecompletion', 'completion'),
|
||||
'downloadcontent' => new lang_string('downloadcoursecontent', 'course'),
|
||||
'timecreated' => new lang_string('timecreated', 'core_reportbuilder'),
|
||||
@ -411,16 +412,10 @@ class course extends base {
|
||||
* @return array
|
||||
*/
|
||||
public static function get_options_for_theme(): array {
|
||||
$options = [];
|
||||
|
||||
$themeobjects = get_list_of_themes();
|
||||
foreach ($themeobjects as $key => $theme) {
|
||||
if (empty($theme->hidefromselector)) {
|
||||
$options[$key] = get_string('pluginname', "theme_{$theme->name}");
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
return array_map(
|
||||
fn(theme_config $theme) => $theme->get_theme_name(),
|
||||
get_list_of_themes(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -454,15 +449,16 @@ class course extends base {
|
||||
return format::userdate($value, $row);
|
||||
}
|
||||
|
||||
if ($this->get_course_field_type($fieldname) === column::TYPE_BOOLEAN) {
|
||||
return format::boolean_as_text($value);
|
||||
}
|
||||
|
||||
// If the column has corresponding filter, determine the value from its options.
|
||||
$options = $this->get_options_for($fieldname);
|
||||
if ($options !== null && array_key_exists($value, $options)) {
|
||||
return $options[$value];
|
||||
}
|
||||
|
||||
if ($this->get_course_field_type($fieldname) === column::TYPE_BOOLEAN) {
|
||||
return format::boolean_as_text($value);
|
||||
}
|
||||
|
||||
if (in_array($fieldname, ['fullname', 'shortname'])) {
|
||||
if (!$row->courseid) {
|
||||
return '';
|
||||
|
@ -27,6 +27,7 @@ use html_writer;
|
||||
use lang_string;
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
use theme_config;
|
||||
use core_user\fields;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
@ -311,14 +312,8 @@ class user extends base {
|
||||
->set_is_sortable($this->is_sortable($userfield))
|
||||
->add_callback([$this, 'format'], $userfield);
|
||||
|
||||
// Some columns also have specific format callbacks.
|
||||
if ($userfield === 'country') {
|
||||
$column->add_callback(static function(string $country): string {
|
||||
$countries = get_string_manager()->get_list_of_countries(true);
|
||||
return $countries[$country] ?? '';
|
||||
});
|
||||
} else if ($userfield === 'description') {
|
||||
// Select enough fields in order to format the column.
|
||||
// Join on the context table so that we can use it for formatting these columns later.
|
||||
if ($userfield === 'description') {
|
||||
$column
|
||||
->add_join("LEFT JOIN {context} {$contexttablealias}
|
||||
ON {$contexttablealias}.contextlevel = " . CONTEXT_USER . "
|
||||
@ -368,6 +363,12 @@ class user extends base {
|
||||
return format::userdate($value, $row);
|
||||
}
|
||||
|
||||
// If the column has corresponding filter, determine the value from its options.
|
||||
$options = $this->get_options_for($fieldname);
|
||||
if ($options !== null && array_key_exists($value, $options)) {
|
||||
return $options[$value];
|
||||
}
|
||||
|
||||
if ($fieldname === 'description') {
|
||||
if (empty($row->id)) {
|
||||
return '';
|
||||
@ -428,6 +429,7 @@ class user extends base {
|
||||
'email' => new lang_string('email'),
|
||||
'city' => new lang_string('city'),
|
||||
'country' => new lang_string('country'),
|
||||
'theme' => new lang_string('theme'),
|
||||
'description' => new lang_string('description'),
|
||||
'firstnamephonetic' => new lang_string('firstnamephonetic'),
|
||||
'lastnamephonetic' => new lang_string('lastnamephonetic'),
|
||||
@ -577,12 +579,43 @@ class user extends base {
|
||||
return $filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets list of options if the filter supports it
|
||||
*
|
||||
* @param string $fieldname
|
||||
* @return null|array
|
||||
*/
|
||||
protected function get_options_for(string $fieldname): ?array {
|
||||
static $cached = [];
|
||||
if (!array_key_exists($fieldname, $cached)) {
|
||||
$callable = [static::class, 'get_options_for_' . $fieldname];
|
||||
if (is_callable($callable)) {
|
||||
$cached[$fieldname] = $callable();
|
||||
} else {
|
||||
$cached[$fieldname] = null;
|
||||
}
|
||||
}
|
||||
return $cached[$fieldname];
|
||||
}
|
||||
|
||||
/**
|
||||
* List of options for the field country.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function get_options_for_country(): array {
|
||||
return array_map('shorten_text', get_string_manager()->get_list_of_countries());
|
||||
return get_string_manager()->get_list_of_countries();
|
||||
}
|
||||
|
||||
/**
|
||||
* List of options for the field theme.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_options_for_theme(): array {
|
||||
return array_map(
|
||||
fn(theme_config $theme) => $theme->get_theme_name(),
|
||||
get_list_of_themes(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class datasource_test extends advanced_testcase {
|
||||
'All column' => [
|
||||
[],
|
||||
[],
|
||||
29,
|
||||
30,
|
||||
],
|
||||
'Include columns (picture, fullname, fullnamewithlink, fullnamewithpicture, fullnamewithpicturelink)' => [
|
||||
['picture', 'fullname*'],
|
||||
@ -65,7 +65,7 @@ class datasource_test extends advanced_testcase {
|
||||
'Exclude columns (picture, fullname, fullnamewithlink, fullnamewithpicture, fullnamewithpicturelink)' => [
|
||||
[],
|
||||
['picture', 'fullname*'],
|
||||
24,
|
||||
25,
|
||||
],
|
||||
];
|
||||
}
|
||||
@ -112,7 +112,7 @@ class datasource_test extends advanced_testcase {
|
||||
'All filters' => [
|
||||
[],
|
||||
[],
|
||||
27,
|
||||
28,
|
||||
],
|
||||
'Include filters (department, phone1, phone2)' => [
|
||||
['department', 'phone*'],
|
||||
@ -122,7 +122,7 @@ class datasource_test extends advanced_testcase {
|
||||
'Exclude filters (department, phone1, phone2)' => [
|
||||
[],
|
||||
['department', 'phone*'],
|
||||
24,
|
||||
25,
|
||||
],
|
||||
];
|
||||
}
|
||||
@ -169,7 +169,7 @@ class datasource_test extends advanced_testcase {
|
||||
'All conditions' => [
|
||||
[],
|
||||
[],
|
||||
27,
|
||||
28,
|
||||
],
|
||||
'Include conditions (department, phone1, phone2)' => [
|
||||
['department', 'phone*'],
|
||||
@ -179,7 +179,7 @@ class datasource_test extends advanced_testcase {
|
||||
'Exclude conditions (department, phone1, phone2)' => [
|
||||
[],
|
||||
['department', 'phone*'],
|
||||
24,
|
||||
25,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
@ -77,6 +77,7 @@ class users_test extends core_reportbuilder_testcase {
|
||||
'idnumber' => 'U0001',
|
||||
'city' => 'London',
|
||||
'country' => 'GB',
|
||||
'theme' => 'boost',
|
||||
'interests' => ['Horses'],
|
||||
]);
|
||||
|
||||
@ -114,6 +115,7 @@ class users_test extends core_reportbuilder_testcase {
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:moodlenetprofile']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:timecreated']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:lastip']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:theme']);
|
||||
|
||||
// Tags.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'tag:name']);
|
||||
@ -159,9 +161,10 @@ class users_test extends core_reportbuilder_testcase {
|
||||
$this->assertEquals($user->moodlenetprofile, $userrow[22]);
|
||||
$this->assertNotEmpty($userrow[23]);
|
||||
$this->assertEquals('0.0.0.0', $userrow[24]);
|
||||
$this->assertEquals('Horses', $userrow[25]);
|
||||
$this->assertStringContainsString('Horses', $userrow[26]);
|
||||
$this->assertEquals($cohort->name, $userrow[27]);
|
||||
$this->assertEquals('Boost', $userrow[25]);
|
||||
$this->assertEquals('Horses', $userrow[26]);
|
||||
$this->assertStringContainsString('Horses', $userrow[27]);
|
||||
$this->assertEquals($cohort->name, $userrow[28]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -280,6 +283,14 @@ class users_test extends core_reportbuilder_testcase {
|
||||
'user:country_operator' => select::EQUAL_TO,
|
||||
'user:country_value' => 'AU',
|
||||
], false],
|
||||
'Filter theme' => ['user:theme', [
|
||||
'user:theme_operator' => select::EQUAL_TO,
|
||||
'user:theme_value' => 'boost',
|
||||
], true],
|
||||
'Filter theme (no match)' => ['user:theme', [
|
||||
'user:theme_operator' => select::EQUAL_TO,
|
||||
'user:theme_value' => 'classic',
|
||||
], false],
|
||||
'Filter description' => ['user:description', [
|
||||
'user:description_operator' => text::CONTAINS,
|
||||
'user:description_value' => 'Hello there',
|
||||
@ -424,6 +435,7 @@ class users_test extends core_reportbuilder_testcase {
|
||||
'address' => 'Big Farm',
|
||||
'city' => 'Barcelona',
|
||||
'country' => 'ES',
|
||||
'theme' => 'boost',
|
||||
'description' => 'Hello there',
|
||||
'moodlenetprofile' => '@zoe1@example.com',
|
||||
'interests' => ['Horses'],
|
||||
|
Loading…
x
Reference in New Issue
Block a user