See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]
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 types. 20 * 21 * @package moodlecore 22 * @subpackage questionbank 23 * @copyright 2008 Tim Hunt 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 27 use core_question\local\bank\question_version_status; 28 29 require_once(__DIR__ . '/../config.php'); 30 require_once($CFG->libdir . '/questionlib.php'); 31 require_once($CFG->libdir . '/adminlib.php'); 32 require_once($CFG->libdir . '/tablelib.php'); 33 34 admin_externalpage_setup('manageqtypes'); 35 36 $systemcontext = context_system::instance(); 37 require_capability('moodle/question:config', $systemcontext); 38 $canviewreports = has_capability('report/questioninstances:view', $systemcontext); 39 40 $thispageurl = new moodle_url('/admin/qtypes.php'); 41 42 $qtypes = question_bank::get_all_qtypes(); 43 $pluginmanager = core_plugin_manager::instance(); 44 45 // Get some data we will need - question counts and which types are needed. 46 // The second JOIN on question_versions (qv2) is to get the latest version of each question. 47 // (Using this sort of JOIN is a known trick for doing this in the fastest possible way.) 48 $counts = $DB->get_records_sql(" 49 SELECT q.qtype, 50 COUNT(qv.id) AS numquestions, 51 SUM(CASE WHEN qv.status = :hiddenstatus THEN 1 ELSE 0 END) AS numhidden, 52 SUM(CASE WHEN qv.status = :draftstatus THEN 1 ELSE 0 END) AS numdraft 53 FROM {question} q 54 JOIN {question_versions} qv ON q.id = qv.questionid 55 LEFT JOIN {question_versions} qv2 ON qv.questionbankentryid = qv2.questionbankentryid AND qv.version < qv2.version 56 WHERE qv2.questionbankentryid IS NULL 57 GROUP BY q.qtype 58 ", [ 59 'hiddenstatus' => question_version_status::QUESTION_STATUS_HIDDEN, 60 'draftstatus' => question_version_status::QUESTION_STATUS_DRAFT, 61 ]); 62 63 $needed = []; 64 foreach ($qtypes as $qtypename => $qtype) { 65 if (!isset($counts[$qtypename])) { 66 $counts[$qtypename] = new stdClass; 67 $counts[$qtypename]->numquestions = 0; 68 $counts[$qtypename]->numhidden = 0; 69 $counts[$qtypename]->numdraft = 0; 70 } 71 $needed[$qtypename] = $counts[$qtypename]->numquestions > 0 || 72 $pluginmanager->other_plugins_that_require($qtype->plugin_name()); 73 $counts[$qtypename]->numquestions -= ($counts[$qtypename]->numhidden + $counts[$qtypename]->numdraft); 74 } 75 $needed['missingtype'] = true; // The system needs the missing question type. 76 foreach ($counts as $qtypename => $count) { 77 if (!isset($qtypes[$qtypename])) { 78 $counts['missingtype']->numquestions += $count->numquestions - ($count->numhidden + $count->numdraft); 79 $counts['missingtype']->numhidden += $count->numhidden; 80 $counts['missingtype']->numdraft += $count->numdraft; 81 } 82 } 83 84 // Work of the correct sort order. 85 $config = get_config('question'); 86 $sortedqtypes = array(); 87 foreach ($qtypes as $qtypename => $qtype) { 88 $sortedqtypes[$qtypename] = $qtype->local_name(); 89 } 90 $sortedqtypes = question_bank::sort_qtype_array($sortedqtypes, $config); 91 92 // Process actions ============================================================ 93 94 // Disable. 95 if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey()) { 96 if (!isset($qtypes[$disable])) { 97 throw new \moodle_exception('unknownquestiontype', 'question', $thispageurl, $disable); 98 } 99 100 $class = \core_plugin_manager::resolve_plugininfo_class('qtype'); 101 $class::enable_plugin($disable, false); 102 redirect($thispageurl); 103 } 104 105 // Enable. 106 if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey()) { 107 if (!isset($qtypes[$enable])) { 108 throw new \moodle_exception('unknownquestiontype', 'question', $thispageurl, $enable); 109 } 110 111 if (!$qtypes[$enable]->menu_name()) { 112 throw new \moodle_exception('cannotenable', 'question', $thispageurl, $enable); 113 } 114 115 $class = \core_plugin_manager::resolve_plugininfo_class('qtype'); 116 $class::enable_plugin($enable, true); 117 redirect($thispageurl); 118 } 119 120 // Move up in order. 121 if (($up = optional_param('up', '', PARAM_PLUGIN)) && confirm_sesskey()) { 122 if (!isset($qtypes[$up])) { 123 throw new \moodle_exception('unknownquestiontype', 'question', $thispageurl, $up); 124 } 125 126 $neworder = question_reorder_qtypes($sortedqtypes, $up, -1); 127 question_save_qtype_order($neworder, $config); 128 redirect($thispageurl); 129 } 130 131 // Move down in order. 132 if (($down = optional_param('down', '', PARAM_PLUGIN)) && confirm_sesskey()) { 133 if (!isset($qtypes[$down])) { 134 throw new \moodle_exception('unknownquestiontype', 'question', $thispageurl, $down); 135 } 136 137 $neworder = question_reorder_qtypes($sortedqtypes, $down, +1); 138 question_save_qtype_order($neworder, $config); 139 redirect($thispageurl); 140 } 141 142 // End of process actions ================================================== 143 144 // Print the page heading. 145 echo $OUTPUT->header(); 146 echo $OUTPUT->heading(get_string('manageqtypes', 'admin')); 147 148 // Set up the table. 149 $table = new flexible_table('qtypeadmintable'); 150 $table->define_baseurl($thispageurl); 151 $table->define_columns(array('questiontype', 'numquestions', 'version', 'requires', 152 'availableto', 'uninstall', 'settings')); 153 $table->define_headers(array(get_string('questiontype', 'question'), get_string('numquestions', 'question'), 154 get_string('version'), get_string('requires', 'admin'), get_string('availableq', 'question'), 155 get_string('settings'), get_string('uninstallplugin', 'core_admin'))); 156 $table->set_attribute('id', 'qtypes'); 157 $table->set_attribute('class', 'admintable generaltable'); 158 $table->setup(); 159 160 // Add a row for each question type. 161 $createabletypes = question_bank::get_creatable_qtypes(); 162 foreach ($sortedqtypes as $qtypename => $localname) { 163 $qtype = $qtypes[$qtypename]; 164 $row = array(); 165 166 // Question icon and name. 167 $fakequestion = new stdClass; 168 $fakequestion->qtype = $qtypename; 169 $icon = print_question_icon($fakequestion, true); 170 $row[] = $icon . ' ' . $localname; 171 172 // Number of questions of this type. 173 if ($counts[$qtypename]->numquestions + $counts[$qtypename]->numhidden + $counts[$qtypename]->numdraft > 0) { 174 if ($counts[$qtypename]->numhidden + $counts[$qtypename]->numdraft > 0) { 175 $strcount = get_string('numquestionsandhidden', 'question', $counts[$qtypename]); 176 } else { 177 $strcount = $counts[$qtypename]->numquestions; 178 } 179 if ($canviewreports) { 180 $row[] = html_writer::link(new moodle_url('/report/questioninstances/index.php', 181 array('qtype' => $qtypename)), $strcount, array('title' => get_string('showdetails', 'admin'))); 182 } else { 183 $strcount; 184 } 185 } else { 186 $row[] = 0; 187 } 188 189 // Question version number. 190 $version = get_config('qtype_' . $qtypename, 'version'); 191 if ($version) { 192 $row[] = $version; 193 } else { 194 $row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'text-muted')); 195 } 196 197 // Other question types required by this one. 198 $plugin = $pluginmanager->get_plugin_info($qtype->plugin_name()); 199 $requiredtypes = $plugin->get_other_required_plugins(); 200 $strtypes = array(); 201 if (!empty($requiredtypes)) { 202 foreach ($requiredtypes as $required => $notused) { 203 $strtypes[] = $pluginmanager->plugin_name($required); 204 } 205 $row[] = implode(', ', $strtypes); 206 } else { 207 $row[] = ''; 208 } 209 210 // Are people allowed to create new questions of this type? 211 $rowclass = ''; 212 if ($qtype->menu_name()) { 213 $createable = isset($createabletypes[$qtypename]); 214 $icons = question_types_enable_disable_icons($qtypename, $createable); 215 if (!$createable) { 216 $rowclass = 'dimmed_text'; 217 } 218 } else { 219 $icons = $OUTPUT->spacer(); 220 } 221 222 // Move icons. 223 $icons .= question_type_icon_html('up', $qtypename, 't/up', get_string('up'), ''); 224 $icons .= question_type_icon_html('down', $qtypename, 't/down', get_string('down'), ''); 225 $row[] = $icons; 226 227 // Settings link, if available. 228 $settings = admin_get_root()->locate('qtypesetting' . $qtypename); 229 if ($settings instanceof admin_externalpage) { 230 $row[] = html_writer::link($settings->url, get_string('settings')); 231 } else if ($settings instanceof admin_settingpage) { 232 $row[] = html_writer::link(new moodle_url('/admin/settings.php', 233 array('section' => 'qtypesetting' . $qtypename)), get_string('settings')); 234 } else { 235 $row[] = ''; 236 } 237 238 // Uninstall link, if available. 239 if ($needed[$qtypename]) { 240 $row[] = ''; 241 } else { 242 $uninstallurl = core_plugin_manager::instance()->get_uninstall_url('qtype_'.$qtypename, 'manage'); 243 if ($uninstallurl) { 244 $row[] = html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'), 245 array('title' => get_string('uninstallqtype', 'question'))); 246 } 247 } 248 249 $table->add_data($row, $rowclass); 250 } 251 252 $table->finish_output(); 253 254 echo $OUTPUT->footer(); 255 256 function question_types_enable_disable_icons($qtypename, $createable) { 257 if ($createable) { 258 return question_type_icon_html('disable', $qtypename, 't/hide', 259 get_string('enabled', 'question'), get_string('disable')); 260 } else { 261 return question_type_icon_html('enable', $qtypename, 't/show', 262 get_string('disabled', 'question'), get_string('enable')); 263 } 264 } 265 266 function question_type_icon_html($action, $qtypename, $icon, $alt, $tip) { 267 global $OUTPUT; 268 return $OUTPUT->action_icon(new moodle_url('/admin/qtypes.php', 269 array($action => $qtypename, 'sesskey' => sesskey())), 270 new pix_icon($icon, $alt, 'moodle', array('title' => '', 'class' => 'iconsmall')), 271 null, array('title' => $tip)); 272 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body