See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
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 * Single insight view page. 19 * 20 * @package report_insights 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 namespace report_insights\output; 26 27 use core_analytics\prediction; 28 29 defined('MOODLE_INTERNAL') || die(); 30 31 /** 32 * Single insight view page. 33 * 34 * @package report_insights 35 * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class insight implements \renderable, \templatable { 39 40 /** 41 * @var \core_analytics\model 42 */ 43 protected $model; 44 45 /** 46 * @var \core_analytics\prediction 47 */ 48 protected $prediction; 49 50 /** 51 * @var bool 52 */ 53 protected $includedetailsaction = false; 54 55 /** 56 * @var \context 57 */ 58 protected $context; 59 60 /** 61 * Constructor 62 * 63 * @param \core_analytics\prediction $prediction 64 * @param \core_analytics\model $model 65 * @param bool $includedetailsaction 66 * @param \context $context 67 * @return void 68 */ 69 public function __construct(\core_analytics\prediction $prediction, \core_analytics\model $model, $includedetailsaction = false, 70 \context $context) { 71 72 $this->prediction = $prediction; 73 $this->model = $model; 74 $this->includedetailsaction = $includedetailsaction; 75 $this->context = $context; 76 } 77 78 /** 79 * Exports the data. 80 * 81 * @param \renderer_base $output 82 * @return \stdClass 83 */ 84 public function export_for_template(\renderer_base $output) { 85 // Get the prediction data. 86 $predictiondata = $this->prediction->get_prediction_data(); 87 88 $target = $this->model->get_target(); 89 90 $data = new \stdClass(); 91 $data->modelid = $this->model->get_id(); 92 $data->contextid = $this->context->id; 93 $data->predictionid = $predictiondata->id; 94 95 $targetname = $target->get_name(); 96 $data->insightname = format_string($targetname); 97 98 $targetinfostr = $targetname->get_identifier() . 'info'; 99 if (get_string_manager()->string_exists($targetinfostr, $targetname->get_component())) { 100 $data->insightdescription = get_string($targetinfostr, $targetname->get_component()); 101 } 102 103 $data->showpredictionheading = true; 104 if (!$target->is_linear()) { 105 $nclasses = count($target::get_classes()); 106 $nignoredclasses = count($target->ignored_predicted_classes()); 107 if ($nclasses - $nignoredclasses <= 1) { 108 // Hide the prediction heading if there is only 1 class displayed. Otherwise it is redundant with the insight name. 109 $data->showpredictionheading = false; 110 } 111 } 112 113 // Get the details. 114 $data->timecreated = userdate($predictiondata->timecreated); 115 $data->timerange = ''; 116 117 if (!empty($predictiondata->timestart) && !empty($predictiondata->timeend)) { 118 $timerange = new \stdClass(); 119 $timerange->timestart = userdate($predictiondata->timestart); 120 $timerange->timeend = userdate($predictiondata->timeend); 121 $data->timerange = get_string('timerangewithdata', 'report_insights', $timerange); 122 } 123 124 // Sample info (determined by the analyser). 125 list($data->sampledescription, $samplerenderable) = $this->model->prediction_sample_description($this->prediction); 126 127 // Sampleimage is a renderable we should pass it to HTML. 128 if ($samplerenderable) { 129 $data->sampleimage = $output->render($samplerenderable); 130 } 131 132 // Prediction info. 133 $predictedvalue = $predictiondata->prediction; 134 $data->predictiondisplayvalue = $target->get_display_value($predictedvalue); 135 list($data->style, $data->outcomeicon) = self::get_calculation_display($target, 136 floatval($predictedvalue), $output); 137 138 $data->actions = actions_exporter::add_prediction_actions($target, $output, $this->prediction, 139 $this->includedetailsaction); 140 $data->bulkactions = actions_exporter::add_bulk_actions($target, $output, [$this->prediction], $this->context); 141 142 // Calculated indicators values. 143 $data->calculations = array(); 144 $calculations = $this->prediction->get_calculations(); 145 foreach ($calculations as $calculation) { 146 147 // Hook for indicators with extra features that should not be displayed (e.g. discrete indicators). 148 if (!$calculation->indicator->should_be_displayed($calculation->value, $calculation->subtype)) { 149 continue; 150 } 151 152 if ($calculation->value === null) { 153 // We don't show values that could not be calculated. 154 continue; 155 } 156 157 $obj = new \stdClass(); 158 $obj->name = call_user_func(array($calculation->indicator, 'get_name')); 159 $obj->displayvalue = $calculation->indicator->get_display_value($calculation->value, $calculation->subtype); 160 list($obj->style, $obj->outcomeicon) = self::get_calculation_display($calculation->indicator, 161 floatval($calculation->value), $output, $calculation->subtype); 162 163 $identifier = $calculation->indicator->get_name()->get_identifier() . 'def'; 164 $component = $calculation->indicator->get_name()->get_component(); 165 if (get_string_manager()->string_exists($identifier, $component)) { 166 $obj->outcomehelp = (new \help_icon($identifier, $component))->export_for_template($output); 167 } 168 $data->calculations[] = $obj; 169 } 170 171 if (empty($data->calculations)) { 172 $data->nocalculations = (object)array( 173 'message' => get_string('nodetailsavailable', 'report_insights'), 174 'closebutton' => false 175 ); 176 } 177 178 // This is only rendered in report_insights/insight_details template for predictions with no action. 179 // We need it to automatically enable the bulk action buttons in report/insights/prediction.php. 180 $filtered = [ 181 \core_analytics\prediction::ACTION_FIXED, 182 \core_analytics\prediction::ACTION_NOT_USEFUL, 183 \core_analytics\prediction::ACTION_USEFUL, 184 \core_analytics\prediction::ACTION_NOT_APPLICABLE, 185 \core_analytics\prediction::ACTION_INCORRECTLY_FLAGGED, 186 ]; 187 if (!$this->prediction->get_executed_actions($filtered)) { 188 $toggleall = new \core\output\checkbox_toggleall('insight-bulk-action-' . $predictedvalue, true, [ 189 'id' => 'id-toggle-all-' . $predictedvalue, 190 'name' => 'toggle-all-' . $predictedvalue, 191 'classes' => 'hidden', 192 'label' => get_string('selectall'), 193 'labelclasses' => 'sr-only', 194 'checked' => false, 195 ]); 196 $data->hiddencheckboxtoggleall = $output->render($toggleall); 197 198 $toggle = new \core\output\checkbox_toggleall('insight-bulk-action-' . $predictedvalue, false, [ 199 'id' => 'id-select-' . $data->predictionid, 200 'name' => 'select-' . $data->predictionid, 201 'label' => get_string('selectprediction', 'report_insights', $data->sampledescription), 202 'labelclasses' => 'accesshide', 203 ]); 204 $data->toggleslave = $output->render($toggle); 205 } 206 207 return $data; 208 } 209 210 /** 211 * Returns display info for the calculated value outcome. 212 * 213 * @param \core_analytics\calculable $calculable 214 * @param float $value 215 * @param \renderer_base $output 216 * @param string|false $subtype 217 * @return array The style as 'success', 'info', 'warning' or 'danger' and pix_icon 218 */ 219 public static function get_calculation_display(\core_analytics\calculable $calculable, $value, $output, $subtype = false) { 220 $outcome = $calculable->get_calculation_outcome($value, $subtype); 221 switch ($outcome) { 222 case \core_analytics\calculable::OUTCOME_NEUTRAL: 223 $style = ''; 224 $text = get_string('outcomeneutral', 'report_insights'); 225 $icon = 't/check'; 226 break; 227 case \core_analytics\calculable::OUTCOME_VERY_POSITIVE: 228 $style = 'success'; 229 $text = get_string('outcomeverypositive', 'report_insights'); 230 $icon = 't/approve'; 231 break; 232 case \core_analytics\calculable::OUTCOME_OK: 233 $style = 'info'; 234 $text = get_string('outcomeok', 'report_insights'); 235 $icon = 't/check'; 236 break; 237 case \core_analytics\calculable::OUTCOME_NEGATIVE: 238 $style = 'warning'; 239 $text = get_string('outcomenegative', 'report_insights'); 240 $icon = 'i/warning'; 241 break; 242 case \core_analytics\calculable::OUTCOME_VERY_NEGATIVE: 243 $style = 'danger'; 244 $text = get_string('outcomeverynegative', 'report_insights'); 245 $icon = 'i/warning'; 246 break; 247 default: 248 throw new \coding_exception('The outcome returned by ' . get_class($calculable) . '::get_calculation_outcome is ' . 249 'not one of the accepted values. Please use \core_analytics\calculable::OUTCOME_VERY_POSITIVE, ' . 250 '\core_analytics\calculable::OUTCOME_OK, \core_analytics\calculable::OUTCOME_NEGATIVE, ' . 251 '\core_analytics\calculable::OUTCOME_VERY_NEGATIVE or \core_analytics\calculable::OUTCOME_NEUTRAL'); 252 } 253 $icon = new \pix_icon($icon, $text); 254 return array($style, $icon->export_for_template($output)); 255 } 256 257 /** 258 * Model getter. 259 * 260 * @return \core_analytics\model 261 */ 262 public function get_model(): \core_analytics\model { 263 return $this->model; 264 } 265 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body