1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Model-related actions. 19 * 20 * @package tool_analytics 21 * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 require_once(__DIR__ . '/../../../config.php'); 26 require_once($CFG->libdir . '/filelib.php'); 27 28 $id = required_param('id', PARAM_INT); 29 $action = required_param('action', PARAM_ALPHANUMEXT); 30 31 require_login(); 32 33 $model = new \core_analytics\model($id); 34 \core_analytics\manager::check_can_manage_models(); 35 36 if (!\core_analytics\manager::is_analytics_enabled()) { 37 $PAGE->set_context(\context_system::instance()); 38 $renderer = $PAGE->get_renderer('tool_analytics'); 39 echo $renderer->render_analytics_disabled(); 40 exit(0); 41 } 42 43 $returnurl = new \moodle_url('/admin/tool/analytics/index.php'); 44 $params = array('id' => $id, 'action' => $action); 45 $url = new \moodle_url('/admin/tool/analytics/model.php', $params); 46 47 switch ($action) { 48 49 case 'edit': 50 $title = get_string('editmodel', 'tool_analytics', $model->get_name()); 51 break; 52 case 'evaluate': 53 $title = get_string('evaluatemodel', 'tool_analytics'); 54 break; 55 case 'scheduledanalysis': 56 $title = get_string('analysis', 'tool_analytics'); 57 break; 58 case 'log': 59 $title = get_string('viewlog', 'tool_analytics'); 60 break; 61 case 'enable': 62 $title = get_string('enable'); 63 break; 64 case 'disable': 65 $title = get_string('disable'); 66 break; 67 case 'delete': 68 $title = get_string('delete'); 69 break; 70 case 'exportdata': 71 $title = get_string('exporttrainingdata', 'tool_analytics'); 72 break; 73 case 'exportmodel': 74 $title = get_string('exportmodel', 'tool_analytics'); 75 break; 76 case 'clear': 77 $title = get_string('clearpredictions', 'tool_analytics'); 78 break; 79 case 'insightsreport': 80 $title = get_string('insightsreport', 'tool_analytics'); 81 break; 82 case 'invalidanalysables': 83 $title = get_string('invalidanalysables', 'tool_analytics'); 84 break; 85 default: 86 throw new moodle_exception('errorunknownaction', 'analytics'); 87 } 88 89 \tool_analytics\output\helper::set_navbar($title, $url); 90 91 $onlycli = get_config('analytics', 'onlycli'); 92 if ($onlycli === false) { 93 // Default applied if no config found. 94 $onlycli = 1; 95 } 96 97 switch ($action) { 98 99 case 'enable': 100 confirm_sesskey(); 101 102 $model->enable(); 103 redirect($returnurl); 104 break; 105 106 case 'disable': 107 confirm_sesskey(); 108 109 $model->update(0, false, false); 110 redirect($returnurl); 111 break; 112 113 case 'delete': 114 confirm_sesskey(); 115 116 $model->delete(); 117 redirect($returnurl); 118 break; 119 120 case 'edit': 121 confirm_sesskey(); 122 123 $invalidcurrenttimesplitting = $model->invalid_timesplitting_selected(); 124 $potentialtimesplittings = $model->get_potential_timesplittings(); 125 126 $customdata = array( 127 'id' => $model->get_id(), 128 'trainedmodel' => $model->is_trained(), 129 'staticmodel' => $model->is_static(), 130 'invalidcurrenttimesplitting' => (!empty($invalidcurrenttimesplitting)), 131 'targetclass' => $model->get_target()->get_id(), 132 'targetname' => $model->get_target()->get_name(), 133 'indicators' => $model->get_potential_indicators(), 134 'timesplittings' => $potentialtimesplittings, 135 'predictionprocessors' => \core_analytics\manager::get_all_prediction_processors(), 136 'supportscontexts' => ($model->get_analyser(['notimesplitting' => true]))::context_restriction_support(), 137 'contexts' => $model->get_contexts(), 138 ); 139 $mform = new \tool_analytics\output\form\edit_model(null, $customdata); 140 141 if ($mform->is_cancelled()) { 142 redirect($returnurl); 143 144 } else if ($data = $mform->get_data()) { 145 146 $timesplitting = \tool_analytics\output\helper::option_to_class($data->timesplitting); 147 148 if (!$model->is_static()) { 149 // Converting option names to class names. 150 $indicators = array(); 151 foreach ($data->indicators as $indicator) { 152 $indicatorclass = \tool_analytics\output\helper::option_to_class($indicator); 153 $indicators[] = \core_analytics\manager::get_indicator($indicatorclass); 154 } 155 $predictionsprocessor = \tool_analytics\output\helper::option_to_class($data->predictionsprocessor); 156 } else { 157 // These fields can not be modified. 158 $indicators = false; 159 $predictionsprocessor = false; 160 } 161 162 if (!isset($data->contexts)) { 163 $data->contexts = null; 164 } 165 166 $model->update($data->enabled, $indicators, $timesplitting, $predictionsprocessor, $data->contexts); 167 redirect($returnurl); 168 } 169 170 echo $OUTPUT->header(); 171 172 $modelobj = $model->get_model_obj(); 173 174 $callable = array('\tool_analytics\output\helper', 'class_to_option'); 175 $modelobj->indicators = array_map($callable, json_decode($modelobj->indicators)); 176 $modelobj->timesplitting = \tool_analytics\output\helper::class_to_option($modelobj->timesplitting); 177 if ($modelobj->contextids) { 178 $modelobj->contexts = array_map($callable, json_decode($modelobj->contextids)); 179 } 180 $modelobj->predictionsprocessor = \tool_analytics\output\helper::class_to_option($modelobj->predictionsprocessor); 181 $mform->set_data($modelobj); 182 $mform->display(); 183 break; 184 185 case 'evaluate': 186 confirm_sesskey(); 187 188 if ($model->is_static()) { 189 throw new moodle_exception('errornostaticevaluate', 'tool_analytics'); 190 } 191 192 if ($onlycli) { 193 throw new moodle_exception('erroronlycli', 'tool_analytics'); 194 } 195 196 // Web interface is used by people who can not use CLI nor code stuff, always use 197 // cached stuff as they will change the model through the web interface as well 198 // which invalidates the previously analysed stuff. 199 $options = ['reuseprevanalysed' => true]; 200 201 $mode = optional_param('mode', false, PARAM_ALPHANUM); 202 if ($mode == 'trainedmodel') { 203 $options['mode'] = 'trainedmodel'; 204 } else { 205 206 // All is the default in core_analytics\model::evaluate() as well. 207 $timesplitting = optional_param('timesplitting', 'all', PARAM_ALPHANUMEXT); 208 if ($timesplitting === 'current') { 209 $options['timesplitting'] = \core_analytics\manager::get_time_splitting($model->get_model_obj()->timesplitting); 210 } else if ($timesplitting !== 'all') { 211 $options['timesplitting'] = \core_analytics\manager::get_time_splitting( 212 \tool_analytics\output\helper::option_to_class($timesplitting) 213 ); 214 } 215 } 216 217 $results = $model->evaluate($options); 218 219 // We reset the theme and the output as some indicators may be using external functions 220 // which reset $PAGE. 221 \tool_analytics\output\helper::reset_page(); 222 echo $OUTPUT->header(); 223 224 $renderer = $PAGE->get_renderer('tool_analytics'); 225 echo $renderer->render_evaluate_results($results, $model->get_analyser()->get_logs()); 226 break; 227 228 case 'scheduledanalysis': 229 confirm_sesskey(); 230 231 if ($onlycli) { 232 throw new moodle_exception('erroronlycli', 'tool_analytics'); 233 } 234 235 $trainresults = $model->train(); 236 $trainlogs = $model->get_analyser()->get_logs(); 237 238 // Looks dumb to get a new instance but better be conservative. 239 $model = new \core_analytics\model($model->get_model_obj()); 240 if ($model->is_trained()) { 241 $predictresults = $model->predict(); 242 $predictlogs = $model->get_analyser()->get_logs(); 243 } else { 244 $predictresults = false; 245 $predictlogs = array(); 246 } 247 248 // We reset the theme and the output as some indicators may be using external functions 249 // which reset $PAGE. 250 \tool_analytics\output\helper::reset_page(); 251 echo $OUTPUT->header(); 252 253 $renderer = $PAGE->get_renderer('tool_analytics'); 254 echo $renderer->render_get_predictions_results($trainresults, $trainlogs, $predictresults, $predictlogs); 255 break; 256 257 case 'log': 258 echo $OUTPUT->header(); 259 260 if ($model->is_static()) { 261 throw new moodle_exception('errornostaticlog', 'tool_analytics'); 262 } 263 264 $renderer = $PAGE->get_renderer('tool_analytics'); 265 $modellogstable = new \tool_analytics\output\model_logs('model-' . $model->get_id(), $model); 266 echo $renderer->render_table($modellogstable); 267 break; 268 269 case 'exportdata': 270 271 if ($model->is_static() || !$model->is_trained()) { 272 throw new moodle_exception('errornoexport', 'tool_analytics'); 273 } 274 275 $file = $model->get_training_data(); 276 if (!$file) { 277 redirect($returnurl, get_string('errortrainingdataexport', 'tool_analytics'), 278 null, \core\output\notification::NOTIFY_ERROR); 279 } 280 281 $filename = 'training-data.' . $model->get_id() . '.' . time() . '.csv'; 282 send_file($file, $filename, null, 0, false, true); 283 break; 284 285 case 'exportmodel': 286 287 $includeweights = optional_param('includeweights', 1, PARAM_INT); 288 289 $zipfilename = 'model-' . $model->get_unique_id() . '-' . microtime(false) . '.zip'; 290 $zipfilepath = $model->export_model($zipfilename, $includeweights); 291 send_temp_file($zipfilepath, $zipfilename); 292 break; 293 294 case 'clear': 295 confirm_sesskey(); 296 297 $model->clear(); 298 redirect($returnurl); 299 break; 300 301 case 'insightsreport': 302 303 $contextid = optional_param('contextid', null, PARAM_INT); 304 305 echo $OUTPUT->header(); 306 307 $renderable = new \tool_analytics\output\insights_report($model, $contextid); 308 $renderer = $PAGE->get_renderer('tool_analytics'); 309 echo $renderer->render($renderable); 310 311 break; 312 313 case 'invalidanalysables': 314 315 echo $OUTPUT->header(); 316 317 $page = optional_param('page', 0, PARAM_INT); 318 // No option in the UI to change this, only for url hackers ;). 319 $perpage = optional_param('perpage', 10, PARAM_INT); 320 321 $renderable = new \tool_analytics\output\invalid_analysables($model, $page, $perpage); 322 $renderer = $PAGE->get_renderer('tool_analytics'); 323 echo $renderer->render($renderable); 324 325 break; 326 } 327 328 echo $OUTPUT->footer();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body