Matching   A
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 342
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 37
eloc 198
dl 0
loc 342
rs 9.44
c 0
b 0
f 0

5 Methods

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