PageRenderTime 27ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/question/format/blackboard/format.php

https://github.com/iarenaza/moodle
PHP | 392 lines | 239 code | 98 blank | 55 comment | 50 complexity | 62ecf580c4343666e6c0684fecc4769c MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-3.0, Apache-2.0
  1. <?php
  2. ////////////////////////////////////////////////////////////////////////////
  3. /// Blackboard 6.0 Format
  4. ///
  5. /// This Moodle class provides all functions necessary to import and export
  6. ///
  7. ///
  8. ////////////////////////////////////////////////////////////////////////////
  9. // Based on default.php, included by ../import.php
  10. /**
  11. * @package questionbank
  12. * @subpackage importexport
  13. */
  14. require_once ("$CFG->libdir/xmlize.php");
  15. class qformat_blackboard extends qformat_default {
  16. function provide_import() {
  17. return true;
  18. }
  19. function readquestions ($lines) {
  20. /// Parses an array of lines into an array of questions,
  21. /// where each item is a question object as defined by
  22. /// readquestion().
  23. $text = implode($lines, " ");
  24. $xml = xmlize($text, 0);
  25. $questions = array();
  26. $this->process_tf($xml, $questions);
  27. $this->process_mc($xml, $questions);
  28. $this->process_ma($xml, $questions);
  29. $this->process_fib($xml, $questions);
  30. $this->process_matching($xml, $questions);
  31. $this->process_essay($xml, $questions);
  32. return $questions;
  33. }
  34. //----------------------------------------
  35. // Process Essay Questions
  36. //----------------------------------------
  37. function process_essay($xml, &$questions ) {
  38. if (isset($xml["POOL"]["#"]["QUESTION_ESSAY"])) {
  39. $essayquestions = $xml["POOL"]["#"]["QUESTION_ESSAY"];
  40. }
  41. else {
  42. return;
  43. }
  44. foreach ($essayquestions as $essayquestion) {
  45. $question = $this->defaultquestion();
  46. $question->qtype = ESSAY;
  47. // determine if the question is already escaped html
  48. $ishtml = $essayquestion["#"]["BODY"][0]["#"]["FLAGS"][0]["#"]["ISHTML"][0]["@"]["value"];
  49. // put questiontext in question object
  50. if ($ishtml) {
  51. $question->questiontext = html_entity_decode(trim($essayquestion["#"]["BODY"][0]["#"]["TEXT"][0]["#"]));
  52. }
  53. // put name in question object
  54. $question->name = substr($question->questiontext, 0, 254);
  55. $question->answer = '';
  56. $question->feedback = '';
  57. $question->fraction = 0;
  58. $questions[] = $question;
  59. }
  60. }
  61. //----------------------------------------
  62. // Process True / False Questions
  63. //----------------------------------------
  64. function process_tf($xml, &$questions) {
  65. if (isset($xml["POOL"]["#"]["QUESTION_TRUEFALSE"])) {
  66. $tfquestions = $xml["POOL"]["#"]["QUESTION_TRUEFALSE"];
  67. }
  68. else {
  69. return;
  70. }
  71. for ($i = 0; $i < sizeof ($tfquestions); $i++) {
  72. $question = $this->defaultquestion();
  73. $question->qtype = TRUEFALSE;
  74. $question->single = 1; // Only one answer is allowed
  75. $thisquestion = $tfquestions[$i];
  76. // determine if the question is already escaped html
  77. $ishtml = $thisquestion["#"]["BODY"][0]["#"]["FLAGS"][0]["#"]["ISHTML"][0]["@"]["value"];
  78. // put questiontext in question object
  79. if ($ishtml) {
  80. $question->questiontext = html_entity_decode(trim($thisquestion["#"]["BODY"][0]["#"]["TEXT"][0]["#"]),ENT_QUOTES,'UTF-8');
  81. }
  82. // put name in question object
  83. $question->name = shorten_text($question->questiontext, 254);
  84. $choices = $thisquestion["#"]["ANSWER"];
  85. $correct_answer = $thisquestion["#"]["GRADABLE"][0]["#"]["CORRECTANSWER"][0]["@"]["answer_id"];
  86. // first choice is true, second is false.
  87. $id = $choices[0]["@"]["id"];
  88. if (strcmp($id, $correct_answer) == 0) { // true is correct
  89. $question->answer = 1;
  90. $question->feedbacktrue = trim(@$thisquestion["#"]["GRADABLE"][0]["#"]["FEEDBACK_WHEN_CORRECT"][0]["#"]);
  91. $question->feedbackfalse = trim(@$thisquestion["#"]["GRADABLE"][0]["#"]["FEEDBACK_WHEN_INCORRECT"][0]["#"]);
  92. } else { // false is correct
  93. $question->answer = 0;
  94. $question->feedbacktrue = trim(@$thisquestion["#"]["GRADABLE"][0]["#"]["FEEDBACK_WHEN_INCORRECT"][0]["#"]);
  95. $question->feedbackfalse = trim(@$thisquestion["#"]["GRADABLE"][0]["#"]["FEEDBACK_WHEN_CORRECT"][0]["#"]);
  96. }
  97. $question->correctanswer = $question->answer;
  98. $questions[] = $question;
  99. }
  100. }
  101. //----------------------------------------
  102. // Process Multiple Choice Questions
  103. //----------------------------------------
  104. function process_mc($xml, &$questions) {
  105. if (isset($xml["POOL"]["#"]["QUESTION_MULTIPLECHOICE"])) {
  106. $mcquestions = $xml["POOL"]["#"]["QUESTION_MULTIPLECHOICE"];
  107. }
  108. else {
  109. return;
  110. }
  111. for ($i = 0; $i < sizeof ($mcquestions); $i++) {
  112. $question = $this->defaultquestion();
  113. $question->qtype = MULTICHOICE;
  114. $question->single = 1; // Only one answer is allowed
  115. $thisquestion = $mcquestions[$i];
  116. // determine if the question is already escaped html
  117. $ishtml = $thisquestion["#"]["BODY"][0]["#"]["FLAGS"][0]["#"]["ISHTML"][0]["@"]["value"];
  118. // put questiontext in question object
  119. if ($ishtml) {
  120. $question->questiontext = html_entity_decode(trim($thisquestion["#"]["BODY"][0]["#"]["TEXT"][0]["#"]),ENT_QUOTES,'UTF-8');
  121. }
  122. // put name of question in question object, careful of length
  123. $question->name = shorten_text($question->questiontext, 254);
  124. $choices = $thisquestion["#"]["ANSWER"];
  125. for ($j = 0; $j < sizeof ($choices); $j++) {
  126. $choice = trim($choices[$j]["#"]["TEXT"][0]["#"]);
  127. // put this choice in the question object.
  128. if ($ishtml) {
  129. $question->answer[$j] = html_entity_decode($choice,ENT_QUOTES,'UTF-8');
  130. }
  131. $question->answer[$j] = $question->answer[$j];
  132. $id = $choices[$j]["@"]["id"];
  133. $correct_answer_id = $thisquestion["#"]["GRADABLE"][0]["#"]["CORRECTANSWER"][0]["@"]["answer_id"];
  134. // if choice is the answer, give 100%, otherwise give 0%
  135. if (strcmp ($id, $correct_answer_id) == 0) {
  136. $question->fraction[$j] = 1;
  137. if ($ishtml) {
  138. $question->feedback[$j] = html_entity_decode(trim(@$thisquestion["#"]["GRADABLE"][0]["#"]["FEEDBACK_WHEN_CORRECT"][0]["#"]),ENT_QUOTES,'UTF-8');
  139. }
  140. $question->feedback[$j] = $question->feedback[$j];
  141. } else {
  142. $question->fraction[$j] = 0;
  143. if ($ishtml) {
  144. $question->feedback[$j] = html_entity_decode(trim(@$thisquestion["#"]["GRADABLE"][0]["#"]["FEEDBACK_WHEN_INCORRECT"][0]["#"]),ENT_QUOTES,'UTF-8');
  145. }
  146. $question->feedback[$j] = $question->feedback[$j];
  147. }
  148. }
  149. $questions[] = $question;
  150. }
  151. }
  152. //----------------------------------------
  153. // Process Multiple Choice Questions With Multiple Answers
  154. //----------------------------------------
  155. function process_ma($xml, &$questions) {
  156. if (isset($xml["POOL"]["#"]["QUESTION_MULTIPLEANSWER"])) {
  157. $maquestions = $xml["POOL"]["#"]["QUESTION_MULTIPLEANSWER"];
  158. }
  159. else {
  160. return;
  161. }
  162. for ($i = 0; $i < sizeof ($maquestions); $i++) {
  163. $question = $this->defaultquestion();
  164. $question->qtype = MULTICHOICE;
  165. $question->defaultgrade = 1;
  166. $question->single = 0; // More than one answers allowed
  167. $question->image = ""; // No images with this format
  168. $thisquestion = $maquestions[$i];
  169. // determine if the question is already escaped html
  170. $ishtml = $thisquestion["#"]["BODY"][0]["#"]["FLAGS"][0]["#"]["ISHTML"][0]["@"]["value"];
  171. // put questiontext in question object
  172. if ($ishtml) {
  173. $question->questiontext = html_entity_decode(trim($thisquestion["#"]["BODY"][0]["#"]["TEXT"][0]["#"]),ENT_QUOTES,'UTF-8');
  174. }
  175. // put name of question in question object
  176. $question->name = shorten_text($question->questiontext, 254);
  177. $choices = $thisquestion["#"]["ANSWER"];
  178. $correctanswers = $thisquestion["#"]["GRADABLE"][0]["#"]["CORRECTANSWER"];
  179. for ($j = 0; $j < sizeof ($choices); $j++) {
  180. $choice = trim($choices[$j]["#"]["TEXT"][0]["#"]);
  181. // put this choice in the question object.
  182. $question->answer[$j] = $choice;
  183. $correctanswercount = sizeof($correctanswers);
  184. $id = $choices[$j]["@"]["id"];
  185. $iscorrect = 0;
  186. for ($k = 0; $k < $correctanswercount; $k++) {
  187. $correct_answer_id = trim($correctanswers[$k]["@"]["answer_id"]);
  188. if (strcmp ($id, $correct_answer_id) == 0) {
  189. $iscorrect = 1;
  190. }
  191. }
  192. if ($iscorrect) {
  193. $question->fraction[$j] = floor(100000/$correctanswercount)/100000; // strange behavior if we have more than 5 decimal places
  194. $question->feedback[$j] = trim($thisquestion["#"]["GRADABLE"][$j]["#"]["FEEDBACK_WHEN_CORRECT"][0]["#"]);
  195. } else {
  196. $question->fraction[$j] = 0;
  197. $question->feedback[$j] = trim($thisquestion["#"]["GRADABLE"][$j]["#"]["FEEDBACK_WHEN_INCORRECT"][0]["#"]);
  198. }
  199. }
  200. $questions[] = $question;
  201. }
  202. }
  203. //----------------------------------------
  204. // Process Fill in the Blank Questions
  205. //----------------------------------------
  206. function process_fib($xml, &$questions) {
  207. if (isset($xml["POOL"]["#"]["QUESTION_FILLINBLANK"])) {
  208. $fibquestions = $xml["POOL"]["#"]["QUESTION_FILLINBLANK"];
  209. }
  210. else {
  211. return;
  212. }
  213. for ($i = 0; $i < sizeof ($fibquestions); $i++) {
  214. $question = $this->defaultquestion();
  215. $question->qtype = SHORTANSWER;
  216. $question->usecase = 0; // Ignore case
  217. $thisquestion = $fibquestions[$i];
  218. // determine if the question is already escaped html
  219. $ishtml = $thisquestion["#"]["BODY"][0]["#"]["FLAGS"][0]["#"]["ISHTML"][0]["@"]["value"];
  220. // put questiontext in question object
  221. if ($ishtml) {
  222. $question->questiontext = html_entity_decode(trim($thisquestion["#"]["BODY"][0]["#"]["TEXT"][0]["#"]),ENT_QUOTES,'UTF-8');
  223. }
  224. // put name of question in question object
  225. $question->name = shorten_text($question->questiontext, 254);
  226. $answer = trim($thisquestion["#"]["ANSWER"][0]["#"]["TEXT"][0]["#"]);
  227. $question->answer[] = $answer;
  228. $question->fraction[] = 1;
  229. $question->feedback = array();
  230. if (is_array( $thisquestion['#']['GRADABLE'][0]['#'] )) {
  231. $question->feedback[0] = trim($thisquestion["#"]["GRADABLE"][0]["#"]["FEEDBACK_WHEN_CORRECT"][0]["#"]);
  232. }
  233. else {
  234. $question->feedback[0] = '';
  235. }
  236. if (is_array( $thisquestion["#"]["GRADABLE"][0]["#"] )) {
  237. $question->feedback[1] = trim($thisquestion["#"]["GRADABLE"][0]["#"]["FEEDBACK_WHEN_INCORRECT"][0]["#"]);
  238. }
  239. else {
  240. $question->feedback[1] = '';
  241. }
  242. $questions[] = $question;
  243. }
  244. }
  245. //----------------------------------------
  246. // Process Matching Questions
  247. //----------------------------------------
  248. function process_matching($xml, &$questions) {
  249. if (isset($xml["POOL"]["#"]["QUESTION_MATCH"])) {
  250. $matchquestions = $xml["POOL"]["#"]["QUESTION_MATCH"];
  251. }
  252. else {
  253. return;
  254. }
  255. for ($i = 0; $i < sizeof ($matchquestions); $i++) {
  256. $question = $this->defaultquestion();
  257. $question->qtype = MATCH;
  258. $thisquestion = $matchquestions[$i];
  259. // determine if the question is already escaped html
  260. $ishtml = $thisquestion["#"]["BODY"][0]["#"]["FLAGS"][0]["#"]["ISHTML"][0]["@"]["value"];
  261. // put questiontext in question object
  262. if ($ishtml) {
  263. $question->questiontext = html_entity_decode(trim($thisquestion["#"]["BODY"][0]["#"]["TEXT"][0]["#"]),ENT_QUOTES,'UTF-8');
  264. }
  265. // put name of question in question object
  266. $question->name = shorten_text($question->questiontext, 254);
  267. $choices = $thisquestion["#"]["CHOICE"];
  268. for ($j = 0; $j < sizeof ($choices); $j++) {
  269. $subquestion = NULL;
  270. $choice = $choices[$j]["#"]["TEXT"][0]["#"];
  271. $choice_id = $choices[$j]["@"]["id"];
  272. $question->subanswers[] = trim($choice);
  273. $correctanswers = $thisquestion["#"]["GRADABLE"][0]["#"]["CORRECTANSWER"];
  274. for ($k = 0; $k < sizeof ($correctanswers); $k++) {
  275. if (strcmp($choice_id, $correctanswers[$k]["@"]["choice_id"]) == 0) {
  276. $answer_id = $correctanswers[$k]["@"]["answer_id"];
  277. $answers = $thisquestion["#"]["ANSWER"];
  278. for ($m = 0; $m < sizeof ($answers); $m++) {
  279. $answer = $answers[$m];
  280. $current_ans_id = $answer["@"]["id"];
  281. if (strcmp ($current_ans_id, $answer_id) == 0) {
  282. $answer = $answer["#"]["TEXT"][0]["#"];
  283. $question->subquestions[] = trim($answer);
  284. break;
  285. }
  286. }
  287. break;
  288. }
  289. }
  290. }
  291. $questions[] = $question;
  292. }
  293. }
  294. }