survey_question.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use ChamiloSession as Session;
  4. /**
  5. * Class survey_question.
  6. */
  7. class survey_question
  8. {
  9. public $buttonList = [];
  10. /** @var FormValidator */
  11. private $form;
  12. /**
  13. * @param FormValidator $form
  14. * @param array $surveyData
  15. */
  16. public function addParentMenu(FormValidator $form, $surveyData)
  17. {
  18. $surveyId = $surveyData['survey_id'];
  19. $questions = SurveyManager::get_questions($surveyId);
  20. $options = [];
  21. foreach ($questions as $question) {
  22. $options[$question['question_id']] = strip_tags($question['question']);
  23. }
  24. $form->addSelect(
  25. 'parent_id',
  26. get_lang('Parent'),
  27. $options,
  28. ['id' => 'parent_id', 'placeholder' => get_lang('Please select an option')]
  29. );
  30. $url = api_get_path(WEB_AJAX_PATH).'survey.ajax.php?'.api_get_cidreq();
  31. $form->addHtml('
  32. <script>
  33. $(function() {
  34. $("#parent_id").on("change", function() {
  35. var questionId = $(this).val()
  36. var params = {
  37. "a": "load_question_options",
  38. "survey_id": "'.$surveyId.'",
  39. "question_id": questionId,
  40. };
  41. $.ajax({
  42. type: "GET",
  43. url: "'.$url.'",
  44. data: params,
  45. async: false,
  46. success: function(data) {
  47. $("#parent_options").html(data);
  48. }
  49. });
  50. console.log();
  51. });
  52. });
  53. </script>
  54. ');
  55. $form->addHtml('<div id="parent_options"></div>');
  56. $form->addHidden('option_id', 0);
  57. }
  58. /**
  59. * @param string $type
  60. *
  61. * @return survey_question
  62. */
  63. public static function createQuestion($type)
  64. {
  65. switch ($type) {
  66. case 'comment':
  67. return new ch_comment();
  68. case 'dropdown':
  69. return new ch_dropdown();
  70. case 'multiplechoice':
  71. return new ch_multiplechoice();
  72. case 'multipleresponse':
  73. return new ch_multipleresponse();
  74. case 'open':
  75. return new ch_open();
  76. case 'pagebreak':
  77. return new ch_pagebreak();
  78. case 'percentage':
  79. return new ch_percentage();
  80. case 'personality':
  81. return new ch_personality();
  82. case 'score':
  83. return new ch_score();
  84. case 'yesno':
  85. return new ch_yesno();
  86. default:
  87. api_not_allowed(true);
  88. break;
  89. }
  90. }
  91. /**
  92. * Generic part of any survey question: the question field.
  93. *
  94. * @param array $surveyData
  95. * @param array $formData
  96. *
  97. * @return FormValidator
  98. */
  99. public function createForm($surveyData, $formData)
  100. {
  101. $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : null;
  102. $questionId = isset($_GET['question_id']) ? (int) $_GET['question_id'] : null;
  103. $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : null;
  104. $type = isset($_GET['type']) ? Security::remove_XSS($_GET['type']) : null;
  105. $toolName = Display::return_icon(
  106. SurveyManager::icon_question($type),
  107. get_lang(ucfirst($type)),
  108. ['align' => 'middle', 'height' => '22px']
  109. ).' ';
  110. if ($action == 'add') {
  111. $toolName .= get_lang('Add a question').': ';
  112. } elseif ($action == 'edit') {
  113. $toolName .= get_lang('Edit question').': ';
  114. }
  115. switch ($_GET['type']) {
  116. case 'yesno':
  117. $toolName .= get_lang('Yes / No');
  118. break;
  119. case 'multiplechoice':
  120. $toolName .= get_lang('Multiple choice');
  121. break;
  122. case 'multipleresponse':
  123. $toolName .= get_lang('Multiple answers');
  124. break;
  125. default:
  126. $toolName .= get_lang(api_ucfirst($type));
  127. }
  128. $sharedQuestionId = isset($formData['shared_question_id']) ? $formData['shared_question_id'] : null;
  129. $url = api_get_self().'?action='.$action.'&type='.$type.'&survey_id='.$surveyId.'&question_id='.$questionId.'&'.api_get_cidreq();
  130. $form = new FormValidator('question_form', 'post', $url);
  131. $form->addHeader($toolName);
  132. $form->addHidden('survey_id', $surveyId);
  133. $form->addHidden('question_id', $questionId);
  134. $form->addHidden('shared_question_id', Security::remove_XSS($sharedQuestionId));
  135. $form->addHidden('type', $type);
  136. $config = [
  137. 'ToolbarSet' => 'SurveyQuestion',
  138. 'Width' => '100%',
  139. 'Height' => '120',
  140. ];
  141. $form->addHtmlEditor(
  142. 'question',
  143. get_lang('Question'),
  144. true,
  145. false,
  146. $config
  147. );
  148. if (api_get_configuration_value('allow_required_survey_questions') &&
  149. in_array($_GET['type'], ['yesno', 'multiplechoice'])) {
  150. $form->addCheckBox('is_required', get_lang('Mandatory?'), get_lang('Yes'));
  151. }
  152. // When survey type = 1??
  153. if ($surveyData['survey_type'] == 1) {
  154. $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
  155. $sql = 'SELECT id,name FROM '.$table_survey_question_group.'
  156. WHERE survey_id = '.(int) $_GET['survey_id'].'
  157. ORDER BY name';
  158. $rs = Database::query($sql);
  159. $glist = null;
  160. while ($row = Database::fetch_array($rs, 'NUM')) {
  161. $glist .= '<option value="'.$row[0].'" >'.$row[1].'</option>';
  162. }
  163. $grouplist = $grouplist1 = $grouplist2 = $glist;
  164. if (!empty($formData['assigned'])) {
  165. $grouplist = str_replace(
  166. '<option value="'.$formData['assigned'].'"',
  167. '<option value="'.$formData['assigned'].'" selected',
  168. $glist
  169. );
  170. }
  171. if (!empty($formData['assigned1'])) {
  172. $grouplist1 = str_replace(
  173. '<option value="'.$formData['assigned1'].'"',
  174. '<option value="'.$formData['assigned1'].'" selected',
  175. $glist
  176. );
  177. }
  178. if (!empty($formData['assigned2'])) {
  179. $grouplist2 = str_replace(
  180. '<option value="'.$formData['assigned2'].'"',
  181. '<option value="'.$formData['assigned2'].'" selected',
  182. $glist
  183. );
  184. }
  185. $this->html .= ' <tr><td colspan="">
  186. <fieldset style="border:1px solid black"><legend>'.get_lang('Condition').'</legend>
  187. <b>'.get_lang('Primary').'</b><br />
  188. '.'<input type="radio" name="choose" value="1" '.(($formData['choose'] == 1) ? 'checked' : '').
  189. '><select name="assigned">'.$grouplist.'</select><br />';
  190. $this->html .= '
  191. <b>'.get_lang('Secondary').'</b><br />
  192. '.'<input type="radio" name="choose" value="2" '.(($formData['choose'] == 2) ? 'checked' : '').
  193. '><select name="assigned1">'.$grouplist1.'</select> '.
  194. '<select name="assigned2">'.$grouplist2.'</select>'
  195. .'</fieldset><br />';
  196. }
  197. $this->setForm($form);
  198. return $form;
  199. }
  200. /**
  201. * Adds submit button.
  202. */
  203. public function renderForm()
  204. {
  205. if (isset($_GET['question_id']) && !empty($_GET['question_id'])) {
  206. /**
  207. * Check if survey has answers first before update it, this is because if you update it, the question
  208. * options will delete and re-insert in database loosing the iid and question_id to verify the correct answers.
  209. */
  210. $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
  211. $answersChecker = SurveyUtil::checkIfSurveyHasAnswers($surveyId);
  212. if (!$answersChecker) {
  213. $this->buttonList[] = $this->getForm()->addButtonUpdate(get_lang('Edit question'), 'save', true);
  214. } else {
  215. $this->getForm()->addHtml('
  216. <div class="form-group">
  217. <label class="col-sm-2 control-label"></label>
  218. <div class="col-sm-8">
  219. <div class="alert alert-info">'.get_lang('You can\'t edit this question because answers by students have already been registered').'</div>
  220. </div>
  221. <div class="col-sm-2"></div>
  222. </div>
  223. ');
  224. }
  225. } else {
  226. $this->buttonList[] = $this->getForm()->addButtonSave(get_lang('Create question'), 'save', true);
  227. }
  228. $this->getForm()->addGroup($this->buttonList, 'buttons');
  229. }
  230. /**
  231. * @return FormValidator
  232. */
  233. public function getForm()
  234. {
  235. return $this->form;
  236. }
  237. /**
  238. * @param FormValidator $form
  239. */
  240. public function setForm($form)
  241. {
  242. $this->form = $form;
  243. }
  244. /**
  245. * @param array $formData
  246. *
  247. * @return mixed
  248. */
  249. public function preSave($formData)
  250. {
  251. $counter = Session::read('answer_count');
  252. $answerList = Session::read('answer_list');
  253. if (empty($answerList)) {
  254. $answerList = isset($formData['answers']) ? $formData['answers'] : [];
  255. Session::write('answer_list', $answerList);
  256. }
  257. if (isset($_POST['answers'])) {
  258. $formData['answers'] = $_POST['answers'];
  259. }
  260. if (empty($counter)) {
  261. $counter = count($answerList) - 1;
  262. Session::write('answer_count', $counter);
  263. }
  264. // Moving an answer up
  265. if (isset($_POST['move_up']) && $_POST['move_up']) {
  266. foreach ($_POST['move_up'] as $key => &$value) {
  267. $id1 = $key;
  268. $content1 = $formData['answers'][$id1];
  269. $id2 = $key - 1;
  270. $content2 = $formData['answers'][$id2];
  271. $formData['answers'][$id1] = $content2;
  272. $formData['answers'][$id2] = $content1;
  273. }
  274. }
  275. // Moving an answer down
  276. if (isset($_POST['move_down']) && $_POST['move_down']) {
  277. foreach ($_POST['move_down'] as $key => &$value) {
  278. $id1 = $key;
  279. $content1 = $formData['answers'][$id1];
  280. $id2 = $key + 1;
  281. $content2 = $formData['answers'][$id2];
  282. $formData['answers'][$id1] = $content2;
  283. $formData['answers'][$id2] = $content1;
  284. }
  285. }
  286. /**
  287. * This solution is a little bit strange but I could not find a different solution.
  288. */
  289. if (isset($_POST['delete_answer'])) {
  290. $deleted = false;
  291. foreach ($_POST['delete_answer'] as $key => &$value) {
  292. $deleted = $key;
  293. $counter--;
  294. Session::write('answer_count', $counter);
  295. }
  296. foreach ($formData['answers'] as $key => &$value) {
  297. if ($key > $deleted) {
  298. $formData['answers'][$key - 1] = $formData['answers'][$key];
  299. unset($formData['answers'][$key]);
  300. }
  301. }
  302. }
  303. // Adding an answer
  304. if (isset($_POST['buttons']) && isset($_POST['buttons']['add_answer'])) {
  305. $counter++;
  306. Session::write('answer_count', $counter);
  307. }
  308. // Removing an answer
  309. if (isset($_POST['buttons']) && isset($_POST['buttons']['remove_answer'])) {
  310. $counter--;
  311. Session::write('answer_count', $counter);
  312. foreach ($formData['answers'] as $index => &$data) {
  313. if ($index > $counter) {
  314. unset($formData['answers'][$index]);
  315. }
  316. }
  317. }
  318. if (!isset($_POST['delete_answer'])) {
  319. if (isset($formData['answers'])) {
  320. foreach ($formData['answers'] as $index => $data) {
  321. if ($index > $counter) {
  322. unset($formData['answers'][$index]);
  323. }
  324. }
  325. for ($i = 0; $i <= $counter; $i++) {
  326. if (!isset($formData['answers'][$i])) {
  327. $formData['answers'][$i] = '';
  328. }
  329. }
  330. }
  331. }
  332. $formData['answers'] = isset($formData['answers']) ? $formData['answers'] : [];
  333. Session::write('answer_list', $formData['answers']);
  334. if (!isset($formData['is_required']) && api_get_configuration_value('survey_mark_question_as_required')) {
  335. $formData['is_required'] = true;
  336. }
  337. return $formData;
  338. }
  339. /**
  340. * @param array $surveyData
  341. * @param array $formData
  342. *
  343. * @return mixed
  344. */
  345. public function save($surveyData, $formData)
  346. {
  347. // Saving a question
  348. if (isset($_POST['buttons']) && isset($_POST['buttons']['save'])) {
  349. Session::erase('answer_count');
  350. Session::erase('answer_list');
  351. $message = SurveyManager::save_question(
  352. $surveyData,
  353. $formData
  354. );
  355. if ($message == 'QuestionAdded' || $message == 'QuestionUpdated') {
  356. header('Location: '.api_get_path(WEB_CODE_PATH).'survey/survey.php?survey_id='.intval($_GET['survey_id']).'&message='.$message.'&'.api_get_cidreq());
  357. exit;
  358. }
  359. }
  360. return $formData;
  361. }
  362. /**
  363. * Adds two buttons. One to add an option, one to remove an option.
  364. *
  365. * @param array $data
  366. */
  367. public function addRemoveButtons($data)
  368. {
  369. $this->buttonList['remove_answer'] = $this->getForm()->createElement(
  370. 'button',
  371. 'remove_answer',
  372. get_lang('Remove option'),
  373. 'minus',
  374. 'default'
  375. );
  376. if (count($data['answers']) <= 2) {
  377. $this->buttonList['remove_answer']->updateAttributes(
  378. ['disabled' => 'disabled']
  379. );
  380. }
  381. $this->buttonList['add_answer'] = $this->getForm()->createElement(
  382. 'button',
  383. 'add_answer',
  384. get_lang('Add option'),
  385. 'plus',
  386. 'default'
  387. );
  388. }
  389. /**
  390. * @param FormValidator $form
  391. * @param array $questionData
  392. * @param array $answers
  393. */
  394. public function render(FormValidator $form, $questionData = [], $answers = [])
  395. {
  396. return null;
  397. }
  398. }