mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
Merge branch 'MDL-80669' of https://github.com/paulholden/moodle
This commit is contained in:
commit
2b724556ee
@ -18,18 +18,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\local\helpers;
|
||||
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\number;
|
||||
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 lang_string;
|
||||
use stdClass;
|
||||
use core\lang_string;
|
||||
use core_customfield\data_controller;
|
||||
use core_customfield\field_controller;
|
||||
use core_customfield\handler;
|
||||
use core_reportbuilder\local\filters\{boolean_select, date, number, select, text};
|
||||
use core_reportbuilder\local\report\{column, filter};
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Helper class for course custom fields.
|
||||
@ -116,24 +111,31 @@ class custom_fields {
|
||||
foreach ($categorieswithfields as $fieldcategory) {
|
||||
$categoryfields = $fieldcategory->get_fields();
|
||||
foreach ($categoryfields as $field) {
|
||||
$customdatatablealias = $this->get_table_alias($field);
|
||||
|
||||
$datacontroller = data_controller::create(0, null, $field);
|
||||
|
||||
$datafield = $datacontroller->datafield();
|
||||
$datafieldsql = "{$customdatatablealias}.{$datafield}";
|
||||
|
||||
// Long text fields should be cast for Oracle, for aggregation support.
|
||||
$customdatatablealias = $this->get_table_alias($field);
|
||||
$customdatasql = "{$customdatatablealias}.{$datafield}";
|
||||
|
||||
// Numeric column (non-text) should coalesce with default, as should text fields for Oracle, for aggregation.
|
||||
$columntype = $this->get_column_type($field, $datafield);
|
||||
if ($columntype === column::TYPE_LONGTEXT && $DB->get_dbfamily() === 'oracle') {
|
||||
$datafieldsql = $DB->sql_order_by_text($datafieldsql, 1024);
|
||||
if (!in_array($columntype, [column::TYPE_TEXT, column::TYPE_LONGTEXT])) {
|
||||
|
||||
// See MDL-78783 regarding no bound parameters, and Oracle limitations of GROUP BY.
|
||||
$customdatasql = "
|
||||
CASE WHEN {$this->tablefieldalias} IS NOT NULL
|
||||
THEN COALESCE({$customdatasql}, " . (float) $datacontroller->get_default_value() . ")
|
||||
ELSE NULL
|
||||
END";
|
||||
} else if ($columntype === column::TYPE_LONGTEXT && $DB->get_dbfamily() === 'oracle') {
|
||||
$customdatasql = $DB->sql_order_by_text($customdatasql, 1024);
|
||||
}
|
||||
|
||||
// Select enough fields to re-create and format each custom field instance value.
|
||||
$selectfields = "{$customdatatablealias}.id, {$customdatatablealias}.contextid";
|
||||
$customdatasqlextra = "{$customdatatablealias}.id, {$customdatatablealias}.contextid";
|
||||
if ($datafield === 'value') {
|
||||
// We will take the format into account when displaying the individual values.
|
||||
$selectfields .= ", {$customdatatablealias}.valueformat, {$customdatatablealias}.valuetrust";
|
||||
$customdatasqlextra .= ", {$customdatatablealias}.valueformat, {$customdatatablealias}.valuetrust";
|
||||
}
|
||||
|
||||
$columns[] = (new column(
|
||||
@ -143,15 +145,19 @@ class custom_fields {
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_join($this->get_table_join($field))
|
||||
->add_field($datafieldsql, $datafield)
|
||||
->add_fields($selectfields)
|
||||
->add_field($customdatasql, $datafield)
|
||||
->add_fields($customdatasqlextra)
|
||||
->add_field($this->tablefieldalias, 'tablefieldalias')
|
||||
->set_type($columntype)
|
||||
->set_is_sortable($columntype !== column::TYPE_LONGTEXT)
|
||||
->add_callback(static function($value, stdClass $row, field_controller $field): string {
|
||||
if ($row->tablefieldalias === null) {
|
||||
->add_callback(static function($value, stdClass $row, field_controller $field, ?string $aggregation): string {
|
||||
if ($row->tablefieldalias === null && $value === null) {
|
||||
return '';
|
||||
}
|
||||
// If aggregating numeric column, populate row ID to ensure the controller is created correctly.
|
||||
if (in_array((string) $aggregation, ['avg', 'max', 'min', 'sum'])) {
|
||||
$row->id ??= -1;
|
||||
}
|
||||
return (string) data_controller::create(0, $row, $field)->export_value();
|
||||
}, $field)
|
||||
// Important. If the handler implements can_view() function, it will be called with parameter $instanceid=0.
|
||||
@ -213,23 +219,42 @@ class custom_fields {
|
||||
foreach ($categorieswithfields as $fieldcategory) {
|
||||
$categoryfields = $fieldcategory->get_fields();
|
||||
foreach ($categoryfields as $field) {
|
||||
$customdatatablealias = $this->get_table_alias($field);
|
||||
|
||||
$datacontroller = data_controller::create(0, null, $field);
|
||||
|
||||
$datafield = $datacontroller->datafield();
|
||||
$datafieldsql = "{$customdatatablealias}.{$datafield}";
|
||||
|
||||
$customdatatablealias = $this->get_table_alias($field);
|
||||
$customdatasql = "{$customdatatablealias}.{$datafield}";
|
||||
$customdataparams = [];
|
||||
|
||||
if ($datafield === 'value') {
|
||||
$datafieldsql = $DB->sql_cast_to_char($datafieldsql);
|
||||
$customdatasql = $DB->sql_cast_to_char($customdatasql);
|
||||
}
|
||||
|
||||
// Account for field default value, when joined to the instance table related to the custom fields.
|
||||
if (($fielddefault = $datacontroller->get_default_value()) !== null) {
|
||||
$paramdefault = database::generate_param_name();
|
||||
|
||||
// Oracle be crazy.
|
||||
$paramdefaultsql = ":{$paramdefault}";
|
||||
if ($DB->get_dbfamily() === 'oracle' && in_array($datafield, ['intvalue', 'decvalue'])) {
|
||||
$paramdefaultsql = $DB->sql_cast_char2int($paramdefaultsql);
|
||||
}
|
||||
|
||||
$customdatasql = "
|
||||
CASE WHEN {$this->tablefieldalias} IS NOT NULL
|
||||
THEN COALESCE({$customdatasql}, {$paramdefaultsql})
|
||||
ELSE NULL
|
||||
END";
|
||||
$customdataparams[$paramdefault] = $fielddefault;
|
||||
}
|
||||
|
||||
$typeclass = $this->get_filter_class_type($datacontroller);
|
||||
$filter = (new filter(
|
||||
$typeclass,
|
||||
$this->get_filter_class_type($datacontroller),
|
||||
'customfield_' . $field->get('shortname'),
|
||||
new lang_string('customfieldcolumn', 'core_reportbuilder', $field->get_formatted_name()),
|
||||
$this->entityname,
|
||||
$datafieldsql
|
||||
$customdatasql,
|
||||
$customdataparams,
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_join($this->get_table_join($field));
|
||||
|
@ -18,15 +18,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\local\helpers;
|
||||
|
||||
use context_system;
|
||||
use core\context\system;
|
||||
use core\lang_string;
|
||||
use core_text;
|
||||
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 lang_string;
|
||||
use core_reportbuilder\local\filters\{boolean_select, date, select, text};
|
||||
use core_reportbuilder\local\report\{column, filter};
|
||||
use profile_field_base;
|
||||
use stdClass;
|
||||
|
||||
@ -111,37 +107,53 @@ class user_profile_fields {
|
||||
global $DB;
|
||||
|
||||
$columns = [];
|
||||
foreach ($this->userprofilefields as $profilefield) {
|
||||
$columntype = $this->get_user_field_type($profilefield->field->datatype);
|
||||
$columnfieldsql = $this->get_table_alias($profilefield) . '.data';
|
||||
|
||||
// Numeric (checkbox/time) fields should be cast, as should all fields for Oracle, for aggregation support.
|
||||
if ($columntype === column::TYPE_BOOLEAN || $columntype === column::TYPE_TIMESTAMP) {
|
||||
$columnfieldsql = "CASE WHEN {$columnfieldsql} IS NULL THEN NULL ELSE " .
|
||||
$DB->sql_cast_char2int($columnfieldsql, true) . " END";
|
||||
} else if ($DB->get_dbfamily() === 'oracle') {
|
||||
$columnfieldsql = $DB->sql_order_by_text($columnfieldsql, 1024);
|
||||
foreach ($this->userprofilefields as $profilefield) {
|
||||
$userinfotablealias = $this->get_table_alias($profilefield);
|
||||
$userinfosql = "{$userinfotablealias}.data";
|
||||
|
||||
if ($DB->get_dbfamily() === 'oracle') {
|
||||
$userinfosql = $DB->sql_order_by_text($userinfosql, 1024);
|
||||
}
|
||||
|
||||
// Numeric column (non-text) should cast/coalesce with default, as should all fields for Oracle, for aggregation.
|
||||
$columntype = $this->get_user_field_type($profilefield->field->datatype);
|
||||
if (!in_array($columntype, [column::TYPE_TEXT, column::TYPE_LONGTEXT])) {
|
||||
|
||||
// See MDL-78783 regarding no bound parameters, and Oracle limitations of GROUP BY.
|
||||
$userinfosql = "
|
||||
CASE WHEN {$this->usertablefieldalias} IS NOT NULL
|
||||
THEN " .
|
||||
$DB->sql_cast_char2int("COALESCE({$userinfosql}, '" . (float) $profilefield->field->defaultdata . "')")
|
||||
. "
|
||||
ELSE NULL
|
||||
END";
|
||||
}
|
||||
|
||||
$columns[] = (new column(
|
||||
'profilefield_' . core_text::strtolower($profilefield->field->shortname),
|
||||
new lang_string('customfieldcolumn', 'core_reportbuilder',
|
||||
format_string($profilefield->field->name, true,
|
||||
['escape' => false, 'context' => context_system::instance()])),
|
||||
format_string($profilefield->field->name, true, ['escape' => false, 'context' => system::instance()])),
|
||||
$this->entityname
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_join($this->get_table_join($profilefield))
|
||||
->add_field($columnfieldsql, 'data')
|
||||
->add_field($userinfosql, 'data')
|
||||
->add_field("{$userinfotablealias}.dataformat")
|
||||
->add_field($this->usertablefieldalias, 'userid')
|
||||
->set_type($columntype)
|
||||
->set_is_sortable($columntype !== column::TYPE_LONGTEXT)
|
||||
->add_callback(static function($value, stdClass $row, profile_field_base $field): string {
|
||||
if ($value === null) {
|
||||
if ($row->userid === null && $value === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$field->data = $value;
|
||||
return (string) $field->display_data();
|
||||
$field->set_user_data(
|
||||
$row->data ?? $field->field->defaultdata,
|
||||
$row->dataformat ?? $field->field->defaultdataformat,
|
||||
);
|
||||
|
||||
return $field->display_data();
|
||||
}, $profilefield);
|
||||
}
|
||||
|
||||
@ -157,48 +169,60 @@ class user_profile_fields {
|
||||
global $DB;
|
||||
|
||||
$filters = [];
|
||||
foreach ($this->userprofilefields as $profilefield) {
|
||||
$field = $this->get_table_alias($profilefield) . '.data';
|
||||
$params = [];
|
||||
|
||||
foreach ($this->userprofilefields as $profilefield) {
|
||||
$userinfotablealias = $this->get_table_alias($profilefield);
|
||||
$userinfosql = "{$userinfotablealias}.data";
|
||||
$userinfoparams = [];
|
||||
|
||||
// Perform casts where necessary, as this is a text DB field.
|
||||
switch ($profilefield->field->datatype) {
|
||||
case 'checkbox':
|
||||
$classname = boolean_select::class;
|
||||
$fieldsql = "COALESCE(" . $DB->sql_cast_char2int($field, true) . ", 0)";
|
||||
$userinfosql = $DB->sql_cast_char2int($userinfosql, true);
|
||||
break;
|
||||
case 'datetime':
|
||||
$classname = date::class;
|
||||
$fieldsql = $DB->sql_cast_char2int($field, true);
|
||||
$userinfosql = $DB->sql_cast_char2int($userinfosql, true);
|
||||
break;
|
||||
case 'menu':
|
||||
$classname = select::class;
|
||||
|
||||
$emptyparam = database::generate_param_name();
|
||||
$fieldsql = "COALESCE(" . $DB->sql_compare_text($field, 255) . ", :{$emptyparam})";
|
||||
$params[$emptyparam] = '';
|
||||
|
||||
$userinfosql = $DB->sql_cast_to_char($userinfosql);
|
||||
break;
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
default:
|
||||
$classname = text::class;
|
||||
|
||||
$emptyparam = database::generate_param_name();
|
||||
$fieldsql = "COALESCE(" . $DB->sql_compare_text($field, 255) . ", :{$emptyparam})";
|
||||
$params[$emptyparam] = '';
|
||||
|
||||
$userinfosql = $DB->sql_cast_to_char($userinfosql);
|
||||
break;
|
||||
}
|
||||
|
||||
// Account for field default value, when joined to the user table.
|
||||
if (($fielddefault = $profilefield->field->defaultdata) !== null) {
|
||||
$paramdefault = database::generate_param_name();
|
||||
|
||||
// Oracle be crazy.
|
||||
$paramdefaultsql = ":{$paramdefault}";
|
||||
if ($DB->get_dbfamily() === 'oracle' && in_array($profilefield->field->datatype, ['checkbox', 'datetime'])) {
|
||||
$paramdefaultsql = $DB->sql_cast_char2int($paramdefaultsql);
|
||||
}
|
||||
|
||||
$userinfosql = "
|
||||
CASE WHEN {$this->usertablefieldalias} IS NOT NULL
|
||||
THEN COALESCE({$userinfosql}, {$paramdefaultsql})
|
||||
ELSE NULL
|
||||
END";
|
||||
$userinfoparams[$paramdefault] = $fielddefault;
|
||||
}
|
||||
|
||||
$filter = (new filter(
|
||||
$classname,
|
||||
'profilefield_' . core_text::strtolower($profilefield->field->shortname),
|
||||
new lang_string('customfieldcolumn', 'core_reportbuilder',
|
||||
format_string($profilefield->field->name, true,
|
||||
['escape' => false, 'context' => context_system::instance()])),
|
||||
format_string($profilefield->field->name, true, ['escape' => false, 'context' => system::instance()])),
|
||||
$this->entityname,
|
||||
$fieldsql,
|
||||
$params
|
||||
$userinfosql,
|
||||
$userinfoparams,
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_join($this->get_table_join($profilefield));
|
||||
|
@ -22,12 +22,8 @@ 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_reportbuilder\local\filters\{boolean_select, date, select, text};
|
||||
use core_reportbuilder\local\report\{column, filter};
|
||||
use core_course\reportbuilder\datasource\{categories, courses};
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
@ -62,13 +58,16 @@ final class custom_fields_test extends core_reportbuilder_testcase {
|
||||
]);
|
||||
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'text', 'name' => 'Text', 'shortname' => 'text']);
|
||||
['categoryid' => $category->get('id'), 'type' => 'text', 'name' => 'Text', 'shortname' => 'text',
|
||||
'configdata' => ['defaultvalue' => 'default']]);
|
||||
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'textarea', 'name' => 'Textarea', 'shortname' => 'textarea']);
|
||||
['categoryid' => $category->get('id'), 'type' => 'textarea', 'name' => 'Textarea', 'shortname' => 'textarea',
|
||||
'configdata' => ['defaultvalue' => 'Default']]);
|
||||
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'checkbox', 'name' => 'Checkbox', 'shortname' => 'checkbox']);
|
||||
['categoryid' => $category->get('id'), 'type' => 'checkbox', 'name' => 'Checkbox', 'shortname' => 'checkbox',
|
||||
'configdata' => ['checkbydefault' => 1]]);
|
||||
|
||||
$generator->create_field(
|
||||
['categoryid' => $category->get('id'), 'type' => 'date', 'name' => 'Date', 'shortname' => 'date']);
|
||||
@ -81,8 +80,7 @@ final class custom_fields_test extends core_reportbuilder_testcase {
|
||||
$coursealias = $courseentity->get_table_alias('course');
|
||||
|
||||
// Create an instance of the customfields helper.
|
||||
return new custom_fields($coursealias . '.id', $courseentity->get_entity_name(),
|
||||
'core_course', 'course');
|
||||
return new custom_fields("{$coursealias}.id", $courseentity->get_entity_name(), 'core_course', 'course');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,51 +170,19 @@ final class custom_fields_test extends core_reportbuilder_testcase {
|
||||
public function test_custom_report_content(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->generate_customfields();
|
||||
$category = $this->getDataGenerator()->create_category(['name' => 'Zebras']);
|
||||
$courseone = $this->getDataGenerator()->create_course(['category' => $category->id, 'fullname' => 'C1']);
|
||||
|
||||
$course = $this->getDataGenerator()->create_course(['customfields' => [
|
||||
// Second course will populate each custom field.
|
||||
$this->generate_customfields();
|
||||
$coursetwo = $this->getDataGenerator()->create_course(['category' => $category->id, 'fullname' => 'C2', 'customfields' => [
|
||||
['shortname' => 'text', 'value' => 'Hello'],
|
||||
['shortname' => 'textarea_editor', 'value' => ['text' => 'Goodbye', 'format' => FORMAT_MOODLE]],
|
||||
['shortname' => 'checkbox', 'value' => true],
|
||||
['shortname' => 'checkbox', 'value' => 0],
|
||||
['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 custom 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_textarea']);
|
||||
$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',
|
||||
'<div class="text_to_html">Goodbye</div>',
|
||||
'Yes',
|
||||
userdate(1669852800),
|
||||
'Dog'
|
||||
], array_values($content[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that adding custom field columns to report returns expected default values for fields
|
||||
*/
|
||||
public function test_custom_report_content_column_defaults(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->generate_customfields();
|
||||
|
||||
$category = $this->getDataGenerator()->create_category(['name' => 'Zebras']);
|
||||
$course = $this->getDataGenerator()->create_course(['category' => $category->id]);
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
$report = $generator->create_report(['name' => 'Categories', 'source' => categories::class, 'default' => 0]);
|
||||
@ -224,13 +190,43 @@ final class custom_fields_test extends core_reportbuilder_testcase {
|
||||
// Add custom field columns to the report.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:name',
|
||||
'sortenabled' => 1]);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname',
|
||||
'sortenabled' => 1]);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_text']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_textarea']);
|
||||
$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([
|
||||
['Category 1', '', ''],
|
||||
[$category->name, $course->fullname, 'Cat'],
|
||||
[
|
||||
'Category 1',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
],
|
||||
[
|
||||
$category->name,
|
||||
$courseone->fullname,
|
||||
'default',
|
||||
format_text('Default'),
|
||||
'Yes',
|
||||
'',
|
||||
'Cat',
|
||||
],
|
||||
[
|
||||
$category->name,
|
||||
$coursetwo->fullname,
|
||||
'Hello',
|
||||
format_text('Goodbye'),
|
||||
'No',
|
||||
userdate(1669852800),
|
||||
'Dog',
|
||||
],
|
||||
], array_map('array_values', $content));
|
||||
}
|
||||
|
||||
@ -244,41 +240,53 @@ final class custom_fields_test extends core_reportbuilder_testcase {
|
||||
'Filter by text custom field' => ['course:customfield_text', [
|
||||
'course:customfield_text_operator' => text::IS_EQUAL_TO,
|
||||
'course:customfield_text_value' => 'Hello',
|
||||
], true],
|
||||
], 'C2'],
|
||||
'Filter by text custom field (default)' => ['course:customfield_text', [
|
||||
'course:customfield_text_operator' => text::IS_EQUAL_TO,
|
||||
'course:customfield_text_value' => 'default',
|
||||
], 'C1'],
|
||||
'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 textarea custom field' => ['course:customfield_textarea', [
|
||||
'course:customfield_textarea_operator' => text::IS_EQUAL_TO,
|
||||
'course:customfield_textarea_value' => 'Goodbye',
|
||||
], true],
|
||||
], 'C2'],
|
||||
'Filter by textarea custom field (default)' => ['course:customfield_textarea', [
|
||||
'course:customfield_textarea_operator' => text::IS_EQUAL_TO,
|
||||
'course:customfield_textarea_value' => 'Default',
|
||||
], 'C1'],
|
||||
'Filter by textarea custom field (no match)' => ['course:customfield_textarea', [
|
||||
'course:customfield_textarea_operator' => text::IS_EQUAL_TO,
|
||||
'course:customfield_textarea_value' => 'Hello',
|
||||
], 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],
|
||||
], 'C2'],
|
||||
'Filter by checkbox custom field (default)' => ['course:customfield_checkbox', [
|
||||
'course:customfield_checkbox_operator' => boolean_select::CHECKED,
|
||||
], 'C1'],
|
||||
'Filter by date custom field' => ['course:customfield_date', [
|
||||
'course:customfield_date_operator' => date::DATE_RANGE,
|
||||
'course:customfield_date_from' => 1622502000,
|
||||
], true],
|
||||
], 'C2'],
|
||||
'Filter by date custom field (no match)' => ['course:customfield_date', [
|
||||
'course:customfield_date_operator' => date::DATE_RANGE,
|
||||
'course:customfield_date_to' => 1622502000,
|
||||
], false],
|
||||
'course:customfield_date_from' => 1672531200,
|
||||
]],
|
||||
'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', [
|
||||
], 'C2'],
|
||||
'Filter by select custom field (default)' => ['course:customfield_select', [
|
||||
'course:customfield_select_operator' => select::EQUAL_TO,
|
||||
'course:customfield_select_value' => 1,
|
||||
], false],
|
||||
], 'C1'],
|
||||
'Filter by select custom field (no match)' => ['course:customfield_select', [
|
||||
'course:customfield_select_operator' => select::EQUAL_TO,
|
||||
'course:customfield_select_value' => 3,
|
||||
]],
|
||||
];
|
||||
}
|
||||
|
||||
@ -287,19 +295,21 @@ final class custom_fields_test extends core_reportbuilder_testcase {
|
||||
*
|
||||
* @param string $filtername
|
||||
* @param array $filtervalues
|
||||
* @param bool $expectmatch
|
||||
* @param string|null $expectmatch
|
||||
*
|
||||
* @dataProvider custom_report_filter_provider
|
||||
*/
|
||||
public function test_custom_report_filter(string $filtername, array $filtervalues, bool $expectmatch): void {
|
||||
public function test_custom_report_filter(string $filtername, array $filtervalues, ?string $expectmatch = null): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->generate_customfields();
|
||||
$this->getDataGenerator()->create_course(['fullname' => 'C1']);
|
||||
|
||||
$course = $this->getDataGenerator()->create_course(['customfields' => [
|
||||
// Second course will populate each custom field.
|
||||
$this->generate_customfields();
|
||||
$this->getDataGenerator()->create_course(['fullname' => 'C2', 'customfields' => [
|
||||
['shortname' => 'text', 'value' => 'Hello'],
|
||||
['shortname' => 'textarea_editor', 'value' => ['text' => 'Goodbye', 'format' => FORMAT_MOODLE]],
|
||||
['shortname' => 'checkbox', 'value' => true],
|
||||
['shortname' => 'checkbox', 'value' => 0],
|
||||
['shortname' => 'date', 'value' => 1669852800],
|
||||
['shortname' => 'select', 'value' => 2],
|
||||
]]);
|
||||
@ -315,9 +325,9 @@ final class custom_fields_test extends core_reportbuilder_testcase {
|
||||
$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]);
|
||||
$content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues);
|
||||
|
||||
if ($expectmatch) {
|
||||
if ($expectmatch !== null) {
|
||||
$this->assertCount(1, $content);
|
||||
$this->assertEquals($course->fullname, reset($content[0]));
|
||||
$this->assertEquals($expectmatch, reset($content[0]));
|
||||
} else {
|
||||
$this->assertEmpty($content);
|
||||
}
|
||||
@ -336,7 +346,7 @@ final class custom_fields_test extends core_reportbuilder_testcase {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->generate_customfields();
|
||||
$course = $this->getDataGenerator()->create_course(['customfields' => [
|
||||
$this->getDataGenerator()->create_course(['customfields' => [
|
||||
['shortname' => 'text', 'value' => 'Hello'],
|
||||
['shortname' => 'textarea_editor', 'value' => ['text' => 'Goodbye', 'format' => FORMAT_MOODLE]],
|
||||
['shortname' => 'checkbox', 'value' => true],
|
||||
|
@ -21,12 +21,8 @@ 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_reportbuilder\local\filters\{boolean_select, date, select, text};
|
||||
use core_reportbuilder\local\report\{column, filter};
|
||||
use core_user\reportbuilder\datasource\users;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
@ -51,28 +47,29 @@ final class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
*/
|
||||
private function generate_userprofilefields(): user_profile_fields {
|
||||
$this->getDataGenerator()->create_custom_profile_field([
|
||||
'shortname' => 'checkbox', 'name' => 'Checkbox field', 'datatype' => 'checkbox']);
|
||||
'shortname' => 'checkbox', 'name' => 'Checkbox field', 'datatype' => 'checkbox', 'defaultdata' => 1]);
|
||||
|
||||
$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,
|
||||
'defaultdata' => 0]);
|
||||
|
||||
$this->getDataGenerator()->create_custom_profile_field([
|
||||
'shortname' => 'menu', 'name' => 'Menu field', 'datatype' => 'menu', 'param1' => "Cat\nDog"]);
|
||||
'shortname' => 'menu', 'name' => 'Menu field', 'datatype' => 'menu', 'param1' => "Cat\nDog", 'defaultdata' => 'Cat']);
|
||||
|
||||
$this->getDataGenerator()->create_custom_profile_field([
|
||||
'shortname' => 'Social', 'name' => 'msn', 'datatype' => 'social', 'param1' => 'msn']);
|
||||
|
||||
$this->getDataGenerator()->create_custom_profile_field([
|
||||
'shortname' => 'text', 'name' => 'Text field', 'datatype' => 'text']);
|
||||
'shortname' => 'text', 'name' => 'Text field', 'datatype' => 'text', 'defaultdata' => 'default']);
|
||||
|
||||
$this->getDataGenerator()->create_custom_profile_field([
|
||||
'shortname' => 'textarea', 'name' => 'Textarea field', 'datatype' => 'textarea']);
|
||||
'shortname' => 'textarea', 'name' => 'Textarea field', 'datatype' => 'textarea', 'defaultdata' => 'Default']);
|
||||
|
||||
$userentity = new user();
|
||||
$useralias = $userentity->get_table_alias('user');
|
||||
|
||||
// Create an instance of the userprofilefield helper.
|
||||
return new user_profile_fields("$useralias.id", $userentity->get_entity_name());
|
||||
return new user_profile_fields("{$useralias}.id", $userentity->get_entity_name());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -207,14 +204,13 @@ final class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
public function test_custom_report_content(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$userprofilefields = $this->generate_userprofilefields();
|
||||
|
||||
// Create test subject with user profile fields content.
|
||||
$user = $this->getDataGenerator()->create_user([
|
||||
$this->generate_userprofilefields();
|
||||
$this->getDataGenerator()->create_user([
|
||||
'firstname' => 'Zebedee',
|
||||
'profile_field_checkbox' => true,
|
||||
'profile_field_checkbox' => 0,
|
||||
'profile_field_datetime' => '2021-12-09',
|
||||
'profile_field_menu' => 'Cat',
|
||||
'profile_field_menu' => 'Dog',
|
||||
'profile_field_Social' => 12345,
|
||||
'profile_field_text' => 'Hello',
|
||||
'profile_field_textarea' => 'Goodbye',
|
||||
@ -225,7 +221,7 @@ final class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
$report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]);
|
||||
|
||||
// Add user profile field columns to the report.
|
||||
$firstname = $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname', 'sortenabled' => 1]);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_checkbox']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_datetime']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_menu']);
|
||||
@ -233,29 +229,26 @@ final class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_text']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_textarea']);
|
||||
|
||||
// Sort the report, Admin -> Zebedee for consistency.
|
||||
report::toggle_report_column_sorting($report->get('id'), $firstname->get('id'), true);
|
||||
|
||||
$content = $this->get_custom_report_content($report->get('id'));
|
||||
$this->assertEquals([
|
||||
[
|
||||
'c0_firstname' => 'Admin',
|
||||
'c1_data' => '',
|
||||
'c2_data' => '',
|
||||
'c3_data' => '',
|
||||
'c4_data' => '',
|
||||
'c5_data' => '',
|
||||
'c6_data' => '',
|
||||
'Admin',
|
||||
'Yes',
|
||||
'Not set',
|
||||
'Cat',
|
||||
'',
|
||||
'default',
|
||||
format_text('Default', options: ['overflowdiv' => true]),
|
||||
], [
|
||||
'c0_firstname' => 'Zebedee',
|
||||
'c1_data' => 'Yes',
|
||||
'c2_data' => '9 December 2021',
|
||||
'c3_data' => 'Cat',
|
||||
'c4_data' => '12345',
|
||||
'c5_data' => 'Hello',
|
||||
'c6_data' => '<div class="no-overflow">Goodbye</div>',
|
||||
'Zebedee',
|
||||
'No',
|
||||
'9 December 2021',
|
||||
'Dog',
|
||||
'12345',
|
||||
'Hello',
|
||||
format_text('Goodbye', options: ['overflowdiv' => true]),
|
||||
],
|
||||
], $content);
|
||||
], array_map('array_values', $content));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -266,49 +259,63 @@ final class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
public static 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,
|
||||
], 'testuser'],
|
||||
'Filter by checkbox profile field (default)' => ['user:profilefield_checkbox', [
|
||||
'user:profilefield_checkbox_operator' => boolean_select::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 datetime profile field (no match)' => ['user:profilefield_datetime', [
|
||||
'user:profilefield_datetime_operator' => date::DATE_RANGE,
|
||||
'user:profilefield_datetime_from' => 1672531200,
|
||||
]],
|
||||
'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',
|
||||
'Filter by menu profile field (default)' => ['user:profilefield_menu', [
|
||||
'user:profilefield_menu_operator' => select::EQUAL_TO,
|
||||
'user:profilefield_menu_value' => 'Cat',
|
||||
], 'admin'],
|
||||
'Filter by menu profile field (no match)' => ['user:profilefield_menu', [
|
||||
'user:profilefield_menu_operator' => select::EQUAL_TO,
|
||||
'user:profilefield_menu_value' => 'Fish',
|
||||
]],
|
||||
'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 social profile field (no match)' => ['user:profilefield_social', [
|
||||
'user:profilefield_social_operator' => text::IS_EQUAL_TO,
|
||||
'user:profilefield_social_value' => '54321',
|
||||
]],
|
||||
'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',
|
||||
'Filter by text profile field (default)' => ['user:profilefield_text', [
|
||||
'user:profilefield_text_operator' => text::IS_EQUAL_TO,
|
||||
'user:profilefield_text_value' => 'default',
|
||||
], 'admin'],
|
||||
'Filter by text profile field (no match)' => ['user:profilefield_text', [
|
||||
'user:profilefield_text_operator' => text::IS_EQUAL_TO,
|
||||
'user:profilefield_text_value' => 'hola',
|
||||
]],
|
||||
'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',
|
||||
'Filter by textarea profile field (default)' => ['user:profilefield_textarea', [
|
||||
'user:profilefield_textarea_operator' => text::IS_EQUAL_TO,
|
||||
'user:profilefield_textarea_value' => 'Default',
|
||||
], 'admin'],
|
||||
'Filter by textarea profile field (no match)' => ['user:profilefield_textarea', [
|
||||
'user:profilefield_textarea_operator' => text::IS_EMPTY,
|
||||
'user:profilefield_textarea_value' => 'Adios',
|
||||
]],
|
||||
];
|
||||
}
|
||||
|
||||
@ -317,19 +324,18 @@ final class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
*
|
||||
* @param string $filtername
|
||||
* @param array $filtervalues
|
||||
* @param string $expectmatchuser
|
||||
* @param string|null $expectmatch
|
||||
*
|
||||
* @dataProvider custom_report_filter_provider
|
||||
*/
|
||||
public function test_custom_report_filter(string $filtername, array $filtervalues, string $expectmatchuser): void {
|
||||
public function test_custom_report_filter(string $filtername, array $filtervalues, ?string $expectmatch = null): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$userprofilefields = $this->generate_userprofilefields();
|
||||
|
||||
// Create test subject with user profile fields content.
|
||||
$user = $this->getDataGenerator()->create_user([
|
||||
$this->generate_userprofilefields();
|
||||
$this->getDataGenerator()->create_user([
|
||||
'username' => 'testuser',
|
||||
'profile_field_checkbox' => true,
|
||||
'profile_field_checkbox' => 0,
|
||||
'profile_field_datetime' => '2021-12-09',
|
||||
'profile_field_menu' => 'Dog',
|
||||
'profile_field_Social' => '12345',
|
||||
@ -348,8 +354,12 @@ final class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
$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]));
|
||||
if ($expectmatch !== null) {
|
||||
$this->assertCount(1, $content);
|
||||
$this->assertEquals($expectmatch, reset($content[0]));
|
||||
} else {
|
||||
$this->assertEmpty($content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -364,8 +374,8 @@ final class user_profile_fields_test extends core_reportbuilder_testcase {
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$userprofilefields = $this->generate_userprofilefields();
|
||||
$user = $this->getDataGenerator()->create_user([
|
||||
$this->generate_userprofilefields();
|
||||
$this->getDataGenerator()->create_user([
|
||||
'profile_field_checkbox' => true,
|
||||
'profile_field_datetime' => '2021-12-09',
|
||||
'profile_field_menu' => 'Dog',
|
||||
|
Loading…
x
Reference in New Issue
Block a user