diff --git a/reportbuilder/classes/local/filters/date.php b/reportbuilder/classes/local/filters/date.php index adbea1033f5..930d1e67380 100644 --- a/reportbuilder/classes/local/filters/date.php +++ b/reportbuilder/classes/local/filters/date.php @@ -64,6 +64,9 @@ class date extends base { /** @var int Date in the future */ public const DATE_FUTURE = 8; + /** @var int Relative date unit for an hour */ + public const DATE_UNIT_HOUR = 0; + /** @var int Relative date unit for a day */ public const DATE_UNIT_DAY = 1; @@ -123,6 +126,7 @@ class date extends base { // Unit selector for last and next operators. $unitlabel = get_string('filterdurationunit', 'core_reportbuilder', $this->get_header()); $units = [ + self::DATE_UNIT_HOUR => get_string('filterdatehours', 'core_reportbuilder'), self::DATE_UNIT_DAY => get_string('filterdatedays', 'core_reportbuilder'), self::DATE_UNIT_WEEK => get_string('filterdateweeks', 'core_reportbuilder'), self::DATE_UNIT_MONTH => get_string('filterdatemonths', 'core_reportbuilder'), @@ -235,7 +239,7 @@ class date extends base { * * @param int $operator One of the ::DATE_LAST/CURRENT/NEXT constants * @param int $dateunitvalue Unit multiplier of the date unit - * @param int $dateunit One of the ::DATE_UNIT_DAY/WEEK/MONTH/YEAR constants + * @param int $dateunit One of the ::DATE_UNIT_* constants * @return int[] Timestamps representing the start/end of timeframe */ private static function get_relative_timeframe(int $operator, int $dateunitvalue, int $dateunit): array { @@ -243,6 +247,17 @@ class date extends base { $datestart = $dateend = new DateTimeImmutable(); switch ($dateunit) { + case self::DATE_UNIT_HOUR: + if ($operator === self::DATE_CURRENT) { + $hour = (int) $datestart->format('G'); + $datestart = $datestart->setTime($hour, 0); + $dateend = $dateend->setTime($hour, 59, 59); + } else if ($operator === self::DATE_LAST) { + $datestart = $datestart->modify("-{$dateunitvalue} hour"); + } else if ($operator === self::DATE_NEXT) { + $dateend = $dateend->modify("+{$dateunitvalue} hour"); + } + break; case self::DATE_UNIT_DAY: if ($operator === self::DATE_CURRENT) { $datestart = $datestart->setTime(0, 0); diff --git a/reportbuilder/tests/local/filters/date_test.php b/reportbuilder/tests/local/filters/date_test.php index 3fc40fbd67c..d14f4472c25 100644 --- a/reportbuilder/tests/local/filters/date_test.php +++ b/reportbuilder/tests/local/filters/date_test.php @@ -221,24 +221,29 @@ class date_test extends advanced_testcase { */ public function get_sql_filter_relative_provider(): array { return [ + 'Last hour' => [date::DATE_LAST, 1, date::DATE_UNIT_HOUR, '-30 minute'], 'Last day' => [date::DATE_LAST, 1, date::DATE_UNIT_DAY, '-6 hour'], 'Last week' => [date::DATE_LAST, 1, date::DATE_UNIT_WEEK, '-3 day'], 'Last month' => [date::DATE_LAST, 1, date::DATE_UNIT_MONTH, '-3 week'], 'Last year' => [date::DATE_LAST, 1, date::DATE_UNIT_YEAR, '-6 month'], + 'Last two hours' => [date::DATE_LAST, 2, date::DATE_UNIT_HOUR, '-90 minute'], 'Last two days' => [date::DATE_LAST, 2, date::DATE_UNIT_DAY, '-25 hour'], 'Last two weeks' => [date::DATE_LAST, 2, date::DATE_UNIT_WEEK, '-10 day'], 'Last two months' => [date::DATE_LAST, 2, date::DATE_UNIT_MONTH, '-7 week'], 'Last two years' => [date::DATE_LAST, 2, date::DATE_UNIT_YEAR, '-15 month'], // Current week is tested separately. + 'Current hour' => [date::DATE_CURRENT, null, date::DATE_UNIT_HOUR], 'Current day' => [date::DATE_CURRENT, null, date::DATE_UNIT_DAY], 'Current month' => [date::DATE_CURRENT, null, date::DATE_UNIT_MONTH], 'Current year' => [date::DATE_CURRENT, null, date::DATE_UNIT_YEAR], + 'Next hour' => [date::DATE_NEXT, 1, date::DATE_UNIT_HOUR, '+30 minute'], 'Next day' => [date::DATE_NEXT, 1, date::DATE_UNIT_DAY, '+6 hour'], 'Next week' => [date::DATE_NEXT, 1, date::DATE_UNIT_WEEK, '+3 day'], 'Next month' => [date::DATE_NEXT, 1, date::DATE_UNIT_MONTH, '+3 week'], 'Next year' => [date::DATE_NEXT, 1, date::DATE_UNIT_YEAR, '+6 month'], + 'Next two hours' => [date::DATE_NEXT, 2, date::DATE_UNIT_HOUR, '+90 minute'], 'Next two days' => [date::DATE_NEXT, 2, date::DATE_UNIT_DAY, '+25 hour'], 'Next two weeks' => [date::DATE_NEXT, 2, date::DATE_UNIT_WEEK, '+10 day'], 'Next two months' => [date::DATE_NEXT, 2, date::DATE_UNIT_MONTH, '+7 week'],