diff --git a/.upgradenotes/MDL-82466-2024071510553022.yml b/.upgradenotes/MDL-82466-2024071510553022.yml new file mode 100644 index 00000000000..cd219f229ed --- /dev/null +++ b/.upgradenotes/MDL-82466-2024071510553022.yml @@ -0,0 +1,7 @@ +issueNumber: MDL-82466 +notes: + core_reportbuilder: + - message: > + New format helper `format_time` method, for use in column callbacks that + represent a duration of time (e.g. "3 days 4 hours") + type: improved diff --git a/admin/classes/reportbuilder/local/entities/task_log.php b/admin/classes/reportbuilder/local/entities/task_log.php index dc541c958b1..4922822744a 100644 --- a/admin/classes/reportbuilder/local/entities/task_log.php +++ b/admin/classes/reportbuilder/local/entities/task_log.php @@ -183,15 +183,7 @@ class task_log extends base { ->set_type(column::TYPE_FLOAT) ->add_field("{$tablealias}.timeend - {$tablealias}.timestart", 'duration') ->set_is_sortable(true) - ->add_callback(static function(float $value): string { - $duration = round($value, 2); - if (empty($duration)) { - // The format_time function returns 'now' when the difference is exactly 0. - // Note: format_time performs concatenation in exactly this fashion so we should do this for consistency. - return '0 ' . get_string('secs', 'moodle'); - } - return format_time($duration); - }); + ->add_callback([format::class, 'format_time'], 2); // Hostname column. $columns[] = (new column( diff --git a/enrol/classes/reportbuilder/local/entities/enrol.php b/enrol/classes/reportbuilder/local/entities/enrol.php index e3d8236029f..f34f16c5ba3 100644 --- a/enrol/classes/reportbuilder/local/entities/enrol.php +++ b/enrol/classes/reportbuilder/local/entities/enrol.php @@ -145,12 +145,11 @@ class enrol extends base { ->set_type(column::TYPE_TIMESTAMP) ->add_fields("{$enrolalias}.enrolperiod") ->set_is_sortable(true) - ->set_callback(static function(?int $enrolperiod): string { - if (!$enrolperiod) { + ->set_callback(static function(?int $enrolperiod, stdClass $row): string { + if ($enrolperiod === 0) { return ''; } - - return format_time($enrolperiod); + return format::format_time($enrolperiod, $row); }); // Start date column. diff --git a/reportbuilder/classes/local/helpers/format.php b/reportbuilder/classes/local/helpers/format.php index 644d7e76aa1..6b0d4520762 100644 --- a/reportbuilder/classes/local/helpers/format.php +++ b/reportbuilder/classes/local/helpers/format.php @@ -41,6 +41,25 @@ class format { return $value ? userdate($value, $format) : ''; } + /** + * Returns formatted time duration (e.g. "3 days 4 hours") + * + * @param float|null $value + * @param stdClass $row + * @param int|null $precision + * @return string + */ + public static function format_time(?float $value, stdClass $row, ?int $precision = 0): string { + if ($value === null) { + return ''; + } + $value = round($value, (int) $precision); + if ($value === 0.0) { + return '0 ' . get_string('secs', 'moodle'); + } + return format_time($value); + } + /** * Returns yes/no string depending on the given value * diff --git a/reportbuilder/tests/local/helpers/format_test.php b/reportbuilder/tests/local/helpers/format_test.php index e354b2f5531..dca11f858d9 100644 --- a/reportbuilder/tests/local/helpers/format_test.php +++ b/reportbuilder/tests/local/helpers/format_test.php @@ -29,7 +29,7 @@ use stdClass; * @copyright 2021 Paul Holden * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class format_test extends advanced_testcase { +final class format_test extends advanced_testcase { /** * Test userdate method @@ -41,12 +41,39 @@ class format_test extends advanced_testcase { $this->assertEquals(userdate($now), $userdate); } + /** + * Data provider for {@see test_format_time} + * + * @return array[] + */ + public static function format_time_provider(): array { + return [ + [null, 0, ''], + [0, 0, '0 secs'], + [2.456, 1, '2.5 secs'], + [3.2, null, '3 secs'], + ]; + } + + /** + * Test format time + * + * @param float|null $value + * @param int|null $precision + * @param string $expected + * + * @dataProvider format_time_provider + */ + public function test_format_time(?float $value, ?int $precision, string $expected): void { + $this->assertEquals($expected, format::format_time($value, (object) [], $precision)); + } + /** * Data provider for {@see test_boolean_as_text} * - * @return array + * @return array[] */ - public function boolean_as_text_provider(): array { + public static function boolean_as_text_provider(): array { return [ [false, get_string('no')], [true, get_string('yes')],