answer.class.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CourseBundle\Entity\CQuizAnswer;
  4. /**
  5. * Class Answer
  6. * Allows to instantiate an object of type Answer
  7. * 5 arrays are created to receive the attributes of each answer belonging to a specified question
  8. * @package chamilo.exercise
  9. *
  10. * @author Olivier Brouckaert
  11. */
  12. class Answer
  13. {
  14. public $questionId;
  15. // these are arrays
  16. public $answer;
  17. public $correct;
  18. public $comment;
  19. public $weighting;
  20. public $position;
  21. public $hotspot_coordinates;
  22. public $hotspot_type;
  23. public $destination;
  24. // these arrays are used to save temporarily new answers
  25. // then they are moved into the arrays above or deleted in the event of cancellation
  26. public $new_answer;
  27. public $new_correct;
  28. public $new_comment;
  29. public $new_weighting;
  30. public $new_position;
  31. public $new_hotspot_coordinates;
  32. public $new_hotspot_type;
  33. public $autoId;
  34. public $nbrAnswers;
  35. public $new_nbrAnswers;
  36. public $new_destination; // id of the next question if feedback option is set to Directfeedback
  37. public $course; //Course information
  38. public $iid;
  39. public $questionJSId;
  40. public $standalone;
  41. /**
  42. * constructor of the class
  43. *
  44. * @author Olivier Brouckaert
  45. * @param int $questionId that answers belong to
  46. * @param int $course_id
  47. */
  48. public function __construct($questionId, $course_id = null)
  49. {
  50. $this->questionId = intval($questionId);
  51. $this->answer = array();
  52. $this->correct = array();
  53. $this->comment = array();
  54. $this->weighting = array();
  55. $this->position = array();
  56. $this->hotspot_coordinates = array();
  57. $this->hotspot_type = array();
  58. $this->destination = array();
  59. // clears $new_* arrays
  60. $this->cancel();
  61. if (!empty($course_id)) {
  62. $courseInfo = api_get_course_info_by_id($course_id);
  63. } else {
  64. $courseInfo = api_get_course_info();
  65. }
  66. $this->course = $courseInfo;
  67. $this->course_id = $courseInfo['real_id'];
  68. // fills arrays
  69. $objExercise = new Exercise($this->course_id);
  70. $exerciseId = isset($_REQUEST['exerciseId']) ? $_REQUEST['exerciseId'] : null;
  71. $objExercise->read($exerciseId);
  72. if ($objExercise->random_answers == '1' && $this->getQuestionType() != CALCULATED_ANSWER) {
  73. $this->readOrderedBy('rand()', '');// randomize answers
  74. } else {
  75. $this->read(); // natural order
  76. }
  77. }
  78. /**
  79. * Clears $new_* arrays
  80. *
  81. * @author Olivier Brouckaert
  82. */
  83. public function cancel()
  84. {
  85. $this->new_answer = array();
  86. $this->new_correct = array();
  87. $this->new_comment = array();
  88. $this->new_weighting = array();
  89. $this->new_position = array();
  90. $this->new_hotspot_coordinates = array();
  91. $this->new_hotspot_type = array();
  92. $this->new_nbrAnswers = 0;
  93. $this->new_destination = array();
  94. }
  95. /**
  96. * Reads answer information from the database
  97. *
  98. * @author Olivier Brouckaert
  99. */
  100. public function read()
  101. {
  102. $TBL_ANSWER = Database::get_course_table(TABLE_QUIZ_ANSWER);
  103. $questionId = $this->questionId;
  104. $sql = "SELECT * FROM $TBL_ANSWER
  105. WHERE
  106. c_id = {$this->course_id} AND
  107. question_id ='".$questionId."'
  108. ORDER BY position";
  109. $result = Database::query($sql);
  110. $i=1;
  111. // while a record is found
  112. while ($object = Database::fetch_object($result)) {
  113. $this->id[$i] = $object->id;
  114. $this->answer[$i] = $object->answer;
  115. $this->correct[$i] = $object->correct;
  116. $this->comment[$i] = $object->comment;
  117. $this->weighting[$i] = $object->ponderation;
  118. $this->position[$i] = $object->position;
  119. $this->hotspot_coordinates[$i] = $object->hotspot_coordinates;
  120. $this->hotspot_type[$i] = $object->hotspot_type;
  121. $this->destination[$i] = $object->destination;
  122. $this->autoId[$i] = $object->id_auto;
  123. $this->iid[$i] = $object->iid;
  124. $i++;
  125. }
  126. $this->nbrAnswers = $i-1;
  127. }
  128. /**
  129. * @param int $id
  130. *
  131. * @return array
  132. */
  133. public function getAnswerByAutoId($id)
  134. {
  135. foreach ($this->autoId as $key => $autoId) {
  136. if ($autoId == $id) {
  137. $result = [
  138. 'answer' => $this->answer[$key],
  139. 'correct' => $this->correct[$key],
  140. 'comment' => $this->comment[$key],
  141. ];
  142. return $result;
  143. }
  144. }
  145. return [];
  146. }
  147. /**
  148. * returns all answer ids from this question Id
  149. *
  150. * @author Yoselyn Castillo
  151. * @return array - $id (answer ids)
  152. */
  153. public function selectAnswerId()
  154. {
  155. $TBL_ANSWER = Database::get_course_table(TABLE_QUIZ_ANSWER);
  156. $questionId = $this->questionId;
  157. $sql="SELECT id FROM
  158. $TBL_ANSWER
  159. WHERE c_id = {$this->course_id} AND question_id ='".$questionId."'";
  160. $result = Database::query($sql);
  161. $id = array();
  162. // while a record is found
  163. if (Database::num_rows($result) > 0) {
  164. while ($object = Database::fetch_array($result)) {
  165. $id[] = $object['id'];
  166. }
  167. }
  168. return $id;
  169. }
  170. /**
  171. * Reads answer information from the data base ordered by parameter
  172. * @param string Field we want to order by
  173. * @param string DESC or ASC
  174. * @param string $field
  175. * @author Frederic Vauthier
  176. */
  177. public function readOrderedBy($field, $order='ASC')
  178. {
  179. $field = Database::escape_string($field);
  180. if (empty($field)) {
  181. $field = 'position';
  182. }
  183. if ($order != 'ASC' && $order!='DESC') {
  184. $order = 'ASC';
  185. }
  186. $TBL_ANSWER = Database::get_course_table(TABLE_QUIZ_ANSWER);
  187. $TBL_QUIZ = Database::get_course_table(TABLE_QUIZ_QUESTION);
  188. $questionId = intval($this->questionId);
  189. $sql = "SELECT type FROM $TBL_QUIZ
  190. WHERE c_id = {$this->course_id} AND id = $questionId";
  191. $result_question = Database::query($sql);
  192. $questionType = Database::fetch_array($result_question);
  193. if ($questionType['type'] == DRAGGABLE) {
  194. // Random is done by submit.js.tpl
  195. $this->read();
  196. return true;
  197. }
  198. $sql = "SELECT
  199. answer,
  200. correct,
  201. comment,
  202. ponderation,
  203. position,
  204. hotspot_coordinates,
  205. hotspot_type,
  206. destination,
  207. id_auto,
  208. iid
  209. FROM $TBL_ANSWER
  210. WHERE
  211. c_id = {$this->course_id} AND
  212. question_id='".$questionId."'
  213. ORDER BY $field $order";
  214. $result=Database::query($sql);
  215. $i = 1;
  216. // while a record is found
  217. $doubt_data = null;
  218. while ($object = Database::fetch_object($result)) {
  219. if ($questionType['type'] == UNIQUE_ANSWER_NO_OPTION && $object->position == 666) {
  220. $doubt_data = $object;
  221. continue;
  222. }
  223. $this->answer[$i] = $object->answer;
  224. $this->correct[$i] = $object->correct;
  225. $this->comment[$i] = $object->comment;
  226. $this->weighting[$i] = $object->ponderation;
  227. $this->position[$i] = $object->position;
  228. $this->hotspot_coordinates[$i] = $object->hotspot_coordinates;
  229. $this->hotspot_type[$i] = $object->hotspot_type;
  230. $this->destination[$i] = $object->destination;
  231. $this->autoId[$i] = $object->id_auto;
  232. $this->iid[$i] = $object->iid;
  233. $i++;
  234. }
  235. if ($questionType['type'] == UNIQUE_ANSWER_NO_OPTION && !empty($doubt_data)) {
  236. $this->answer[$i] = $doubt_data->answer;
  237. $this->correct[$i] = $doubt_data->correct;
  238. $this->comment[$i] = $doubt_data->comment;
  239. $this->weighting[$i] = $doubt_data->ponderation;
  240. $this->position[$i] = $doubt_data->position;
  241. $this->hotspot_coordinates[$i] = isset($object->hotspot_coordinates) ? $object->hotspot_coordinates : 0;
  242. $this->hotspot_type[$i] = isset($object->hotspot_type) ? $object->hotspot_type : 0;
  243. $this->destination[$i] = $doubt_data->destination;
  244. $this->autoId[$i] = $doubt_data->id_auto;
  245. $this->iid[$i] = $doubt_data->iid;
  246. $i++;
  247. }
  248. $this->nbrAnswers = $i-1;
  249. }
  250. /**
  251. * returns the autoincrement id identificator
  252. *
  253. * @author Juan Carlos Ra�a
  254. * @return integer - answer num
  255. */
  256. public function selectAutoId($id)
  257. {
  258. return isset($this->autoId[$id]) ? $this->autoId[$id] : 0;
  259. }
  260. /**
  261. * returns the number of answers in this question
  262. *
  263. * @author Olivier Brouckaert
  264. * @return integer - number of answers
  265. */
  266. public function selectNbrAnswers()
  267. {
  268. return $this->nbrAnswers;
  269. }
  270. /**
  271. * returns the question ID which the answers belong to
  272. *
  273. * @author Olivier Brouckaert
  274. * @return integer - the question ID
  275. */
  276. public function selectQuestionId()
  277. {
  278. return $this->questionId;
  279. }
  280. /**
  281. * returns the question ID of the destination question
  282. *
  283. * @author Julio Montoya
  284. * @param integer $id
  285. * @return integer - the question ID
  286. */
  287. public function selectDestination($id)
  288. {
  289. return isset($this->destination[$id]) ? $this->destination[$id] : null;
  290. }
  291. /**
  292. * returns the answer title
  293. *
  294. * @author Olivier Brouckaert
  295. * @param - integer $id - answer ID
  296. * @return string - answer title
  297. */
  298. public function selectAnswer($id)
  299. {
  300. return isset($this->answer[$id]) ? $this->answer[$id] : null;
  301. }
  302. /**
  303. * return array answer by id else return a bool
  304. * @param integer $auto_id
  305. */
  306. public function selectAnswerByAutoId($auto_id)
  307. {
  308. $TBL_ANSWER = Database::get_course_table(TABLE_QUIZ_ANSWER);
  309. $auto_id = intval($auto_id);
  310. $sql = "SELECT id, answer, id_auto FROM $TBL_ANSWER
  311. WHERE c_id = {$this->course_id} AND id_auto='$auto_id'";
  312. $rs = Database::query($sql);
  313. if (Database::num_rows($rs) > 0) {
  314. $row = Database::fetch_array($rs, 'ASSOC');
  315. return $row;
  316. }
  317. return false;
  318. }
  319. /**
  320. * returns the answer title from an answer's position
  321. *
  322. * @author Yannick Warnier
  323. * @param - integer $id - answer ID
  324. * @return bool - answer title
  325. */
  326. public function selectAnswerIdByPosition($pos)
  327. {
  328. foreach ($this->position as $k => $v) {
  329. if ($v != $pos) {
  330. continue;
  331. }
  332. return $k;
  333. }
  334. return false;
  335. }
  336. /**
  337. * Returns a list of answers
  338. * @author Yannick Warnier <ywarnier@beeznest.org>
  339. * @return array List of answers where each answer is an array
  340. * of (id, answer, comment, grade) and grade=weighting
  341. */
  342. public function getAnswersList($decode = false)
  343. {
  344. $list = array();
  345. for ($i = 1; $i <= $this->nbrAnswers; $i++) {
  346. if (!empty($this->answer[$i])) {
  347. //Avoid problems when parsing elements with accents
  348. if ($decode) {
  349. $this->answer[$i] = api_html_entity_decode($this->answer[$i], ENT_QUOTES, api_get_system_encoding());
  350. $this->comment[$i] = api_html_entity_decode($this->comment[$i], ENT_QUOTES, api_get_system_encoding());
  351. }
  352. $list[] = array(
  353. 'id' => $i,
  354. 'answer' => $this->answer[$i],
  355. 'comment' => $this->comment[$i],
  356. 'grade' => $this->weighting[$i],
  357. 'hotspot_coord' => $this->hotspot_coordinates[$i],
  358. 'hotspot_type' => $this->hotspot_type[$i],
  359. 'correct' => $this->correct[$i],
  360. 'destination' => $this->destination[$i]
  361. );
  362. }
  363. }
  364. return $list;
  365. }
  366. /**
  367. * Returns a list of grades
  368. * @author Yannick Warnier <ywarnier@beeznest.org>
  369. * @return array List of grades where grade=weighting (?)
  370. */
  371. public function getGradesList()
  372. {
  373. $list = array();
  374. for ($i = 0; $i<$this->nbrAnswers;$i++){
  375. if(!empty($this->answer[$i])){
  376. $list[$i] = $this->weighting[$i];
  377. }
  378. }
  379. return $list;
  380. }
  381. /**
  382. * Returns the question type
  383. * @author Yannick Warnier <ywarnier@beeznest.org>
  384. * @return integer The type of the question this answer is bound to
  385. */
  386. public function getQuestionType()
  387. {
  388. $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
  389. $sql = "SELECT type FROM $TBL_QUESTIONS
  390. WHERE c_id = {$this->course_id} AND id = '".$this->questionId."'";
  391. $res = Database::query($sql);
  392. if (Database::num_rows($res)<=0){
  393. return null;
  394. }
  395. $row = Database::fetch_array($res);
  396. return $row['type'];
  397. }
  398. /**
  399. * tells if answer is correct or not
  400. *
  401. * @author Olivier Brouckaert
  402. * @param - integer $id - answer ID
  403. * @return integer - 0 if bad answer, not 0 if good answer
  404. */
  405. public function isCorrect($id)
  406. {
  407. return isset($this->correct[$id]) ? $this->correct[$id] : null;
  408. }
  409. /**
  410. * returns answer comment
  411. *
  412. * @author Olivier Brouckaert
  413. * @param - integer $id - answer ID
  414. * @return string - answer comment
  415. */
  416. public function selectComment($id)
  417. {
  418. return isset($this->comment[$id]) ? $this->comment[$id] : null;
  419. }
  420. /**
  421. * returns answer weighting
  422. *
  423. * @author Olivier Brouckaert
  424. * @param - integer $id - answer ID
  425. * @param integer $id
  426. * @return integer - answer weighting
  427. */
  428. public function selectWeighting($id)
  429. {
  430. return isset($this->weighting[$id]) ? $this->weighting[$id] : null;
  431. }
  432. /**
  433. * returns answer position
  434. *
  435. * @author Olivier Brouckaert
  436. * @param - integer $id - answer ID
  437. * @return integer - answer position
  438. */
  439. function selectPosition($id)
  440. {
  441. return isset($this->position[$id]) ? $this->position[$id] : null;
  442. }
  443. /**
  444. * returns answer hotspot coordinates
  445. *
  446. * @author Olivier Brouckaert
  447. * @param integer Answer ID
  448. * @param integer $id
  449. * @return integer Answer position
  450. */
  451. public function selectHotspotCoordinates($id)
  452. {
  453. return isset($this->hotspot_coordinates[$id]) ? $this->hotspot_coordinates[$id] : null;
  454. }
  455. /**
  456. * returns answer hotspot type
  457. *
  458. * @author Toon Keppens
  459. * @param integer Answer ID
  460. * @param integer $id
  461. * @return integer Answer position
  462. */
  463. public function selectHotspotType($id)
  464. {
  465. return isset($this->hotspot_type[$id]) ? $this->hotspot_type[$id] : null;
  466. }
  467. /**
  468. * Creates a new answer
  469. *
  470. * @author Olivier Brouckaert
  471. * @param string $answer answer title
  472. * @param integer $correct 0 if bad answer, not 0 if good answer
  473. * @param string $comment answer comment
  474. * @param integer $weighting answer weighting
  475. * @param integer $position answer position
  476. * @param array $new_hotspot_coordinates Coordinates for hotspot exercises (optional)
  477. * @param integer $new_hotspot_type Type for hotspot exercises (optional)
  478. * @param string $destination
  479. */
  480. public function createAnswer(
  481. $answer,
  482. $correct,
  483. $comment,
  484. $weighting,
  485. $position,
  486. $new_hotspot_coordinates = null,
  487. $new_hotspot_type = null,
  488. $destination = ''
  489. ) {
  490. $this->new_nbrAnswers++;
  491. $id = $this->new_nbrAnswers;
  492. $this->new_answer[$id] = $answer;
  493. $this->new_correct[$id] = $correct;
  494. $this->new_comment[$id] = $comment;
  495. $this->new_weighting[$id] = $weighting;
  496. $this->new_position[$id] = $position;
  497. $this->new_hotspot_coordinates[$id] = $new_hotspot_coordinates;
  498. $this->new_hotspot_type[$id] = $new_hotspot_type;
  499. $this->new_destination[$id] = $destination;
  500. }
  501. /**
  502. * Updates an answer
  503. *
  504. * @author Toon Keppens
  505. * @param int $iid
  506. * @param string $answer
  507. * @param string $comment
  508. * @param string $correct
  509. * @param string $weighting
  510. * @param string $position
  511. * @param string $destination
  512. * @param string $hotspot_coordinates
  513. * @param string $hotspot_type
  514. */
  515. public function updateAnswers(
  516. $iid,
  517. $answer,
  518. $comment,
  519. $correct,
  520. $weighting,
  521. $position,
  522. $destination,
  523. $hotspot_coordinates,
  524. $hotspot_type
  525. ) {
  526. $em = Database::getManager();
  527. /** @var CQuizAnswer $quizAnswer */
  528. $quizAnswer = $em->find('ChamiloCourseBundle:CQuizAnswer', $iid);
  529. $quizAnswer
  530. ->setAnswer($answer)
  531. ->setComment($comment)
  532. ->setCorrect($correct)
  533. ->setPonderation($weighting)
  534. ->setPosition($position)
  535. ->setDestination($destination)
  536. ->setHotspotCoordinates($hotspot_coordinates)
  537. ->setHotspotType($hotspot_type);
  538. $em->merge($quizAnswer);
  539. $em->flush();
  540. }
  541. /**
  542. * Records answers into the data base
  543. *
  544. * @author Olivier Brouckaert
  545. */
  546. public function save()
  547. {
  548. $answerTable = Database::get_course_table(TABLE_QUIZ_ANSWER);
  549. $em = Database::getManager();
  550. $questionId = intval($this->questionId);
  551. $c_id = $this->course['real_id'];
  552. $correctList = [];
  553. $answerList = [];
  554. for ($i=1; $i <= $this->new_nbrAnswers; $i++) {
  555. $answer = $this->new_answer[$i];
  556. $correct = isset($this->new_correct[$i]) ? $this->new_correct[$i] : '';
  557. $comment = isset($this->new_comment[$i]) ? $this->new_comment[$i] : '';
  558. $weighting = isset($this->new_weighting[$i]) ? $this->new_weighting[$i] : '';
  559. $position = isset($this->new_position[$i]) ? $this->new_position[$i] : '';
  560. $hotspot_coordinates = isset($this->new_hotspot_coordinates[$i]) ? $this->new_hotspot_coordinates[$i] : '';
  561. $hotspot_type = isset($this->new_hotspot_type[$i]) ? $this->new_hotspot_type[$i] : '';
  562. $destination = isset($this->new_destination[$i]) ? $this->new_destination[$i] : '';
  563. $autoId = $this->selectAutoId($i);
  564. $iid = isset($this->iid[$i]) ? $this->iid[$i] : 0;
  565. if (!isset($this->position[$i])) {
  566. $quizAnswer = new CQuizAnswer();
  567. $quizAnswer
  568. ->setIdAuto($autoId)
  569. ->setCId($c_id)
  570. ->setQuestionId($questionId)
  571. ->setAnswer($answer)
  572. ->setCorrect($correct)
  573. ->setComment($comment)
  574. ->setPonderation($weighting)
  575. ->setPosition($position)
  576. ->setHotspotCoordinates($hotspot_coordinates)
  577. ->setHotspotType($hotspot_type)
  578. ->setDestination($destination);
  579. $em->persist($quizAnswer);
  580. $em->flush();
  581. $iid = $quizAnswer->getIid();
  582. if ($iid) {
  583. $quizAnswer
  584. ->setId($iid)
  585. ->setIdAuto($iid);
  586. $em->merge($quizAnswer);
  587. $em->flush();
  588. $questionType = $this->getQuestionType();
  589. if (in_array(
  590. $questionType,
  591. [MATCHING, MATCHING_DRAGGABLE]
  592. )) {
  593. $answer = new Answer($this->questionId);
  594. $answer->read();
  595. $correctAnswerId = $answer->selectAnswerIdByPosition($correct);
  596. // Continue to avoid matching question bug if $correctAnswerId returns false
  597. // See : https://support.chamilo.org/issues/8334
  598. if ($questionType == MATCHING && !$correctAnswerId) {
  599. continue;
  600. }
  601. $correctAnswerAutoId = $answer->selectAutoId($correct);
  602. $quizAnswer->setCorrect($correctAnswerAutoId ? $correctAnswerAutoId : 0);
  603. $em->merge($quizAnswer);
  604. $em->flush();
  605. }
  606. }
  607. } else {
  608. // https://support.chamilo.org/issues/6558
  609. // function updateAnswers already escape_string, error if we do it twice.
  610. // Feed function updateAnswers with none escaped strings
  611. $this->updateAnswers(
  612. $iid,
  613. $this->new_answer[$i],
  614. $this->new_comment[$i],
  615. $this->new_correct[$i],
  616. $this->new_weighting[$i],
  617. $this->new_position[$i],
  618. $this->new_destination[$i],
  619. $this->new_hotspot_coordinates[$i],
  620. $this->new_hotspot_type[$i]
  621. );
  622. }
  623. $answerList[$i] = $iid;
  624. if ($correct) {
  625. $correctList[$iid] = true;
  626. }
  627. }
  628. $questionType = self::getQuestionType();
  629. if ($questionType == DRAGGABLE) {
  630. foreach ($this->new_correct as $value => $status) {
  631. if (!empty($status)) {
  632. $correct = $answerList[$status];
  633. $myAutoId = $answerList[$value];
  634. $sql = "UPDATE $answerTable
  635. SET correct = '$correct'
  636. WHERE
  637. id_auto = $myAutoId
  638. ";
  639. Database::query($sql);
  640. }
  641. }
  642. }
  643. if (count($this->position) > $this->new_nbrAnswers) {
  644. $i = $this->new_nbrAnswers + 1;
  645. while ($this->position[$i]) {
  646. $position = $this->position[$i];
  647. $sql = "DELETE FROM $answerTable
  648. WHERE
  649. c_id = {$this->course_id} AND
  650. question_id = '".$questionId."' AND
  651. position ='$position'";
  652. Database::query($sql);
  653. $i++;
  654. }
  655. }
  656. // moves $new_* arrays
  657. $this->answer = $this->new_answer;
  658. $this->correct = $this->new_correct;
  659. $this->comment = $this->new_comment;
  660. $this->weighting = $this->new_weighting;
  661. $this->position = $this->new_position;
  662. $this->hotspot_coordinates = $this->new_hotspot_coordinates;
  663. $this->hotspot_type = $this->new_hotspot_type;
  664. $this->nbrAnswers = $this->new_nbrAnswers;
  665. $this->destination = $this->new_destination;
  666. $this->cancel();
  667. }
  668. /**
  669. * Duplicates answers by copying them into another question
  670. *
  671. * @author Olivier Brouckaert
  672. * @param int question id
  673. * @param array destination course info (result of the function api_get_course_info() )
  674. * @param string $newQuestionId
  675. */
  676. public function duplicate($newQuestionId, $course_info = null)
  677. {
  678. if (empty($course_info)) {
  679. $course_info = $this->course;
  680. }
  681. $fixed_list = array();
  682. if (self::getQuestionType() == MULTIPLE_ANSWER_TRUE_FALSE ||
  683. self::getQuestionType() == MULTIPLE_ANSWER_TRUE_FALSE
  684. ) {
  685. // Selecting origin options
  686. $origin_options = Question::readQuestionOption(
  687. $this->selectQuestionId(),
  688. $this->course['real_id']
  689. );
  690. if (!empty($origin_options)) {
  691. foreach ($origin_options as $item) {
  692. $new_option_list[] = $item['id'];
  693. }
  694. }
  695. $destination_options = Question::readQuestionOption($newQuestionId, $course_info['real_id']);
  696. $i = 0;
  697. if (!empty($destination_options)) {
  698. foreach($destination_options as $item) {
  699. $fixed_list[$new_option_list[$i]] = $item['id'];
  700. $i++;
  701. }
  702. }
  703. }
  704. // if at least one answer
  705. if ($this->nbrAnswers) {
  706. // inserts new answers into data base
  707. $c_id = $course_info['real_id'];
  708. for ($i=1;$i <= $this->nbrAnswers;$i++) {
  709. if ($this->course['id'] != $course_info['id']) {
  710. $this->answer[$i] = DocumentManager::replace_urls_inside_content_html_from_copy_course(
  711. $this->answer[$i],
  712. $this->course['id'],
  713. $course_info['id']
  714. );
  715. $this->comment[$i] = DocumentManager::replace_urls_inside_content_html_from_copy_course(
  716. $this->comment[$i],
  717. $this->course['id'],
  718. $course_info['id']
  719. );
  720. }
  721. $correct = $this->correct[$i];
  722. if (self::getQuestionType() == MULTIPLE_ANSWER_TRUE_FALSE ||
  723. self::getQuestionType() == MULTIPLE_ANSWER_TRUE_FALSE
  724. ) {
  725. $correct = $fixed_list[intval($correct)];
  726. }
  727. $quizAnswer = new CQuizAnswer();
  728. $quizAnswer
  729. ->setCId($c_id)
  730. ->setQuestionId($newQuestionId)
  731. ->setAnswer($this->answer[$i])
  732. ->setCorrect($correct)
  733. ->setComment($this->comment[$i])
  734. ->setPonderation($this->weighting[$i])
  735. ->setPosition($this->position[$i])
  736. ->setHotspotCoordinates($this->hotspot_coordinates[$i])
  737. ->setHotspotType($this->hotspot_type[$i])
  738. ->setDestination($this->destination[$i]);
  739. $em = Database::getManager();
  740. $em->persist($quizAnswer);
  741. $em->flush();
  742. $quizAnswer
  743. ->setId($quizAnswer->getIid())
  744. ->setIdAuto($quizAnswer->getIid());
  745. $em->merge($quizAnswer);
  746. $em->flush();
  747. }
  748. }
  749. }
  750. /**
  751. * Get the necessary JavaScript for some answers
  752. * @return string
  753. */
  754. public function getJs()
  755. {
  756. //if ($this->questionId == 2)
  757. return "<script>
  758. jsPlumb.ready(function() {
  759. if ($('#drag{$this->questionId}_question').length > 0) {
  760. MatchingDraggable.init('{$this->questionId}');
  761. }
  762. });
  763. </script>";
  764. }
  765. /**
  766. * Check if a answer is correct by an answer auto id
  767. * @param $needle int The answer auto id
  768. * @return bool
  769. */
  770. public function isCorrectByAutoId($needle)
  771. {
  772. $key = 0;
  773. foreach ($this->autoId as $autoIdKey => $autoId) {
  774. if ($autoId == $needle) {
  775. $key = $autoIdKey;
  776. }
  777. }
  778. if (!$key) {
  779. return false;
  780. }
  781. return $this->isCorrect($key) ? true : false;
  782. }
  783. }