MDL-82809 reportbuilder: load custom/profile fields consistently.
Ensure that provided columns and filters for each use appropriate checks to determine their availability (based on user permissions, etc), rather than conditionally adding them to the entity.
This commit is contained in:
@@ -74,30 +74,27 @@ class course extends base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom fields helper
|
||||
*
|
||||
* @return custom_fields
|
||||
*/
|
||||
protected function get_custom_fields(): custom_fields {
|
||||
$customfields = new custom_fields($this->get_table_alias('course') . '.id', $this->get_entity_name(),
|
||||
'core_course', 'course');
|
||||
$customfields->add_joins($this->get_joins());
|
||||
return $customfields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the entity, adding all course and custom course fields
|
||||
* Initialise the entity
|
||||
*
|
||||
* @return base
|
||||
*/
|
||||
public function initialise(): base {
|
||||
$customfields = $this->get_custom_fields();
|
||||
$tablealias = $this->get_table_alias('course');
|
||||
|
||||
$customfields = (new custom_fields(
|
||||
"{$tablealias}.id",
|
||||
$this->get_entity_name(),
|
||||
'core_course',
|
||||
'course',
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
$columns = array_merge($this->get_all_columns(), $customfields->get_columns());
|
||||
foreach ($columns as $column) {
|
||||
$this->add_column($column);
|
||||
}
|
||||
|
||||
// All the filters defined by the entity can also be used as conditions.
|
||||
$filters = array_merge($this->get_all_filters(), $customfields->get_filters());
|
||||
foreach ($filters as $filter) {
|
||||
$this
|
||||
|
||||
@@ -266,13 +266,12 @@ class custom_fields {
|
||||
$datafieldsql
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_join($this->get_table_join($field));
|
||||
->add_join($this->get_table_join($field))
|
||||
->set_is_available($this->handler->can_view($field, 0));
|
||||
|
||||
// Options are stored inside configdata json string and we need to convert it to array.
|
||||
if ($field->get('type') === 'select') {
|
||||
$filter->set_options_callback(static function() use ($field): array {
|
||||
return $field->get_options();
|
||||
});
|
||||
// If using a select filter, then populate the options.
|
||||
if ($filter->get_filter_class() === select::class) {
|
||||
$filter->set_options_callback(fn(): array => $field->get_options());
|
||||
}
|
||||
|
||||
$filters[] = $filter;
|
||||
|
||||
@@ -64,18 +64,7 @@ class user_profile_fields {
|
||||
public function __construct(string $usertablefieldalias, string $entityname) {
|
||||
$this->usertablefieldalias = $usertablefieldalias;
|
||||
$this->entityname = $entityname;
|
||||
$this->userprofilefields = $this->get_user_profile_fields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of available/visible user profile fields
|
||||
*
|
||||
* @return profile_field_base[]
|
||||
*/
|
||||
private function get_user_profile_fields(): array {
|
||||
return array_filter(profile_get_user_fields_with_data(0), static function(profile_field_base $profilefield): bool {
|
||||
return $profilefield->is_visible();
|
||||
});
|
||||
$this->userprofilefields = profile_get_user_fields_with_data(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,7 +172,8 @@ class user_profile_fields {
|
||||
|
||||
$field->data = $value;
|
||||
return (string) $field->display_data();
|
||||
}, $profilefield);
|
||||
}, $profilefield)
|
||||
->set_is_available($profilefield->is_visible());
|
||||
}
|
||||
|
||||
return $columns;
|
||||
@@ -240,11 +230,12 @@ class user_profile_fields {
|
||||
$params
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_join($this->get_table_join($profilefield));
|
||||
->add_join($this->get_table_join($profilefield))
|
||||
->set_is_available($profilefield->is_visible());
|
||||
|
||||
// If menu type then set filter options as appropriate.
|
||||
if ($profilefield->field->datatype === 'menu') {
|
||||
$filter->set_options($profilefield->options);
|
||||
// If using a select filter, then populate the options.
|
||||
if ($filter->get_filter_class() === select::class) {
|
||||
$filter->set_options_callback(fn(): array => $profilefield->options);
|
||||
}
|
||||
|
||||
$filters[] = $filter;
|
||||
|
||||
@@ -67,8 +67,10 @@ class custom_fields_test extends core_reportbuilder_testcase {
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'textarea', 'name' => 'Textarea', 'shortname' => 'textarea']);
|
||||
|
||||
// This field is available only to course teachers.
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'checkbox', 'name' => 'Checkbox', 'shortname' => 'checkbox']);
|
||||
['categoryid' => $category->get('id'), 'type' => 'checkbox', 'name' => 'Checkbox', 'shortname' => 'checkbox',
|
||||
'configdata' => ['visibility' => 1]]);
|
||||
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'date', 'name' => 'Date', 'shortname' => 'date']);
|
||||
@@ -90,10 +92,11 @@ class custom_fields_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
public function test_get_columns(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$customfields = $this->generate_customfields();
|
||||
$columns = $customfields->get_columns();
|
||||
|
||||
$columns = $customfields->get_columns();
|
||||
$this->assertCount(5, $columns);
|
||||
$this->assertContainsOnlyInstancesOf(column::class, $columns);
|
||||
|
||||
@@ -114,6 +117,19 @@ class custom_fields_test extends core_reportbuilder_testcase {
|
||||
[true, false, true, true, true],
|
||||
array_map(fn(column $column) => $column->get_is_sortable(), $columns)
|
||||
);
|
||||
|
||||
// Column available.
|
||||
$this->assertEquals(
|
||||
[true, true, true, true, true],
|
||||
array_map(fn(column $column) => $column->get_is_available(), $columns),
|
||||
);
|
||||
|
||||
// Column available, for non-privileged user.
|
||||
$this->setUser(null);
|
||||
$this->assertEquals(
|
||||
[true, true, false, true, true],
|
||||
array_map(fn(column $column) => $column->get_is_available(), $customfields->get_columns()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,18 +183,32 @@ class custom_fields_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
public function test_get_filters(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$customfields = $this->generate_customfields();
|
||||
$filters = $customfields->get_filters();
|
||||
|
||||
$filters = $customfields->get_filters();
|
||||
$this->assertCount(5, $filters);
|
||||
$this->assertContainsOnlyInstancesOf(filter::class, $filters);
|
||||
|
||||
// Filter titles.
|
||||
// Filter headers.
|
||||
$this->assertEquals(
|
||||
['Text', 'Textarea', 'Checkbox', 'Date', 'Select'],
|
||||
array_map(fn(filter $filter) => $filter->get_header(), $filters)
|
||||
);
|
||||
|
||||
// Filter available.
|
||||
$this->assertEquals(
|
||||
[true, true, true, true, true],
|
||||
array_map(fn(filter $filter) => $filter->get_is_available(), $filters),
|
||||
);
|
||||
|
||||
// Filter available, for non-privileged user.
|
||||
$this->setUser(null);
|
||||
$this->assertEquals(
|
||||
[true, true, false, true, true],
|
||||
array_map(fn(filter $filter) => $filter->get_is_available(), $customfields->get_filters()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,6 +216,7 @@ class custom_fields_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
public function test_custom_report_content(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$this->generate_customfields();
|
||||
|
||||
@@ -308,6 +339,7 @@ class custom_fields_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
public function test_custom_report_filter(string $filtername, array $filtervalues, bool $expectmatch): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$this->generate_customfields();
|
||||
|
||||
|
||||
@@ -53,8 +53,10 @@ class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
$this->getDataGenerator()->create_custom_profile_field([
|
||||
'shortname' => 'checkbox', 'name' => 'Checkbox field', 'datatype' => 'checkbox']);
|
||||
|
||||
// This field is available only to admins.
|
||||
$this->getDataGenerator()->create_custom_profile_field([
|
||||
'shortname' => 'datetime', 'name' => 'Date field', 'datatype' => 'datetime', 'param2' => 2022, 'param3' => 0]);
|
||||
'shortname' => 'datetime', 'name' => 'Date field', 'datatype' => 'datetime', 'param2' => 2022, 'param3' => 0,
|
||||
'visible' => PROFILE_VISIBLE_NONE]);
|
||||
|
||||
$this->getDataGenerator()->create_custom_profile_field([
|
||||
'shortname' => 'menu', 'name' => 'Menu field', 'datatype' => 'menu', 'param1' => "Cat\nDog"]);
|
||||
@@ -80,55 +82,88 @@ class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
public function test_get_columns(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$userentity = new user();
|
||||
$useralias = $userentity->get_table_alias('user');
|
||||
$this->setAdminUser();
|
||||
|
||||
// Get pre-existing user profile fields.
|
||||
$initialuserprofilefields = new user_profile_fields("$useralias.id", $userentity->get_entity_name());
|
||||
$initialcolumns = $initialuserprofilefields->get_columns();
|
||||
$initialcolumntitles = array_map(static function(column $column): string {
|
||||
return $column->get_title();
|
||||
}, $initialcolumns);
|
||||
$initialcolumntypes = array_map(static function(column $column): int {
|
||||
return $column->get_type();
|
||||
}, $initialcolumns);
|
||||
$userentity = new user();
|
||||
$initialcolumns = (new user_profile_fields(
|
||||
$userentity->get_table_alias('user') . '.id',
|
||||
$userentity->get_entity_name(),
|
||||
))->get_columns();
|
||||
|
||||
// Add new custom profile fields.
|
||||
$userprofilefields = $this->generate_userprofilefields();
|
||||
$columns = $userprofilefields->get_columns();
|
||||
|
||||
// Columns count should be equal to start + 6.
|
||||
$this->assertCount(count($initialcolumns) + 6, $columns);
|
||||
// Ensure pre-existing fields are ignored in subsequent assertions.
|
||||
$columns = array_slice($userprofilefields->get_columns(), count($initialcolumns));
|
||||
$this->assertCount(6, $columns);
|
||||
$this->assertContainsOnlyInstancesOf(column::class, $columns);
|
||||
|
||||
// Assert column titles.
|
||||
$columntitles = array_map(static function(column $column): string {
|
||||
return $column->get_title();
|
||||
}, $columns);
|
||||
$expectedcolumntitles = array_merge($initialcolumntitles, [
|
||||
// Column titles.
|
||||
$this->assertEquals([
|
||||
'Checkbox field',
|
||||
'Date field',
|
||||
'Menu field',
|
||||
'MSN ID',
|
||||
'Text field',
|
||||
'Textarea field',
|
||||
]);
|
||||
$this->assertEquals($expectedcolumntitles, $columntitles);
|
||||
], array_map(
|
||||
fn(column $column): string => $column->get_title(),
|
||||
$columns,
|
||||
));
|
||||
|
||||
// Assert column types.
|
||||
$columntypes = array_map(static function(column $column): int {
|
||||
return $column->get_type();
|
||||
}, $columns);
|
||||
$expectedcolumntypes = array_merge($initialcolumntypes, [
|
||||
// Column types.
|
||||
$this->assertEquals([
|
||||
column::TYPE_BOOLEAN,
|
||||
column::TYPE_TIMESTAMP,
|
||||
column::TYPE_TEXT,
|
||||
column::TYPE_TEXT,
|
||||
column::TYPE_TEXT,
|
||||
column::TYPE_LONGTEXT,
|
||||
]);
|
||||
$this->assertEquals($expectedcolumntypes, $columntypes);
|
||||
], array_map(
|
||||
fn(column $column): int => $column->get_type(),
|
||||
$columns,
|
||||
));
|
||||
|
||||
// Column sortable.
|
||||
$this->assertEquals([
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
], array_map(
|
||||
fn(column $column): bool => $column->get_is_sortable(),
|
||||
$columns,
|
||||
));
|
||||
|
||||
// Column available.
|
||||
$this->assertEquals([
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
], array_map(
|
||||
fn(column $column): bool => $column->get_is_available(),
|
||||
$columns,
|
||||
));
|
||||
|
||||
// Column available, for non-privileged user.
|
||||
$this->setUser(null);
|
||||
$this->assertEquals([
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
], array_map(
|
||||
fn(column $column): bool => $column->get_is_available(),
|
||||
array_slice($userprofilefields->get_columns(), count($initialcolumns)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,38 +201,62 @@ class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
public function test_get_filters(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$userentity = new user();
|
||||
$useralias = $userentity->get_table_alias('user');
|
||||
$this->setAdminUser();
|
||||
|
||||
// Get pre-existing user profile fields.
|
||||
$initialuserprofilefields = new user_profile_fields("$useralias.id", $userentity->get_entity_name());
|
||||
$initialfilters = $initialuserprofilefields->get_filters();
|
||||
$initialfilterheaders = array_map(static function(filter $filter): string {
|
||||
return $filter->get_header();
|
||||
}, $initialfilters);
|
||||
$userentity = new user();
|
||||
$initialfilters = (new user_profile_fields(
|
||||
$userentity->get_table_alias('user') . '.id',
|
||||
$userentity->get_entity_name(),
|
||||
))->get_filters();
|
||||
|
||||
// Add new custom profile fields.
|
||||
$userprofilefields = $this->generate_userprofilefields();
|
||||
$filters = $userprofilefields->get_filters();
|
||||
|
||||
// Filters count should be equal to start + 6.
|
||||
$this->assertCount(count($initialfilters) + 6, $filters);
|
||||
// Ensure pre-existing fields are ignored in subsequent assertions.
|
||||
$filters = array_slice($userprofilefields->get_filters(), count($initialfilters));
|
||||
$this->assertCount(6, $filters);
|
||||
$this->assertContainsOnlyInstancesOf(filter::class, $filters);
|
||||
|
||||
// Assert filter headers.
|
||||
$filterheaders = array_map(static function(filter $filter): string {
|
||||
return $filter->get_header();
|
||||
}, $filters);
|
||||
$expectedfilterheaders = array_merge($initialfilterheaders, [
|
||||
// Filter headers.
|
||||
$this->assertEquals([
|
||||
'Checkbox field',
|
||||
'Date field',
|
||||
'Menu field',
|
||||
'MSN ID',
|
||||
'Text field',
|
||||
'Textarea field',
|
||||
]);
|
||||
$this->assertEquals($expectedfilterheaders, $filterheaders);
|
||||
], array_map(
|
||||
fn(filter $filter): string => $filter->get_header(),
|
||||
$filters,
|
||||
));
|
||||
|
||||
// Filter available.
|
||||
$this->assertEquals([
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
], array_map(
|
||||
fn(filter $filter): bool => $filter->get_is_available(),
|
||||
$filters,
|
||||
));
|
||||
|
||||
// Filter available, for non-privileged user.
|
||||
$this->setUser(null);
|
||||
$this->assertEquals([
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
], array_map(
|
||||
fn(filter $filter): bool => $filter->get_is_available(),
|
||||
array_slice($userprofilefields->get_filters(), count($initialfilters)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,6 +264,7 @@ class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
public function test_custom_report_content(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$userprofilefields = $this->generate_userprofilefields();
|
||||
|
||||
@@ -322,6 +382,7 @@ class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
public function test_custom_report_filter(string $filtername, array $filtervalues, string $expectmatchuser): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$userprofilefields = $this->generate_userprofilefields();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user