MDL-61667 analytics: Create missing models on install/upgrade
Similarly to how the scheduled tasks work, we now automatically check and make sure that all the models specified in the component's db/analytics.php file exist during the installation or upgrade of the component.
This commit is contained in:
@@ -607,6 +607,27 @@ class manager {
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that all the models declared by the component are up to date.
|
||||
*
|
||||
* This is intended to be called during the installation / upgrade to automatically create missing models.
|
||||
*
|
||||
* @param string $componentname The name of the component to load models for.
|
||||
* @return array \core_analytics\model[] List of actually created models.
|
||||
*/
|
||||
public static function update_default_models_for_component(string $componentname): array {
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach (static::load_default_models_for_component($componentname) as $definition) {
|
||||
if (!\core_analytics\model::exists(static::get_target($definition['target']))) {
|
||||
$result[] = static::create_declared_model($definition);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of models declared by the given component.
|
||||
*
|
||||
|
||||
@@ -337,4 +337,38 @@ class analytics_manager_testcase extends advanced_testcase {
|
||||
$existing->update(0, false, false);
|
||||
$this->assertEquals(0, $DB->get_field('analytics_models', 'enabled', ['target' => $target->get_id()], MUST_EXIST));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the implementation of the {@link \core_analytics\manager::update_default_models_for_component()}.
|
||||
*/
|
||||
public function test_update_default_models_for_component() {
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminuser();
|
||||
|
||||
$noteaching = \core_analytics\manager::get_target('\core\analytics\target\no_teaching');
|
||||
$dropout = \core_analytics\manager::get_target('\core\analytics\target\course_dropout');
|
||||
|
||||
$this->assertTrue(\core_analytics\model::exists($noteaching));
|
||||
$this->assertTrue(\core_analytics\model::exists($dropout));
|
||||
|
||||
foreach (\core_analytics\manager::get_all_models() as $model) {
|
||||
$model->delete();
|
||||
}
|
||||
|
||||
$this->assertFalse(\core_analytics\model::exists($noteaching));
|
||||
$this->assertFalse(\core_analytics\model::exists($dropout));
|
||||
|
||||
$updated = \core_analytics\manager::update_default_models_for_component('moodle');
|
||||
|
||||
$this->assertEquals(2, count($updated));
|
||||
$this->assertTrue(array_pop($updated) instanceof \core_analytics\model);
|
||||
$this->assertTrue(array_pop($updated) instanceof \core_analytics\model);
|
||||
$this->assertTrue(\core_analytics\model::exists($noteaching));
|
||||
$this->assertTrue(\core_analytics\model::exists($dropout));
|
||||
|
||||
$repeated = \core_analytics\manager::update_default_models_for_component('moodle');
|
||||
|
||||
$this->assertSame([], $repeated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ information provided here is intended especially for developers.
|
||||
* \core_analytics\regressor::evaluate_regression and \core_analytics\classifier::evaluate_classification
|
||||
have been updated to include a new $trainedmodeldir param. This new param will be used to evaluate the
|
||||
existing trained model.
|
||||
* Plugins and core subsystems can now declare default prediction models by describing them in
|
||||
their db/analytics.php file. Models should not be created manually via the db/install.php
|
||||
file any more.
|
||||
* The method \core_analytics\manager::add_builtin_models() has been deprecated. The functionality
|
||||
has been replaced with automatic update of models provided by the core moodle component. There
|
||||
is no need to call this method explicitly any more. Instead, adding new models can be achieved
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Defines the built-in prediction models provided by the Moodle core.
|
||||
*
|
||||
* @package core
|
||||
* @category analytics
|
||||
* @copyright 2019 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$models = [
|
||||
[
|
||||
'target' => '\core\analytics\target\course_dropout',
|
||||
'indicators' => [
|
||||
'\core\analytics\indicator\any_access_after_end',
|
||||
'\core\analytics\indicator\any_access_before_start',
|
||||
'\core\analytics\indicator\any_write_action_in_course',
|
||||
'\core\analytics\indicator\read_actions',
|
||||
'\core_course\analytics\indicator\completion_enabled',
|
||||
'\core_course\analytics\indicator\potential_cognitive_depth',
|
||||
'\core_course\analytics\indicator\potential_social_breadth',
|
||||
'\mod_assign\analytics\indicator\cognitive_depth',
|
||||
'\mod_assign\analytics\indicator\social_breadth',
|
||||
'\mod_book\analytics\indicator\cognitive_depth',
|
||||
'\mod_book\analytics\indicator\social_breadth',
|
||||
'\mod_chat\analytics\indicator\cognitive_depth',
|
||||
'\mod_chat\analytics\indicator\social_breadth',
|
||||
'\mod_choice\analytics\indicator\cognitive_depth',
|
||||
'\mod_choice\analytics\indicator\social_breadth',
|
||||
'\mod_data\analytics\indicator\cognitive_depth',
|
||||
'\mod_data\analytics\indicator\social_breadth',
|
||||
'\mod_feedback\analytics\indicator\cognitive_depth',
|
||||
'\mod_feedback\analytics\indicator\social_breadth',
|
||||
'\mod_folder\analytics\indicator\cognitive_depth',
|
||||
'\mod_folder\analytics\indicator\social_breadth',
|
||||
'\mod_forum\analytics\indicator\cognitive_depth',
|
||||
'\mod_forum\analytics\indicator\social_breadth',
|
||||
'\mod_glossary\analytics\indicator\cognitive_depth',
|
||||
'\mod_glossary\analytics\indicator\social_breadth',
|
||||
'\mod_imscp\analytics\indicator\cognitive_depth',
|
||||
'\mod_imscp\analytics\indicator\social_breadth',
|
||||
'\mod_label\analytics\indicator\cognitive_depth',
|
||||
'\mod_label\analytics\indicator\social_breadth',
|
||||
'\mod_lesson\analytics\indicator\cognitive_depth',
|
||||
'\mod_lesson\analytics\indicator\social_breadth',
|
||||
'\mod_lti\analytics\indicator\cognitive_depth',
|
||||
'\mod_lti\analytics\indicator\social_breadth',
|
||||
'\mod_page\analytics\indicator\cognitive_depth',
|
||||
'\mod_page\analytics\indicator\social_breadth',
|
||||
'\mod_quiz\analytics\indicator\cognitive_depth',
|
||||
'\mod_quiz\analytics\indicator\social_breadth',
|
||||
'\mod_resource\analytics\indicator\cognitive_depth',
|
||||
'\mod_resource\analytics\indicator\social_breadth',
|
||||
'\mod_scorm\analytics\indicator\cognitive_depth',
|
||||
'\mod_scorm\analytics\indicator\social_breadth',
|
||||
'\mod_survey\analytics\indicator\cognitive_depth',
|
||||
'\mod_survey\analytics\indicator\social_breadth',
|
||||
'\mod_url\analytics\indicator\cognitive_depth',
|
||||
'\mod_url\analytics\indicator\social_breadth',
|
||||
'\mod_wiki\analytics\indicator\cognitive_depth',
|
||||
'\mod_wiki\analytics\indicator\social_breadth',
|
||||
'\mod_workshop\analytics\indicator\cognitive_depth',
|
||||
'\mod_workshop\analytics\indicator\social_breadth',
|
||||
],
|
||||
],
|
||||
[
|
||||
'target' => '\core\analytics\target\no_teaching',
|
||||
'indicators' => [
|
||||
'\core_course\analytics\indicator\no_teacher',
|
||||
'\core_course\analytics\indicator\no_student',
|
||||
],
|
||||
'timesplitting' => '\core\analytics\time_splitting\single_range',
|
||||
'enabled' => true,
|
||||
],
|
||||
];
|
||||
@@ -774,80 +774,6 @@ function xmldb_main_upgrade($oldversion) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$admin = get_admin();
|
||||
|
||||
$targetname = '\core\analytics\target\course_dropout';
|
||||
if (!$DB->record_exists('analytics_models', array('target' => $targetname))) {
|
||||
// We can not use API calls to create the built-in models.
|
||||
$modelobj = new stdClass();
|
||||
$modelobj->target = $targetname;
|
||||
$modelobj->indicators = json_encode(array(
|
||||
'\mod_assign\analytics\indicator\cognitive_depth',
|
||||
'\mod_assign\analytics\indicator\social_breadth',
|
||||
'\mod_book\analytics\indicator\cognitive_depth',
|
||||
'\mod_book\analytics\indicator\social_breadth',
|
||||
'\mod_chat\analytics\indicator\cognitive_depth',
|
||||
'\mod_chat\analytics\indicator\social_breadth',
|
||||
'\mod_choice\analytics\indicator\cognitive_depth',
|
||||
'\mod_choice\analytics\indicator\social_breadth',
|
||||
'\mod_data\analytics\indicator\cognitive_depth',
|
||||
'\mod_data\analytics\indicator\social_breadth',
|
||||
'\mod_feedback\analytics\indicator\cognitive_depth',
|
||||
'\mod_feedback\analytics\indicator\social_breadth',
|
||||
'\mod_folder\analytics\indicator\cognitive_depth',
|
||||
'\mod_folder\analytics\indicator\social_breadth',
|
||||
'\mod_forum\analytics\indicator\cognitive_depth',
|
||||
'\mod_forum\analytics\indicator\social_breadth',
|
||||
'\mod_glossary\analytics\indicator\cognitive_depth',
|
||||
'\mod_glossary\analytics\indicator\social_breadth',
|
||||
'\mod_imscp\analytics\indicator\cognitive_depth',
|
||||
'\mod_imscp\analytics\indicator\social_breadth',
|
||||
'\mod_label\analytics\indicator\cognitive_depth',
|
||||
'\mod_label\analytics\indicator\social_breadth',
|
||||
'\mod_lesson\analytics\indicator\cognitive_depth',
|
||||
'\mod_lesson\analytics\indicator\social_breadth',
|
||||
'\mod_lti\analytics\indicator\cognitive_depth',
|
||||
'\mod_lti\analytics\indicator\social_breadth',
|
||||
'\mod_page\analytics\indicator\cognitive_depth',
|
||||
'\mod_page\analytics\indicator\social_breadth',
|
||||
'\mod_quiz\analytics\indicator\cognitive_depth',
|
||||
'\mod_quiz\analytics\indicator\social_breadth',
|
||||
'\mod_resource\analytics\indicator\cognitive_depth',
|
||||
'\mod_resource\analytics\indicator\social_breadth',
|
||||
'\mod_scorm\analytics\indicator\cognitive_depth',
|
||||
'\mod_scorm\analytics\indicator\social_breadth',
|
||||
'\mod_survey\analytics\indicator\cognitive_depth',
|
||||
'\mod_survey\analytics\indicator\social_breadth',
|
||||
'\mod_url\analytics\indicator\cognitive_depth',
|
||||
'\mod_url\analytics\indicator\social_breadth',
|
||||
'\mod_wiki\analytics\indicator\cognitive_depth',
|
||||
'\mod_wiki\analytics\indicator\social_breadth',
|
||||
'\mod_workshop\analytics\indicator\cognitive_depth',
|
||||
'\mod_workshop\analytics\indicator\social_breadth',
|
||||
));
|
||||
$modelobj->version = $now;
|
||||
$modelobj->timecreated = $now;
|
||||
$modelobj->timemodified = $now;
|
||||
$modelobj->usermodified = $admin->id;
|
||||
$DB->insert_record('analytics_models', $modelobj);
|
||||
}
|
||||
|
||||
$targetname = '\core\analytics\target\no_teaching';
|
||||
if (!$DB->record_exists('analytics_models', array('target' => $targetname))) {
|
||||
$modelobj = new stdClass();
|
||||
$modelobj->enabled = 1;
|
||||
$modelobj->trained = 1;
|
||||
$modelobj->target = $targetname;
|
||||
$modelobj->indicators = json_encode(array('\core_course\analytics\indicator\no_teacher'));
|
||||
$modelobj->timesplitting = '\core\analytics\time_splitting\single_range';
|
||||
$modelobj->version = $now;
|
||||
$modelobj->timecreated = $now;
|
||||
$modelobj->timemodified = $now;
|
||||
$modelobj->usermodified = $admin->id;
|
||||
$DB->insert_record('analytics_models', $modelobj);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2017072000.02);
|
||||
}
|
||||
|
||||
@@ -578,6 +578,7 @@ function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
|
||||
log_update_descriptions($component);
|
||||
external_update_descriptions($component);
|
||||
\core\task\manager::reset_scheduled_tasks_for_component($component);
|
||||
\core_analytics\manager::update_default_models_for_component($component);
|
||||
message_update_providers($component);
|
||||
\core\message\inbound\manager::update_handlers_for_component($component);
|
||||
if ($type === 'message') {
|
||||
@@ -616,6 +617,7 @@ function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
|
||||
log_update_descriptions($component);
|
||||
external_update_descriptions($component);
|
||||
\core\task\manager::reset_scheduled_tasks_for_component($component);
|
||||
\core_analytics\manager::update_default_models_for_component($component);
|
||||
message_update_providers($component);
|
||||
\core\message\inbound\manager::update_handlers_for_component($component);
|
||||
if ($type === 'message') {
|
||||
@@ -649,6 +651,7 @@ function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
|
||||
log_update_descriptions($component);
|
||||
external_update_descriptions($component);
|
||||
\core\task\manager::reset_scheduled_tasks_for_component($component);
|
||||
\core_analytics\manager::update_default_models_for_component($component);
|
||||
message_update_providers($component);
|
||||
\core\message\inbound\manager::update_handlers_for_component($component);
|
||||
if ($type === 'message') {
|
||||
@@ -756,6 +759,7 @@ function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
|
||||
log_update_descriptions($component);
|
||||
external_update_descriptions($component);
|
||||
\core\task\manager::reset_scheduled_tasks_for_component($component);
|
||||
\core_analytics\manager::update_default_models_for_component($component);
|
||||
message_update_providers($component);
|
||||
\core\message\inbound\manager::update_handlers_for_component($component);
|
||||
upgrade_plugin_mnet_functions($component);
|
||||
@@ -790,6 +794,7 @@ function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
|
||||
log_update_descriptions($component);
|
||||
external_update_descriptions($component);
|
||||
\core\task\manager::reset_scheduled_tasks_for_component($component);
|
||||
\core_analytics\manager::update_default_models_for_component($component);
|
||||
message_update_providers($component);
|
||||
\core\message\inbound\manager::update_handlers_for_component($component);
|
||||
upgrade_plugin_mnet_functions($component);
|
||||
@@ -826,6 +831,7 @@ function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
|
||||
log_update_descriptions($component);
|
||||
external_update_descriptions($component);
|
||||
\core\task\manager::reset_scheduled_tasks_for_component($component);
|
||||
\core_analytics\manager::update_default_models_for_component($component);
|
||||
message_update_providers($component);
|
||||
\core\message\inbound\manager::update_handlers_for_component($component);
|
||||
upgrade_plugin_mnet_functions($component);
|
||||
@@ -947,6 +953,7 @@ function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
|
||||
log_update_descriptions($component);
|
||||
external_update_descriptions($component);
|
||||
\core\task\manager::reset_scheduled_tasks_for_component($component);
|
||||
\core_analytics\manager::update_default_models_for_component($component);
|
||||
message_update_providers($component);
|
||||
\core\message\inbound\manager::update_handlers_for_component($component);
|
||||
upgrade_plugin_mnet_functions($component);
|
||||
@@ -987,6 +994,7 @@ function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
|
||||
log_update_descriptions($component);
|
||||
external_update_descriptions($component);
|
||||
\core\task\manager::reset_scheduled_tasks_for_component($component);
|
||||
\core_analytics\manager::update_default_models_for_component($component);
|
||||
message_update_providers($component);
|
||||
\core\message\inbound\manager::update_handlers_for_component($component);
|
||||
core_tag_area::reset_definitions_for_component($component);
|
||||
@@ -1022,6 +1030,7 @@ function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
|
||||
log_update_descriptions($component);
|
||||
external_update_descriptions($component);
|
||||
\core\task\manager::reset_scheduled_tasks_for_component($component);
|
||||
\core_analytics\manager::update_default_models_for_component($component);
|
||||
message_update_providers($component);
|
||||
\core\message\inbound\manager::update_handlers_for_component($component);
|
||||
upgrade_plugin_mnet_functions($component);
|
||||
@@ -1738,6 +1747,7 @@ function install_core($version, $verbose) {
|
||||
log_update_descriptions('moodle');
|
||||
external_update_descriptions('moodle');
|
||||
\core\task\manager::reset_scheduled_tasks_for_component('moodle');
|
||||
\core_analytics\manager::update_default_models_for_component('moodle');
|
||||
message_update_providers('moodle');
|
||||
\core\message\inbound\manager::update_handlers_for_component('moodle');
|
||||
core_tag_area::reset_definitions_for_component('moodle');
|
||||
@@ -1805,6 +1815,7 @@ function upgrade_core($version, $verbose) {
|
||||
log_update_descriptions('moodle');
|
||||
external_update_descriptions('moodle');
|
||||
\core\task\manager::reset_scheduled_tasks_for_component('moodle');
|
||||
\core_analytics\manager::update_default_models_for_component('moodle');
|
||||
message_update_providers('moodle');
|
||||
\core\message\inbound\manager::update_handlers_for_component('moodle');
|
||||
core_tag_area::reset_definitions_for_component('moodle');
|
||||
|
||||
Reference in New Issue
Block a user