Passed
Push — 1.11.x ( bce6cd...c146d9 )
by Angel Fernando Quiroz
12:25
created

main/exercise/UniqueAnswerImage.php (1 issue)

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use ChamiloSession as Session;
6
7
/**
8
 * UniqueAnswerImage.
9
 *
10
 * @author Angel Fernando Quiroz Campos <[email protected]>
11
 */
12
class UniqueAnswerImage extends UniqueAnswer
13
{
14
    public $typePicture = 'uaimg.png';
15
    public $explanationLangVar = 'UniqueAnswerImage';
16
17
    /**
18
     * UniqueAnswerImage constructor.
19
     */
20
    public function __construct()
21
    {
22
        parent::__construct();
23
        $this->type = UNIQUE_ANSWER_IMAGE;
24
        $this->isContent = $this->getIsContent();
25
    }
26
27
    /**
28
     * {@inheritdoc}
29
     *
30
     * @throws Exception
31
     */
32
    public function createAnswersForm($form)
33
    {
34
        $objExercise = Session::read('objExercise');
35
        $editorConfig = [
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
        $numberAnswers = isset($_POST['nb_answers']) ? (int) $_POST['nb_answers'] : 4;
44
        $numberAnswers += (isset($_POST['lessAnswers']) ? -1 : (isset($_POST['moreAnswers']) ? 1 : 0));
45
46
        $feedbackTitle = '';
47
        switch ($objExercise->getFeedbackType()) {
48
            case EXERCISE_FEEDBACK_TYPE_DIRECT:
49
                // Scenario
50
                $commentTitle = '<th width="20%">'.get_lang('Comment').'</th>';
51
                $feedbackTitle = '<th width="20%">'.get_lang('Scenario').'</th>';
52
                break;
53
            case EXERCISE_FEEDBACK_TYPE_POPUP:
54
                $commentTitle = '<th width="20%">'.get_lang('Comment').'</th>';
55
                break;
56
            default:
57
                $commentTitle = '<th width="40%">'.get_lang('Comment').'</th>';
58
                break;
59
        }
60
61
        $html = '<div class="alert alert-success" role="alert">'.
62
                get_lang('UniqueAnswerImagePreferredSize200x150').'</div>';
63
64
        $zoomOptions = api_get_configuration_value('quiz_image_zoom');
65
        if (isset($zoomOptions['options'])) {
66
            $finderFolder = api_get_path(WEB_PATH).'vendor/studio-42/elfinder/';
67
            $html .= '<!-- elFinder CSS (REQUIRED) -->';
68
            $html .= '<link rel="stylesheet" type="text/css" media="screen"
69
                href="'.$finderFolder.'css/elfinder.full.css">';
70
            $html .= '<link rel="stylesheet" type="text/css" media="screen" href="'.$finderFolder.'css/theme.css">';
71
            $html .= '<!-- elFinder JS (REQUIRED) -->';
72
            $html .= '<script type="text/javascript" src="'.$finderFolder.'js/elfinder.full.js"></script>';
73
            $html .= '<!-- elFinder translation (OPTIONAL) -->';
74
            $language = 'en';
75
            $platformLanguage = api_get_interface_language();
76
            $iso = api_get_language_isocode($platformLanguage);
77
            $filePart = "vendor/studio-42/elfinder/js/i18n/elfinder.$iso.js";
78
            $file = api_get_path(SYS_PATH).$filePart;
79
            $includeFile = '';
80
            if (file_exists($file)) {
81
                $includeFile = '<script type="text/javascript" src="'.api_get_path(WEB_PATH).$filePart.'"></script>';
82
                $language = $iso;
83
            }
84
            $html .= $includeFile;
85
86
            $html .= '<script type="text/javascript" charset="utf-8">
87
            $(function() {
88
                $(".add_img_link").on("click", function(e){
89
                    e.preventDefault();
90
                    e.stopPropagation();
91
92
                    var name = $(this).prop("name");
93
                    var id = parseInt(name.match(/[0-9]+/));
94
95
                    $([document.documentElement, document.body]).animate({
96
                        scrollTop: $("#elfinder").offset().top
97
                    }, 1000);
98
99
                    var elf = $("#elfinder").elfinder({
100
                        url : "'.api_get_path(WEB_LIBRARY_PATH).'elfinder/connectorAction.php?'.api_get_cidreq().'",
101
                        getFileCallback: function(file) {
102
                            var filePath = file; //file contains the relative url.
103
                            var imageZoom = filePath.url;
104
                            var iname = "answer["+id+"]";
105
106
                            CKEDITOR.instances[iname].insertHtml(\'
107
                                <img
108
                                    id="zoom_picture"
109
                                    class="zoom_picture"
110
                                    src="\'+imageZoom+\'"
111
                                    data-zoom-image="\'+imageZoom+\'"
112
                                    width="200px"
113
                                    height="150px"
114
                                />\');
115
116
                            $("#elfinder").elfinder("destroy"); //close the window after image is selected
117
                        },
118
                        startPathHash: "l2_Lw", // Sets the course driver as default
119
                        resizable: false,
120
                        lang: "'.$language.'"
121
                    }).elfinder("instance"+id);
122
                });
123
            });
124
            </script>';
125
            $html .= '<div id="elfinder"></div>';
126
        }
127
128
        $html .= '<table class="table table-striped table-hover">
129
            <thead>
130
                <tr style="text-align: center;">
131
                    <th width="10">'.get_lang('Number').'</th>
132
                    <th>'.get_lang('True').'</th>
133
                    <th>'.get_lang('Answer').'</th>
134
                        '.$commentTitle.'
135
                        '.$feedbackTitle.'
136
                    <th width="15">'.get_lang('Weighting').'</th>
137
                </tr>
138
            </thead>
139
            <tbody>';
140
141
        $form->addHeader(get_lang('Answers'));
142
        $form->addHtml($html);
143
144
        $defaults = [];
145
        $correct = 0;
146
147
        if (!empty($this->iid)) {
148
            $answer = new Answer($this->iid);
149
            $answer->read();
150
151
            if ($answer->nbrAnswers > 0 && !$form->isSubmitted()) {
152
                $numberAnswers = $answer->nbrAnswers;
153
            }
154
        }
155
156
        $form->addElement('hidden', 'nb_answers');
157
158
        //Feedback SELECT
159
        $questionList = $objExercise->selectQuestionList();
160
        $selectQuestion = [];
161
        $selectQuestion[0] = get_lang('SelectTargetQuestion');
162
163
        if (is_array($questionList)) {
164
            foreach ($questionList as $key => $questionid) {
165
                //To avoid warning messages
166
                if (!is_numeric($questionid)) {
167
                    continue;
168
                }
169
170
                $question = Question::read($questionid);
171
                $questionTitle = strip_tags($question->selectTitle());
172
                $selectQuestion[$questionid] = "Q$key: $questionTitle";
173
            }
174
        }
175
176
        $selectQuestion[-1] = get_lang('ExitTest');
177
178
        $list = new LearnpathList(api_get_user_id());
179
        $flatList = $list->get_flat_list();
180
        $selectLpId = [];
181
        $selectLpId[0] = get_lang('SelectTargetLP');
182
183
        foreach ($flatList as $id => $details) {
184
            $selectLpId[$id] = cut($details['lp_name'], 20);
185
        }
186
187
        $tempScenario = [];
188
        if ($numberAnswers < 1) {
189
            $numberAnswers = 1;
190
            echo Display::return_message(get_lang('YouHaveToCreateAtLeastOneAnswer'));
191
        }
192
193
        for ($i = 1; $i <= $numberAnswers; $i++) {
194
            $form->addHtml('<tr>');
195
            if (isset($answer) && is_object($answer)) {
196
                if ($answer->correct[$i]) {
197
                    $correct = $i;
198
                }
199
200
                $defaults['answer['.$i.']'] = $answer->answer[$i];
201
                $defaults['comment['.$i.']'] = $answer->comment[$i];
202
                $defaults['weighting['.$i.']'] = float_format(
203
                    $answer->weighting[$i],
204
                    1
205
                );
206
207
                $itemList = explode('@@', $answer->destination[$i]);
208
209
                $try = $itemList[0];
210
                $lp = $itemList[1];
211
                $listDestination = $itemList[2];
212
                $url = $itemList[3];
213
214
                $tryResult = 0;
215
                if (0 != $try) {
216
                    $tryResult = 1;
217
                }
218
219
                $urlResult = '';
220
                if (0 != $url) {
221
                    $urlResult = $url;
222
                }
223
224
                $tempScenario['url'.$i] = $urlResult;
225
                $tempScenario['try'.$i] = $tryResult;
226
                $tempScenario['lp'.$i] = $lp;
227
                $tempScenario['destination'.$i] = $listDestination;
228
            } else {
229
                $defaults['answer[1]'] = get_lang('DefaultUniqueAnswer1');
230
                $defaults['weighting[1]'] = 10;
231
                $defaults['answer[2]'] = get_lang('DefaultUniqueAnswer2');
232
                $defaults['weighting[2]'] = 0;
233
234
                $tempScenario['destination'.$i] = ['0'];
235
                $tempScenario['lp'.$i] = ['0'];
236
            }
237
238
            $defaults['scenario'] = $tempScenario;
239
            $renderer = $form->defaultRenderer();
240
            $renderer->setElementTemplate(
241
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
242
                'correct'
243
            );
244
            $renderer->setElementTemplate(
245
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
246
                'counter['.$i.']'
247
            );
248
            $renderer->setElementTemplate(
249
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}'.
250
                    (isset($zoomOptions['options']) ?
251
                    '<br><div class="form-group ">
252
                        <label for="question_admin_form_btn_add_img['.$i.']" class="col-sm-2 control-label"></label>
253
                        <div class="col-sm-8">
254
                            <button class="add_img_link btn btn-info btn-sm"
255
                                name="btn_add_img['.$i.']"
256
                                type="submit"
257
                                id="question_admin_form_btn_add_img['.$i.']">
258
                                <em class="fa fa-plus"></em> '.get_lang('AddImageWithZoom').'
259
                            </button>
260
                        </div>
261
                        <div class="col-sm-2"></div>
262
                    </div>' : '').'</td>',
263
                'answer['.$i.']'
264
            );
265
            $renderer->setElementTemplate(
266
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
267
                'comment['.$i.']'
268
            );
269
            $renderer->setElementTemplate(
270
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
271
                'weighting['.$i.']'
272
            );
273
274
            $answerNumber = $form->addElement('text', 'counter['.$i.']', null, ' value = "'.$i.'"');
275
            $answerNumber->freeze();
276
277
            $form->addElement('radio', 'correct', null, null, $i, 'class="checkbox"');
278
            $form->addHtmlEditor('answer['.$i.']', null, null, false, $editorConfig);
279
280
            $form->addRule('answer['.$i.']', get_lang('ThisFieldIsRequired'), 'required');
281
282
            switch ($objExercise->getFeedbackType()) {
283
                case EXERCISE_FEEDBACK_TYPE_DIRECT:
284
                    $this->setDirectOptions($i, $form, $renderer, $selectLpId, $selectQuestion);
285
                    break;
286
                case EXERCISE_FEEDBACK_TYPE_POPUP:
287
                default:
288
                    $form->addHtmlEditor('comment['.$i.']', null, null, false, $editorConfig);
289
                    break;
290
            }
291
292
            $form->addText('weighting['.$i.']', null, null, ['class' => 'col-md-1', 'value' => '0']);
293
            $form->addHtml('</tr>');
294
        }
295
296
        $form->addHtml('</tbody>');
297
        $form->addHtml('</table>');
298
299
        global $text;
300
        $buttonGroup = [];
301
        if ($objExercise->edit_exercise_in_lp == true ||
302
            (empty($this->exerciseList) && empty($objExercise->iid))
303
        ) {
304
            //setting the save button here and not in the question class.php
305
            $buttonGroup[] = $form->addButtonDelete(get_lang('LessAnswer'), 'lessAnswers', true);
306
            $buttonGroup[] = $form->addButtonCreate(get_lang('PlusAnswer'), 'moreAnswers', true);
307
            $buttonGroup[] = $form->addButtonSave($text, 'submitQuestion', true);
308
            $form->addGroup($buttonGroup);
309
        }
310
311
        // We check the first radio button to be sure a radio button will be check
312
        if (0 == $correct) {
313
            $correct = 1;
314
        }
315
316
        $defaults['correct'] = $correct;
317
318
        if (!empty($this->iid)) {
319
            $form->setDefaults($defaults);
320
        } else {
321
            if (1 == $this->isContent) {
322
                // Default sample content.
323
                $form->setDefaults($defaults);
324
            } else {
325
                $form->setDefaults(['correct' => 1]);
326
            }
327
        }
328
329
        $form->setConstants(['nb_answers' => $numberAnswers]);
330
    }
331
332
    /**
333
     * {@inheritdoc}
334
     */
335
    public function processAnswersCreation($form, $exercise)
336
    {
337
        $questionWeighting = $nbrGoodAnswers = 0;
338
        $correct = $form->getSubmitValue('correct');
339
        $objAnswer = new Answer($this->iid);
340
        $numberAnswers = $form->getSubmitValue('nb_answers');
341
342
        for ($i = 1; $i <= $numberAnswers; $i++) {
343
            $answer = trim(str_replace(['<p>', '</p>'], '', $form->getSubmitValue('answer['.$i.']')));
344
            $comment = trim(str_replace(['<p>', '</p>'], '', $form->getSubmitValue('comment['.$i.']')));
345
            $weighting = trim($form->getSubmitValue('weighting['.$i.']'));
346
347
            $scenario = $form->getSubmitValue('scenario');
348
349
            //$listDestination = $form -> getSubmitValue('destination'.$i);
350
            //$destinationStr = $form -> getSubmitValue('destination'.$i);
351
            if (!empty($scenario)) {
352
                $try = $scenario['try'.$i];
353
                $lp = $scenario['lp'.$i];
354
                $destination = $scenario['destination'.$i];
355
                $url = trim($scenario['url'.$i]);
356
            }
357
358
            /*
359
              How we are going to parse the destination value
360
361
              here we parse the destination value which is a string
362
              1@@3@@2;4;4;@@http://www.chamilo.org
363
364
              where: try_again@@lp_id@@selected_questions@@url
365
366
              try_again = is 1 || 0
367
              lp_id = id of a learning path (0 if dont select)
368
              selected_questions= ids of questions
369
              url= an url
370
371
              $destinationStr='';
372
              foreach ($listDestination as $destination_id)
373
              {
374
              $destinationStr.=$destination_id.';';
375
              } */
376
            $goodAnswer = $correct == $i ? true : false;
377
            if ($goodAnswer) {
378
                $nbrGoodAnswers++;
379
                $weighting = abs($weighting);
380
381
                if ($weighting > 0) {
382
                    $questionWeighting += $weighting;
383
                }
384
            }
385
386
            if (empty($try)) {
387
                $try = 0;
388
            }
389
390
            if (empty($lp)) {
391
                $lp = 0;
392
            }
393
394
            if (empty($destination)) {
395
                $destination = 0;
396
            }
397
398
            if ($url == '') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $url does not seem to be defined for all execution paths leading up to this point.
Loading history...
399
                $url = 0;
400
            }
401
402
            //1@@1;2;@@2;4;4;@@http://www.chamilo.org
403
            $dest = $try.'@@'.$lp.'@@'.$destination.'@@'.$url;
404
405
            $objAnswer->createAnswer(
406
                $answer,
407
                $goodAnswer,
408
                $comment,
409
                $weighting,
410
                $i,
411
                null,
412
                null,
413
                $dest
414
            );
415
        }
416
417
        // saves the answers into the data base
418
        $objAnswer->save();
419
420
        // sets the total weighting of the question
421
        $this->updateWeighting($questionWeighting);
422
        $this->save($exercise);
423
    }
424
425
    /**
426
     * {@inheritdoc}
427
     */
428
    public function return_header(Exercise $exercise, $counter = null, $score = [])
429
    {
430
        if ($exercise->showExpectedChoice()) {
431
            $header = '<table class="'.$this->question_table_class.'">
432
			<tr>
433
				<th>'.get_lang('Choice').'</th>';
434
            if ($exercise->showExpectedChoiceColumn()) {
435
                $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
436
            }
437
            $header .= '<th>'.get_lang('Answer').'</th>';
438
            $header .= '<th>'.get_lang('Status').'</th>';
439
            if (false === $exercise->hideComment) {
440
                $header .= '<th>'.get_lang('Comment').'</th>';
441
            }
442
            $header .= '</tr>';
443
        } else {
444
            $header = parent::return_header($exercise, $counter, $score);
445
        }
446
447
        return $header;
448
    }
449
}
450