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 28require_once(__DIR__ . '/../config.php'); 29require_once($CFG->libdir . '/questionlib.php'); 30require_once($CFG->libdir . '/adminlib.php'); 31require_once($CFG->libdir . '/tablelib.php'); 32 33admin_externalpage_setup('manageqtypes'); 34 35$systemcontext = context_system::instance(); 36require_capability('moodle/question:config', $systemcontext); 37$canviewreports = has_capability('report/questioninstances:view', $systemcontext); 38 39$thispageurl = new moodle_url('/admin/qtypes.php'); 40 41$qtypes = question_bank::get_all_qtypes(); 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(" 46 SELECT qtype, COUNT(1) as numquestions, SUM(hidden) as numhidden 47 FROM {question} GROUP BY qtype", array()); 48$needed = array(); 49foreach ($qtypes as $qtypename => $qtype) { 50 if (!isset($counts[$qtypename])) { 51 $counts[$qtypename] = new stdClass; 52 $counts[$qtypename]->numquestions = 0; 53 $counts[$qtypename]->numhidden = 0; 54 } 55 $needed[$qtypename] = $counts[$qtypename]->numquestions > 0 || 56 $pluginmanager->other_plugins_that_require($qtype->plugin_name()); 57 $counts[$qtypename]->numquestions -= $counts[$qtypename]->numhidden; 58} 59$needed['missingtype'] = true; // The system needs the missing question type. 60foreach ($counts as $qtypename => $count) { 61 if (!isset($qtypes[$qtypename])) { 62 $counts['missingtype']->numquestions += $count->numquestions - $count->numhidden; 63 $counts['missingtype']->numhidden += $count->numhidden; 64 } 65} 66 67// Work of the correct sort order. 68$config = get_config('question'); 69$sortedqtypes = array(); 70foreach ($qtypes as $qtypename => $qtype) { 71 $sortedqtypes[$qtypename] = $qtype->local_name(); 72} 73$sortedqtypes = question_bank::sort_qtype_array($sortedqtypes, $config); 74 75// Process actions ============================================================ 76 77// Disable. 78if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey()) { 79 if (!isset($qtypes[$disable])) { 80 print_error('unknownquestiontype', 'question', $thispageurl, $disable); 81 } 82 83 set_config($disable . '_disabled', 1, 'question'); 84 redirect($thispageurl); 85} 86 87// Enable. 88if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey()) { 89 if (!isset($qtypes[$enable])) { 90 print_error('unknownquestiontype', 'question', $thispageurl, $enable); 91 } 92 93 if (!$qtypes[$enable]->menu_name()) { 94 print_error('cannotenable', 'question', $thispageurl, $enable); 95 } 96 97 unset_config($enable . '_disabled', 'question'); 98 redirect($thispageurl); 99} 100 101// Move up in order. 102if (($up = optional_param('up', '', PARAM_PLUGIN)) && confirm_sesskey()) { 103 if (!isset($qtypes[$up])) { 104 print_error('unknownquestiontype', 'question', $thispageurl, $up); 105 } 106 107 $neworder = question_reorder_qtypes($sortedqtypes, $up, -1); 108 question_save_qtype_order($neworder, $config); 109 redirect($thispageurl); 110} 111 112// Move down in order. 113if (($down = optional_param('down', '', PARAM_PLUGIN)) && confirm_sesskey()) { 114 if (!isset($qtypes[$down])) { 115 print_error('unknownquestiontype', 'question', $thispageurl, $down); 116 } 117 118 $neworder = question_reorder_qtypes($sortedqtypes, $down, +1); 119 question_save_qtype_order($neworder, $config); 120 redirect($thispageurl); 121} 122 123// End of process actions ================================================== 124 125// Print the page heading. 126echo $OUTPUT->header(); 127echo $OUTPUT->heading(get_string('manageqtypes', 'admin')); 128 129// Set up the table. 130$table = new flexible_table('qtypeadmintable'); 131$table->define_baseurl($thispageurl); 132$table->define_columns(array('questiontype', 'numquestions', 'version', 'requires', 133 'availableto', 'uninstall', 'settings')); 134$table->define_headers(array(get_string('questiontype', 'question'), get_string('numquestions', 'question'), 135 get_string('version'), get_string('requires', 'admin'), get_string('availableq', 'question'), 136 get_string('settings'), get_string('uninstallplugin', 'core_admin'))); 137$table->set_attribute('id', 'qtypes'); 138$table->set_attribute('class', 'admintable generaltable'); 139$table->setup(); 140 141// Add a row for each question type. 142$createabletypes = question_bank::get_creatable_qtypes(); 143foreach ($sortedqtypes as $qtypename => $localname) { 144 $qtype = $qtypes[$qtypename]; 145 $row = array(); 146 147 // Question icon and name. 148 $fakequestion = new stdClass; 149 $fakequestion->qtype = $qtypename; 150 $icon = print_question_icon($fakequestion, true); 151 $row[] = $icon . ' ' . $localname; 152 153 // Number of questions of this type. 154 if ($counts[$qtypename]->numquestions + $counts[$qtypename]->numhidden > 0) { 155 if ($counts[$qtypename]->numhidden > 0) { 156 $strcount = get_string('numquestionsandhidden', 'question', $counts[$qtypename]); 157 } else { 158 $strcount = $counts[$qtypename]->numquestions; 159 } 160 if ($canviewreports) { 161 $row[] = html_writer::link(new moodle_url('/report/questioninstances/index.php', 162 array('qtype' => $qtypename)), $strcount, array('title' => get_string('showdetails', 'admin'))); 163 } else { 164 $strcount; 165 } 166 } else { 167 $row[] = 0; 168 } 169 170 // Question version number. 171 $version = get_config('qtype_' . $qtypename, 'version'); 172 if ($version) { 173 $row[] = $version; 174 } else { 175 $row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'text-muted')); 176 } 177 178 // Other question types required by this one. 179 $plugin = $pluginmanager->get_plugin_info($qtype->plugin_name()); 180 $requiredtypes = $plugin->get_other_required_plugins(); 181 $strtypes = array(); 182 if (!empty($requiredtypes)) { 183 foreach ($requiredtypes as $required => $notused) { 184 $strtypes[] = $pluginmanager->plugin_name($required); 185 } 186 $row[] = implode(', ', $strtypes); 187 } else { 188 $row[] = ''; 189 } 190 191 // Are people allowed to create new questions of this type? 192 $rowclass = ''; 193 if ($qtype->menu_name()) { 194 $createable = isset($createabletypes[$qtypename]); 195 $icons = question_types_enable_disable_icons($qtypename, $createable); 196 if (!$createable) { 197 $rowclass = 'dimmed_text'; 198 } 199 } else { 200 $icons = $OUTPUT->spacer(); 201 } 202 203 // Move icons. 204 $icons .= question_type_icon_html('up', $qtypename, 't/up', get_string('up'), ''); 205 $icons .= question_type_icon_html('down', $qtypename, 't/down', get_string('down'), ''); 206 $row[] = $icons; 207 208 // Settings link, if available. 209 $settings = admin_get_root()->locate('qtypesetting' . $qtypename); 210 if ($settings instanceof admin_externalpage) { 211 $row[] = html_writer::link($settings->url, get_string('settings')); 212 } else if ($settings instanceof admin_settingpage) { 213 $row[] = html_writer::link(new moodle_url('/admin/settings.php', 214 array('section' => 'qtypesetting' . $qtypename)), get_string('settings')); 215 } else { 216 $row[] = ''; 217 } 218 219 // Uninstall link, if available. 220 if ($needed[$qtypename]) { 221 $row[] = ''; 222 } else { 223 $uninstallurl = core_plugin_manager::instance()->get_uninstall_url('qtype_'.$qtypename, 'manage'); 224 if ($uninstallurl) { 225 $row[] = html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'), 226 array('title' => get_string('uninstallqtype', 'question'))); 227 } 228 } 229 230 $table->add_data($row, $rowclass); 231} 232 233$table->finish_output(); 234 235echo $OUTPUT->footer(); 236 237function question_types_enable_disable_icons($qtypename, $createable) { 238 if ($createable) { 239 return question_type_icon_html('disable', $qtypename, 't/hide', 240 get_string('enabled', 'question'), get_string('disable')); 241 } else { 242 return question_type_icon_html('enable', $qtypename, 't/show', 243 get_string('disabled', 'question'), get_string('enable')); 244 } 245} 246 247function question_type_icon_html($action, $qtypename, $icon, $alt, $tip) { 248 global $OUTPUT; 249 return $OUTPUT->action_icon(new moodle_url('/admin/qtypes.php', 250 array($action => $qtypename, 'sesskey' => sesskey())), 251 new pix_icon($icon, $alt, 'moodle', array('title' => '', 'class' => 'iconsmall')), 252 null, array('title' => $tip)); 253} 254 255