Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
   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 edit form.
  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  namespace tool_analytics\output\form;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  require_once($CFG->dirroot.'/lib/formslib.php');
  30  
  31  /**
  32   * Model edit form.
  33   *
  34   * @package   tool_analytics
  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 edit_model extends \moodleform {
  39  
  40      /**
  41       * Form definition
  42       */
  43      public function definition() {
  44          global $OUTPUT;
  45  
  46          $mform = $this->_form;
  47  
  48          if ($this->_customdata['trainedmodel'] && $this->_customdata['staticmodel'] === false) {
  49              $message = get_string('edittrainedwarning', 'tool_analytics');
  50              $mform->addElement('html', $OUTPUT->notification($message, \core\output\notification::NOTIFY_WARNING));
  51          }
  52  
  53          $mform->addElement('advcheckbox', 'enabled', get_string('enabled', 'tool_analytics'));
  54  
  55          // Target.
  56          if (!empty($this->_customdata['targets'])) {
  57              $targets = array('' => '');
  58              foreach ($this->_customdata['targets'] as $classname => $target) {
  59                  $optionname = \tool_analytics\output\helper::class_to_option($classname);
  60                  $targets[$optionname] = $target->get_name();
  61              }
  62  
  63              $mform->addElement('select', 'target', get_string('target', 'tool_analytics'), $targets);
  64              $mform->addHelpButton('target', 'target', 'tool_analytics');
  65              $mform->addRule('target', get_string('required'), 'required', null, 'client');
  66          }
  67  
  68          if (!empty($this->_customdata['targetname']) && !empty($this->_customdata['targetclass'])) {
  69              $mform->addElement('static', 'targetname', get_string('target', 'tool_analytics'), $this->_customdata['targetname']);
  70              $mform->addElement('hidden', 'target',
  71                  \tool_analytics\output\helper::class_to_option($this->_customdata['targetclass']));
  72              // We won't update the model's target so no worries about its format (we can't use PARAM_ALPHANUMEXT
  73              // because of class_to_option).
  74              $mform->setType('target', PARAM_TEXT);
  75          }
  76  
  77          // Indicators.
  78          if (!$this->_customdata['staticmodel']) {
  79              $indicators = array();
  80              foreach ($this->_customdata['indicators'] as $classname => $indicator) {
  81                  $optionname = \tool_analytics\output\helper::class_to_option($classname);
  82                  $indicators[$optionname] = $indicator->get_name();
  83              }
  84              $options = array(
  85                  'multiple' => true
  86              );
  87              $mform->addElement('autocomplete', 'indicators', get_string('indicators', 'tool_analytics'), $indicators, $options);
  88              $mform->setType('indicators', PARAM_ALPHANUMEXT);
  89              $mform->addHelpButton('indicators', 'indicators', 'tool_analytics');
  90          }
  91  
  92          // Time-splitting methods.
  93          if (!empty($this->_customdata['invalidcurrenttimesplitting'])) {
  94              $mform->addElement('html', $OUTPUT->notification(
  95                  get_string('invalidcurrenttimesplitting', 'tool_analytics'),
  96                  \core\output\notification::NOTIFY_WARNING)
  97              );
  98          }
  99  
 100          $timesplittings = array('' => '');
 101          foreach ($this->_customdata['timesplittings'] as $classname => $timesplitting) {
 102              $optionname = \tool_analytics\output\helper::class_to_option($classname);
 103              $timesplittings[$optionname] = $timesplitting->get_name();
 104          }
 105          $mform->addElement('select', 'timesplitting', get_string('timesplittingmethod', 'analytics'), $timesplittings);
 106          $mform->addHelpButton('timesplitting', 'timesplittingmethod', 'analytics');
 107  
 108          // Contexts restriction.
 109          if (!empty($this->_customdata['supportscontexts'])) {
 110  
 111              $options = [
 112                  'ajax' => 'tool_analytics/potential-contexts',
 113                  'multiple' => true,
 114                  'noselectionstring' => get_string('all')
 115              ];
 116  
 117              if (!empty($this->_customdata['id'])) {
 118                  $options['modelid'] = $this->_customdata['id'];
 119                  $contexts = $this->load_current_contexts();
 120              } else {
 121                  // No need to preload any selected contexts.
 122                  $contexts = [];
 123              }
 124  
 125              $mform->addElement('autocomplete', 'contexts', get_string('contexts', 'tool_analytics'), $contexts, $options);
 126              $mform->setType('contexts', PARAM_INT);
 127              $mform->addHelpButton('contexts', 'contexts', 'tool_analytics');
 128          }
 129  
 130          // Predictions processor.
 131          if (!$this->_customdata['staticmodel']) {
 132              $defaultprocessor = \core_analytics\manager::get_predictions_processor_name(
 133                  \core_analytics\manager::get_predictions_processor()
 134              );
 135              $predictionprocessors = ['' => get_string('defaultpredictoroption', 'analytics', $defaultprocessor)];
 136              foreach ($this->_customdata['predictionprocessors'] as $classname => $predictionsprocessor) {
 137                  if ($predictionsprocessor->is_ready() !== true) {
 138                      continue;
 139                  }
 140                  $optionname = \tool_analytics\output\helper::class_to_option($classname);
 141                  $predictionprocessors[$optionname] = \core_analytics\manager::get_predictions_processor_name($predictionsprocessor);
 142              }
 143  
 144              $mform->addElement('select', 'predictionsprocessor', get_string('predictionsprocessor', 'analytics'),
 145                  $predictionprocessors);
 146              $mform->addHelpButton('predictionsprocessor', 'predictionsprocessor', 'analytics');
 147          }
 148  
 149          if (!empty($this->_customdata['id'])) {
 150              $mform->addElement('hidden', 'id', $this->_customdata['id']);
 151              $mform->setType('id', PARAM_INT);
 152  
 153              $mform->addElement('hidden', 'action', 'edit');
 154              $mform->setType('action', PARAM_ALPHANUMEXT);
 155          }
 156  
 157          $this->add_action_buttons();
 158      }
 159  
 160      /**
 161       * Form validation
 162       *
 163       * @param array $data data from the form.
 164       * @param array $files files uploaded.
 165       *
 166       * @return array of errors.
 167       */
 168      public function validation($data, $files) {
 169          $errors = parent::validation($data, $files);
 170  
 171          $targetclass = \tool_analytics\output\helper::option_to_class($data['target']);
 172          $target = \core_analytics\manager::get_target($targetclass);
 173  
 174          if (!empty($data['timesplitting'])) {
 175              $timesplittingclass = \tool_analytics\output\helper::option_to_class($data['timesplitting']);
 176              if (\core_analytics\manager::is_valid($timesplittingclass, '\core_analytics\local\time_splitting\base') === false) {
 177                  $errors['timesplitting'] = get_string('errorinvalidtimesplitting', 'analytics');
 178              }
 179  
 180              $timesplitting = \core_analytics\manager::get_time_splitting($timesplittingclass);
 181              if (!$target->can_use_timesplitting($timesplitting)) {
 182                  $errors['timesplitting'] = get_string('invalidtimesplitting', 'tool_analytics');
 183              }
 184          }
 185  
 186          if (!empty($data['contexts'])) {
 187  
 188              $analyserclass = $target->get_analyser_class();
 189              if (!$potentialcontexts = $analyserclass::potential_context_restrictions()) {
 190                  $errors['contexts'] = get_string('errornocontextrestrictions', 'analytics');
 191              } else {
 192  
 193                  // Flip the contexts array so we can just diff by key.
 194                  $selectedcontexts = array_flip($data['contexts']);
 195                  $invalidcontexts = array_diff_key($selectedcontexts, $potentialcontexts);
 196                  if (!empty($invalidcontexts)) {
 197                      $errors['contexts'] = get_string('errorinvalidcontexts', 'analytics');
 198                  }
 199              }
 200          }
 201  
 202          if (!$this->_customdata['staticmodel']) {
 203              if (empty($data['indicators'])) {
 204                  $errors['indicators'] = get_string('errornoindicators', 'analytics');
 205              } else {
 206                  foreach ($data['indicators'] as $indicator) {
 207                      $realindicatorname = \tool_analytics\output\helper::option_to_class($indicator);
 208                      if (\core_analytics\manager::is_valid($realindicatorname, '\core_analytics\local\indicator\base') === false) {
 209                          $errors['indicators'] = get_string('errorinvalidindicator', 'analytics', $realindicatorname);
 210                      }
 211                  }
 212              }
 213          }
 214  
 215          if (!empty($data['enabled']) && empty($data['timesplitting'])) {
 216              $errors['enabled'] = get_string('errorcantenablenotimesplitting', 'tool_analytics');
 217          }
 218  
 219          return $errors;
 220      }
 221  
 222      /**
 223       * Load the currently selected context options.
 224       *
 225       * @return array
 226       */
 227      protected function load_current_contexts() {
 228          $contexts = [];
 229          foreach ($this->_customdata['contexts'] as $context) {
 230              $contexts[$context->id] = $context->get_context_name(true, true);
 231          }
 232  
 233          return $contexts;
 234      }
 235  }