Passed
Push — 1.11.x ( 5d4e40...348220 )
by Julito
14:20 queued 02:11
created

survey_question::getParents()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 11
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 16
rs 9.9
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use ChamiloSession as Session;
6
7
/**
8
 * Class survey_question.
9
 */
10
class survey_question
11
{
12
    public $buttonList = [];
13
    /** @var FormValidator */
14
    private $form;
15
16
    /**
17
     * @param array $surveyData
18
     */
19
    public function addParentMenu($formData, FormValidator $form, $surveyData)
20
    {
21
        $surveyId = $surveyData['survey_id'];
22
        $questionId = isset($formData['question_id']) ? $formData['question_id'] : 0;
23
        $parentId = isset($formData['parent_id']) ? $formData['parent_id'] : 0;
24
        $optionId = isset($formData['parent_option_id']) ? $formData['parent_option_id'] : 0;
25
        $questions = SurveyManager::get_questions($surveyId);
26
27
        $newQuestionList = [];
28
        foreach ($questions as $question) {
29
            $newQuestionList[$question['sort']] = $question;
30
        }
31
        ksort($newQuestionList);
32
33
        $options = [];
34
        foreach ($newQuestionList as $question) {
35
            if (!empty($questionId)) {
36
                if ($question['question_id'] == $questionId) {
37
                    break;
38
                }
39
            }
40
            $options[$question['question_id']] = strip_tags($question['question']);
41
        }
42
        $form->addSelect(
43
            'parent_id',
44
            get_lang('Parent'),
45
            $options,
46
            ['id' => 'parent_id', 'placeholder' => get_lang('SelectAnOption')]
47
        );
48
        $url = api_get_path(WEB_AJAX_PATH).
49
            'survey.ajax.php?'.api_get_cidreq().'&a=load_question_options&survey_id='.$surveyId;
50
        $form->addHtml('
51
            <script>
52
                $(function() {
53
                    $("#parent_id").on("change", function() {
54
                        var questionId = $(this).val()
55
                        var $select = $("#parent_option_id");
56
                        $select.empty();
57
58
                        if (questionId === "") {
59
                              $("#option_list").hide();
60
                        } else {
61
                            $.getJSON({
62
                                url: "'.$url.'" + "&question_id=" + questionId,
63
                                success: function(data) {
64
                                    $("#option_list").show();
65
                                    $.each(data, function(key, value) {
66
                                        $("<option>").val(key).text(value).appendTo($select);
67
                                    });
68
                                }
69
                            });
70
                        }
71
                    });
72
                });
73
            </script>
74
        ');
75
76
        $style = 'display:none';
77
        $options = [ ];
78
        if (!empty($optionId) && !empty($parentId)) {
79
            $parentData = SurveyManager::get_question($parentId);
80
            $style = '';
81
            foreach ($parentData['answer_data'] as $answer) {
82
                $options[$answer['iid']] = strip_tags($answer['data']);
83
            }
84
        }
85
86
        $form->addHtml('<div id="option_list" style="'.$style.'">');
87
        $form->addSelect(
88
            'parent_option_id',
89
            get_lang('Option'),
90
            $options,
91
            ['id' => 'parent_option_id', 'disable_js' => true]
92
        );
93
        $form->addHtml('</div>');
94
    }
95
96
    /**
97
     * @param string $type
98
     *
99
     * @return survey_question
100
     */
101
    public static function createQuestion($type)
102
    {
103
        switch ($type) {
104
            case 'comment':
105
                return new ch_comment();
106
            case 'dropdown':
107
                return new ch_dropdown();
108
            case 'multiplechoice':
109
                return new ch_multiplechoice();
110
            case 'multipleresponse':
111
                return new ch_multipleresponse();
112
            case 'open':
113
                return new ch_open();
114
            case 'pagebreak':
115
                return new ch_pagebreak();
116
            case 'percentage':
117
                return new ch_percentage();
118
            case 'personality':
119
                return new ch_personality();
120
            case 'score':
121
                return new ch_score();
122
            case 'yesno':
123
                return new ch_yesno();
124
            case 'selectivedisplay':
125
                return new ch_selectivedisplay();
126
            case 'multiplechoiceother':
127
                return new ch_multiplechoiceother();
128
            default:
129
                api_not_allowed(true);
130
                break;
131
        }
132
    }
133
134
    /**
135
     * Generic part of any survey question: the question field.
136
     *
137
     * @param array $surveyData
138
     * @param array $formData
139
     *
140
     * @return FormValidator
141
     */
142
    public function createForm($surveyData, $formData)
143
    {
144
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : null;
145
        $questionId = isset($_GET['question_id']) ? (int) $_GET['question_id'] : null;
146
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : null;
147
        $type = isset($_GET['type']) ? Security::remove_XSS($_GET['type']) : null;
148
149
        $actionHeader = get_lang('EditQuestion').': ';
150
        if ($action === 'add') {
151
            $actionHeader = get_lang('AddQuestion').': ';
152
        }
153
154
        $questionComment = '';
155
        $allowParent = false;
156
        switch ($type) {
157
            case 'open':
158
                $toolName = get_lang('Open');
159
                $questionComment = get_lang('QuestionTags');
160
                break;
161
            case 'yesno':
162
                $toolName = get_lang('YesNo');
163
                $allowParent = true;
164
                break;
165
            case 'multiplechoice':
166
                $toolName = get_lang('UniqueSelect');
167
                $allowParent = true;
168
                break;
169
            case 'multipleresponse':
170
                $toolName = get_lang('MultipleResponse');
171
                $allowParent = true;
172
                break;
173
            case 'selectivedisplay':
174
                $toolName = get_lang('SurveyQuestionSelectiveDisplay');
175
                $questionComment = get_lang('SurveyQuestionSelectiveDisplayComment');
176
                break;
177
            case 'multiplechoiceother':
178
                $toolName = get_lang('SurveyMultipleAnswerWithOther');
179
                break;
180
            default:
181
                $toolName = get_lang(api_ucfirst($type));
182
        }
183
184
        if (false === api_get_configuration_value('survey_question_dependency')) {
185
            $allowParent = false;
186
        }
187
188
        $icon = Display::return_icon(
189
                SurveyManager::icon_question($type),
190
                $toolName,
191
                ['align' => 'middle', 'height' => '22px']
192
            ).' ';
193
194
        $toolName = $icon.$actionHeader.$toolName;
195
        $sharedQuestionId = isset($formData['shared_question_id']) ? $formData['shared_question_id'] : null;
196
197
        $url = api_get_self().'?action='.$action.'&type='.$type.'&survey_id='.$surveyId.'&question_id='.$questionId.'&'.api_get_cidreq();
198
        $form = new FormValidator('question_form', 'post', $url);
199
        $form->addHeader($toolName);
200
        if (!empty($questionComment)) {
201
            $form->addHtml(Display::return_message($questionComment, 'info', false));
202
        }
203
        $form->addHidden('survey_id', $surveyId);
204
        $form->addHidden('question_id', $questionId);
205
        $form->addHidden('shared_question_id', Security::remove_XSS($sharedQuestionId));
206
        $form->addHidden('type', $type);
207
208
        $config = [
209
            'ToolbarSet' => 'SurveyQuestion',
210
            'Width' => '100%',
211
            'Height' => '120',
212
        ];
213
        $form->addHtmlEditor(
214
            'question',
215
            get_lang('Question'),
216
            true,
217
            false,
218
            $config
219
        );
220
221
        if (api_get_configuration_value('allow_required_survey_questions') &&
222
            in_array($_GET['type'], ['yesno', 'multiplechoice'])) {
223
            $form->addCheckBox('is_required', get_lang('IsMandatory'), get_lang('Yes'));
224
        }
225
226
        if ($allowParent) {
227
            $this->addParentMenu($formData, $form, $surveyData);
228
        }
229
230
        if ($surveyData['survey_type'] == 1) {
231
            $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
232
            $sql = 'SELECT id, name FROM '.$table_survey_question_group.'
233
                    WHERE survey_id = '.$surveyId.'
234
                    ORDER BY name';
235
            $rs = Database::query($sql);
236
            $glist = null;
237
            while ($row = Database::fetch_array($rs, 'NUM')) {
238
                $glist .= '<option value="'.$row[0].'" >'.$row[1].'</option>';
239
            }
240
241
            $grouplist = $grouplist1 = $grouplist2 = $glist;
242
            if (!empty($formData['assigned'])) {
243
                $grouplist = str_replace(
244
                    '<option value="'.$formData['assigned'].'"',
245
                    '<option value="'.$formData['assigned'].'" selected',
246
                    $glist
247
                );
248
            }
249
250
            if (!empty($formData['assigned1'])) {
251
                $grouplist1 = str_replace(
252
                    '<option value="'.$formData['assigned1'].'"',
253
                    '<option value="'.$formData['assigned1'].'" selected',
254
                    $glist
255
                );
256
            }
257
258
            if (!empty($formData['assigned2'])) {
259
                $grouplist2 = str_replace(
260
                    '<option value="'.$formData['assigned2'].'"',
261
                    '<option value="'.$formData['assigned2'].'" selected',
262
                    $glist
263
                );
264
            }
265
266
            $this->html .= '<tr><td colspan="">
0 ignored issues
show
Bug Best Practice introduced by
The property html does not exist on survey_question. Did you maybe forget to declare it?
Loading history...
267
			<fieldset style="border:1px solid black">
268
			    <legend>'.get_lang('Condition').'</legend>
269
			    <b>'.get_lang('Primary').'</b><br />
270
			    <input type="radio" name="choose" value="1" '.(($formData['choose'] == 1) ? 'checked' : '').'>
271
			    <select name="assigned">'.$grouplist.'</select><br />';
272
            $this->html .= '
273
			<b>'.get_lang('Secondary').'</b><br />
274
			    <input type="radio" name="choose" value="2" '.(($formData['choose'] == 2) ? 'checked' : '').'>
275
			    <select name="assigned1">'.$grouplist1.'</select>
276
                <select name="assigned2">'.$grouplist2.'</select>
277
            </fieldset><br />';
278
        }
279
280
        $this->setForm($form);
281
282
        return $form;
283
    }
284
285
    /**
286
     * Adds submit button.
287
     */
288
    public function renderForm()
289
    {
290
        if (isset($_GET['question_id']) && !empty($_GET['question_id'])) {
291
            /**
292
             * Check if survey has answers first before update it, this is because if you update it, the question
293
             * options will delete and re-insert in database loosing the iid and question_id to verify the correct answers.
294
             */
295
            $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
296
            $answersChecker = SurveyUtil::checkIfSurveyHasAnswers($surveyId);
297
            if (!$answersChecker) {
298
                $this->buttonList[] = $this->getForm()->addButtonUpdate(get_lang('ModifyQuestionSurvey'), 'save', true);
299
            } else {
300
                $this->getForm()->addHtml('
301
                    <div class="form-group">
302
                        <label class="col-sm-2 control-label"></label>
303
                        <div class="col-sm-8">
304
                            <div class="alert alert-info">'.
305
                            get_lang('YouCantNotEditThisQuestionBecauseAlreadyExistAnswers').'</div>
306
                        </div>
307
                        <div class="col-sm-2"></div>
308
                    </div>
309
                ');
310
            }
311
        } else {
312
            $this->buttonList[] = $this->getForm()->addButtonSave(get_lang('CreateQuestionSurvey'), 'save', true);
313
        }
314
315
        $this->getForm()->addGroup($this->buttonList, 'buttons');
316
    }
317
318
    /**
319
     * @return FormValidator
320
     */
321
    public function getForm()
322
    {
323
        return $this->form;
324
    }
325
326
    /**
327
     * @param FormValidator $form
328
     */
329
    public function setForm($form)
330
    {
331
        $this->form = $form;
332
    }
333
334
    /**
335
     * @param array $formData
336
     *
337
     * @return mixed
338
     */
339
    public function preSave($formData)
340
    {
341
        $counter = Session::read('answer_count');
342
        $answerList = Session::read('answer_list');
343
344
        if (empty($answerList)) {
345
            $answerList = isset($formData['answers']) ? $formData['answers'] : [];
346
            Session::write('answer_list', $answerList);
347
        }
348
349
        if (isset($_POST['answers'])) {
350
            $formData['answers'] = $_POST['answers'];
351
        }
352
353
        if (empty($counter)) {
354
            $counter = count($answerList) - 1;
355
            Session::write('answer_count', $counter);
356
        }
357
358
        // Moving an answer up
359
        if (isset($_POST['move_up']) && $_POST['move_up']) {
360
            foreach ($_POST['move_up'] as $key => &$value) {
361
                $id1 = $key;
362
                $content1 = $formData['answers'][$id1];
363
                $id2 = $key - 1;
364
                $content2 = $formData['answers'][$id2];
365
                $formData['answers'][$id1] = $content2;
366
                $formData['answers'][$id2] = $content1;
367
            }
368
        }
369
370
        // Moving an answer down
371
        if (isset($_POST['move_down']) && $_POST['move_down']) {
372
            foreach ($_POST['move_down'] as $key => &$value) {
373
                $id1 = $key;
374
                $content1 = $formData['answers'][$id1];
375
                $id2 = $key + 1;
376
                $content2 = $formData['answers'][$id2];
377
                $formData['answers'][$id1] = $content2;
378
                $formData['answers'][$id2] = $content1;
379
            }
380
        }
381
382
        /**
383
         * Deleting a specific answer is only saved in the session until the
384
         * "Save question" button is pressed. This means all options are kept
385
         * in the survey_question_option table until the question is saved.
386
         */
387
        if (isset($_POST['delete_answer'])) {
388
            $deleted = false;
389
            foreach ($_POST['delete_answer'] as $key => &$value) {
390
                $deleted = $key;
391
                $counter--;
392
                Session::write('answer_count', $counter);
393
            }
394
395
            $newAnswers = [];
396
            $newAnswersId = [];
397
            foreach ($formData['answers'] as $key => &$value) {
398
                if ($key > $deleted) {
399
                    // swap with previous (deleted) option slot
400
                    $newAnswers[$key - 1] = $formData['answers'][$key];
401
                    $newAnswersId[$key - 1] = $formData['answersid'][$key];
402
                    unset($formData['answers'][$key]);
403
                    unset($formData['answersid'][$key]);
404
                } elseif ($key === $deleted) {
405
                    // delete option
406
                    unset($formData['answers'][$deleted]);
407
                    unset($formData['answersid'][$deleted]);
408
                } else {
409
                    // keep as is
410
                    $newAnswers[$key] = $value;
411
                    $newAnswersId[$key] = $formData['answersid'][$key];
412
                }
413
            }
414
            unset($formData['answers']);
415
            unset($formData['answersid']);
416
            $formData['answers'] = $newAnswers;
417
            $formData['answersid'] = $newAnswersId;
418
        }
419
420
        // Adding an answer
421
        if (isset($_POST['buttons']) && isset($_POST['buttons']['add_answer'])) {
422
            if (isset($_REQUEST['type']) && 'multiplechoiceother' === $_REQUEST['type']) {
423
                $counter--;
424
            }
425
            $counter++;
426
            Session::write('answer_count', $counter);
427
        }
428
429
        // Removing an answer
430
        if (isset($_POST['buttons']) && isset($_POST['buttons']['remove_answer'])) {
431
            $counter--;
432
            Session::write('answer_count', $counter);
433
            foreach ($formData['answers'] as $index => &$data) {
434
                if ($index > $counter) {
435
                    unset($formData['answers'][$index]);
436
                    unset($formData['answersid'][$index]);
437
                }
438
            }
439
        }
440
441
        if (!isset($_POST['delete_answer'])) {
442
            // Make sure we have an array of answers
443
            if (!isset($formData['answers'])) {
444
                $formData['answers'] = [];
445
            }
446
            // Check if no deleted answer remains at the end of the answers
447
            // array and add empty answers if the array is too short
448
            foreach ($formData['answers'] as $index => $data) {
449
                if ($index > $counter) {
450
                    unset($formData['answers'][$index]);
451
                }
452
            }
453
454
            for ($i = 0; $i <= $counter; $i++) {
455
                if (!isset($formData['answers'][$i])) {
456
                    $formData['answers'][$i] = '';
457
                }
458
            }
459
        }
460
461
        $formData['answers'] = isset($formData['answers']) ? $formData['answers'] : [];
462
        Session::write('answer_list', $formData['answers']);
463
464
        if (!isset($formData['is_required']) && api_get_configuration_value('survey_mark_question_as_required')) {
465
            $formData['is_required'] = true;
466
        }
467
468
        return $formData;
469
    }
470
471
    /**
472
     * @param array $surveyData
473
     * @param array $formData
474
     *
475
     * @return mixed
476
     */
477
    public function save($surveyData, $formData, $dataFromDatabase = [])
478
    {
479
        // Saving a question
480
        if (isset($_POST['buttons']) && isset($_POST['buttons']['save'])) {
481
            Session::erase('answer_count');
482
            Session::erase('answer_list');
483
            $message = SurveyManager::save_question($surveyData, $formData, true, $dataFromDatabase);
484
485
            if ($message === 'QuestionAdded' || $message === 'QuestionUpdated') {
486
                $url = api_get_path(WEB_CODE_PATH).'survey/survey.php?survey_id='.intval($_GET['survey_id']).'&message='.$message.'&'.api_get_cidreq();
487
                header('Location: '.$url);
488
                exit;
489
            }
490
        }
491
492
        return $formData;
493
    }
494
495
    /**
496
     * Adds two buttons. One to add an option, one to remove an option.
497
     *
498
     * @param array $data
499
     */
500
    public function addRemoveButtons($data)
501
    {
502
        $this->buttonList['remove_answer'] = $this->getForm()->createElement(
503
            'button',
504
            'remove_answer',
505
            get_lang('RemoveAnswer'),
506
            'minus',
507
            'default'
508
        );
509
510
        if (count($data['answers']) <= 2) {
511
            $this->buttonList['remove_answer']->updateAttributes(
512
                ['disabled' => 'disabled']
513
            );
514
        }
515
516
        $this->buttonList['add_answer'] = $this->getForm()->createElement(
517
            'button',
518
            'add_answer',
519
            get_lang('AddAnswer'),
520
            'plus',
521
            'default'
522
        );
523
    }
524
525
    public static function getJs()
526
    {
527
        return '
528
            <style>
529
            .with_parent {
530
                display: none;
531
            }
532
            </style>
533
            <script>
534
            $(function() {
535
            });
536
            </script>';
537
    }
538
539
    public static function getParents($questionId, $list = [])
540
    {
541
        $courseId = api_get_course_int_id();
542
        $questionId = (int) $questionId;
543
544
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
545
        $sql = "SELECT parent_id FROM $table
546
                WHERE c_id = $courseId AND question_id = $questionId ";
547
        $result = Database::query($sql);
548
        $row = Database::fetch_array($result, 'ASSOC');
549
        if ($row && !empty($row['parent_id'])) {
550
            $list[] = $row['parent_id'];
551
            $list = self::getParents($row['parent_id'], $list);
552
        }
553
554
        return $list;
555
    }
556
557
    public static function getQuestionJs($question)
558
    {
559
        $list = self::getDependecy($question);
560
        if (empty($list)) {
561
            return '';
562
        }
563
564
        $js = '';
565
        $questionId = $question['question_id'];
566
        $newList = [];
567
        foreach ($list as $child) {
568
            $childQuestionId = $child['question_id'];
569
            $optionId = $child['parent_option_id'];
570
            $newList[$optionId] = $childQuestionId;
571
        }
572
573
        $js .= '
574
            <script>
575
            $(function() {
576
                var list = '.json_encode($newList).';
577
                $("input[name=question'.$questionId.']").on("click", function() {
578
                    $.each(list, function(index, value) {
579
                        $(".with_parent_" + value).hide();
580
                        $(".with_parent_" + value).find("input").prop("checked", false);
581
                        $(".with_parent_only_hide_" + value).hide();
582
                    });
583
584
                    var questionId = $(this).val();
585
                    var questionToShow = list[questionId];
586
                    $(".with_parent_" + questionToShow).show();
587
                });
588
            });
589
            </script>';
590
591
        return $js;
592
    }
593
594
    public static function getDependecy($question)
595
    {
596
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
597
        $questionId = $question['question_id'];
598
        $courseId = api_get_course_int_id();
599
600
        // Getting the information of the question
601
        $sql = "SELECT * FROM $table
602
		        WHERE c_id = $courseId AND parent_id = $questionId ";
603
        $result = Database::query($sql);
604
        $row = Database::store_result($result, 'ASSOC');
605
606
        return $row;
607
    }
608
609
    /**
610
     * @param array $questionData
611
     * @param array $answers
612
     */
613
    public function render(FormValidator $form, $questionData = [], $answers = [])
0 ignored issues
show
Unused Code introduced by
The parameter $answers is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

613
    public function render(FormValidator $form, $questionData = [], /** @scrutinizer ignore-unused */ $answers = [])

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $questionData is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

613
    public function render(FormValidator $form, /** @scrutinizer ignore-unused */ $questionData = [], $answers = [])

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
614
    {
615
        return null;
616
    }
617
}
618