PageRenderTime 62ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/db/upgrade.php

https://github.com/KieranRBriggs/moodle-mod_hotpot
PHP | 831 lines | 563 code | 112 blank | 156 comment | 87 complexity | e496a585e6669b0e2479683e4ad8c3e2 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. * mod/hotpot/db/upgrade.php
  18. *
  19. * @package mod-hotpot
  20. * @copyright 2010 Gordon Bateson <gordon.bateson@gmail.com>
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. defined('MOODLE_INTERNAL') || die();
  24. /**
  25. * xmldb_hotpot_upgrade
  26. *
  27. * @param xxx $oldversion
  28. * @return xxx
  29. */
  30. function xmldb_hotpot_upgrade($oldversion) {
  31. global $CFG, $DB;
  32. // this flag will be set to true if any upgrade needs to empty the HotPot cache
  33. $empty_cache = false;
  34. $dbman = $DB->get_manager();
  35. //===== 1.9.0 upgrade line ======//
  36. // update hotpot grades from sites earlier than Moodle 1.9, 27th March 2008
  37. $newversion = 2007101511;
  38. if ($oldversion < $newversion) {
  39. // ensure "hotpot_upgrade_grades" function is available
  40. require_once $CFG->dirroot.'/mod/hotpot/lib.php';
  41. hotpot_upgrade_grades();
  42. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  43. }
  44. $newversion = 2008011200;
  45. if ($oldversion < $newversion) {
  46. // remove unused config setting
  47. unset_config('hotpot_initialdisable');
  48. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  49. }
  50. $newversion = 2010080301;
  51. if ($oldversion < $newversion) {
  52. // remove unused config settings
  53. unset_config('hotpot_showtimes');
  54. unset_config('hotpot_excelencodings');
  55. // modify table: hotpot
  56. $table = new xmldb_table('hotpot');
  57. // expected structure of hotpot table when we start this upgrade:
  58. // (i.e. this is how things were at the end of Moodle 1.9)
  59. // id, course, name, summary, timeopen, timeclose, location, reference,
  60. // outputformat, navigation, studentfeedback, studentfeedbackurl,
  61. // forceplugins, shownextquiz, review, grade, grademethod, attempts,
  62. // password, subnet, clickreporting, timecreated, timemodified
  63. // convert, move and rename fields ($newname => $oldfield)
  64. $fields = array(
  65. // same name
  66. 'outputformat' => new xmldb_field('outputformat', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL), // (int -> varchar)
  67. 'timeopen' => new xmldb_field('timeopen', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'studentfeedbackurl'),
  68. 'timeclose' => new xmldb_field('timeclose', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'timeopen'),
  69. 'grademethod' => new xmldb_field('grademethod', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'grade'),
  70. // new name
  71. 'sourcefile' => new xmldb_field('reference', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'name'),
  72. 'sourcelocation' => new xmldb_field('location', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'sourcefile'),
  73. 'entrytext' => new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'sourcelocation'),
  74. 'reviewoptions' => new xmldb_field('review', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'),
  75. 'attemptlimit' => new xmldb_field('attempts', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'reviewoptions'),
  76. 'gradeweighting' => new xmldb_field('grade', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'attemptlimit'),
  77. );
  78. foreach ($fields as $newname => $field) {
  79. if ($dbman->field_exists($table, $field)) {
  80. xmldb_hotpot_fix_previous_field($dbman, $table, $field);
  81. $dbman->change_field_type($table, $field);
  82. if ($field->getName() != $newname) {
  83. $dbman->rename_field($table, $field, $newname);
  84. }
  85. }
  86. }
  87. // add fields
  88. $fields = array(
  89. new xmldb_field('sourcefile', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'name'),
  90. new xmldb_field('sourcetype', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'sourcefile'),
  91. new xmldb_field('sourceitemid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'sourcetype'),
  92. new xmldb_field('sourcelocation', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'sourceitemid'),
  93. new xmldb_field('configfile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'sourcelocation'),
  94. new xmldb_field('configitemid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'configfile'),
  95. new xmldb_field('configlocation', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'configitemid'),
  96. new xmldb_field('entrycm', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'configlocation'),
  97. new xmldb_field('entrygrade', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '100', 'entrycm'),
  98. new xmldb_field('entrypage', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entrygrade'),
  99. new xmldb_field('entrytext', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'entrypage'),
  100. new xmldb_field('entryformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entrytext'),
  101. new xmldb_field('entryoptions', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entryformat'),
  102. new xmldb_field('exitpage', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entryoptions'),
  103. new xmldb_field('exittext', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'exitpage'),
  104. new xmldb_field('exitformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'exittext'),
  105. new xmldb_field('exitoptions', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'exitformat'),
  106. new xmldb_field('exitcm', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'exitoptions'),
  107. new xmldb_field('title', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '3', 'navigation'),
  108. new xmldb_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'title'),
  109. new xmldb_field('stoptext', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'stopbutton'),
  110. new xmldb_field('usefilters', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'stoptext'),
  111. new xmldb_field('useglossary', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'usefilters'),
  112. new xmldb_field('usemediafilter', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'useglossary'),
  113. new xmldb_field('timelimit', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'timeclose'),
  114. new xmldb_field('delay1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'timelimit'),
  115. new xmldb_field('delay2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'delay1'),
  116. new xmldb_field('delay3', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2', 'delay2'),
  117. new xmldb_field('discarddetails', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'clickreporting')
  118. );
  119. foreach ($fields as $field) {
  120. if (! $dbman->field_exists($table, $field)) {
  121. xmldb_hotpot_fix_previous_field($dbman, $table, $field);
  122. $dbman->add_field($table, $field);
  123. }
  124. }
  125. // remove field: forceplugins (replaced by "usemediafilter")
  126. $field = new xmldb_field('forceplugins', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  127. if ($dbman->field_exists($table, $field)) {
  128. $DB->execute('UPDATE {hotpot} SET '."usemediafilter='moodle'".' WHERE forceplugins=1');
  129. $dbman->drop_field($table, $field);
  130. }
  131. // remove field: shownextquiz (replaced by "exitcm")
  132. $field = new xmldb_field('shownextquiz', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  133. if ($dbman->field_exists($table, $field)) {
  134. // set exitcm to show next HotPot: -4 = hotpot::ACTIVITY_SECTION_QUIZPORT
  135. $DB->execute('UPDATE {hotpot} SET exitcm=-4 WHERE shownextquiz=1');
  136. $dbman->drop_field($table, $field);
  137. }
  138. // append "id" to fields that are foreign keys in other hotpot tables
  139. $fields = array(
  140. // $tablename => $fieldnames array
  141. 'hotpot_attempts' => array('hotpot'),
  142. 'hotpot_details' => array('attempt'),
  143. 'hotpot_questions' => array('hotpot'),
  144. 'hotpot_responses' => array('attempt', 'question'),
  145. );
  146. foreach ($fields as $tablename => $fieldnames) {
  147. $table = new xmldb_table($tablename);
  148. foreach ($fieldnames as $fieldname) {
  149. $field = new xmldb_field($fieldname, XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  150. if ($dbman->field_exists($table, $field)) {
  151. // maybe we should remove all indexes and keys
  152. // using this $fieldname before we rename the field
  153. $dbman->rename_field($table, $field, $fieldname.'id');
  154. }
  155. }
  156. }
  157. // create new table: hotpot_cache
  158. $table = new xmldb_table('hotpot_cache');
  159. if (!$dbman->table_exists($table)) {
  160. $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
  161. $table->add_field('hotpotid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  162. $table->add_field('slasharguments', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL);
  163. $table->add_field('hotpot_enableobfuscate', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL);
  164. $table->add_field('hotpot_enableswf', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL);
  165. $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
  166. $table->add_field('sourcefile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
  167. $table->add_field('sourcetype', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
  168. $table->add_field('sourcelocation', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL);
  169. $table->add_field('sourcelastmodified', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
  170. $table->add_field('sourceetag', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
  171. $table->add_field('configfile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
  172. $table->add_field('configlocation', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  173. $table->add_field('configlastmodified', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
  174. $table->add_field('configetag', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
  175. $table->add_field('navigation', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  176. $table->add_field('title', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  177. $table->add_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, null, null, '0');
  178. $table->add_field('stoptext', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
  179. $table->add_field('usefilters', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, '0');
  180. $table->add_field('useglossary', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, '0');
  181. $table->add_field('usemediafilter', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, '0');
  182. $table->add_field('studentfeedback', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0');
  183. $table->add_field('studentfeedbackurl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
  184. $table->add_field('timelimit', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
  185. $table->add_field('delay3', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '-1');
  186. $table->add_field('clickreporting', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  187. $table->add_field('content', XMLDB_TYPE_TEXT, 'medium', null, XMLDB_NOTNULL);
  188. $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL);
  189. $table->add_field('md5key', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL);
  190. // Add keys to table hotpot_cache
  191. $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
  192. $table->add_key('hotpotid', XMLDB_KEY_FOREIGN, array('hotpotid'), 'hotpot', array('id'));
  193. // Add indexes to table hotpot_cache
  194. $table->add_index('hotpotid-md5key', XMLDB_INDEX_NOTUNIQUE, array('hotpotid', 'md5key'));
  195. $dbman->create_table($table);
  196. }
  197. // add new logging actions
  198. log_update_descriptions('mod/hotpot');
  199. // hotpot savepoint reached
  200. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  201. }
  202. $newversion = 2010080302;
  203. if ($oldversion < $newversion) {
  204. // navigation setting of "none" is now "0" (was "6")
  205. $DB->execute('UPDATE {hotpot} SET navigation=0 WHERE navigation=6');
  206. // navigation's "give up" button, is replaced by the "stopbutton" field
  207. $DB->execute('UPDATE {hotpot} SET stopbutton=0 WHERE navigation=5');
  208. $DB->execute('UPDATE {hotpot} SET navigation=0 WHERE navigation=5');
  209. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  210. }
  211. $newversion = 2010080303;
  212. if ($oldversion < $newversion) {
  213. // modify table: hotpot_attempts
  214. $table = new xmldb_table('hotpot_attempts');
  215. // add field: timemodified
  216. $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  217. if (! $dbman->field_exists($table, $field)) {
  218. $dbman->add_field($table, $field);
  219. $DB->execute('UPDATE {hotpot_attempts} SET timemodified = timefinish WHERE timemodified=0');
  220. $DB->execute('UPDATE {hotpot_attempts} SET timemodified = timestart WHERE timemodified=0');
  221. }
  222. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  223. }
  224. $newversion = 2010080305;
  225. if ($oldversion < $newversion) {
  226. // modify table: hotpot
  227. $table = new xmldb_table('hotpot');
  228. // change fields
  229. // - entrycm (-> signed)
  230. // - outputformat (-> varchar)
  231. // - timelimit (-> signed)
  232. // - delay3 (-> signed)
  233. // - attemptlimit (-> unsigned)
  234. // - gradeweighting (-> unsigned)
  235. // - grademethod (-> unsigned)
  236. $fields = array(
  237. new xmldb_field('entrycm', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'),
  238. new xmldb_field('outputformat', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL),
  239. new xmldb_field('timelimit', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'),
  240. new xmldb_field('delay3', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2'),
  241. new xmldb_field('attemptlimit', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'),
  242. new xmldb_field('gradeweighting', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'),
  243. new xmldb_field('grademethod', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0')
  244. );
  245. foreach ($fields as $field) {
  246. if ($dbman->field_exists($table, $field)) {
  247. xmldb_hotpot_fix_previous_field($dbman, $table, $field);
  248. $dbman->change_field_type($table, $field);
  249. }
  250. }
  251. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  252. }
  253. $newversion = 2010080306;
  254. if ($oldversion < $newversion) {
  255. // modify table: hotpot
  256. $table = new xmldb_table('hotpot');
  257. // rename field: gradelimit -> gradeweighting
  258. $field = new xmldb_field('gradelimit', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  259. if ($dbman->field_exists($table, $field)) {
  260. $dbman->rename_field($table, $field, 'gradeweighting');
  261. }
  262. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  263. }
  264. $newversion = 2010080308;
  265. if ($oldversion < $newversion) {
  266. // add display fields to hotpot
  267. // (these fields were missing from access.xml so won't be on new sites)
  268. $tables = array(
  269. 'hotpot' => array(
  270. new xmldb_field('title', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '3', 'navigation'),
  271. new xmldb_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'title'),
  272. new xmldb_field('stoptext', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'stopbutton'),
  273. new xmldb_field('usefilters', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'stoptext'),
  274. new xmldb_field('useglossary', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'usefilters'),
  275. new xmldb_field('usemediafilter', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'useglossary'),
  276. )
  277. );
  278. foreach ($tables as $tablename => $fields) {
  279. $table = new xmldb_table($tablename);
  280. foreach ($fields as $field) {
  281. xmldb_hotpot_fix_previous_field($dbman, $table, $field);
  282. if ($dbman->field_exists($table, $field)) {
  283. $dbman->change_field_type($table, $field);
  284. } else {
  285. $dbman->add_field($table, $field);
  286. }
  287. }
  288. }
  289. $table = new xmldb_table('hotpot');
  290. $field = new xmldb_field('forceplugins', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
  291. if ($dbman->field_exists($table, $field)) {
  292. $DB->execute('UPDATE {hotpot} SET '."usemediafilter='moodle'".' WHERE forceplugins=1');
  293. $dbman->drop_field($table, $field);
  294. }
  295. // force certain fields to be not null
  296. $tables = array(
  297. 'hotpot' => array(
  298. new xmldb_field('entrygrade', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '100')
  299. ),
  300. 'hotpot_cache' => array(
  301. new xmldb_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'),
  302. new xmldb_field('usefilters', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'),
  303. new xmldb_field('useglossary', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'),
  304. new xmldb_field('studentfeedback', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'),
  305. )
  306. );
  307. foreach ($tables as $tablename => $fields) {
  308. $table = new xmldb_table($tablename);
  309. foreach ($fields as $field) {
  310. if ($dbman->field_exists($table, $field)) {
  311. $dbman->change_field_type($table, $field);
  312. }
  313. }
  314. }
  315. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  316. }
  317. $newversion = 2010080309;
  318. if ($oldversion < $newversion) {
  319. // force certain text fields to be not null
  320. $tables = array(
  321. 'hotpot' => array(
  322. new xmldb_field('sourcefile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL),
  323. new xmldb_field('entrytext', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL),
  324. new xmldb_field('exittext', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL),
  325. new xmldb_field('stoptext', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL)
  326. )
  327. );
  328. foreach ($tables as $tablename => $fields) {
  329. $table = new xmldb_table($tablename);
  330. foreach ($fields as $field) {
  331. if ($dbman->field_exists($table, $field)) {
  332. $fieldname = $field->getName();
  333. $DB->set_field_select($tablename, $fieldname, '', "$fieldname IS NULL");
  334. $dbman->change_field_type($table, $field);
  335. }
  336. }
  337. }
  338. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  339. }
  340. $newversion = 2010080311;
  341. if ($oldversion < $newversion) {
  342. require_once($CFG->dirroot.'/mod/hotpot/locallib.php');
  343. /////////////////////////////////////
  344. /// new file storage migrate code ///
  345. /////////////////////////////////////
  346. // set up sql strings to select HotPots with Moodle 1.x file paths (i.e. no leading slash)
  347. $strupdating = get_string('migratingfiles', 'hotpot');
  348. $select = 'h.*, cm.id AS cmid';
  349. $from = '{hotpot} h, {course_modules} cm, {modules} m';
  350. $where = 'm.name=? AND m.id=cm.module AND cm.instance=h.id AND h.sourcefile<>?'.
  351. ' AND '.$DB->sql_like('h.sourcefile', '?', false, false, true); // NOT LIKE
  352. $params = array('hotpot', '', '/%', 0);
  353. $orderby = 'h.course, h.id';
  354. // get HotPot records to update
  355. if ($count = $DB->count_records_sql("SELECT COUNT('x') FROM $from WHERE $where", $params)) {
  356. $rs = $DB->get_recordset_sql("SELECT $select FROM $from WHERE $where ORDER BY $orderby", $params);
  357. } else {
  358. $rs = false;
  359. }
  360. // loop through HotPot records that need to be updated
  361. if ($rs) {
  362. $i = 0;
  363. $bar = new progress_bar('hotpotmigratefiles', 500, true);
  364. // get file storage object
  365. $fs = get_file_storage();
  366. $coursecontext = null;
  367. foreach ($rs as $hotpot) {
  368. // apply for more script execution time (3 mins)
  369. upgrade_set_timeout();
  370. // set $courseid from $hotpot->sourcelocation
  371. // 0 : HOTPOT_LOCATION_COURSEFILES
  372. // 1 : HOTPOT_LOCATION_SITEFILES
  373. // 2 : HOTPOT_LOCATION_WWW (not used)
  374. if ($hotpot->sourcelocation) {
  375. $courseid = SITEID;
  376. } else {
  377. $courseid = $hotpot->course;
  378. }
  379. // get course context (only if we need to)
  380. if (is_null($coursecontext) || $coursecontext->instanceid != $courseid) {
  381. $coursecontext = get_context_instance(CONTEXT_COURSE, $courseid);
  382. }
  383. // actually there shouldn't be any urls in HotPot activities,
  384. // but this code will also be used to convert QuizPort to TaskChain
  385. if (preg_match('/^https?:\/\//i', $hotpot->sourcefile)) {
  386. $url = $hotpot->sourcefile;
  387. $path = parse_url($url, PHP_URL_PATH);
  388. } else {
  389. $url = '';
  390. $path = $hotpot->sourcefile;
  391. }
  392. $path = clean_param($path, PARAM_PATH);
  393. // this information should be enough to access the file
  394. // if it has been migrated into Moodle 2.0 file system
  395. $filename = basename($path);
  396. $filepath = dirname($path);
  397. if ($filepath=='.' || $filepath=='') {
  398. $filepath = '/';
  399. } else {
  400. $filepath = '/'.ltrim($filepath, '/'); // require leading slash
  401. $filepath = rtrim($filepath, '/').'/'; // require trailing slash
  402. }
  403. $filehash = sha1('/'.$coursecontext->id.'/course/legacy/0'.$filepath.$filename);
  404. // we might need the old file path, if the file has not been migrated
  405. $oldfilepath = $CFG->dataroot.'/'.$courseid.$filepath.$filename;
  406. // set parameters used to add file to filearea
  407. // (sortorder=1 siginifies the "mainfile" in this filearea)
  408. $context = get_context_instance(CONTEXT_MODULE, $hotpot->cmid);
  409. $file_record = array(
  410. 'contextid'=>$context->id, 'component'=>'mod_hotpot', 'filearea'=>'sourcefile',
  411. 'sortorder'=>1, 'itemid'=>0, 'filepath'=>$filepath, 'filename'=>$filename
  412. );
  413. // initialize sourcefile settings
  414. $hotpot->sourcefile = $filepath.$filename;
  415. $hotpot->sourcetype = '';
  416. $hotpot->sourceitemid = 0;
  417. if ($file = $fs->get_file($context->id, 'mod_hotpot', 'sourcefile', 0, $filepath, $filename)) {
  418. // file already exists for this context - shouldn't happen !!
  419. // maybe an earlier upgrade failed for some reason ?
  420. // anyway we must do this check, so that create_file_from_xxx() does not abort
  421. } else if ($url) {
  422. // file is on an external url - unusual ?!
  423. $file = false; // $fs->create_file_from_url($file_record, $url);
  424. } else if ($file = $fs->get_file_by_hash($filehash)) {
  425. // $file has already been migrated to Moodle's file system
  426. // this is the route we expect most people to come :-)
  427. $file = $fs->create_file_from_storedfile($file_record, $file);
  428. } else if (file_exists($oldfilepath)) {
  429. // $file still exists on server's filesystem - unusual ?!
  430. $file = $fs->create_file_from_pathname($file_record, $oldfilepath);
  431. } else {
  432. // file was not migrated and is not on server's filesystem
  433. $file = false;
  434. }
  435. // if source file did not exist, notify user of the problem
  436. if (empty($file)) {
  437. if ($url) {
  438. $msg = "course_modules.id=$hotpot->cmid, url=$url";
  439. } else {
  440. $msg = "course_modules.id=$hotpot->cmid, path=$path";
  441. }
  442. $params = array('update'=>$hotpot->cmid, 'onclick'=>'this.target="_blank"');
  443. $msg = html_writer::link(new moodle_url('/course/modedit.php', $params), $msg);
  444. $msg = get_string('sourcefilenotfound', 'hotpot', $msg);
  445. echo html_writer::tag('div', $msg, array('class'=>'notifyproblem'));
  446. }
  447. // set $hotpot->sourcetype
  448. if ($pos = strrpos($hotpot->sourcefile, '.')) {
  449. $filetype = substr($hotpot->sourcefile, $pos+1);
  450. switch ($filetype) {
  451. case 'jcl': $hotpot->sourcetype = 'hp_6_jcloze_xml'; break;
  452. case 'jcw': $hotpot->sourcetype = 'hp_6_jcross_xml'; break;
  453. case 'jmt': $hotpot->sourcetype = 'hp_6_jmatch_xml'; break;
  454. case 'jmx': $hotpot->sourcetype = 'hp_6_jmix_xml'; break;
  455. case 'jqz': $hotpot->sourcetype = 'hp_6_jquiz_xml'; break;
  456. case 'rhb': $hotpot->sourcetype = 'hp_6_rhubarb_xml'; break;
  457. case 'sqt': $hotpot->sourcetype = 'hp_6_sequitur_xml'; break;
  458. case 'htm':
  459. case 'html':
  460. default:
  461. if ($file) {
  462. $pathnamehash = $fs->get_pathname_hash($context->id, 'mod_hotpot', 'sourcefile', 0, $filepath, $filename);
  463. if ($contenthash = $DB->get_field('files', 'contenthash', array('pathnamehash'=>$pathnamehash))) {
  464. $l1 = $contenthash[0].$contenthash[1];
  465. $l2 = $contenthash[2].$contenthash[3];
  466. if (file_exists("$CFG->dataroot/filedir/$l1/$l2/$contenthash")) {
  467. $hotpot->sourcetype = hotpot::get_sourcetype($file);
  468. } else {
  469. $msg = html_writer::link(
  470. new moodle_url('/course/modedit.php', array('update'=>$hotpot->cmid)),
  471. "course_modules.id=$hotpot->cmid, path=$path"
  472. );
  473. $msg .= html_writer::empty_tag('br');
  474. $msg .= "filedir path=$l1/$l2/$contenthash";
  475. $msg = get_string('sourcefilenotfound', 'hotpot', $msg);
  476. echo html_writer::tag('div', $msg, array('class'=>'notifyproblem'));
  477. }
  478. }
  479. }
  480. }
  481. }
  482. // JMatch has 2 output formats
  483. // 14 : v6 : drop down menus : hp_6_jmatch_xml_v6
  484. // 15 : v6+ : drag-and-drop : hp_6_jmatch_xml_v6_plus
  485. // JMix has 2 output formats
  486. // 14 : v6 : links : hp_6_jmix_xml_v6
  487. // 15 : v6+ : drag-and-drop : hp_6_jmix_xml_v6_plus
  488. // since drag-and-drop is the "best" outputformat for both types of quiz,
  489. // we only need to worry about HotPots whose outputformat was 14 (="v6")
  490. // set $hotpot->outputformat
  491. if ($hotpot->outputformat==14 && ($hotpot->sourcetype=='hp_6_jmatch_xml' || $hotpot->sourcetype=='hp_6_jmix_xml')) {
  492. $hotpot->outputformat = $hotpot->sourcetype.'_v6';
  493. } else {
  494. $hotpot->outputformat = ''; // = "best" output format
  495. }
  496. $DB->update_record('hotpot', $hotpot);
  497. // update progress bar
  498. $i++;
  499. $bar->update($i, $count, $strupdating.": ($i/$count)");
  500. }
  501. $rs->close();
  502. }
  503. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  504. }
  505. $newversion = 2010080316;
  506. if ($oldversion < $newversion) {
  507. // because the HotPot activities were probably hidden until now
  508. // we need to reset the course caches (using "course/lib.php")
  509. require_once($CFG->dirroot.'/course/lib.php');
  510. $courseids = array();
  511. if ($hotpots = $DB->get_records('hotpot', null, '', 'id,course')) {
  512. foreach ($hotpots as $hotpot) {
  513. $courseids[$hotpot->course] = true;
  514. }
  515. $courseids = array_keys($courseids);
  516. }
  517. unset($hotpots, $hotpot);
  518. foreach ($courseids as $courseid) {
  519. rebuild_course_cache($courseid, true);
  520. }
  521. unset($courseids, $courseid);
  522. // reset theme cache to force inclusion of new hotpot css
  523. theme_reset_all_caches();
  524. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  525. }
  526. $newversion = 2010080325;
  527. if ($oldversion < $newversion) {
  528. $table = new xmldb_table('hotpot');
  529. $fieldnames = array('sourceitemid', 'configitemid');
  530. foreach ($fieldnames as $fieldname) {
  531. $field = new xmldb_field($fieldname);
  532. if ($dbman->field_exists($table, $field)) {
  533. $dbman->drop_field($table, $field);
  534. }
  535. }
  536. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  537. }
  538. $newversion = 2010080330;
  539. if ($oldversion < $newversion) {
  540. require_once($CFG->dirroot.'/mod/hotpot/lib.php');
  541. hotpot_refresh_events();
  542. }
  543. $newversion = 2010080333;
  544. if ($oldversion < $newversion) {
  545. update_capabilities('mod/hotpot');
  546. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  547. }
  548. $newversion = 2010080339;
  549. if ($oldversion < $newversion) {
  550. $table = new xmldb_table('hotpot');
  551. $field = new xmldb_field('exitgrade', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'exitcm');
  552. xmldb_hotpot_fix_previous_field($dbman, $table, $field);
  553. if (! $dbman->field_exists($table, $field)) {
  554. $dbman->add_field($table, $field);
  555. }
  556. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  557. }
  558. $newversion = 2010080340;
  559. if ($oldversion < $newversion) {
  560. // force all text fields to be long text, the default for Moodle 2.3 and later
  561. $tables = array(
  562. 'hotpot' => array(
  563. new xmldb_field('entrytext', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL),
  564. new xmldb_field('exittext', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)
  565. ),
  566. 'hotpot_cache' => array(
  567. new xmldb_field('content', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)
  568. ),
  569. 'hotpot_details' => array(
  570. new xmldb_field('details', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)
  571. ),
  572. 'hotpot_questions' => array(
  573. new xmldb_field('name', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)
  574. ),
  575. 'hotpot_strings' => array(
  576. new xmldb_field('string', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)
  577. )
  578. );
  579. foreach ($tables as $tablename => $fields) {
  580. $table = new xmldb_table($tablename);
  581. foreach ($fields as $field) {
  582. if ($dbman->field_exists($table, $field)) {
  583. $fieldname = $field->getName();
  584. $DB->set_field_select($tablename, $fieldname, '', "$fieldname IS NULL");
  585. $dbman->change_field_type($table, $field);
  586. }
  587. }
  588. }
  589. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  590. }
  591. $newversion = 2010080342;
  592. if ($oldversion < $newversion) {
  593. // force all MySQL integer fields to be signed, the default for Moodle 2.3 and later
  594. if ($DB->get_dbfamily() == 'mysql') {
  595. $prefix = $DB->get_prefix();
  596. $tables = $DB->get_tables();
  597. foreach ($tables as $table) {
  598. if (substr($table, 0, 6)=='hotpot') {
  599. $rs = $DB->get_recordset_sql("SHOW COLUMNS FROM {$CFG->prefix}$table WHERE type LIKE '%unsigned%'");
  600. foreach ($rs as $column) {
  601. // copied from as "lib/db/upgradelib.php"
  602. $type = preg_replace('/\s*unsigned/i', 'signed', $column->type);
  603. $notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
  604. $default = (is_null($column->default) || $column->default === '') ? '' : "DEFAULT '$column->default'";
  605. $autoinc = (stripos($column->extra, 'auto_increment') === false) ? '' : 'AUTO_INCREMENT';
  606. $sql = "ALTER TABLE `{$prefix}$table` MODIFY COLUMN `$column->field` $type $notnull $default $autoinc";
  607. $DB->change_database_structure($sql);
  608. }
  609. }
  610. }
  611. }
  612. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  613. }
  614. $newversion = 2010080352;
  615. if ($oldversion < $newversion) {
  616. $empty_cache = true;
  617. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  618. }
  619. $newversion = 2010080353;
  620. if ($oldversion < $newversion) {
  621. // remove any unwanted "course_files" folders that may have been created
  622. // when restoring Moodle 1.9 HotPot activities to a Moodle 2.x site
  623. // select all HotPot activities which have a "course_files" folder
  624. // but whose "sourcefile" path does not require such a folder
  625. $select = 'f.*,'.
  626. 'h.id AS hotpotid,'.
  627. 'h.sourcefile AS sourcefile';
  628. $from = '{hotpot} h,'.
  629. '{course_modules} cm,'.
  630. '{context} c,'.
  631. '{files} f';
  632. $where = $DB->sql_like('h.sourcefile', '?', false, false, true). // NOT LIKE
  633. ' AND h.id=cm.instance'.
  634. ' AND cm.id=c.instanceid'.
  635. ' AND c.id=f.contextid'.
  636. ' AND f.component=?'.
  637. ' AND f.filearea=?'.
  638. ' AND f.filepath=?'.
  639. ' AND f.filename=?';
  640. $params = array('/course_files/%', 'mod_hotpot', 'sourcefile', '/course_files/', '.');
  641. if ($filerecords = $DB->get_records_sql("SELECT $select FROM $from WHERE $where", $params)) {
  642. $fs = get_file_storage();
  643. foreach ($filerecords as $filerecord) {
  644. xmldb_hotpot_move_file($fs->get_file_instance($filerecord), '/');
  645. }
  646. }
  647. upgrade_mod_savepoint(true, "$newversion", 'hotpot');
  648. }
  649. if ($empty_cache) {
  650. $DB->delete_records('hotpot_cache');
  651. }
  652. return true;
  653. }
  654. /**
  655. * xmldb_hotpot_move_file
  656. *
  657. * move a file or folder (within the same context)
  658. * if $file is a directory, then all subfolders and files will also be moved
  659. * if the destination file/folder already exists, then $file will be deleted
  660. *
  661. * @param stored_file $file
  662. * @param string $new_filepath
  663. * @param string $new_filename (optional, default='')
  664. * @return void, but may update filearea
  665. */
  666. function xmldb_hotpot_move_file($file, $new_filepath, $new_filename='') {
  667. $fs = get_file_storage();
  668. $contextid = $file->get_contextid();
  669. $component = $file->get_component();
  670. $filearea = $file->get_filearea();
  671. $itemid = $file->get_itemid();
  672. $filepath = $file->get_filepath();
  673. $filename = $file->get_filename();
  674. if ($file->is_directory()) {
  675. $children = $fs->get_directory_files($contextid, $component, $filearea, $itemid, $filepath);
  676. $filepath = '/^'.preg_quote($filepath, '/').'/';
  677. foreach ($children as $child) {
  678. xmldb_hotpot_move_file($child, preg_replace($filepath, $new_filepath, $child->get_filepath(), 1));
  679. }
  680. }
  681. if ($new_filename=='') {
  682. $new_filename = $filename;
  683. }
  684. if ($fs->file_exists($contextid, $component, $filearea, $itemid, $new_filepath, $new_filename)) {
  685. $file->delete(); // new file already exists
  686. } else {
  687. $file->rename($new_filepath, $new_filename);
  688. }
  689. }
  690. /**
  691. * xmldb_hotpot_fix_previous_fields
  692. *
  693. * @param xxx $dbman
  694. * @param xmldb_table $table
  695. * @param array of xmldb_field $fields (passed by reference)
  696. * @return void, but may update some items in $fields array
  697. */
  698. function xmldb_hotpot_fix_previous_fields($dbman, $table, &$fields) {
  699. foreach ($fields as $i => $field) {
  700. xmldb_hotpot_fix_previous_field($dbman, $table, $fields[$i]);
  701. }
  702. }
  703. /**
  704. * xmldb_hotpot_fix_previous_field
  705. *
  706. * @param xxx $dbman
  707. * @param xmldb_table $table
  708. * @param xmldb_field $field (passed by reference)
  709. * @return void, but may update $field->previous
  710. */
  711. function xmldb_hotpot_fix_previous_field($dbman, $table, &$field) {
  712. $previous = $field->getPrevious();
  713. if (empty($previous) || $dbman->field_exists($table, $previous)) {
  714. // $previous field exists - do nothing
  715. } else {
  716. // $previous field does not exist, so remove it
  717. $field->setPrevious(null);
  718. }
  719. }