Passed
Pull Request — master (#6637)
by
unknown
14:37 queued 06:29
created

Matching::processAnswersCreation()   B

Complexity

Conditions 6
Paths 20

Size

Total Lines 43
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 28
nc 20
nop 2
dl 0
loc 43
rs 8.8497
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CourseBundle\Entity\CQuizAnswer;
6
7
/**
8
 * Class Matching
9
 * Matching questions type class.
10
 *
11
 * This class allows to instantiate an object of
12
 * type MULTIPLE_ANSWER (MULTIPLE CHOICE, MULTIPLE ANSWER)
13
 * extending the class question
14
 *
15
 * @author Eric Marguin
16
 */
17
class Matching extends Question
18
{
19
    public $typePicture = 'matching.png';
20
    public $explanationLangVar = 'Matching';
21
22
    public function __construct()
23
    {
24
        parent::__construct();
25
        $this->type = MATCHING;
26
        $this->isContent = $this->getIsContent();
27
    }
28
29
    public function createAnswersForm($form)
30
    {
31
        $defaults = [];
32
        $nb_matches = $nb_options = 2;
33
        $matches = [];
34
        $answer = null;
35
        $counter = 1;
36
37
        if (isset($this->id)) {
38
            $answer = new Answer($this->id);
39
            $answer->read();
40
            if ($answer->nbrAnswers > 0) {
41
                for ($i = 1; $i <= $answer->nbrAnswers; $i++) {
42
                    $correct = $answer->isCorrect($i);
43
                    if (empty($correct)) {
44
                        $matches[$answer->selectAutoId($i)] = chr(64 + $counter);
45
                        $counter++;
46
                    }
47
                }
48
            }
49
        }
50
51
        if ($form->isSubmitted()) {
52
            $nb_matches = $form->getSubmitValue('nb_matches');
53
            $nb_options = $form->getSubmitValue('nb_options');
54
            if (isset($_POST['lessOptions'])) {
55
                $nb_matches--;
56
                $nb_options--;
57
            }
58
            if (isset($_POST['moreOptions'])) {
59
                $nb_matches++;
60
                $nb_options++;
61
            }
62
        } elseif (!empty($this->id)) {
63
            if ($answer->nbrAnswers > 0) {
64
                $nb_matches = $nb_options = 0;
65
                for ($i = 1; $i <= $answer->nbrAnswers; $i++) {
66
                    if ($answer->isCorrect($i)) {
67
                        $nb_matches++;
68
                        $defaults['answer['.$nb_matches.']'] = $answer->selectAnswer($i);
69
                        if (MATCHING === $this->type) {
70
                            $defaults['weighting['.$nb_matches.']'] = float_format($answer->selectWeighting($i), 1);
71
                        }
72
                        $defaults['matches['.$nb_matches.']'] = $answer->correct[$i];
73
                    } else {
74
                        $nb_options++;
75
                        $defaults['option['.$nb_options.']'] = $answer->selectAnswer($i);
76
                    }
77
                }
78
            }
79
        } else {
80
            $defaults['answer[1]'] = get_lang('First step');
81
            $defaults['answer[2]'] = get_lang('Second step');
82
            $defaults['matches[2]'] = '2';
83
            $defaults['option[1]'] = get_lang('Note down the address');
84
            $defaults['option[2]'] = get_lang('Contact the emergency services');
85
        }
86
87
        if (empty($matches)) {
88
            for ($i = 1; $i <= $nb_options; $i++) {
89
                // fill the array with A, B, C.....
90
                $matches[$i] = chr(64 + $i);
91
            }
92
        } else {
93
            for ($i = $counter; $i <= $nb_options; $i++) {
94
                // fill the array with A, B, C.....
95
                $matches[$i] = chr(64 + $i);
96
            }
97
        }
98
99
        $form->addElement('hidden', 'nb_matches', $nb_matches);
100
        $form->addElement('hidden', 'nb_options', $nb_options);
101
102
        $thWeighting = '';
103
        if (MATCHING === $this->type) {
104
            $thWeighting = '<th width="10%">'.get_lang('Score').'</th>';
105
        }
106
107
        // DISPLAY MATCHES
108
        $html = '<table class="table table-striped table-hover">
109
        <thead>
110
            <tr>
111
                <th width="5%">'.get_lang('N°').'</th>
112
                <th width="70%">'.get_lang('Answer').'</th>
113
                <th width="15%">'.get_lang('Matches To').'</th>
114
                '.$thWeighting.'
115
            </tr>
116
        </thead>
117
        <tbody>';
118
119
        $form->addHeader(get_lang('Match them'));
120
        $form->addHtml($html);
121
122
        if ($nb_matches < 1) {
123
            $nb_matches = 1;
124
            Display::addFlash(
125
                Display::return_message(get_lang('You have to create at least one answer'))
126
            );
127
        }
128
129
        $editorConfig = [
130
            'ToolbarSet' => 'TestMatching',
131
            'Width' => '100%',
132
            'Height' => '125',
133
        ];
134
135
        for ($i = 1; $i <= $nb_matches; $i++) {
136
            $renderer = &$form->defaultRenderer();
137
            $renderer->setElementTemplate(
138
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
139
                "answer[$i]"
140
            );
141
142
            $renderer->setElementTemplate(
143
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
144
                "matches[$i]"
145
            );
146
147
            $renderer->setElementTemplate(
148
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
149
                "weighting[$i]"
150
            );
151
152
            $form->addHtml('<tr>');
153
            $form->addHtml("<td>$i</td>");
154
            $form->addHtmlEditor(
155
                "answer[$i]",
156
                null,
157
                null,
158
                false,
159
                $editorConfig
160
            );
161
            $form->addSelect(
162
                "matches[$i]",
163
                null,
164
                $matches,
165
                ['id' => 'matches_'.$i]
166
            );
167
            if (MATCHING === $this->type) {
168
                $form->addText(
169
                    "weighting[$i]",
170
                    null,
171
                    true,
172
                    ['id' => 'weighting_'.$i, 'value' => 10]
173
                );
174
            } else {
175
                $form->addHidden("weighting[$i]", "0");
176
            }
177
            $form->addHtml('</tr>');
178
        }
179
180
        $form->addHtml('</tbody></table>');
181
182
        // DISPLAY OPTIONS
183
        $html = '<table class="table table-striped table-hover">
184
            <thead>
185
                <tr>
186
                    <th width="15%">'.get_lang('N°').'</th>
187
                    <th width="85%">'.get_lang('Answer').'</th>
188
                </tr>
189
            </thead>
190
            <tbody>';
191
192
        $form->addHtml($html);
193
194
        if ($nb_options < 1) {
195
            $nb_options = 1;
196
            Display::addFlash(
197
                Display::return_message(get_lang('You have to create at least one answer'))
198
            );
199
        }
200
201
        for ($i = 1; $i <= $nb_options; $i++) {
202
            $renderer = &$form->defaultRenderer();
203
            $renderer->setElementTemplate(
204
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
205
                "option[$i]"
206
            );
207
208
            $form->addHtml('<tr>');
209
            $form->addHtml('<td>'.chr(64 + $i).'</td>');
210
            $form->addHtmlEditor(
211
                "option[$i]",
212
                null,
213
                null,
214
                false,
215
                $editorConfig
216
            );
217
218
            $form->addHtml('</tr>');
219
        }
220
221
        $form->addHtml('</table>');
222
223
        if (MATCHING_COMBINATION === $this->type) {
224
            $form->addText('questionWeighting', get_lang('Score'), true, ['value' => 10]);
225
226
            if (!empty($this->id)) {
227
                $defaults['questionWeighting'] = $this->weighting;
228
            }
229
        }
230
231
        global $text;
232
        $group = [];
233
        // setting the save button here and not in the question class.php
234
        $group[] = $form->addButtonDelete(get_lang('Remove element'), 'lessOptions', true);
235
        $group[] = $form->addButtonCreate(get_lang('Add element'), 'moreOptions', true);
236
        $group[] = $form->addButtonSave($text, 'submitQuestion', true);
237
        $form->addGroup($group);
238
239
        if (!empty($this->id)) {
240
            $form->setDefaults($defaults);
241
        } else {
242
            if (1 == $this->isContent) {
243
                $form->setDefaults($defaults);
244
            }
245
        }
246
247
        $form->setConstants(
248
            [
249
                'nb_matches' => $nb_matches,
250
                'nb_options' => $nb_options,
251
            ]
252
        );
253
    }
254
255
    public function processAnswersCreation($form, $exercise)
256
    {
257
        $nb_matches = $form->getSubmitValue('nb_matches');
258
        $nb_options = $form->getSubmitValue('nb_options');
259
        $this->weighting = 0;
260
        $position = 0;
261
        $objAnswer = new Answer($this->id);
262
263
        // Insert the options
264
        for ($i = 1; $i <= $nb_options; $i++) {
265
            $position++;
266
            $option = $form->getSubmitValue('option['.$i.']');
267
            $objAnswer->createAnswer($option, 0, '', 0, $position);
268
        }
269
270
        // Insert the answers
271
        for ($i = 1; $i <= $nb_matches; $i++) {
272
            $position++;
273
            $answer  = $form->getSubmitValue('answer['.$i.']');
274
            $matches = $form->getSubmitValue('matches['.$i.']');
275
            $rowWeight = (MATCHING === $this->type)
276
                ? (float) $form->getSubmitValue('weighting['.$i.']')
277
                : 0.0;
278
279
            if (MATCHING === $this->type) {
280
                $this->weighting += $rowWeight;
281
            }
282
283
            $objAnswer->createAnswer(
284
                $answer,
285
                $matches,
286
                '',
287
                $rowWeight,
288
                $position
289
            );
290
        }
291
292
        if (MATCHING_COMBINATION === $this->type) {
293
            $this->weighting = (float) $form->getSubmitValue('questionWeighting');
294
        }
295
296
        $objAnswer->save();
297
        $this->save($exercise);
298
    }
299
300
    public function return_header(Exercise $exercise, $counter = null, $score = [])
301
    {
302
        $header = parent::return_header($exercise, $counter, $score);
303
        $header .= '<table class="'.$this->questionTableClass.'">';
304
        $header .= '<tr>';
305
        $header .= '<th>'.get_lang('Elements list').'</th>';
306
        if (!in_array($exercise->results_disabled, [
307
            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
308
        ])
309
        ) {
310
            $header .= '<th>'.get_lang('Your choice').'</th>';
311
            if ($exercise->showExpectedChoiceColumn()) {
312
                $header .= '<th>'.get_lang('Expected choice').'</th>';
313
            }
314
        }
315
316
        if ($exercise->showExpectedChoice()) {
317
            $header .= '<th class="text-center">'.get_lang('Status').'</th>';
318
        }
319
        $header .= '</tr>';
320
321
        return $header;
322
    }
323
324
    /**
325
     * Check if a answer is correct.
326
     *
327
     * @param int $position
328
     * @param int $answer
329
     * @param int $questionId
330
     *
331
     * @return bool
332
     */
333
    public static function isCorrect($position, $answer, $questionId)
334
    {
335
        $count = Database::getManager()
336
            ->getRepository(CQuizAnswer::class)
337
            ->count(['iid' => $position, 'correct' => $answer, 'question' => $questionId]);
338
339
        return (bool) $count;
340
    }
341
}
342