Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * Allows the admin to manage question behaviours.
  20   *
  21   * @package    moodlecore
  22   * @subpackage questionengine
  23   * @copyright  2011 The Open University
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  
  28  require_once(__DIR__ . '/../config.php');
  29  require_once($CFG->libdir . '/questionlib.php');
  30  require_once($CFG->libdir . '/adminlib.php');
  31  require_once($CFG->libdir . '/tablelib.php');
  32  
  33  // Check permissions.
  34  require_login(null, false);
  35  $systemcontext = context_system::instance();
  36  require_capability('moodle/question:config', $systemcontext);
  37  
  38  admin_externalpage_setup('manageqbehaviours');
  39  $thispageurl = new moodle_url('/admin/qbehaviours.php');
  40  
  41  $behaviours = core_component::get_plugin_list('qbehaviour');
  42  $pluginmanager = core_plugin_manager::instance();
  43  
  44  // Get some data we will need - question counts and which types are needed.
  45  $counts = $DB->get_records_sql_menu("
  46          SELECT behaviour, COUNT(1)
  47          FROM {question_attempts} GROUP BY behaviour");
  48  $needed = array();
  49  $archetypal = array();
  50  foreach ($behaviours as $behaviour => $notused) {
  51      if (!array_key_exists($behaviour, $counts)) {
  52          $counts[$behaviour] = 0;
  53      }
  54      $needed[$behaviour] = ($counts[$behaviour] > 0) ||
  55              $pluginmanager->other_plugins_that_require('qbehaviour_' . $behaviour);
  56      $archetypal[$behaviour] = question_engine::is_behaviour_archetypal($behaviour);
  57  }
  58  foreach ($counts as $behaviour => $count) {
  59      if (!array_key_exists($behaviour, $behaviours)) {
  60          $counts['missing'] += $count;
  61      }
  62  }
  63  $needed['missing'] = true;
  64  
  65  // Work of the correct sort order.
  66  $config = get_config('question');
  67  $sortedbehaviours = array();
  68  foreach ($behaviours as $behaviour => $notused) {
  69      $sortedbehaviours[$behaviour] = question_engine::get_behaviour_name($behaviour);
  70  }
  71  if (!empty($config->behavioursortorder)) {
  72      $sortedbehaviours = question_engine::sort_behaviours($sortedbehaviours,
  73              $config->behavioursortorder, '');
  74  }
  75  
  76  if (!empty($config->disabledbehaviours)) {
  77      $disabledbehaviours = explode(',', $config->disabledbehaviours);
  78  } else {
  79      $disabledbehaviours = array();
  80  }
  81  
  82  // Process actions ============================================================
  83  
  84  // Disable.
  85  if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey()) {
  86      if (!isset($behaviours[$disable])) {
  87          print_error('unknownbehaviour', 'question', $thispageurl, $disable);
  88      }
  89  
  90      if (array_search($disable, $disabledbehaviours) === false) {
  91          $disabledbehaviours[] = $disable;
  92          set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
  93      }
  94      core_plugin_manager::reset_caches();
  95      redirect($thispageurl);
  96  }
  97  
  98  // Enable.
  99  if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey()) {
 100      if (!isset($behaviours[$enable])) {
 101          print_error('unknownbehaviour', 'question', $thispageurl, $enable);
 102      }
 103  
 104      if (!$archetypal[$enable]) {
 105          print_error('cannotenablebehaviour', 'question', $thispageurl, $enable);
 106      }
 107  
 108      if (($key = array_search($enable, $disabledbehaviours)) !== false) {
 109          unset($disabledbehaviours[$key]);
 110          set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
 111      }
 112      core_plugin_manager::reset_caches();
 113      redirect($thispageurl);
 114  }
 115  
 116  // Move up in order.
 117  if (($up = optional_param('up', '', PARAM_PLUGIN)) && confirm_sesskey()) {
 118      if (!isset($behaviours[$up])) {
 119          print_error('unknownbehaviour', 'question', $thispageurl, $up);
 120      }
 121  
 122      // This function works fine for behaviours, as well as qtypes.
 123      $neworder = question_reorder_qtypes($sortedbehaviours, $up, -1);
 124      set_config('behavioursortorder', implode(',', $neworder), 'question');
 125      redirect($thispageurl);
 126  }
 127  
 128  // Move down in order.
 129  if (($down = optional_param('down', '', PARAM_PLUGIN)) && confirm_sesskey()) {
 130      if (!isset($behaviours[$down])) {
 131          print_error('unknownbehaviour', 'question', $thispageurl, $down);
 132      }
 133  
 134      // This function works fine for behaviours, as well as qtypes.
 135      $neworder = question_reorder_qtypes($sortedbehaviours, $down, +1);
 136      set_config('behavioursortorder', implode(',', $neworder), 'question');
 137      redirect($thispageurl);
 138  }
 139  
 140  // End of process actions ==================================================
 141  
 142  // Print the page heading.
 143  echo $OUTPUT->header();
 144  echo $OUTPUT->heading(get_string('manageqbehaviours', 'admin'));
 145  
 146  // Set up the table.
 147  $table = new flexible_table('qbehaviouradmintable');
 148  $table->define_baseurl($thispageurl);
 149  $table->define_columns(array('behaviour', 'numqas', 'version', 'requires',
 150          'available', 'uninstall'));
 151  $table->define_headers(array(get_string('behaviour', 'question'), get_string('numqas', 'question'),
 152          get_string('version'), get_string('requires', 'admin'),
 153          get_string('availableq', 'question'), get_string('uninstallplugin', 'core_admin')));
 154  $table->set_attribute('id', 'qbehaviours');
 155  $table->set_attribute('class', 'generaltable admintable');
 156  $table->setup();
 157  
 158  // Add a row for each question type.
 159  foreach ($sortedbehaviours as $behaviour => $behaviourname) {
 160      $row = array();
 161  
 162      // Question icon and name.
 163      $row[] = $behaviourname;
 164  
 165      // Count
 166      $row[] = $counts[$behaviour];
 167  
 168      // Question version number.
 169      $version = get_config('qbehaviour_' . $behaviour, 'version');
 170      if ($version) {
 171          $row[] = $version;
 172      } else {
 173          $row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'text-muted'));
 174      }
 175  
 176      // Other question types required by this one.
 177      $plugin = $pluginmanager->get_plugin_info('qbehaviour_' . $behaviour);
 178      $required = $plugin->get_other_required_plugins();
 179      if (!empty($required)) {
 180          $strrequired = array();
 181          foreach ($required as $component => $notused) {
 182              $strrequired[] = $pluginmanager->plugin_name($component);
 183          }
 184          $row[] = implode(', ', $strrequired);
 185      } else {
 186          $row[] = '';
 187      }
 188  
 189      // Are people allowed to select this behaviour?
 190      $rowclass = '';
 191      if ($archetypal[$behaviour]) {
 192          $enabled = array_search($behaviour, $disabledbehaviours) === false;
 193          $icons = question_behaviour_enable_disable_icons($behaviour, $enabled);
 194          if (!$enabled) {
 195              $rowclass = 'dimmed_text';
 196          }
 197      } else {
 198          $icons = $OUTPUT->spacer(array('class' => 'iconsmall'));
 199      }
 200  
 201      // Move icons.
 202      $icons .= question_behaviour_icon_html('up', $behaviour, 't/up', get_string('up'), null);
 203      $icons .= question_behaviour_icon_html('down', $behaviour, 't/down', get_string('down'), null);
 204      $row[] = $icons;
 205  
 206      // Delete link, if available.
 207      if ($needed[$behaviour]) {
 208          $row[] = '';
 209      } else {
 210          $uninstallurl = core_plugin_manager::instance()->get_uninstall_url('qbehaviour_'.$behaviour, 'manage');
 211          if ($uninstallurl) {
 212              $row[] = html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'),
 213                  array('title' => get_string('uninstallbehaviour', 'question')));
 214          }
 215      }
 216  
 217      $table->add_data($row, $rowclass);
 218  }
 219  
 220  $table->finish_output();
 221  
 222  echo $OUTPUT->footer();
 223  
 224  function question_behaviour_enable_disable_icons($behaviour, $enabled) {
 225      if ($enabled) {
 226          return question_behaviour_icon_html('disable', $behaviour, 't/hide',
 227                  get_string('enabled', 'question'), get_string('disable'));
 228      } else {
 229          return question_behaviour_icon_html('enable', $behaviour, 't/show',
 230                  get_string('disabled', 'question'), get_string('enable'));
 231      }
 232  }
 233  
 234  function question_behaviour_icon_html($action, $behaviour, $icon, $alt, $tip) {
 235      global $OUTPUT;
 236      return $OUTPUT->action_icon(new moodle_url('/admin/qbehaviours.php',
 237              array($action => $behaviour, 'sesskey' => sesskey())),
 238              new pix_icon($icon, $alt, 'moodle', array('title' => '', 'class' => 'iconsmall')),
 239              null, array('title' => $tip));
 240  }
 241