PageRenderTime 48ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/admin/qbehaviours.php

https://github.com/kpike/moodle
PHP | 302 lines | 205 code | 47 blank | 50 comment | 42 complexity | cada4f02d32ec26b82467f5bfb5381cb MD5 | raw file
  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. * Allows the admin to manage question behaviours.
  18. *
  19. * @package moodlecore
  20. * @subpackage questionengine
  21. * @copyright 2011 The Open University
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. */
  24. require_once(dirname(__FILE__) . '/../config.php');
  25. require_once($CFG->libdir . '/questionlib.php');
  26. require_once($CFG->libdir . '/adminlib.php');
  27. require_once($CFG->libdir . '/tablelib.php');
  28. // Check permissions.
  29. require_login();
  30. $systemcontext = get_context_instance(CONTEXT_SYSTEM);
  31. require_capability('moodle/question:config', $systemcontext);
  32. admin_externalpage_setup('manageqbehaviours');
  33. $thispageurl = new moodle_url('/admin/qbehaviours.php');
  34. $behaviours = get_plugin_list('qbehaviour');
  35. // Get some data we will need - question counts and which types are needed.
  36. $counts = $DB->get_records_sql_menu("
  37. SELECT behaviour, COUNT(1)
  38. FROM {question_attempts} GROUP BY behaviour");
  39. $needed = array();
  40. $archetypal = array();
  41. foreach ($behaviours as $behaviour => $notused) {
  42. if (!array_key_exists($behaviour, $counts)) {
  43. $counts[$behaviour] = 0;
  44. }
  45. $needed[$behaviour] = $counts[$behaviour] > 0;
  46. $archetypal[$behaviour] = question_engine::is_behaviour_archetypal($behaviour);
  47. }
  48. foreach ($behaviours as $behaviour => $notused) {
  49. foreach (question_engine::get_behaviour_required_behaviours($behaviour) as $reqbehaviour) {
  50. $needed[$reqbehaviour] = true;
  51. }
  52. }
  53. foreach ($counts as $behaviour => $count) {
  54. if (!array_key_exists($behaviour, $behaviours)) {
  55. $counts['missingtype'] += $count;
  56. }
  57. }
  58. // Work of the correct sort order.
  59. $config = get_config('question');
  60. $sortedbehaviours = array();
  61. foreach ($behaviours as $behaviour => $notused) {
  62. $sortedbehaviours[$behaviour] = question_engine::get_behaviour_name($behaviour);
  63. }
  64. if (!empty($config->behavioursortorder)) {
  65. $sortedbehaviours = question_engine::sort_behaviours($sortedbehaviours,
  66. $config->behavioursortorder, '');
  67. }
  68. if (!empty($config->disabledbehaviours)) {
  69. $disabledbehaviours = explode(',', $config->disabledbehaviours);
  70. } else {
  71. $disabledbehaviours = array();
  72. }
  73. // Process actions ============================================================
  74. // Disable.
  75. if (($disable = optional_param('disable', '', PARAM_SAFEDIR)) && confirm_sesskey()) {
  76. if (!isset($behaviours[$disable])) {
  77. print_error('unknownbehaviour', 'question', $thispageurl, $disable);
  78. }
  79. if (array_search($disable, $disabledbehaviours) === false) {
  80. $disabledbehaviours[] = $disable;
  81. set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
  82. }
  83. redirect($thispageurl);
  84. }
  85. // Enable.
  86. if (($enable = optional_param('enable', '', PARAM_SAFEDIR)) && confirm_sesskey()) {
  87. if (!isset($behaviours[$enable])) {
  88. print_error('unknownbehaviour', 'question', $thispageurl, $enable);
  89. }
  90. if (!$archetypal[$enable]) {
  91. print_error('cannotenablebehaviour', 'question', $thispageurl, $enable);
  92. }
  93. if (($key = array_search($enable, $disabledbehaviours)) !== false) {
  94. unset($disabledbehaviours[$key]);
  95. set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
  96. }
  97. redirect($thispageurl);
  98. }
  99. // Move up in order.
  100. if (($up = optional_param('up', '', PARAM_SAFEDIR)) && confirm_sesskey()) {
  101. if (!isset($behaviours[$up])) {
  102. print_error('unknownbehaviour', 'question', $thispageurl, $up);
  103. }
  104. // This function works fine for behaviours, as well as qtypes.
  105. $neworder = question_reorder_qtypes($sortedbehaviours, $up, -1);
  106. set_config('behavioursortorder', implode(',', $neworder), 'question');
  107. redirect($thispageurl);
  108. }
  109. // Move down in order.
  110. if (($down = optional_param('down', '', PARAM_SAFEDIR)) && confirm_sesskey()) {
  111. if (!isset($behaviours[$down])) {
  112. print_error('unknownbehaviour', 'question', $thispageurl, $down);
  113. }
  114. // This function works fine for behaviours, as well as qtypes.
  115. $neworder = question_reorder_qtypes($sortedbehaviours, $down, +1);
  116. set_config('behavioursortorder', implode(',', $neworder), 'question');
  117. redirect($thispageurl);
  118. }
  119. // Delete.
  120. if (($delete = optional_param('delete', '', PARAM_SAFEDIR)) && confirm_sesskey()) {
  121. // Check it is OK to delete this question type.
  122. if ($delete == 'missing') {
  123. print_error('cannotdeletemissingbehaviour', 'question', $thispageurl);
  124. }
  125. if (!isset($behaviours[$delete])) {
  126. print_error('unknownbehaviour', 'question', $thispageurl, $delete);
  127. }
  128. $behaviourname = $sortedbehaviours[$delete];
  129. if ($counts[$delete] > 0) {
  130. print_error('cannotdeletebehaviourinuse', 'question', $thispageurl, $behaviourname);
  131. }
  132. if ($needed[$delete] > 0) {
  133. print_error('cannotdeleteneededbehaviour', 'question', $thispageurl, $behaviourname);
  134. }
  135. // If not yet confirmed, display a confirmation message.
  136. if (!optional_param('confirm', '', PARAM_BOOL)) {
  137. echo $OUTPUT->header();
  138. echo $OUTPUT->heading(get_string('deletebehaviourareyousure', 'question', $behaviourname));
  139. echo $OUTPUT->confirm(
  140. get_string('deletebehaviourareyousuremessage', 'question', $behaviourname),
  141. new moodle_url($thispageurl, array('delete' => $delete, 'confirm' => 1)),
  142. $thispageurl);
  143. echo $OUTPUT->footer();
  144. exit;
  145. }
  146. // Do the deletion.
  147. echo $OUTPUT->header();
  148. echo $OUTPUT->heading(get_string('deletingbehaviour', 'question', $behaviourname));
  149. // Delete any configuration records.
  150. if (!unset_all_config_for_plugin('qbehaviour_' . $delete)) {
  151. echo $OUTPUT->notification(get_string('errordeletingconfig', 'admin', 'qbehaviour_' . $delete));
  152. }
  153. if (($key = array_search($delete, $disabledbehaviours)) !== false) {
  154. unset($disabledbehaviours[$key]);
  155. set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
  156. }
  157. $behaviourorder = explode(',', $config->behavioursortorder);
  158. if (($key = array_search($delete, $behaviourorder)) !== false) {
  159. unset($behaviourorder[$key]);
  160. set_config('behavioursortorder', implode(',', $behaviourorder), 'question');
  161. }
  162. // Then the tables themselves
  163. drop_plugin_tables($delete, get_plugin_directory('qbehaviour', $delete) . '/db/install.xml', false);
  164. // Remove event handlers and dequeue pending events
  165. events_uninstall('qbehaviour_' . $delete);
  166. $a->behaviour = $behaviourname;
  167. $a->directory = get_plugin_directory('qbehaviour', $delete);
  168. echo $OUTPUT->box(get_string('qbehaviourdeletefiles', 'question', $a), 'generalbox', 'notice');
  169. echo $OUTPUT->continue_button($thispageurl);
  170. echo $OUTPUT->footer();
  171. exit;
  172. }
  173. // End of process actions ==================================================
  174. // Print the page heading.
  175. echo $OUTPUT->header();
  176. echo $OUTPUT->heading(get_string('manageqbehaviours', 'admin'));
  177. // Set up the table.
  178. $table = new flexible_table('qbehaviouradmintable');
  179. $table->define_baseurl($thispageurl);
  180. $table->define_columns(array('behaviour', 'numqas', 'version', 'requires',
  181. 'available', 'delete'));
  182. $table->define_headers(array(get_string('behaviour', 'question'), get_string('numqas', 'question'),
  183. get_string('version'), get_string('requires', 'admin'),
  184. get_string('availableq', 'question'), get_string('delete')));
  185. $table->set_attribute('id', 'qbehaviours');
  186. $table->set_attribute('class', 'generaltable generalbox boxaligncenter boxwidthwide');
  187. $table->setup();
  188. // Add a row for each question type.
  189. foreach ($sortedbehaviours as $behaviour => $behaviourname) {
  190. $row = array();
  191. // Question icon and name.
  192. $row[] = $behaviourname;
  193. // Count
  194. $row[] = $counts[$behaviour];
  195. // Question version number.
  196. $version = get_config('qbehaviour_' . $behaviour, 'version');
  197. if ($version) {
  198. $row[] = $version;
  199. } else {
  200. $row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'disabled'));
  201. }
  202. // Other question types required by this one.
  203. $requiredbehaviours = question_engine::get_behaviour_required_behaviours($behaviour);
  204. if (!empty($requiredbehaviours)) {
  205. $strrequiredbehaviours = array();
  206. foreach ($requiredbehaviours as $required) {
  207. $strrequiredbehaviours[] = $sortedbehaviours[$required];
  208. }
  209. $row[] = implode(', ', $strrequiredbehaviours);
  210. } else {
  211. $row[] = '';
  212. }
  213. // Are people allowed to create new questions of this type?
  214. $rowclass = '';
  215. if ($archetypal[$behaviour]) {
  216. $enabled = array_search($behaviour, $disabledbehaviours) === false;
  217. $icons = question_behaviour_enable_disable_icons($behaviour, $enabled);
  218. if (!$enabled) {
  219. $rowclass = 'dimmed_text';
  220. }
  221. } else {
  222. $icons = $OUTPUT->spacer() . ' ';
  223. }
  224. // Move icons.
  225. $icons .= question_behaviour_icon_html('up', $behaviour, 't/up', get_string('up'), null);
  226. $icons .= question_behaviour_icon_html('down', $behaviour, 't/down', get_string('down'), null);
  227. $row[] = $icons;
  228. // Delete link, if available.
  229. if ($needed[$behaviour]) {
  230. $row[] = '';
  231. } else {
  232. $row[] = html_writer::link(new moodle_url($thispageurl,
  233. array('delete' => $behaviour, 'sesskey' => sesskey())), get_string('delete'),
  234. array('title' => get_string('uninstallbehaviour', 'question')));
  235. }
  236. $table->add_data($row, $rowclass);
  237. }
  238. $table->finish_output();
  239. echo $OUTPUT->footer();
  240. function question_behaviour_enable_disable_icons($behaviour, $enabled) {
  241. if ($enabled) {
  242. return question_behaviour_icon_html('disable', $behaviour, 'i/hide',
  243. get_string('enabled', 'question'), get_string('disable'));
  244. } else {
  245. return question_behaviour_icon_html('enable', $behaviour, 'i/show',
  246. get_string('disabled', 'question'), get_string('enable'));
  247. }
  248. }
  249. function question_behaviour_icon_html($action, $behaviour, $icon, $alt, $tip) {
  250. global $OUTPUT;
  251. return $OUTPUT->action_icon(new moodle_url('/admin/qbehaviours.php',
  252. array($action => $behaviour, 'sesskey' => sesskey())),
  253. new pix_icon($icon, $alt, 'moodle', array('title' => '')),
  254. null, array('title' => $tip)) . ' ';
  255. }