Passed
Push — master ( 346325...dc78e4 )
by
unknown
23:25 queued 14:41
created

UniqueAnswer::processAnswersCreation()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 36
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 24
nc 4
nop 2
dl 0
loc 36
rs 9.536
c 1
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use ChamiloSession as Session;
6
7
/**
8
 * Class UniqueAnswer.
9
 *
10
 * This class allows to instantiate an object of type UNIQUE_ANSWER
11
 * (MULTIPLE CHOICE, UNIQUE ANSWER),
12
 * extending the class question
13
 *
14
 * @author Eric Marguin
15
 * @author Julio Montoya
16
 */
17
class UniqueAnswer extends Question
18
{
19
    public $typePicture = 'mcua.png';
20
    public $explanationLangVar = 'Multiple choice';
21
22
    public function __construct()
23
    {
24
        parent::__construct();
25
        $this->type = UNIQUE_ANSWER;
26
        $this->isContent = $this->getIsContent();
27
    }
28
29
    public function createAnswersForm($form)
30
    {
31
        // Getting the exercise list
32
        /** @var Exercise $obj_ex */
33
        $obj_ex = Session::read('objExercise');
34
35
        $editor_config = [
36
            'ToolbarSet' => 'TestProposedAnswer',
37
            'Width' => '100%',
38
            'Height' => '125',
39
        ];
40
41
        //this line defines how many questions by default appear when creating a choice question
42
        // The previous default value was 2. See task #1759.
43
        $nb_answers = isset($_POST['nb_answers']) ? (int) $_POST['nb_answers'] : 4;
44
        $nb_answers += (isset($_POST['lessAnswers']) ? -1 : (isset($_POST['moreAnswers']) ? 1 : 0));
45
46
        $feedback_title = '';
47
        switch ($obj_ex->getFeedbackType()) {
48
            case EXERCISE_FEEDBACK_TYPE_DIRECT:
49
                // Scenario
50
                $comment_title = '<th width="20%">'.get_lang('Comment').'</th>';
51
                break;
52
            case EXERCISE_FEEDBACK_TYPE_POPUP:
53
                $comment_title = '<th width="20%">'.get_lang('Comment').'</th>';
54
55
                break;
56
            default:
57
                $comment_title = '<th width="40%">'.get_lang('Comment').'</th>';
58
59
                break;
60
        }
61
62
        $html = '<table class="table table-striped table-hover">
63
            <thead>
64
                <tr style="text-align: center;">
65
                    <th width="5%">'.get_lang('N°').'</th>
66
                    <th width="5%"> '.get_lang('True').'</th>
67
                    <th width="40%">'.get_lang('Answer').'</th>
68
                        '.$comment_title.'
69
                    <th width="10%">'.get_lang('Score').'</th>
70
                </tr>
71
            </thead>
72
            <tbody>';
73
74
        $form->addHeader(get_lang('Answers'));
75
        $form->addHtml($html);
76
77
        $defaults = [];
78
        $correct = 0;
79
        if (!empty($this->id)) {
80
            $answer = new Answer($this->id);
81
            $answer->read();
82
            if ($answer->nbrAnswers > 0 && !$form->isSubmitted()) {
83
                $nb_answers = $answer->nbrAnswers;
84
            }
85
        }
86
        $form->addHidden('nb_answers', $nb_answers);
87
88
        $obj_ex->setQuestionList(true);
89
        $question_list = $obj_ex->getQuestionList();
90
        $select_question = [];
91
        $select_question[0] = get_lang('Select target question');
92
        if (is_array($question_list)) {
93
            foreach ($question_list as $key => $questionid) {
94
                //To avoid warning messages
95
                if (!is_numeric($questionid)) {
96
                    continue;
97
                }
98
                $question = Question::read($questionid);
99
                $questionTitle = strip_tags($question->selectTitle());
100
                $select_question[$questionid] = "Q$key: $questionTitle";
101
            }
102
        }
103
        $select_question[-1] = get_lang('Exit test');
104
105
        $list = new LearnpathList(api_get_user_id());
106
        $flat_list = $list->get_flat_list();
107
        $select_lp_id = [];
108
        $select_lp_id[0] = get_lang('Select target course');
109
110
        foreach ($flat_list as $id => $details) {
111
            $select_lp_id[$id] = cut($details['lp_name'], 20);
112
        }
113
114
        $temp_scenario = [];
115
        if ($nb_answers < 1) {
116
            $nb_answers = 1;
117
            echo Display::return_message(get_lang('You have to create at least one answer'));
118
        }
119
120
        for ($i = 1; $i <= $nb_answers; $i++) {
121
            $form->addHtml('<tr>');
122
            if (isset($answer) && is_object($answer)) {
123
                if (isset($answer->correct[$i]) && $answer->correct[$i]) {
124
                    $correct = $i;
125
                }
126
                $defaults['answer['.$i.']'] = isset($answer->answer[$i]) ? $answer->answer[$i] : '';
127
                $defaults['comment['.$i.']'] = isset($answer->comment[$i]) ? $answer->comment[$i] : '';
128
                $defaults['weighting['.$i.']'] = isset($answer->weighting[$i]) ? float_format($answer->weighting[$i], 1) : 0;
129
            } else {
130
                $defaults['answer[1]'] = get_lang('A then B then C');
131
                $defaults['weighting[1]'] = 10;
132
                $defaults['answer[2]'] = get_lang('A then C then B');
133
                $defaults['weighting[2]'] = 0;
134
                $temp_scenario['destination'.$i] = ['0'];
135
                $temp_scenario['lp'.$i] = ['0'];
136
            }
137
            $defaults['scenario'] = $temp_scenario;
138
139
            $renderer = $form->defaultRenderer();
140
141
            $renderer->setElementTemplate(
142
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
143
                'correct'
144
            );
145
            $renderer->setElementTemplate(
146
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
147
                'counter['.$i.']'
148
            );
149
            $renderer->setElementTemplate(
150
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
151
                'answer['.$i.']'
152
            );
153
            $renderer->setElementTemplate(
154
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
155
                'comment['.$i.']'
156
            );
157
            $renderer->setElementTemplate(
158
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
159
                'weighting['.$i.']'
160
            );
161
162
            $answerNumber = $form->addText(
163
                'counter['.$i.']',
164
                null,
165
                false,
166
                ['value' => $i]
167
            );
168
            $answerNumber->freeze();
169
170
            $form->addElement(
171
                'radio',
172
                'correct',
173
                null,
174
                null,
175
                $i,
176
                ['class' => 'checkbox']
177
            );
178
179
            $form->addHtmlEditor('answer['.$i.']', null, null, false, $editor_config);
180
181
            $form->addRule(
182
                'answer['.$i.']',
183
                get_lang('Required field'),
184
                'required'
185
            );
186
187
            switch ($obj_ex->getFeedbackType()) {
188
                case EXERCISE_FEEDBACK_TYPE_DIRECT:
189
                    $this->setDirectOptions($i, $form, $renderer, $select_lp_id, $select_question);
190
191
                    break;
192
                case EXERCISE_FEEDBACK_TYPE_POPUP:
193
                default:
194
                    $form->addHtmlEditor('comment['.$i.']', null, null, false, $editor_config);
195
196
                    break;
197
            }
198
            $form->addText('weighting['.$i.']', null, null, ['value' => '0']);
199
            $form->addHtml('</tr>');
200
        }
201
202
        $form->addHtml('</tbody>');
203
        $form->addHtml('</table>');
204
205
        global $text;
206
        $buttonGroup = [];
207
208
        if (true == $obj_ex->edit_exercise_in_lp ||
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
209
            (empty($this->exerciseList) && empty($obj_ex->id))
210
        ) {
211
212
            //setting the save button here and not in the question class.php
213
            $buttonGroup[] = $form->addButtonDelete(get_lang('Remove answer option'), 'lessAnswers', true);
214
            $buttonGroup[] = $form->addButtonCreate(get_lang('Add answer option'), 'moreAnswers', true);
215
            $buttonGroup[] = $form->addButton(
216
                'submitQuestion',
217
                $text,
218
                'check',
219
                'primary',
220
                'default',
221
                null,
222
                ['id' => 'submit-question'],
223
                true
224
            );
225
            $form->addGroup($buttonGroup);
226
        }
227
228
        // We check the first radio button to be sure a radio button will be check
229
        if (0 == $correct) {
230
            $correct = 1;
231
        }
232
233
        if (isset($_POST) && isset($_POST['correct'])) {
234
            $correct = (int) $_POST['correct'];
235
        }
236
237
        $defaults['correct'] = $correct;
238
239
        if (!empty($this->id)) {
240
241
            if (!empty($this->id)) {
242
                $table = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
243
                $res = Database::select(
244
                    'destination',
245
                    $table,
246
                    ['where' => ['question_id = ? AND quiz_id = ?' => [$this->id, $obj_ex->id]], 'limit' => 1],
247
                    'first'
248
                );
249
250
                if (!empty($res['destination'])) {
251
                    $json = json_decode($res['destination'], true);
252
                    $defaults['scenario_success_selector'] = $json['success'] ?? '';
253
                    $defaults['scenario_failure_selector'] = $json['failure'] ?? '';
254
255
                    if (str_starts_with($json['success'] ?? '', '/')) {
256
                        $defaults['scenario_success_selector'] = 'url';
257
                        $defaults['scenario_success_url'] = $json['success'];
258
                    }
259
                    if (str_starts_with($json['failure'] ?? '', '/')) {
260
                        $defaults['scenario_failure_selector'] = 'url';
261
                        $defaults['scenario_failure_url'] = $json['failure'];
262
                    }
263
                }
264
            }
265
            $form->setDefaults($defaults);
266
        } else {
267
            if (1 == $this->isContent) {
268
                // Default sample content.
269
                $form->setDefaults($defaults);
270
            } else {
271
                $correct = 1;
272
                if (isset($_POST) && isset($_POST['correct'])) {
273
                    $correct = (int) $_POST['correct'];
274
                }
275
276
                $form->setDefaults(['correct' => $correct]);
277
            }
278
        }
279
        $form->setConstants(['nb_answers' => $nb_answers]);
280
    }
281
282
    public function setDirectOptions($i, FormValidator $form, $renderer, $select_lp_id, $select_question)
283
    {
284
        $editor_config = [
285
            'ToolbarSet' => 'TestProposedAnswer',
286
            'Width' => '100%',
287
            'Height' => '125',
288
        ];
289
290
        $form->addHtmlEditor(
291
            'comment['.$i.']',
292
            null,
293
            null,
294
            false,
295
            $editor_config
296
        );
297
    }
298
299
    public function processAnswersCreation($form, $exercise)
300
    {
301
        $questionWeighting = 0;
302
        $nbrGoodAnswers    = 0;
303
        $correct           = $form->getSubmitValue('correct');
304
        $objAnswer         = new Answer($this->id);
305
        $nb_answers        = (int) $form->getSubmitValue('nb_answers');
306
307
        for ($i = 1; $i <= $nb_answers; $i++) {
308
            $answer    = trim($form->getSubmitValue('answer['.$i.']'));
309
            $comment   = trim($form->getSubmitValue('comment['.$i.']'));
310
            $weighting = trim($form->getSubmitValue('weighting['.$i.']'));
311
            $goodAnswer = ($correct == $i);
312
313
            if ($goodAnswer) {
314
                $nbrGoodAnswers++;
315
                $weighting = abs($weighting);
316
                if ($weighting > 0) {
317
                    $questionWeighting += $weighting;
318
                }
319
            }
320
321
            $objAnswer->createAnswer(
322
                $answer,
323
                $goodAnswer,
324
                $comment,
325
                $weighting,
326
                $i
327
            );
328
        }
329
330
        $objAnswer->save();
331
332
        // Update question total weighting and persist changes.
333
        $this->updateWeighting($questionWeighting);
334
        $this->save($exercise);
335
    }
336
337
    public function return_header(Exercise $exercise, $counter = null, $score = [])
338
    {
339
        $header = parent::return_header($exercise, $counter, $score);
340
        $header .= '<table class="'.$this->questionTableClass.'"><tr>';
341
342
        $header .= '<th>'.get_lang('Your choice').'</th>';
343
        if ($exercise->showExpectedChoiceColumn()) {
344
            $header .= '<th>'.get_lang('Expected choice').'</th>';
345
        }
346
347
        $header .= '<th>'.get_lang('Answer').'</th>';
348
        if ($exercise->showExpectedChoice()) {
349
            $header .= '<th class="text-center">'.get_lang('Status').'</th>';
350
        }
351
        if (false === $exercise->hideComment) {
352
            $header .= '<th>'.get_lang('Comment').'</th>';
353
        }
354
        $header .= '</tr>';
355
356
        return $header;
357
    }
358
}
359