diff --git a/lang/en/reportbuilder.php b/lang/en/reportbuilder.php index 9d3ff9216dc..d2f21096ada 100644 --- a/lang/en/reportbuilder.php +++ b/lang/en/reportbuilder.php @@ -234,6 +234,7 @@ $string['privacy:metadata:user_filter:timemodified'] = 'The time when the user f $string['recurrence'] = 'Recurrence'; $string['recurrenceannually'] = 'Annually'; $string['recurrencedaily'] = 'Daily'; +$string['recurrencehourly'] = 'Hourly'; $string['recurrencemonthly'] = 'Monthly'; $string['recurrenceweekdays'] = 'Daily (weekdays only)'; $string['recurrenceweekly'] = 'Weekly'; diff --git a/reportbuilder/classes/local/helpers/schedule.php b/reportbuilder/classes/local/helpers/schedule.php index d5126ae8af4..141d36ac433 100644 --- a/reportbuilder/classes/local/helpers/schedule.php +++ b/reportbuilder/classes/local/helpers/schedule.php @@ -20,8 +20,8 @@ namespace core_reportbuilder\local\helpers; use context_user; use core\{clock, di}; +use core\exception\{coding_exception, invalid_parameter_exception}; use core_user; -use invalid_parameter_exception; use stdClass; use stored_file; use table_dataformat_export_format; @@ -237,6 +237,7 @@ class schedule { * @param model $schedule * @param int|null $timenow Deprecated since Moodle 4.5 - please use {@see clock} dependency injection * @return int + * @throws coding_exception */ public static function calculate_next_send_time(model $schedule, ?int $timenow = null): int { global $CFG; @@ -266,6 +267,9 @@ class schedule { ] = usergetdate($timescheduled, $CFG->timezone); switch ($recurrence) { + case model::RECURRENCE_HOURLY: + $hour += 1; + break; case model::RECURRENCE_DAILY: $day += 1; break; @@ -289,6 +293,9 @@ class schedule { case model::RECURRENCE_ANNUALLY: $year += 1; break; + default: + throw new coding_exception('Invalid recurrence value', $recurrence); + break; } // We need to recursively increment the timestamp until we get one after the current time. @@ -382,6 +389,7 @@ class schedule { public static function get_recurrence_options(): array { return [ model::RECURRENCE_NONE => get_string('none'), + model::RECURRENCE_HOURLY => get_string('recurrencehourly', 'core_reportbuilder'), model::RECURRENCE_DAILY => get_string('recurrencedaily', 'core_reportbuilder'), model::RECURRENCE_WEEKDAYS => get_string('recurrenceweekdays', 'core_reportbuilder'), model::RECURRENCE_WEEKLY => get_string('recurrenceweekly', 'core_reportbuilder'), diff --git a/reportbuilder/classes/local/models/schedule.php b/reportbuilder/classes/local/models/schedule.php index 393bddd893f..d468d5ec2f3 100644 --- a/reportbuilder/classes/local/models/schedule.php +++ b/reportbuilder/classes/local/models/schedule.php @@ -49,6 +49,9 @@ class schedule extends persistent { /** @var int No recurrence */ public const RECURRENCE_NONE = 0; + /** @var int Hourly recurrence */ + public const RECURRENCE_HOURLY = 6; + /** @var int Daily recurrence */ public const RECURRENCE_DAILY = 1; @@ -125,6 +128,7 @@ class schedule extends persistent { 'default' => self::RECURRENCE_NONE, 'choices' => [ self::RECURRENCE_NONE, + self::RECURRENCE_HOURLY, self::RECURRENCE_DAILY, self::RECURRENCE_WEEKDAYS, self::RECURRENCE_WEEKLY, diff --git a/reportbuilder/tests/local/helpers/schedule_test.php b/reportbuilder/tests/local/helpers/schedule_test.php index 805090e2363..99fa5c7286b 100644 --- a/reportbuilder/tests/local/helpers/schedule_test.php +++ b/reportbuilder/tests/local/helpers/schedule_test.php @@ -19,8 +19,8 @@ declare(strict_types=1); namespace core_reportbuilder\local\helpers; use advanced_testcase; -use invalid_parameter_exception; use core\clock; +use core\exception\{coding_exception, invalid_parameter_exception}; use core_cohort\reportbuilder\audience\cohortmember; use core_reportbuilder_generator; use core_reportbuilder\local\models\schedule as model; @@ -413,6 +413,9 @@ final class schedule_test extends advanced_testcase { 'Recurrence, time scheduled in future' => [ model::RECURRENCE_DAILY, '2021-06-05 12:00', '2021-06-05 12:00', ], + 'Hourly recurrence' => [ + model::RECURRENCE_HOURLY, '2021-06-04 20:30', '2021-06-04 23:30', + ], 'Daily recurrence' => [ model::RECURRENCE_DAILY, '2021-06-02 12:00', '2021-06-05 12:00', ], @@ -458,4 +461,27 @@ final class schedule_test extends advanced_testcase { $scheduleexpected = strtotime("{$expected} UTC"); $this->assertEquals($scheduleexpected, schedule::calculate_next_send_time($schedule)); } + + /** + * Test for calculating next schedule send time with an invalid recurrence value + */ + public function test_calculate_next_send_time_invalid_recurrence(): void { + $this->resetAfterTest(); + + /** @var core_reportbuilder_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); + $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); + + // Create model manually, as the generator automatically calculates next send itself. + $schedule = new model(0, (object) [ + 'reportid' => $report->get('id'), + 'name' => 'My schedule', + 'recurrence' => -42, + 'timescheduled' => $this->clock->time() - DAYSECS, + ]); + + $this->expectException(coding_exception::class); + $this->expectExceptionMessage('Invalid recurrence value'); + schedule::calculate_next_send_time($schedule); + } }