survey_question::createForm()   F
last analyzed

Complexity

Conditions 23
Paths > 20000

Size

Total Lines 153
Code Lines 116

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 116
c 0
b 0
f 0
nc 67584
nop 2
dl 0
loc 153
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CourseBundle\Entity\CSurvey;
6
use Chamilo\CourseBundle\Entity\CSurveyQuestion;
7
use ChamiloSession as Session;
8
9
/**
10
 * Class survey_question.
11
 */
12
class survey_question
13
{
14
    public $buttonList = [];
15
    /** @var FormValidator */
16
    private $form;
17
18
    /**
19
     * @param array $surveyData
20
     */
21
    public function addParentMenu($formData, FormValidator $form, $surveyData)
22
    {
23
        $surveyId = $surveyData['iid'];
24
        $questionId = isset($formData['question_id']) ? $formData['question_id'] : 0;
25
        $parentId = isset($formData['parent_id']) ? $formData['parent_id'] : 0;
26
        $optionId = isset($formData['parent_option_id']) ? $formData['parent_option_id'] : 0;
27
        $questions = SurveyManager::get_questions($surveyId);
28
29
        $newQuestionList = [];
30
        $allowTypes = ['yesno', 'multiplechoice', 'multipleresponse'];
31
        foreach ($questions as $question) {
32
            if (in_array($question['type'], $allowTypes)) {
33
                $newQuestionList[$question['sort']] = $question;
34
            }
35
        }
36
        ksort($newQuestionList);
37
38
        $options = [];
39
        foreach ($newQuestionList as $question) {
40
            if (!empty($questionId)) {
41
                if ($question['question_id'] == $questionId) {
42
                    break;
43
                }
44
            }
45
            $options[$question['question_id']] = strip_tags($question['question']);
46
        }
47
        $form->addSelect(
48
            'parent_id',
49
            get_lang('Parent'),
50
            $options,
51
            ['id' => 'parent_id', 'placeholder' => get_lang('Please select an option')]
52
        );
53
        $url = api_get_path(WEB_AJAX_PATH).
54
            'survey.ajax.php?'.api_get_cidreq().'&a=load_question_options&survey_id='.$surveyId;
55
        $form->addHtml('
56
            <script>
57
                $(function() {
58
                    $("#parent_id").on("change", function() {
59
                        var questionId = $(this).val()
60
                        var $select = $("#parent_option_id");
61
                        $select.empty();
62
63
                        if (questionId === "") {
64
                              $("#option_list").hide();
65
                        } else {
66
                            $.getJSON({
67
                                url: "'.$url.'" + "&question_id=" + questionId,
68
                            success: function(data) {
69
                                $("#option_list").show();
70
                                    $.each(data, function(key, value) {
71
                                        $("<option>").val(key).text(value).appendTo($select);
72
                                    });
73
                            }
74
                        });
75
                        }
76
                    });
77
                });
78
            </script>
79
        ');
80
81
        $style = 'display:none';
82
        $options = [];
83
        if (!empty($optionId) && !empty($parentId)) {
84
            $parentData = SurveyManager::get_question($parentId);
85
            $style = '';
86
            foreach ($parentData['answer_data'] as $answer) {
87
                $options[$answer['iid']] = strip_tags($answer['data']);
88
            }
89
        }
90
91
        $form->addHtml('<div id="option_list" style="'.$style.'">');
92
        $form->addSelect(
93
            'parent_option_id',
94
            get_lang('Option'),
95
            $options,
96
            ['id' => 'parent_option_id', 'disable_js' => true]
97
        );
98
        $form->addHtml('</div>');
99
    }
100
101
    /**
102
     * @param string $type
103
     *
104
     * @return survey_question
105
     */
106
    public static function createQuestion($type)
107
    {
108
        switch ($type) {
109
            case 'comment':
110
                return new ch_comment();
111
            case 'dropdown':
112
                return new ch_dropdown();
113
            case 'multiplechoice':
114
                return new ch_multiplechoice();
115
            case 'multipleresponse':
116
                return new ch_multipleresponse();
117
            case 'open':
118
                return new ch_open();
119
            case 'pagebreak':
120
                return new ch_pagebreak();
121
            case 'percentage':
122
                return new ch_percentage();
123
            case 'personality':
124
                return new ch_personality();
125
            case 'score':
126
                return new ch_score();
127
            case 'yesno':
128
                return new ch_yesno();
129
            case 'selectivedisplay':
130
                return new ch_selectivedisplay();
131
            case 'multiplechoiceother':
132
                return new ch_multiplechoiceother();
133
            default:
134
                api_not_allowed(true);
135
                break;
136
        }
137
    }
138
139
    /**
140
     * Generic part of any survey question: the question field.
141
     *
142
     * @param array $surveyData
143
     * @param array $formData
144
     *
145
     * @return FormValidator
146
     */
147
    public function createForm($surveyData, $formData)
148
    {
149
        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : null;
150
        $questionId = isset($_GET['question_id']) ? (int) $_GET['question_id'] : null;
151
        $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : null;
152
        $type = isset($_GET['type']) ? Security::remove_XSS($_GET['type']) : null;
153
154
        $actionHeader = get_lang('Edit question').': ';
155
        if ('add' === $action) {
156
            $actionHeader = get_lang('Add a question').': ';
157
        }
158
159
        $questionComment = '';
160
        $allowParent = false;
161
        switch ($type) {
162
            case 'open':
163
                $toolName = get_lang('Open');
164
                $questionComment = get_lang("You can use the tags {{class_name}} and {{student_full_name}} in the question to be able to multiply questions. On the survey list page, in the action field, you have a button to multiply a question that will look for the {{class_name}} tag, duplicate the question for all the classes subscribed to the course, and rename it with the name of the class. It will also add a page ending to make a new page for each class. Then it will look for the {{student_full_name}} tag and duplicate the question for all the students in the class (for each class) and rename it with the student's full name.");
165
                $allowParent = true;
166
                break;
167
            case 'yesno':
168
                $toolName = get_lang('Yes / No');
169
                $allowParent = true;
170
                break;
171
            case 'multiplechoice':
172
                $toolName = get_lang('Multiple choice');
173
                $allowParent = true;
174
                break;
175
            case 'multipleresponse':
176
                $toolName = get_lang('Multiple answers');
177
                $allowParent = true;
178
                break;
179
            case 'selectivedisplay':
180
                $toolName = get_lang('Selective display');
181
                $questionComment = get_lang(
182
                    "This question, when located on a single survey page with a first multiple choice question, will only show if the first *option* of the first question is selected. For example, 'Did you go on holiday?' -> if answering the first option 'Yes', the selective display question will appear with a list of possible holiday locations to select from."
183
                );
184
                $allowParent = true;
185
                break;
186
            case 'multiplechoiceother':
187
                $toolName = get_lang('Multiple choice with free text');
188
                $questionComment = get_lang(
189
                    'Offer some pre-defined options, then let the user answer by text if no option matches.'
190
                );
191
                $allowParent = true;
192
                break;
193
            case 'pagebreak':
194
                $toolName = get_lang(api_ucfirst($type));
195
                $allowParent = false;
196
                break;
197
            default:
198
                $toolName = get_lang(api_ucfirst($type));
199
                $allowParent = true;
200
                break;
201
        }
202
203
        $icon = Display::getMdiIcon(
204
                SurveyManager::icon_question($type),
205
                'ch-tool-icon',
206
                null,
207
                ICON_SIZE_SMALL,
208
                $toolName
209
            ).' ';
210
211
        $toolName = $icon.$actionHeader.$toolName;
212
        $sharedQuestionId = $formData['shared_question_id'] ?? null;
213
214
        $url = api_get_self().
215
            '?action='.$action.'&type='.$type.'&survey_id='.$surveyId.'&question_id='.$questionId.'&'.api_get_cidreq();
216
        $form = new FormValidator('question_form', 'post', $url);
217
        $form->addHeader($toolName);
218
        if (!empty($questionComment)) {
219
            $form->addHtml(Display::return_message($questionComment, 'info', false));
220
        }
221
        $form->addHidden('survey_id', $surveyId);
222
        $form->addHidden('question_id', $questionId);
223
        $form->addHidden('shared_question_id', Security::remove_XSS($sharedQuestionId));
224
        $form->addHidden('type', $type);
225
226
        $config = [
227
            'ToolbarSet' => 'SurveyQuestion',
228
            'Width' => '100%',
229
            'Height' => '120',
230
        ];
231
        $form->addHtmlEditor(
232
            'question',
233
            get_lang('Question'),
234
            true,
235
            false,
236
            $config
237
        );
238
239
        if (in_array($_GET['type'], ['yesno', 'multiplechoice'])) {
240
            $form->addCheckBox('is_required', get_lang('Mandatory?'), get_lang('Yes'));
241
        }
242
243
        if ($allowParent) {
244
            $this->addParentMenu($formData, $form, $surveyData);
245
        }
246
        // When survey type = 1??
247
        if (1 == $surveyData['survey_type']) {
248
            $table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
249
            $sql = 'SELECT id, title FROM '.$table_survey_question_group.'
250
                    WHERE survey_id = '.$surveyId.'
251
                    ORDER BY name';
252
            $rs = Database::query($sql);
253
            $glist = null;
254
            while ($row = Database::fetch_array($rs, 'NUM')) {
255
                $glist .= '<option value="'.$row[0].'" >'.$row[1].'</option>';
256
            }
257
258
            $grouplist = $grouplist1 = $grouplist2 = $glist;
259
            if (!empty($formData['assigned'])) {
260
                $grouplist = str_replace(
261
                    '<option value="'.$formData['assigned'].'"',
262
                    '<option value="'.$formData['assigned'].'" selected',
263
                    $glist
264
                );
265
            }
266
267
            if (!empty($formData['assigned1'])) {
268
                $grouplist1 = str_replace(
269
                    '<option value="'.$formData['assigned1'].'"',
270
                    '<option value="'.$formData['assigned1'].'" selected',
271
                    $glist
272
                );
273
            }
274
275
            if (!empty($formData['assigned2'])) {
276
                $grouplist2 = str_replace(
277
                    '<option value="'.$formData['assigned2'].'"',
278
                    '<option value="'.$formData['assigned2'].'" selected',
279
                    $glist
280
                );
281
            }
282
283
            $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...
284
                <fieldset style="border:1px solid black">
285
                    <legend>'.get_lang('Condition').'</legend>
286
                <b>'.get_lang('Primary').'</b><br />
287
			    <input type="radio" name="choose" value="1" '.((1 == $formData['choose']) ? 'checked' : '').'>
288
			    <select name="assigned">'.$grouplist.'</select><br />';
289
            $this->html .= '
290
			<b>'.get_lang('Secondary').'</b><br />
291
			    <input type="radio" name="choose" value="2" '.((2 == $formData['choose']) ? 'checked' : '').'>
292
			    <select name="assigned1">'.$grouplist1.'</select>
293
                <select name="assigned2">'.$grouplist2.'</select>
294
            </fieldset><br />';
295
        }
296
297
        $this->setForm($form);
298
299
        return $form;
300
    }
301
302
    /**
303
     * Adds submit button.
304
     */
305
    public function renderForm()
306
    {
307
        if (isset($_GET['question_id']) && !empty($_GET['question_id'])) {
308
            /**
309
             * Prevent the edition of already-answered questions to avoid
310
             * inconsistent answers. Use the configuration option
311
             * survey_allow_answered_question_edit to change this behaviour.
312
             */
313
            $surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : 0;
314
            $answersChecker = SurveyUtil::checkIfSurveyHasAnswers($surveyId);
315
            $allowQuestionEdit = ('true' === api_get_setting('survey.survey_allow_answered_question_edit'));
316
            if ($allowQuestionEdit || !$answersChecker) {
317
                $this->buttonList[] = $this->getForm()->addButtonUpdate(get_lang('Edit question'), 'save', true);
318
            } else {
319
                $this->getForm()->addHtml('
320
                    <div class="form-group">
321
                        <label class="col-sm-2 control-label"></label>
322
                        <div class="col-sm-8">
323
                            <div class="alert alert-info">'.
324
                            get_lang("You can't edit this question because answers by students have already been registered").'</div>
325
                        </div>
326
                        <div class="col-sm-2"></div>
327
                    </div>
328
                ');
329
            }
330
        } else {
331
            $this->buttonList[] = $this->getForm()->addButtonSave(get_lang('Create question'), 'save', true);
332
        }
333
334
        $this->getForm()->addGroup($this->buttonList, 'buttons');
335
    }
336
337
    /**
338
     * @return FormValidator
339
     */
340
    public function getForm()
341
    {
342
        return $this->form;
343
    }
344
345
    /**
346
     * @param FormValidator $form
347
     */
348
    public function setForm($form)
349
    {
350
        $this->form = $form;
351
    }
352
353
    /**
354
     * @param array $formData
355
     *
356
     * @return mixed
357
     */
358
    public function preSave($formData)
359
    {
360
        $counter = Session::read('answer_count');
361
        $answerList = Session::read('answer_list');
362
363
        if (empty($answerList)) {
364
            $answerList = $formData['answers'] ?? [];
365
            Session::write('answer_list', $answerList);
366
        }
367
368
        if (isset($_POST['answers'])) {
369
            $formData['question'] = $_POST['question'];
370
            $formData['answers'] = $_POST['answers'];
371
        }
372
373
        if (empty($counter)) {
374
            $counter = count($answerList) - 1;
375
            Session::write('answer_count', $counter);
376
        }
377
378
        // Moving an answer up
379
        if (isset($_POST['move_up']) && $_POST['move_up']) {
380
            foreach ($_POST['move_up'] as $key => &$value) {
381
                $id1 = $key;
382
                $content1 = $formData['answers'][$id1];
383
                $id2 = $key - 1;
384
                $content2 = $formData['answers'][$id2];
385
                $formData['answers'][$id1] = $content2;
386
                $formData['answers'][$id2] = $content1;
387
            }
388
        }
389
390
        // Moving an answer down
391
        if (isset($_POST['move_down']) && $_POST['move_down']) {
392
            foreach ($_POST['move_down'] as $key => &$value) {
393
                $id1 = $key;
394
                $content1 = $formData['answers'][$id1];
395
                $id2 = $key + 1;
396
                $content2 = $formData['answers'][$id2];
397
                $formData['answers'][$id1] = $content2;
398
                $formData['answers'][$id2] = $content1;
399
            }
400
        }
401
402
        /**
403
         * Deleting a specific answer is only saved in the session until the
404
         * "Save question" button is pressed. This means all options are kept
405
         * in the survey_question_option table until the question is saved.
406
         */
407
        if (isset($_POST['delete_answer'])) {
408
            $deleted = false;
409
            foreach ($_POST['delete_answer'] as $key => &$value) {
410
                $deleted = $key;
411
                $counter--;
412
                Session::write('answer_count', $counter);
413
            }
414
415
            $newAnswers = [];
416
            $newAnswersId = [];
417
            foreach ($formData['answers'] as $key => &$value) {
418
                if ($key > $deleted) {
419
                    // swap with previous (deleted) option slot
420
                    $newAnswers[$key - 1] = $formData['answers'][$key];
421
                    $newAnswersId[$key - 1] = $formData['answersid'][$key] ?? 0;
422
                    unset($formData['answers'][$key]);
423
                    unset($formData['answersid'][$key]);
424
                } elseif ($key === $deleted) {
425
                    // delete option
426
                    unset($formData['answers'][$deleted]);
427
                    unset($formData['answersid'][$deleted]);
428
                } else {
429
                    // keep as is
430
                    $newAnswers[$key] = $value;
431
                    if (isset($formData['answersid'])) {
432
                        $newAnswersId[$key] = $formData['answersid'][$key];
433
                    }
434
                }
435
            }
436
            unset($formData['answers']);
437
            unset($formData['answersid']);
438
            $formData['answers'] = $newAnswers;
439
            $formData['answersid'] = $newAnswersId;
440
        }
441
442
        // Adding an answer
443
        if (isset($_POST['buttons']) && isset($_POST['buttons']['add_answer'])) {
444
            if (isset($_REQUEST['type']) && 'multiplechoiceother' === $_REQUEST['type'] && $counter > 2) {
445
                $counter--;
446
            }
447
            $counter++;
448
            Session::write('answer_count', $counter);
449
        }
450
451
        // Removing an answer
452
        if (isset($_POST['buttons']) && isset($_POST['buttons']['remove_answer'])) {
453
            $counter--;
454
            Session::write('answer_count', $counter);
455
            foreach ($formData['answers'] as $index => &$data) {
456
                if ($index > $counter) {
457
                    unset($formData['answers'][$index]);
458
                    unset($formData['answersid'][$index]);
459
                }
460
            }
461
        }
462
463
        if (!isset($_POST['delete_answer'])) {
464
            // Make sure we have an array of answers
465
            if (!isset($formData['answers'])) {
466
                $formData['answers'] = [];
467
            }
468
            // Check if no deleted answer remains at the end of the answers
469
            // array and add empty answers if the array is too short
470
            foreach ($formData['answers'] as $index => $data) {
471
                if ($index > $counter) {
472
                    unset($formData['answers'][$index]);
473
                }
474
            }
475
476
            for ($i = 0; $i <= $counter; $i++) {
477
                if (!isset($formData['answers'][$i])) {
478
                    $formData['answers'][$i] = '';
479
                }
480
            }
481
        }
482
483
        $formData['answers'] = isset($formData['answers']) ? $formData['answers'] : [];
484
        Session::write('answer_list', $formData['answers']);
485
486
        if (!isset($formData['is_required']) && ('true' === api_get_setting('survey.survey_mark_question_as_required'))) {
487
            $formData['is_required'] = true;
488
        }
489
490
        return $formData;
491
    }
492
493
    public function save(CSurvey $survey, array $formData, array $dataFromDatabase = [])
494
    {
495
        // Saving a question
496
        if (isset($_POST['buttons']) && isset($_POST['buttons']['save'])) {
497
            Session::erase('answer_count');
498
            Session::erase('answer_list');
499
            $result = SurveyManager::saveQuestion($survey, $formData, true, $dataFromDatabase);
500
            if (false === $result['error']) {
501
                Display::addFlash(Display::return_message($result['message']));
502
                $url = api_get_path(WEB_CODE_PATH).'survey/survey.php?survey_id='.$survey->getIid().'&'.api_get_cidreq();
503
                header('Location: '.$url);
504
                exit;
505
            }
506
        }
507
508
        return $formData;
509
    }
510
511
    /**
512
     * Adds two buttons. One to add an option, one to remove an option.
513
     *
514
     * @param array $data
515
     */
516
    public function addRemoveButtons($data)
517
    {
518
        $this->buttonList['remove_answer'] = $this->getForm()->createElement(
519
            'button',
520
            'remove_answer',
521
            get_lang('Remove option'),
522
            'minus',
523
            'default'
524
        );
525
526
        if (count($data['answers']) <= 2) {
527
            $this->buttonList['remove_answer']->updateAttributes(
528
                ['disabled' => 'disabled']
529
            );
530
        }
531
532
        $this->buttonList['add_answer'] = $this->getForm()->createElement(
533
            'button',
534
            'add_answer',
535
            get_lang('Add option'),
536
            'plus',
537
            'default'
538
        );
539
    }
540
541
    /**
542
     * Get the JS for questions that can depend on a previous question
543
     * (and that hides those questions until something changes in the previous
544
     * question).
545
     *
546
     * @return string HTML code
547
     */
548
    public static function getJs()
549
    {
550
        return '
551
            <style>
552
            .with_parent {
553
                display: none;
554
            }
555
            </style>
556
            <script>
557
            $(function() {
558
            });
559
            </script>';
560
    }
561
562
    /**
563
     * Get the question parents recursively, if any. This function depends on
564
     * the existence of a parent_id field, which depends on the
565
     * 'survey_question_dependency' setting and its corresponding SQL
566
     * requirements.
567
     *
568
     * @param int   $questionId The c_survey_question.question.id
569
     * @param array $list       An array of parents to be extended by this method
570
     *
571
     * @return array The completed array of parents
572
     */
573
    public static function getParents($questionId, $list = [])
574
    {
575
        $courseId = api_get_course_int_id();
576
        $questionId = (int) $questionId;
577
578
        $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
579
        $sql = "SELECT parent_id FROM $table
580
                WHERE c_id = $courseId AND question_id = $questionId ";
581
        $result = Database::query($sql);
582
        $row = Database::fetch_assoc($result);
583
        if ($row && !empty($row['parent_id'])) {
584
            $list[] = $row['parent_id'];
585
            $list = self::getParents($row['parent_id'], $list);
586
        }
587
588
        return $list;
589
    }
590
591
    /**
592
     * Creates the JS code for the given parent question so that it shows
593
     * the children questions when a specific answer of the parent is selected.
594
     *
595
     * @param array $question An array with the question details
596
     *
597
     * @return string JS code to add to the HTML survey question page
598
     */
599
    public static function getQuestionJs($question)
600
    {
601
        if (empty($question)) {
602
            return '';
603
        }
604
605
        $list = self::getDependency($question);
606
607
        if (empty($list)) {
608
            return '';
609
        }
610
611
        $type = $question['type'];
612
        $questionId = $question['question_id'];
613
        $newList = [];
614
        foreach ($list as $child) {
615
            $childQuestionId = $child['question_id'];
616
            $optionId = $child['parent_option_id'];
617
            $newList[$optionId][] = $childQuestionId;
618
        }
619
620
        if ('multipleresponse' === $type) {
621
            $multiple = '';
622
            foreach ($newList as $optionId => $child) {
623
                $multiple .= '
624
                    $(\'input[name="question'.$questionId.'['.$optionId.']"]\').on("change", function() {
625
                        var isChecked= $(this).is(\':checked\');
626
                        var checkedValue = $(this).val();
627
                        if (isChecked) {
628
                            $.each(list, function(index, value) {
629
                                $(".with_parent_" + value).find("input").prop("checked", false);
630
                            });
631
632
                            var questionId = $(this).val();
633
                            var questionToShow = list[questionId];
634
                            $(".with_parent_" + questionToShow).show();
635
                        } else {
636
                            var checkedValue = list[checkedValue];
637
                        }
638
                    });
639
                ';
640
            }
641
642
            $js = '
643
            <script>
644
            $(function() {
645
                var list = '.json_encode($newList).';
646
                '.$multiple.'
647
            });
648
            </script>';
649
650
            return $js;
651
        }
652
653
        $js = '
654
            <script>
655
            $(function() {
656
                var list = '.json_encode($newList).';
657
                $("input[name=question'.$questionId.']").on("click", function() {
658
                    $.each(list, function(index, value) {
659
                         $.each(value, function(index, itemValue) {
660
                            $(".with_parent_" + itemValue).hide();
661
                            $(".with_parent_" + itemValue).find("input").prop("checked", false);
662
                            $(".with_parent_only_hide_" + itemValue).hide();
663
                        });
664
                    });
665
666
                    var questionId = $(this).val();
667
                    var questionToShowList = list[questionId];
668
                    $.each(questionToShowList, function(index, value) {
669
                        $(".with_parent_" + value).show();
670
                    });
671
                });
672
            });
673
            </script>';
674
675
        return $js;
676
    }
677
678
    /**
679
     * Returns the (children) questions that have the given question as parent.
680
     *
681
     * @param array $question An array describing the parent question
682
     *
683
     * @return array The questions that have the given question as parent
684
     */
685
    public static function getDependency(array $question): ?array
686
    {
687
        $questionId = $question['question_id'];
688
689
        $em = Database::getManager();
690
691
        $queryBuilder = $em->createQueryBuilder();
692
        $queryBuilder->select('q')
693
            ->from(CSurveyQuestion::class, 'q')
694
            ->where('q.parent = :parent')
695
            ->setParameter('parent', $questionId);
696
697
        return $queryBuilder->getQuery()->getArrayResult();
698
    }
699
700
    /**
701
     * This method is not implemented at this level (returns null).
702
     *
703
     * @param array $questionData
704
     * @param array $answers
705
     */
706
    public function render(FormValidator $form, $questionData = [], $answers = [])
707
    {
708
        return null;
709
    }
710
}
711