diff --git a/analytics/classes/analysis.php b/analytics/classes/analysis.php index 270a9f63a79..25d926a1698 100644 --- a/analytics/classes/analysis.php +++ b/analytics/classes/analysis.php @@ -216,6 +216,7 @@ class analysis { $result = new \stdClass(); + $timesplitting->set_modelid($this->analyser->get_modelid()); if (!$timesplitting->is_valid_analysable($analysable)) { $result->status = \core_analytics\model::ANALYSABLE_REJECTED_TIME_SPLITTING_METHOD; $result->message = get_string('invalidanalysablefortimesplitting', 'analytics', diff --git a/analytics/classes/local/time_splitting/base.php b/analytics/classes/local/time_splitting/base.php index 00884ed34e0..7150e21243b 100644 --- a/analytics/classes/local/time_splitting/base.php +++ b/analytics/classes/local/time_splitting/base.php @@ -100,6 +100,15 @@ abstract class base { $this->validate_ranges(); } + /** + * Assigns the model id to this time-splitting method it case it needs it. + * + * @param int $modelid + */ + public function set_modelid(int $modelid) { + $this->modelid = $modelid; + } + /** * get_analysable * diff --git a/analytics/classes/model.php b/analytics/classes/model.php index ced29b272a0..d83c733d80a 100644 --- a/analytics/classes/model.php +++ b/analytics/classes/model.php @@ -1014,6 +1014,7 @@ class model { // Append new elements (we can not get duplicates because sample-analysable relation is N-1). $timesplitting = $this->get_time_splitting(); + $timesplitting->set_modelid($this->get_id()); $timesplitting->set_analysable($data->analysable); $range = $timesplitting->get_range_by_index($rangeindex); @@ -1076,6 +1077,7 @@ class model { $analysable = $this->get_analyser()->get_sample_analysable($sampleid); $timesplitting = $this->get_time_splitting(); + $timesplitting->set_modelid($this->get_id()); $timesplitting->set_analysable($analysable); $range = $timesplitting->get_range_by_index($rangeindex); if ($range) { diff --git a/analytics/tests/analysis_test.php b/analytics/tests/analysis_test.php index 9d763cd6b18..ca92bb991dc 100644 --- a/analytics/tests/analysis_test.php +++ b/analytics/tests/analysis_test.php @@ -24,6 +24,8 @@ defined('MOODLE_INTERNAL') || die(); +require_once(__DIR__ . '/../../analytics/tests/fixtures/test_timesplitting_upcoming_seconds.php'); + /** * Unit tests for the analysis class. * @@ -40,20 +42,45 @@ class analytics_analysis_testcase extends advanced_testcase { public function test_fill_firstanalyses_cache() { $this->resetAfterTest(); - $this->insert_used(1, 1, 'training', 123); - $this->insert_used(1, 2, 'training', 124); - $this->insert_used(1, 1, 'prediction', 125); + $modelid = 1; - $firstanalyses = \core_analytics\analysis::fill_firstanalyses_cache(1); + $params = ['startdate' => (new DateTimeImmutable('-5 seconds'))->getTimestamp()]; + $course1 = $this->getDataGenerator()->create_course($params); + $course2 = $this->getDataGenerator()->create_course($params); + $analysable1 = new \core_analytics\course($course1); + + $afewsecsago = time() - 5; + $earliest = $afewsecsago - 1; + + $this->insert_used($modelid, $course1->id, 'training', $afewsecsago); + + // Course2 processed after course1. + $this->insert_used($modelid, $course2->id, 'training', $afewsecsago + 1); + + // After the first process involving course1. + $this->insert_used($modelid, $course1->id, 'prediction', $afewsecsago + 5); + + $firstanalyses = \core_analytics\analysis::fill_firstanalyses_cache($modelid); $this->assertCount(2, $firstanalyses); - $this->assertEquals(123, $firstanalyses['1_1']); - $this->assertEquals(124, $firstanalyses['1_2']); + $this->assertEquals($afewsecsago, $firstanalyses[$modelid . '_' . $course1->id]); + $this->assertEquals($afewsecsago + 1, $firstanalyses[$modelid . '_' . $course2->id]); // The cached elements gets refreshed. - $this->insert_used(1, 1, 'prediction', 122); - $firstanalyses = \core_analytics\analysis::fill_firstanalyses_cache(1, 1); + $this->insert_used($modelid, $course1->id, 'prediction', $earliest); + $firstanalyses = \core_analytics\analysis::fill_firstanalyses_cache($modelid, $course1->id); $this->assertCount(1, $firstanalyses); - $this->assertEquals(122, $firstanalyses['1_1']); + $this->assertEquals($earliest, $firstanalyses[$modelid . '_' . $course1->id]); + + // Upcoming periodic time-splitting methods can read and process the cached data. + $seconds = new test_timesplitting_upcoming_seconds(); + $seconds->set_modelid($modelid); + $seconds->set_analysable($analysable1); + + // The generated ranges should start from the cached firstanalysis value, which is $earliest. + $ranges = $seconds->get_all_ranges(); + $this->assertCount(7, $ranges); + $firstrange = reset($ranges); + $this->assertEquals($earliest, $firstrange['time']); } private function insert_used($modelid, $analysableid, $action, $timestamp) {