diff --git a/admin/settings/reportbuilder.php b/admin/settings/reportbuilder.php index 9b76d04e2d4..20998771508 100644 --- a/admin/settings/reportbuilder.php +++ b/admin/settings/reportbuilder.php @@ -64,3 +64,15 @@ $settings->add(new admin_setting_configcheckbox( new lang_string('customreportsliveediting_desc', 'core_reportbuilder'), 1)); $ADMIN->add('reportbuilder', $settings); + +$ADMIN->add( + 'reportbuilder', new accesscallback( + 'reportbuildercustomfields', + get_string('reportbuildercustomfields', 'core_reportbuilder'), + (new moodle_url('/reportbuilder/customfield.php'))->out(), + static function(): bool { + return has_capability('moodle/reportbuilder:configurecustomfields', context_system::instance()); + }, + empty($CFG->enablecustomreports) + ) +); diff --git a/lang/en/reportbuilder.php b/lang/en/reportbuilder.php index c18cf021315..d00e6483ea6 100644 --- a/lang/en/reportbuilder.php +++ b/lang/en/reportbuilder.php @@ -240,6 +240,7 @@ $string['renameaudience'] = 'Rename audience \'{$a}\''; $string['renamecolumn'] = 'Rename column \'{$a}\''; $string['renamefilter'] = 'Rename filter \'{$a}\''; $string['reportbuilder'] = 'Report builder'; +$string['reportbuildercustomfields'] = 'Custom report fields'; $string['reportcreated'] = 'Report created'; $string['reportdeleted'] = 'Report deleted'; $string['reports'] = 'Reports'; diff --git a/lang/en/role.php b/lang/en/role.php index 5cb88358ac7..fef9a8fed88 100644 --- a/lang/en/role.php +++ b/lang/en/role.php @@ -392,6 +392,7 @@ $string['rating:rate'] = 'Add ratings to items'; $string['rating:view'] = 'View the total rating you received'; $string['rating:viewany'] = 'View total ratings that anyone received'; $string['rating:viewall'] = 'View all raw ratings given by individuals'; +$string['reportbuilder:configurecustomfields'] = 'Configure custom report fields'; $string['reportbuilder:edit'] = 'Edit your own custom reports'; $string['reportbuilder:editall'] = 'Edit all custom reports'; $string['reportbuilder:scheduleviewas'] = 'Schedule reports to be viewed as other users'; diff --git a/lib/db/access.php b/lib/db/access.php index 780796962d0..8198db76db2 100644 --- a/lib/db/access.php +++ b/lib/db/access.php @@ -2749,6 +2749,14 @@ $capabilities = array( 'archetypes' => [], ], + // Allow users to configure custom fields for custom reports. + 'moodle/reportbuilder:configurecustomfields' => [ + 'captype' => 'write', + 'riskbitmap' => RISK_PERSONAL, + 'contextlevel' => CONTEXT_SYSTEM, + 'archetypes' => [], + ], + // Allow users to schedule reports as other users. 'moodle/reportbuilder:scheduleviewas' => [ 'captype' => 'read', diff --git a/lib/phpunit/classes/util.php b/lib/phpunit/classes/util.php index 0460dfe839c..7736b036865 100644 --- a/lib/phpunit/classes/util.php +++ b/lib/phpunit/classes/util.php @@ -273,6 +273,9 @@ class phpunit_util extends testing_util { if (class_exists('\core_group\customfield\grouping_handler')) { \core_group\customfield\grouping_handler::reset_caches(); } + if (class_exists('\core_reportbuilder\customfield\report_handler')) { + \core_reportbuilder\customfield\report_handler::reset_caches(); + } // Clear static cache within restore. if (class_exists('restore_section_structure_step')) { diff --git a/reportbuilder/classes/customfield/report_handler.php b/reportbuilder/classes/customfield/report_handler.php new file mode 100644 index 00000000000..37b9933aba4 --- /dev/null +++ b/reportbuilder/classes/customfield/report_handler.php @@ -0,0 +1,139 @@ +. + +declare(strict_types=1); + +namespace core_reportbuilder\customfield; + +use core\context; +use core\context\system; +use core\exception\coding_exception; +use core\url; +use core_customfield\field_controller; +use core_reportbuilder\local\models\report; +use core_reportbuilder\manager; +use core_reportbuilder\permission; + +/** + * Report handler for custom fields + * + * @package core_reportbuilder + * @copyright 2025 David Carrillo + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class report_handler extends \core_customfield\handler { + /** + * @var report_handler|null + */ + protected static ?report_handler $singleton = null; + + /** + * Returns a singleton + * + * @param int $itemid + * @return self + */ + public static function create(int $itemid = 0): self { + if (static::$singleton === null) { + self::$singleton = new static($itemid); + } + return self::$singleton; + } + + /** + * Run reset code after unit tests to reset the singleton usage. + */ + public static function reset_caches(): void { + if (!PHPUNIT_TEST) { + throw new coding_exception('This feature is only intended for use in unit tests'); + } + + static::$singleton = null; + } + + /** + * The current user can configure custom fields on this component. + * + * @return bool true if the current can configure custom fields, false otherwise + */ + public function can_configure(): bool { + return has_capability('moodle/reportbuilder:configurecustomfields', $this->get_configuration_context()); + } + + /** + * The current user can edit custom fields on the given report. + * + * @param field_controller $field + * @param int $instanceid id of the report to test edit permission + * @return bool true if the current can edit custom fields, false otherwise + */ + public function can_edit(field_controller $field, int $instanceid = 0): bool { + if ($instanceid > 0) { + $report = report::get_record(['id' => $instanceid], MUST_EXIST); + return permission::can_edit_report($report); + } else { + return permission::can_create_report(); + } + } + + /** + * The current user can view custom fields on the given report. + * + * @param field_controller $field + * @param int $instanceid id of the report to test edit permission + * @return bool true if the current can edit custom fields, false otherwise + */ + public function can_view(field_controller $field, int $instanceid): bool { + if ($instanceid > 0) { + $report = report::get_record(['id' => $instanceid], MUST_EXIST); + return permission::can_view_report($report); + } + + return permission::can_view_reports_list(); + } + + /** + * Context that should be used for new categories created by this handler + * + * @return context the context for configuration + */ + public function get_configuration_context(): context { + return system::instance(); + } + + /** + * URL for configuration of the fields on this handler. + * + * @return url The URL to configure custom fields for this component + */ + public function get_configuration_url(): url { + return new url('/reportbuilder/customfield.php'); + } + + /** + * Returns the context for the data associated with the given instanceid. + * + * @param int $instanceid id of the record to get the context for + * @return context the context for the given record + */ + public function get_instance_context(int $instanceid = 0): context { + if ($instanceid > 0) { + return (manager::get_report_from_id($instanceid))->get_context(); + } else { + return system::instance(); + } + } +} diff --git a/reportbuilder/classes/external/custom_report_details_exporter.php b/reportbuilder/classes/external/custom_report_details_exporter.php index 256b9248d6e..320d0151d28 100644 --- a/reportbuilder/classes/external/custom_report_details_exporter.php +++ b/reportbuilder/classes/external/custom_report_details_exporter.php @@ -18,13 +18,14 @@ declare(strict_types=1); namespace core_reportbuilder\external; -use core_user; -use renderer_base; +use core_customfield\external\field_data_exporter; use core\external\persistent_exporter; +use core\output\renderer_base; use core_reportbuilder\datasource; use core_reportbuilder\manager; use core_reportbuilder\local\models\report; use core_tag\external\{tag_item_exporter, util}; +use core\user; use core_user\external\user_summary_exporter; /** @@ -63,6 +64,7 @@ class custom_report_details_exporter extends persistent_exporter { 'type' => tag_item_exporter::read_properties_definition(), 'multiple' => true, ], + 'customfields' => ['type' => field_data_exporter::read_properties_definition()], 'modifiedby' => ['type' => user_summary_exporter::read_properties_definition()], ]; } @@ -74,12 +76,18 @@ class custom_report_details_exporter extends persistent_exporter { * @return array */ protected function get_other_values(renderer_base $output): array { + $reportid = $this->persistent->get('id'); $source = $this->persistent->get('source'); - $usermodified = core_user::get_user($this->persistent->get('usermodified')); + $usermodified = user::get_user($this->persistent->get('usermodified')); return [ 'sourcename' => manager::report_source_exists($source, datasource::class) ? $source::get_name() : null, - 'tags' => util::get_item_tags('core_reportbuilder', 'reportbuilder_report', $this->persistent->get('id')), + 'tags' => util::get_item_tags('core_reportbuilder', 'reportbuilder_report', $reportid), + 'customfields' => (new field_data_exporter(null, [ + 'component' => 'core_reportbuilder', + 'area' => 'report', + 'instanceid' => $reportid, + ]))->export($output), 'modifiedby' => (new user_summary_exporter($usermodified))->export($output), ]; } diff --git a/reportbuilder/classes/form/report.php b/reportbuilder/classes/form/report.php index fa5dbc1d660..679010b1da6 100644 --- a/reportbuilder/classes/form/report.php +++ b/reportbuilder/classes/form/report.php @@ -25,6 +25,7 @@ use moodle_url; use core_form\dynamic_form; use core_reportbuilder\datasource; use core_reportbuilder\manager; +use core_reportbuilder\customfield\report_handler; use core_reportbuilder\local\helpers\report as reporthelper; use core_tag_tag; @@ -92,6 +93,8 @@ class report extends dynamic_form { public function definition() { $mform = $this->_form; + $mform->addElement('header', 'general', get_string('general', 'form')); + $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); @@ -119,6 +122,10 @@ class report extends dynamic_form { $mform->addElement('tags', 'tags', get_string('tags'), [ 'component' => 'core_reportbuilder', 'itemtype' => 'reportbuilder_report', ]); + + // Add custom fields to the form. + $reportid = empty($this->_customdata['id']) ? 0 : $this->_customdata['id']; + report_handler::create()->instance_form_definition($mform, $reportid); } /** @@ -144,7 +151,9 @@ class report extends dynamic_form { public function set_data_for_dynamic_submission(): void { if ($persistent = $this->get_custom_report()?->get_report_persistent()) { $tags = core_tag_tag::get_item_tags_array('core_reportbuilder', 'reportbuilder_report', $persistent->get('id')); - $this->set_data(array_merge((array) $persistent->to_record(), ['tags' => $tags])); + $data = (object) array_merge((array) $persistent->to_record(), ['tags' => $tags]); + report_handler::create()->instance_form_before_set_data($data); + $this->set_data($data); } } diff --git a/reportbuilder/classes/local/helpers/report.php b/reportbuilder/classes/local/helpers/report.php index 805d187cc33..7a70fd28917 100644 --- a/reportbuilder/classes/local/helpers/report.php +++ b/reportbuilder/classes/local/helpers/report.php @@ -67,6 +67,10 @@ class report { $report->get_context(), $data->tags); } + // Report custom fields. + $data->id = $report->get('id'); + \core_reportbuilder\customfield\report_handler::create()->instance_form_save($data, true); + return $report; } @@ -93,6 +97,9 @@ class report { $report->get_context(), $data->tags); } + // Report custom fields. + \core_reportbuilder\customfield\report_handler::create()->instance_form_save($data, false); + return $report; } @@ -177,6 +184,12 @@ class report { } } + // Duplicate custom fields. + $reportdata = $report->to_record(); + \core_reportbuilder\customfield\report_handler::create()->instance_form_before_set_data($reportdata); + $reportdata->id = $newreport->get('id'); + \core_reportbuilder\customfield\report_handler::create()->instance_form_save($reportdata); + return $newreport; } diff --git a/reportbuilder/classes/local/systemreports/reports_list.php b/reportbuilder/classes/local/systemreports/reports_list.php index e695dfb62b4..7348d0290f6 100644 --- a/reportbuilder/classes/local/systemreports/reports_list.php +++ b/reportbuilder/classes/local/systemreports/reports_list.php @@ -28,7 +28,7 @@ use core_reportbuilder\manager; use core_reportbuilder\system_report; use core_reportbuilder\local\entities\user; use core_reportbuilder\local\filters\{boolean_select, date, tags, text, select}; -use core_reportbuilder\local\helpers\{audience, format}; +use core_reportbuilder\local\helpers\{audience, custom_fields, format}; use core_reportbuilder\local\report\{action, column, filter}; use core_reportbuilder\output\report_name_editable; use core_reportbuilder\local\models\report; @@ -288,6 +288,17 @@ class reports_list extends system_report { $this->add_filter_from_entity('user:userselect') ->set_header(new lang_string('usermodified', 'reportbuilder')) ->set_is_available(has_capability('moodle/user:viewalldetails', $this->get_context())); + + // Custom fields filters. + $customfields = new custom_fields( + 'rb.id', + $this->get_report_entity_name(), + 'core_reportbuilder', + 'report', + ); + foreach ($customfields->get_filters() as $filter) { + $this->add_filter($filter); + } } /** diff --git a/reportbuilder/customfield.php b/reportbuilder/customfield.php new file mode 100644 index 00000000000..b26cc6c9283 --- /dev/null +++ b/reportbuilder/customfield.php @@ -0,0 +1,38 @@ +. + +/** + * Manage report custom fields + * + * @package core_reportbuilder + * @copyright 2025 David Carrillo + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../config.php'); +require_once($CFG->libdir.'/adminlib.php'); + +admin_externalpage_setup('reportbuildercustomfields'); + +/** @var \core_customfield\output\renderer $output */ +$output = $PAGE->get_renderer('core_customfield'); +$handler = core_reportbuilder\customfield\report_handler::create(); +$outputpage = new \core_customfield\output\management($handler); + +echo $output->header(), + $output->heading(new lang_string('reportbuildercustomfields', 'core_reportbuilder')), + $output->render($outputpage), + $output->footer(); diff --git a/reportbuilder/tests/behat/customfields.feature b/reportbuilder/tests/behat/customfields.feature new file mode 100644 index 00000000000..2be5a037b04 --- /dev/null +++ b/reportbuilder/tests/behat/customfields.feature @@ -0,0 +1,43 @@ +@core @core_reportbuilder @javascript +Feature: Manage custom fields for custom reports + In order to manage custom fields for custom reports + As an admin + I need to create new and edit existing report custom fields + + Scenario: Create and edit custom fields in a custom report + Given the following "core_reportbuilder > Report" exists: + | name | My report | + | source | core_user\reportbuilder\datasource\users | + | default | 1 | + When I log in as "admin" + And I navigate to "Reports > Report builder > Custom report fields" in site administration + Then I should see "Custom report fields" + And I press "Add a new category" + And I should see "Other fields" + And I click on "Add a new custom field" "link" + And I click on "Short text" "link" + And I set the following fields to these values: + | Name | Description | + | Short name | description | + And I press "Save changes" + And I navigate to "Reports > Report builder > Custom reports" in site administration + And I press "Edit report details" action in the "My report" report row + And I should see "Other fields" in the "Edit report details" "dialogue" + And I set the following fields in the "Edit report details" "dialogue" to these values: + | Description | My awesome report description | + And I click on "Save" "button" in the "Edit report details" "dialogue" + And I should see "Report updated" + And I click on "Filters" "button" + And I set the following fields in the "Description" "core_reportbuilder > Filter" to these values: + | Description operator | Contains | + | Description value | awesome | + And I click on "Apply" "button" in the "[data-region='report-filters']" "css_element" + And the following should exist in the "Reports list" table: + | Name | Report source | + | My report | Users | + And I set the following fields in the "Description" "core_reportbuilder > Filter" to these values: + | Description operator | Does not contain | + | Description value | awesome | + And I click on "Apply" "button" in the "[data-region='report-filters']" "css_element" + And I should not see "My report" + And I should see "Nothing to display" diff --git a/reportbuilder/tests/behat/customreports.feature b/reportbuilder/tests/behat/customreports.feature index b998834bb23..e24d11304f4 100644 --- a/reportbuilder/tests/behat/customreports.feature +++ b/reportbuilder/tests/behat/customreports.feature @@ -285,10 +285,17 @@ Feature: Manage custom reports | username | firstname | lastname | email | suspended | | user1 | User | 1 | user1@example.com | 1 | | user2 | User | 2 | user2@example.com | 0 | + And the following "custom field categories" exist: + | name | component | area | itemid | + | Newcat | core_reportbuilder | report | 0 | + And the following "custom fields" exist: + | name | category | type | shortname | description | configdata | + | Myshorttext | Newcat | text | f1 | d1 | | And the following "core_reportbuilder > Report" exists: - | name | My report | - | source | core_user\reportbuilder\datasource\users | - | default | 1 | + | name | My report | + | source | core_user\reportbuilder\datasource\users | + | default | 1 | + | customfield_f1 | My short text | And the following "core_reportbuilder > Audience" exists: | report | My report | | classname | core_reportbuilder\reportbuilder\audience\allusers | @@ -317,6 +324,8 @@ Feature: Manage custom reports And "All users" "core_reportbuilder > Audience" should exist And I click on the "Schedules" dynamic tab And I should see "My schedule" in the "Report schedules" "table" + And I press "Edit details" + And the field "Myshorttext" matches value "My short text" Scenario: Delete custom report Given the following "core_reportbuilder > Reports" exist: diff --git a/reportbuilder/tests/external/custom_report_details_exporter_test.php b/reportbuilder/tests/external/custom_report_details_exporter_test.php index 2585e2d4c16..03aaa03ea57 100644 --- a/reportbuilder/tests/external/custom_report_details_exporter_test.php +++ b/reportbuilder/tests/external/custom_report_details_exporter_test.php @@ -19,6 +19,7 @@ declare(strict_types=1); namespace core_reportbuilder\external; use advanced_testcase; +use core_customfield_generator; use core_reportbuilder_generator; use core_user\reportbuilder\datasource\users; @@ -39,13 +40,26 @@ final class custom_report_details_exporter_test extends advanced_testcase { global $PAGE; $this->resetAfterTest(); + $this->setAdminUser(); - $user = $this->getDataGenerator()->create_user(); - $this->setUser($user); + /** @var core_customfield_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('core_customfield'); + $category = $generator->create_category(['component' => 'core_reportbuilder', 'area' => 'report']); + $generator->create_field([ + 'categoryid' => $category->get('id'), + 'name' => 'My field', + 'shortname' => 'myfield', + 'type' => 'number', + ]); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); - $report = $generator->create_report(['name' => 'My report', 'source' => users::class, 'tags' => ['cat', 'dog']]); + $report = $generator->create_report([ + 'name' => 'My report', + 'source' => users::class, + 'tags' => ['cat', 'dog'], + 'customfield_myfield' => 42, + ]); $exporter = new custom_report_details_exporter($report); $export = $exporter->export($PAGE->get_renderer('core_reportbuilder')); @@ -62,8 +76,12 @@ final class custom_report_details_exporter_test extends advanced_testcase { $this->assertObjectHasProperty('tags', $export); $this->assertEquals(['cat', 'dog'], array_column($export->tags, 'name')); + // We use the custom field exporter for report custom fields. + $this->assertObjectHasProperty('customfields', $export); + $this->assertEquals(['42'], array_column($export->customfields->data, 'value')); + // We use the user exporter for the modifier of the report. $this->assertObjectHasProperty('modifiedby', $export); - $this->assertEquals(fullname($user), $export->modifiedby->fullname); + $this->assertEquals('Admin User', $export->modifiedby->fullname); } } diff --git a/reportbuilder/tests/external/reports/listing_test.php b/reportbuilder/tests/external/reports/listing_test.php index 36edd28882d..57119fd188d 100644 --- a/reportbuilder/tests/external/reports/listing_test.php +++ b/reportbuilder/tests/external/reports/listing_test.php @@ -19,11 +19,11 @@ declare(strict_types=1); namespace core_reportbuilder\external\reports; use context_system; +use core_customfield_generator; use core_reportbuilder_generator; use core_external\external_api; use externallib_advanced_testcase; use core_reportbuilder\exception\report_access_exception; -use core_reportbuilder\local\models\report; use core_user\reportbuilder\datasource\users; defined('MOODLE_INTERNAL') || die(); @@ -48,11 +48,26 @@ final class listing_test extends externallib_advanced_testcase { $this->resetAfterTest(); $this->setAdminUser(); + /** @var core_customfield_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('core_customfield'); + $category = $generator->create_category(['component' => 'core_reportbuilder', 'area' => 'report']); + $generator->create_field([ + 'categoryid' => $category->get('id'), + 'name' => 'My field', + 'shortname' => 'myfield', + 'type' => 'number', + ]); + /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); // Create three reports. - $reportone = $generator->create_report(['name' => 'Report one', 'source' => users::class, 'tags' => ['cat', 'dog']]); + $reportone = $generator->create_report([ + 'name' => 'Report one', + 'source' => users::class, + 'tags' => ['cat', 'dog'], + 'customfield_myfield' => 42, + ]); $reporttwo = $generator->create_report(['name' => 'Report two', 'source' => users::class]); $reportthree = $generator->create_report(['name' => 'Report three', 'source' => users::class]); @@ -76,6 +91,12 @@ final class listing_test extends externallib_advanced_testcase { [], ], array_map(fn(array $tags) => array_column($tags, 'name'), $tagscolumn)); + $customfieldscolumn = array_column($result['reports'], 'customfields'); + $this->assertEquals([ + ['42'], + [null], + ], array_map(fn(array $customfields) => array_column($customfields['data'], 'value'), $customfieldscolumn)); + $this->assertEmpty($result['warnings']); } diff --git a/reportbuilder/tests/external/reports/retrieve_test.php b/reportbuilder/tests/external/reports/retrieve_test.php index 44e89bd188f..1fdc563c88f 100644 --- a/reportbuilder/tests/external/reports/retrieve_test.php +++ b/reportbuilder/tests/external/reports/retrieve_test.php @@ -18,6 +18,7 @@ declare(strict_types=1); namespace core_reportbuilder\external\reports; +use core_customfield_generator; use core_reportbuilder_generator; use core_external\external_api; use externallib_advanced_testcase; @@ -49,11 +50,26 @@ final class retrieve_test extends externallib_advanced_testcase { $this->getDataGenerator()->create_user(['firstname' => 'Zoe', 'lastname' => 'Zebra', 'email' => 'u1@example.com']); $this->getDataGenerator()->create_user(['firstname' => 'Charlie', 'lastname' => 'Carrot', 'email' => 'u2@example.com']); + /** @var core_customfield_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('core_customfield'); + $category = $generator->create_category(['component' => 'core_reportbuilder', 'area' => 'report']); + $generator->create_field([ + 'categoryid' => $category->get('id'), + 'name' => 'My field', + 'shortname' => 'myfield', + 'type' => 'number', + ]); + /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); - $report = $generator->create_report(['name' => 'My report', 'source' => users::class, 'default' => false, - 'tags' => ['cat', 'dog']]); + $report = $generator->create_report([ + 'name' => 'My report', + 'source' => users::class, + 'default' => false, + 'tags' => ['cat', 'dog'], + 'customfield_myfield' => 42, + ]); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullname', 'sortenabled' => 1]); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:email']); @@ -87,6 +103,7 @@ final class retrieve_test extends externallib_advanced_testcase { $this->assertArrayHasKey('details', $result); $this->assertEquals('My report', $result['details']['name']); $this->assertEquals(['cat', 'dog'], array_column($result['details']['tags'], 'name')); + $this->assertEquals(['42'], array_column($result['details']['customfields']['data'], 'value')); $this->assertArrayHasKey('data', $result); $this->assertEquals(['Full name', 'Email address'], $result['data']['headers']); diff --git a/reportbuilder/tests/generator/lib.php b/reportbuilder/tests/generator/lib.php index 9ddcf8b197e..8bc7432d443 100644 --- a/reportbuilder/tests/generator/lib.php +++ b/reportbuilder/tests/generator/lib.php @@ -61,6 +61,9 @@ class core_reportbuilder_generator extends component_generator_base { // Include default setup unless specifically disabled in passed record. $default = (bool) ($record['default'] ?? true); + // Report custom fields. + \core_reportbuilder\customfield\report_handler::create()->instance_form_before_set_data((object)$record); + // If setting up default report, purge caches to ensure any default attributes are always loaded in tests. $report = helper::create_report((object) $record, $default); if ($default) { diff --git a/version.php b/version.php index 4cc1f6784fd..5613e0d9c0d 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2025030800.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2025030800.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '5.0dev+ (Build: 20250308)'; // Human-friendly version name