Passed
Pull Request — 1.11.x (#3871)
by Angel Fernando Quiroz
10:43
created

Answer::updateAnswers()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 33
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 16
nc 2
nop 9
dl 0
loc 33
rs 9.7333
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CourseBundle\Entity\CQuizAnswer;
6
7
/**
8
 * Class Answer
9
 * Allows to instantiate an object of type Answer, as a *list* of answers for one question
10
 * 5 arrays are created to receive the attributes of each answer belonging to a specified question.
11
 *
12
 * @author Olivier Brouckaert
13
 */
14
class Answer
15
{
16
    /* The question of which we want the possible answers */
17
    public $questionId;
18
19
    // these are arrays
20
    public $answer;
21
    public $correct;
22
    public $comment;
23
    public $weighting;
24
    public $position;
25
    public $hotspot_coordinates;
26
    public $hotspot_type;
27
    public $destination;
28
    // these arrays are used to save temporarily new answers
29
    // then they are moved into the arrays above or deleted in the event of cancellation
30
    public $new_answer;
31
    public $new_correct;
32
    public $new_comment;
33
    public $new_weighting;
34
    public $new_position;
35
    public $new_hotspot_coordinates;
36
    public $new_hotspot_type;
37
    public $autoId;
38
    /** @var int Number of answers in the question */
39
    public $nbrAnswers;
40
    public $new_nbrAnswers;
41
    public $new_destination; // id of the next question if feedback option is set to Directfeedback
42
    public $course; //Course information
43
    public $iid;
44
    public $questionJSId;
45
    public $standalone;
46
    /** @var Exercise|null */
47
    private $exercise;
48
49
    /**
50
     * @author Olivier Brouckaert
51
     *
52
     * @param int      $questionId that answers belong to
53
     * @param int      $course_id
54
     * @param Exercise $exercise
55
     * @param bool     $readAnswer
56
     */
57
    public function __construct($questionId, $course_id = 0, $exercise = null, $readAnswer = true)
58
    {
59
        $this->questionId = (int) $questionId;
60
        $this->answer = [];
61
        $this->correct = [];
62
        $this->comment = [];
63
        $this->weighting = [];
64
        $this->position = [];
65
        $this->hotspot_coordinates = [];
66
        $this->hotspot_type = [];
67
        $this->destination = [];
68
        // clears $new_* arrays
69
        $this->cancel();
70
71
        if (!empty($course_id)) {
72
            $courseInfo = api_get_course_info_by_id($course_id);
73
        } else {
74
            $courseInfo = api_get_course_info();
75
        }
76
77
        $this->course = $courseInfo;
78
        $this->course_id = $courseInfo['real_id'];
79
80
        if (empty($exercise)) {
81
            // fills arrays
82
            $objExercise = new Exercise($this->course_id);
83
            $exerciseId = isset($_REQUEST['exerciseId']) ? $_REQUEST['exerciseId'] : null;
84
            $objExercise->read($exerciseId, false);
85
        } else {
86
            $objExercise = $exercise;
87
        }
88
        $this->exercise = $objExercise;
89
90
        if ($readAnswer) {
91
            if ($objExercise->random_answers == '1' && $this->getQuestionType() != CALCULATED_ANSWER) {
92
                $this->readOrderedBy('rand()', ''); // randomize answers
93
            } else {
94
                $this->read(); // natural order
95
            }
96
        }
97
    }
98
99
    /**
100
     * Clears $new_* arrays.
101
     *
102
     * @author Olivier Brouckaert
103
     */
104
    public function cancel()
105
    {
106
        $this->new_answer = [];
107
        $this->new_correct = [];
108
        $this->new_comment = [];
109
        $this->new_weighting = [];
110
        $this->new_position = [];
111
        $this->new_hotspot_coordinates = [];
112
        $this->new_hotspot_type = [];
113
        $this->new_nbrAnswers = 0;
114
        $this->new_destination = [];
115
    }
116
117
    /**
118
     * Reads answer information from the database.
119
     *
120
     * @author Olivier Brouckaert
121
     */
122
    public function read()
123
    {
124
        $table = Database::get_course_table(TABLE_QUIZ_ANSWER);
125
        $questionId = $this->questionId;
126
127
        $sql = "SELECT * FROM $table
128
                WHERE question_id = $questionId
129
                ORDER BY position";
130
131
        $result = Database::query($sql);
132
        $i = 1;
133
134
        // while a record is found
135
        while ($object = Database::fetch_object($result)) {
136
            $this->id[$i] = $object->iid;
137
            $this->iid[$i] = $object->iid;
138
            $this->answer[$i] = $object->answer;
139
            $this->correct[$i] = $object->correct;
140
            $this->comment[$i] = $object->comment;
141
            $this->weighting[$i] = $object->ponderation;
142
            $this->position[$i] = $object->position;
143
            $this->hotspot_coordinates[$i] = $object->hotspot_coordinates;
144
            $this->hotspot_type[$i] = $object->hotspot_type;
145
            $this->destination[$i] = $object->destination;
146
            $this->autoId[$i] = $object->id_auto;
147
            $i++;
148
        }
149
        $this->nbrAnswers = $i - 1;
150
    }
151
152
    /**
153
     * Get answers already added to question.
154
     *
155
     * @return array
156
     */
157
    public function getAnswers()
158
    {
159
        $table = Database::get_course_table(TABLE_QUIZ_ANSWER);
160
        $questionId = $this->questionId;
161
162
        $sql = "SELECT * FROM $table
163
                WHERE question_id = $questionId
164
                ORDER BY position";
165
166
        $result = Database::query($sql);
167
168
        $answers = [];
169
170
        // while a record is found
171
        while ($answer = Database::fetch_assoc($result)) {
172
            $answers[] = $answer;
173
        }
174
175
        return $answers;
176
    }
177
178
    /**
179
     * @param int $id
180
     *
181
     * @return array
182
     */
183
    public function getAnswerByAutoId($id)
184
    {
185
        foreach ($this->autoId as $key => $autoId) {
186
            if ($autoId == $id) {
187
                return [
188
                    'answer' => $this->answer[$key],
189
                    'correct' => $this->correct[$key],
190
                    'comment' => $this->comment[$key],
191
                ];
192
            }
193
        }
194
195
        return [];
196
    }
197
198
    /**
199
     * returns all answer ids from this question Id.
200
     *
201
     * @author Yoselyn Castillo
202
     *
203
     * @return array - $id (answer ids)
204
     */
205
    public function selectAnswerId()
206
    {
207
        $table = Database::get_course_table(TABLE_QUIZ_ANSWER);
208
        $questionId = $this->questionId;
209
210
        $sql = "SELECT iid FROM $table WHERE question_id = $questionId";
211
212
        $result = Database::query($sql);
213
        $id = [];
214
        // while a record is found
215
        if (Database::num_rows($result) > 0) {
216
            while ($object = Database::fetch_array($result)) {
217
                $id[] = $object['iid'];
218
            }
219
        }
220
221
        return $id;
222
    }
223
224
    /**
225
     * Reads answer information from the data base ordered by parameter.
226
     *
227
     * @param string $field Field we want to order by
228
     * @param string $order DESC or ASC
229
     *
230
     * @return bool
231
     *
232
     * @author Frederic Vauthier
233
     */
234
    public function readOrderedBy($field, $order = 'ASC')
235
    {
236
        $field = Database::escape_string($field);
237
        if (empty($field)) {
238
            $field = 'position';
239
        }
240
241
        if ('ASC' != $order && 'DESC' != $order) {
242
            $order = 'ASC';
243
        }
244
245
        $TBL_ANSWER = Database::get_course_table(TABLE_QUIZ_ANSWER);
246
        $TBL_QUESTION = Database::get_course_table(TABLE_QUIZ_QUESTION);
247
        $questionId = (int) $this->questionId;
248
249
        $sql = "SELECT type FROM $TBL_QUESTION
250
                WHERE iid = $questionId";
251
        $result_question = Database::query($sql);
252
        $questionType = Database::fetch_array($result_question);
253
254
        if (DRAGGABLE == $questionType['type']) {
255
            // Random is done by submit.js.tpl
256
            $this->read();
257
258
            return true;
259
        }
260
261
        $sql = "SELECT
262
                    answer,
263
                    correct,
264
                    comment,
265
                    ponderation,
266
                    position,
267
                    hotspot_coordinates,
268
                    hotspot_type,
269
                    destination,
270
                    id_auto,
271
                    iid
272
                FROM $TBL_ANSWER
273
                WHERE
274
                    question_id='".$questionId."'
275
                ORDER BY $field $order";
276
        $result = Database::query($sql);
277
278
        $i = 1;
279
        // while a record is found
280
        $doubt_data = null;
281
        while ($object = Database::fetch_object($result)) {
282
            if ($questionType['type'] == UNIQUE_ANSWER_NO_OPTION && $object->position == 666) {
283
                $doubt_data = $object;
284
                continue;
285
            }
286
            $this->answer[$i] = $object->answer;
287
            $this->correct[$i] = $object->correct;
288
            $this->comment[$i] = $object->comment;
289
            $this->weighting[$i] = $object->ponderation;
290
            $this->position[$i] = $object->position;
291
            $this->hotspot_coordinates[$i] = $object->hotspot_coordinates;
292
            $this->hotspot_type[$i] = $object->hotspot_type;
293
            $this->destination[$i] = $object->destination;
294
            $this->autoId[$i] = $object->id_auto;
295
            $this->iid[$i] = $object->iid;
296
            $i++;
297
        }
298
299
        if ($questionType['type'] == UNIQUE_ANSWER_NO_OPTION && !empty($doubt_data)) {
300
            $this->answer[$i] = $doubt_data->answer;
301
            $this->correct[$i] = $doubt_data->correct;
302
            $this->comment[$i] = $doubt_data->comment;
303
            $this->weighting[$i] = $doubt_data->ponderation;
304
            $this->position[$i] = $doubt_data->position;
305
            $this->hotspot_coordinates[$i] = isset($object->hotspot_coordinates) ? $object->hotspot_coordinates : 0;
306
            $this->hotspot_type[$i] = isset($object->hotspot_type) ? $object->hotspot_type : 0;
307
            $this->destination[$i] = $doubt_data->destination;
308
            $this->autoId[$i] = $doubt_data->id_auto;
309
            $this->iid[$i] = $doubt_data->iid;
310
            $i++;
311
        }
312
        $this->nbrAnswers = $i - 1;
313
314
        return true;
315
    }
316
317
    /**
318
     * returns the autoincrement id.
319
     *
320
     * @author Juan Carlos Ra�a
321
     *
322
     * @return int Answer num
323
     */
324
    public function selectAutoId($id)
325
    {
326
        return isset($this->autoId[$id]) ? $this->autoId[$id] : 0;
327
    }
328
329
    /**
330
     * Returns the unique ID (iid field).
331
     *
332
     * @return int Answer ID
333
     */
334
    public function selectId($id)
335
    {
336
        return isset($this->iid[$id]) ? $this->iid[$id] : 0;
337
    }
338
339
    /**
340
     * returns the number of answers in this question.
341
     *
342
     * @author Olivier Brouckaert
343
     *
344
     * @return int - number of answers
345
     */
346
    public function selectNbrAnswers()
347
    {
348
        return $this->nbrAnswers;
349
    }
350
351
    /**
352
     * returns the question ID which the answers belong to.
353
     *
354
     * @author Olivier Brouckaert
355
     *
356
     * @return int - the question ID
357
     */
358
    public function selectQuestionId()
359
    {
360
        return $this->questionId;
361
    }
362
363
    /**
364
     * returns the question ID of the destination question.
365
     *
366
     * @author Julio Montoya
367
     *
368
     * @param int $id
369
     *
370
     * @return int - the question ID
371
     */
372
    public function selectDestination($id)
373
    {
374
        return isset($this->destination[$id]) ? $this->destination[$id] : null;
375
    }
376
377
    /**
378
     * returns the answer title.
379
     *
380
     * @author Olivier Brouckaert
381
     *
382
     * @param - integer $id - answer ID
383
     *
384
     * @return string - answer title
385
     */
386
    public function selectAnswer($id)
387
    {
388
        return isset($this->answer[$id]) ? $this->answer[$id] : null;
389
    }
390
391
    /**
392
     * return array answer by id else return a bool.
393
     *
394
     * @param int $auto_id
395
     *
396
     * @return array
397
     */
398
    public function selectAnswerByAutoId($auto_id)
399
    {
400
        $table = Database::get_course_table(TABLE_QUIZ_ANSWER);
401
        $auto_id = (int) $auto_id;
402
        $sql = "SELECT iid, answer, id_auto FROM $table
403
                WHERE c_id = {$this->course_id} AND id_auto='$auto_id'";
404
        $rs = Database::query($sql);
405
406
        if (Database::num_rows($rs) > 0) {
407
            return Database::fetch_array($rs, 'ASSOC');
408
        }
409
410
        return false;
411
    }
412
413
    /**
414
     * return array answer by iid. Else return a bool.
415
     *
416
     * @param int $iid
417
     *
418
     * @return array
419
     */
420
    public function selectAnswerById($id)
421
    {
422
        if (empty($id)) {
423
            return false;
424
        }
425
        $table = Database::get_course_table(TABLE_QUIZ_ANSWER);
426
        $id = (int) $id;
427
        $sql = "SELECT iid, answer, id_auto FROM $table
428
                WHERE iid = $id";
429
        $rs = Database::query($sql);
430
431
        if (Database::num_rows($rs) > 0) {
432
            return Database::fetch_array($rs, 'ASSOC');
433
        }
434
435
        return false;
436
    }
437
438
    /**
439
     * returns the answer title from an answer's position.
440
     *
441
     * @author Yannick Warnier
442
     *
443
     * @param - integer $pos - answer ID
444
     *
445
     * @return bool - answer title
446
     */
447
    public function selectAnswerIdByPosition($pos)
448
    {
449
        foreach ($this->position as $k => $v) {
450
            if ($v != $pos) {
451
                continue;
452
            }
453
454
            return $k;
455
        }
456
457
        return false;
458
    }
459
460
    /**
461
     * Returns a list of answers.
462
     *
463
     * @author Yannick Warnier <[email protected]>
464
     *
465
     * @param bool $decode
466
     *
467
     * @return array List of answers where each answer is an array
468
     *               of (id, answer, comment, grade) and grade=weighting
469
     */
470
    public function getAnswersList($decode = false)
471
    {
472
        $list = [];
473
        for ($i = 1; $i <= $this->nbrAnswers; $i++) {
474
            if (!empty($this->answer[$i])) {
475
                //Avoid problems when parsing elements with accents
476
                if ($decode) {
477
                    $this->answer[$i] = api_html_entity_decode(
478
                        $this->answer[$i],
479
                        ENT_QUOTES,
480
                        api_get_system_encoding()
481
                    );
482
                    $this->comment[$i] = api_html_entity_decode(
483
                        $this->comment[$i],
484
                        ENT_QUOTES,
485
                        api_get_system_encoding()
486
                    );
487
                }
488
489
                $list[] = [
490
                    'iid' => $i,
491
                    'answer' => $this->answer[$i],
492
                    'comment' => $this->comment[$i],
493
                    'grade' => $this->weighting[$i],
494
                    'hotspot_coord' => $this->hotspot_coordinates[$i],
495
                    'hotspot_type' => $this->hotspot_type[$i],
496
                    'correct' => $this->correct[$i],
497
                    'destination' => $this->destination[$i],
498
                ];
499
            }
500
        }
501
502
        return $list;
503
    }
504
505
    /**
506
     * Returns a list of grades.
507
     *
508
     * @author Yannick Warnier <[email protected]>
509
     *
510
     * @return array List of grades where grade=weighting (?)
511
     */
512
    public function getGradesList()
513
    {
514
        $list = [];
515
        for ($i = 0; $i < $this->nbrAnswers; $i++) {
516
            if (!empty($this->answer[$i])) {
517
                $list[$i] = $this->weighting[$i];
518
            }
519
        }
520
521
        return $list;
522
    }
523
524
    /**
525
     * Returns the question type.
526
     *
527
     * @author    Yannick Warnier <[email protected]>
528
     *
529
     * @return int The type of the question this answer is bound to
530
     */
531
    public function getQuestionType()
532
    {
533
        $table = Database::get_course_table(TABLE_QUIZ_QUESTION);
534
        $sql = "SELECT type FROM $table
535
                WHERE iid = {$this->questionId}";
536
        $res = Database::query($sql);
537
        if (Database::num_rows($res) <= 0) {
538
            return null;
539
        }
540
        $row = Database::fetch_array($res);
541
542
        return (int) $row['type'];
543
    }
544
545
    /**
546
     * tells if answer is correct or not.
547
     *
548
     * @author Olivier Brouckaert
549
     *
550
     * @param - integer $id - answer ID
551
     *
552
     * @return int - 0 if bad answer, not 0 if good answer
553
     */
554
    public function isCorrect($id)
555
    {
556
        return isset($this->correct[$id]) ? $this->correct[$id] : null;
557
    }
558
559
    /**
560
     * returns answer comment.
561
     *
562
     * @author Olivier Brouckaert
563
     *
564
     * @param - integer $id - answer ID
565
     *
566
     * @return string - answer comment
567
     */
568
    public function selectComment($id)
569
    {
570
        return isset($this->comment[$id]) ? $this->comment[$id] : null;
571
    }
572
573
    /**
574
     * returns answer weighting.
575
     *
576
     * @author Olivier Brouckaert
577
     *
578
     * @param - integer $id - answer ID
579
     *
580
     * @return int - answer weighting
581
     */
582
    public function selectWeighting($id)
583
    {
584
        return isset($this->weighting[$id]) ? $this->weighting[$id] : null;
585
    }
586
587
    /**
588
     * returns answer position.
589
     *
590
     * @author Olivier Brouckaert
591
     *
592
     * @param - integer $id - answer ID
593
     *
594
     * @return int - answer position
595
     */
596
    public function selectPosition($id)
597
    {
598
        return isset($this->position[$id]) ? $this->position[$id] : null;
599
    }
600
601
    /**
602
     * returns answer hotspot coordinates.
603
     *
604
     * @author Olivier Brouckaert
605
     *
606
     * @param int $id Answer ID
607
     *
608
     * @return int Answer position
609
     */
610
    public function selectHotspotCoordinates($id)
611
    {
612
        return isset($this->hotspot_coordinates[$id]) ? $this->hotspot_coordinates[$id] : null;
613
    }
614
615
    /**
616
     * returns answer hotspot type.
617
     *
618
     * @author Toon Keppens
619
     *
620
     * @param int $id Answer ID
621
     *
622
     * @return int Answer position
623
     */
624
    public function selectHotspotType($id)
625
    {
626
        return isset($this->hotspot_type[$id]) ? $this->hotspot_type[$id] : null;
627
    }
628
629
    /**
630
     * Creates a new answer.
631
     *
632
     * @author Olivier Brouckaert
633
     *
634
     * @param string $answer                  answer title
635
     * @param int    $correct                 0 if bad answer, not 0 if good answer
636
     * @param string $comment                 answer comment
637
     * @param int    $weighting               answer weighting
638
     * @param int    $position                answer position
639
     * @param array  $new_hotspot_coordinates Coordinates for hotspot exercises (optional)
640
     * @param int    $new_hotspot_type        Type for hotspot exercises (optional)
641
     * @param string $destination
642
     */
643
    public function createAnswer(
644
        $answer,
645
        $correct,
646
        $comment,
647
        $weighting,
648
        $position,
649
        $new_hotspot_coordinates = null,
650
        $new_hotspot_type = null,
651
        $destination = ''
652
    ) {
653
        $this->new_nbrAnswers++;
654
        $id = $this->new_nbrAnswers;
655
        $this->new_answer[$id] = $answer;
656
        $this->new_correct[$id] = $correct;
657
        $this->new_comment[$id] = $comment;
658
        $this->new_weighting[$id] = $weighting;
659
        $this->new_position[$id] = $position;
660
        $this->new_hotspot_coordinates[$id] = $new_hotspot_coordinates;
661
        $this->new_hotspot_type[$id] = $new_hotspot_type;
662
        $this->new_destination[$id] = $destination;
663
    }
664
665
    /**
666
     * Updates an answer.
667
     *
668
     * @author Toon Keppens
669
     *
670
     * @param int    $iid
671
     * @param string $answer
672
     * @param string $comment
673
     * @param string $correct
674
     * @param string $weighting
675
     * @param string $position
676
     * @param string $destination
677
     * @param string $hotSpotCoordinates
678
     * @param string $hotSpotType
679
     *
680
     * @return CQuizAnswer
681
     */
682
    public function updateAnswers(
683
        $iid,
684
        $answer,
685
        $comment,
686
        $correct,
687
        $weighting,
688
        $position,
689
        $destination,
690
        $hotSpotCoordinates,
691
        $hotSpotType
692
    ) {
693
        $em = Database::getManager();
694
695
        /** @var CQuizAnswer $quizAnswer */
696
        $quizAnswer = $em->find('ChamiloCourseBundle:CQuizAnswer', $iid);
697
        if ($quizAnswer) {
0 ignored issues
show
introduced by
$quizAnswer is of type Chamilo\CourseBundle\Entity\CQuizAnswer, thus it always evaluated to true.
Loading history...
698
            $quizAnswer
699
                ->setAnswer($answer)
700
                ->setComment($comment)
701
                ->setCorrect($correct)
702
                ->setPonderation($weighting)
703
                ->setPosition($position)
704
                ->setDestination($destination)
705
                ->setHotspotCoordinates($hotSpotCoordinates)
706
                ->setHotspotType($hotSpotType);
707
708
            $em->merge($quizAnswer);
709
            $em->flush();
710
711
            return $quizAnswer;
712
        }
713
714
        return false;
715
    }
716
717
    /**
718
     * Records answers into the data base.
719
     *
720
     * @author Olivier Brouckaert
721
     */
722
    public function save()
723
    {
724
        $answerTable = Database::get_course_table(TABLE_QUIZ_ANSWER);
725
        $em = Database::getManager();
726
        $questionId = (int) $this->questionId;
727
728
        $courseId = $this->course['real_id'];
729
        $answerList = [];
730
731
        for ($i = 1; $i <= $this->new_nbrAnswers; $i++) {
732
            $answer = $this->new_answer[$i];
733
            $correct = isset($this->new_correct[$i]) ? $this->new_correct[$i] : '';
734
            $comment = isset($this->new_comment[$i]) ? $this->new_comment[$i] : '';
735
            $weighting = isset($this->new_weighting[$i]) ? $this->new_weighting[$i] : '';
736
            $position = isset($this->new_position[$i]) ? $this->new_position[$i] : '';
737
            $hotspot_coordinates = isset($this->new_hotspot_coordinates[$i]) ? $this->new_hotspot_coordinates[$i] : '';
738
            $hotspot_type = isset($this->new_hotspot_type[$i]) ? $this->new_hotspot_type[$i] : '';
739
            $destination = isset($this->new_destination[$i]) ? $this->new_destination[$i] : '';
740
            $autoId = $this->selectAutoId($i);
741
            $iid = isset($this->iid[$i]) ? $this->iid[$i] : 0;
742
743
            if (!isset($this->position[$i])) {
744
                $quizAnswer = new CQuizAnswer();
745
                $quizAnswer
746
                    ->setIdAuto($autoId)
747
                    ->setCId($courseId)
748
                    ->setQuestionId($questionId)
749
                    ->setAnswer($answer)
750
                    ->setCorrect($correct)
751
                    ->setComment($comment)
752
                    ->setPonderation($weighting)
753
                    ->setPosition($position)
754
                    ->setHotspotCoordinates($hotspot_coordinates)
755
                    ->setHotspotType($hotspot_type)
756
                    ->setDestination($destination);
757
758
                $em->persist($quizAnswer);
759
                $em->flush();
760
761
                $iid = $quizAnswer->getId();
762
763
                if ($iid) {
764
                    $quizAnswer
765
                        ->setId($iid)
766
                        ->setIdAuto($iid);
767
768
                    $questionType = $this->getQuestionType();
769
                    if (in_array(
770
                        $questionType,
771
                        [MATCHING, MATCHING_DRAGGABLE]
772
                    )) {
773
                        $answer = new Answer($this->questionId, $courseId, $this->exercise, false);
774
                        $answer->read();
775
                        $correctAnswerId = $answer->selectAnswerIdByPosition($correct);
776
777
                        // Continue to avoid matching question bug if $correctAnswerId returns false
778
                        // See : https://support.chamilo.org/issues/8334
779
                        if ($questionType == MATCHING && !$correctAnswerId) {
780
                            $em->merge($quizAnswer);
781
                            $em->flush();
782
                            continue;
783
                        }
784
                        $correctAnswerAutoId = $answer->selectAutoId($correct);
785
                        $quizAnswer->setCorrect($correctAnswerAutoId ? $correctAnswerAutoId : 0);
786
                    }
787
788
                    $em->merge($quizAnswer);
789
                    $em->flush();
790
                }
791
            } else {
792
                // https://support.chamilo.org/issues/6558
793
                // function updateAnswers already escape_string, error if we do it twice.
794
                // Feed function updateAnswers with none escaped strings
795
                $this->updateAnswers(
796
                    $iid,
797
                    $this->new_answer[$i],
798
                    $this->new_comment[$i],
799
                    $this->new_correct[$i],
800
                    $this->new_weighting[$i],
801
                    $this->new_position[$i],
802
                    $this->new_destination[$i],
803
                    $this->new_hotspot_coordinates[$i],
804
                    $this->new_hotspot_type[$i]
805
                );
806
            }
807
808
            $answerList[$i] = $iid;
809
        }
810
811
        $questionType = $this->getQuestionType();
812
813
        switch ($questionType) {
814
            case MATCHING_DRAGGABLE:
815
                foreach ($this->new_correct as $value => $status) {
816
                    if (!empty($status)) {
817
                        if (isset($answerList[$status])) {
818
                            $correct = $answerList[$status];
819
                        } else {
820
                            $correct = $status;
821
                        }
822
                        $myAutoId = $answerList[$value];
823
                        $sql = "UPDATE $answerTable
824
                            SET correct = '$correct'
825
                            WHERE
826
                                id_auto = $myAutoId
827
                            ";
828
                        Database::query($sql);
829
                    }
830
                }
831
                break;
832
            case DRAGGABLE:
833
                foreach ($this->new_correct as $value => $status) {
834
                    if (!empty($status)) {
835
                        $correct = $answerList[$status];
836
                        $myAutoId = $answerList[$value];
837
                        $sql = "UPDATE $answerTable
838
                            SET correct = '$correct'
839
                            WHERE
840
                                id_auto = $myAutoId
841
                            ";
842
                        Database::query($sql);
843
                    }
844
                }
845
                break;
846
        }
847
848
        if (count($this->position) > $this->new_nbrAnswers) {
849
            $i = $this->new_nbrAnswers + 1;
850
            while ($this->position[$i]) {
851
                $position = $this->position[$i];
852
                $sql = "DELETE FROM $answerTable
853
                        WHERE
854
                            c_id = {$this->course_id} AND
855
                            question_id = {$questionId} AND
856
                            position ='$position'";
857
                Database::query($sql);
858
                $i++;
859
            }
860
        }
861
862
        // moves $new_* arrays
863
        $this->answer = $this->new_answer;
864
        $this->correct = $this->new_correct;
865
        $this->comment = $this->new_comment;
866
        $this->weighting = $this->new_weighting;
867
        $this->position = $this->new_position;
868
        $this->hotspot_coordinates = $this->new_hotspot_coordinates;
869
        $this->hotspot_type = $this->new_hotspot_type;
870
        $this->nbrAnswers = $this->new_nbrAnswers;
871
        $this->destination = $this->new_destination;
872
873
        $this->cancel();
874
    }
875
876
    /**
877
     * Duplicates answers by copying them into another question.
878
     *
879
     * @author Olivier Brouckaert
880
     *
881
     * @param Question $newQuestion
882
     * @param array    $course_info destination course info (result of the function api_get_course_info() )
883
     */
884
    public function duplicate($newQuestion, $course_info = null)
885
    {
886
        $newQuestionId = $newQuestion->iid;
887
888
        if (empty($course_info)) {
889
            $course_info = $this->course;
890
        }
891
892
        $fixed_list = [];
893
        $tableAnswer = Database::get_course_table(TABLE_QUIZ_ANSWER);
894
895
        if (self::getQuestionType() == MULTIPLE_ANSWER_TRUE_FALSE ||
896
            self::getQuestionType() == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY
897
        ) {
898
            // Selecting origin options
899
            $origin_options = Question::readQuestionOption(
900
                $this->selectQuestionId(),
901
                $this->course['real_id']
902
            );
903
904
            if (!empty($origin_options)) {
905
                foreach ($origin_options as $item) {
906
                    $new_option_list[] = $item['iid'];
907
                }
908
            }
909
910
            $destination_options = Question::readQuestionOption(
911
                $newQuestionId,
912
                $course_info['real_id']
913
            );
914
            $i = 0;
915
            if (!empty($destination_options)) {
916
                foreach ($destination_options as $item) {
917
                    $fixed_list[$new_option_list[$i]] = $item['iid'];
918
                    $i++;
919
                }
920
            }
921
        }
922
923
        // if at least one answer
924
        if ($this->nbrAnswers) {
925
            // inserts new answers into data base
926
            $courseId = $course_info['real_id'];
927
            $correctAnswers = [];
928
            $onlyAnswers = [];
929
            $allAnswers = [];
930
931
            $em = Database::getManager();
932
933
            if (in_array($newQuestion->type, [MATCHING, MATCHING_DRAGGABLE])) {
934
                $temp = [];
935
                for ($i = 1; $i <= $this->nbrAnswers; $i++) {
936
                    $answer = [
937
                        'iid' => $this->iid[$i],
938
                        'answer' => $this->answer[$i],
939
                        'correct' => $this->correct[$i],
940
                        'comment' => $this->comment[$i],
941
                        'weighting' => $this->weighting[$i],
942
                        'ponderation' => $this->weighting[$i],
943
                        'position' => $this->position[$i],
944
                        'hotspot_coordinates' => $this->hotspot_coordinates[$i],
945
                        'hotspot_type' => $this->hotspot_type[$i],
946
                        'destination' => $this->destination[$i],
947
                    ];
948
                    $temp[$answer['position']] = $answer;
949
                    $allAnswers[$this->iid[$i]] = $this->answer[$i];
950
                }
951
952
                foreach ($temp as $answer) {
953
                    if ($this->course['id'] != $course_info['id']) {
954
                        // check resources inside html from ckeditor tool and copy correct urls into recipient course
955
                        $answer['answer'] = DocumentManager::replaceUrlWithNewCourseCode(
956
                            $answer['answer'],
957
                            $this->course['id'],
958
                            $course_info['id']
959
                        );
960
961
                        $answer['comment'] = DocumentManager::replaceUrlWithNewCourseCode(
962
                            $answer['comment'],
963
                            $this->course['id'],
964
                            $course_info['id']
965
                        );
966
                    }
967
968
                    $quizAnswer = new CQuizAnswer();
969
                    $quizAnswer
970
                        ->setCId($courseId)
971
                        ->setQuestionId($newQuestionId)
972
                        ->setAnswer($answer['answer'])
973
                        ->setCorrect($answer['correct'])
974
                        ->setComment($answer['comment'])
975
                        ->setPonderation($answer['ponderation'])
976
                        ->setPosition($answer['position'])
977
                        ->setHotspotCoordinates($answer['hotspot_coordinates'])
978
                        ->setHotspotType($answer['hotspot_type'])
979
                        ->setIdAuto(0);
980
981
                    $em->persist($quizAnswer);
982
                    $em->flush();
983
984
                    $answerId = $quizAnswer->getId();
985
986
                    if ($answerId) {
987
                        $quizAnswer
988
                            ->setId($answerId)
989
                            ->setIdAuto($answerId);
990
991
                        $em->merge($quizAnswer);
992
                        $em->flush();
993
994
                        $correctAnswers[$answerId] = $answer['correct'];
995
                        $onlyAnswers[$answerId] = $answer['answer'];
996
                    }
997
                }
998
            } else {
999
                for ($i = 1; $i <= $this->nbrAnswers; $i++) {
1000
                    if ($this->course['id'] != $course_info['id']) {
1001
                        $this->answer[$i] = DocumentManager::replaceUrlWithNewCourseCode(
1002
                            $this->answer[$i],
1003
                            $this->course['id'],
1004
                            $course_info['id']
1005
                        );
1006
                        $this->comment[$i] = DocumentManager::replaceUrlWithNewCourseCode(
1007
                            $this->comment[$i],
1008
                            $this->course['id'],
1009
                            $course_info['id']
1010
                        );
1011
                    }
1012
1013
                    $correct = $this->correct[$i];
1014
                    if ($newQuestion->type == MULTIPLE_ANSWER_TRUE_FALSE ||
1015
                        $newQuestion->type == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY
1016
                    ) {
1017
                        $correct = $fixed_list[intval($correct)];
1018
                    }
1019
1020
                    $quizAnswer = new CQuizAnswer();
1021
                    $quizAnswer
1022
                        ->setCId($courseId)
1023
                        ->setQuestionId($newQuestionId)
1024
                        ->setAnswer($this->answer[$i])
1025
                        ->setCorrect($correct)
1026
                        ->setComment($this->comment[$i])
1027
                        ->setPonderation($this->weighting[$i])
1028
                        ->setPosition($this->position[$i])
1029
                        ->setHotspotCoordinates($this->hotspot_coordinates[$i])
1030
                        ->setHotspotType($this->hotspot_type[$i])
1031
                        ->setDestination($this->destination[$i]);
1032
1033
                    $em->persist($quizAnswer);
1034
                    $em->flush();
1035
1036
                    $answerId = $quizAnswer->getId();
1037
                    $quizAnswer
1038
                        ->setId($answerId)
1039
                        ->setIdAuto($answerId);
1040
1041
                    $em->merge($quizAnswer);
1042
                    $em->flush();
1043
1044
                    $correctAnswers[$answerId] = $correct;
1045
                    $onlyAnswers[$answerId] = $this->answer[$i];
1046
                    $allAnswers[$this->iid[$i]] = $this->answer[$i];
1047
                }
1048
            }
1049
1050
            // Fix correct answers
1051
            if (in_array($newQuestion->type, [DRAGGABLE, MATCHING, MATCHING_DRAGGABLE])) {
1052
                $onlyAnswersFlip = array_flip($onlyAnswers);
1053
                foreach ($correctAnswers as $answer_id => $correct_answer) {
1054
                    $params = [];
1055
                    if (isset($allAnswers[$correct_answer]) &&
1056
                        isset($onlyAnswersFlip[$allAnswers[$correct_answer]])
1057
                    ) {
1058
                        $params['correct'] = $onlyAnswersFlip[$allAnswers[$correct_answer]];
1059
                        Database::update(
1060
                            $tableAnswer,
1061
                            $params,
1062
                            [
1063
                                'iid = ? AND c_id = ? AND question_id = ? ' => [
1064
                                    $answer_id,
1065
                                    $courseId,
1066
                                    $newQuestionId,
1067
                                ],
1068
                            ]
1069
                        );
1070
                    }
1071
                }
1072
            }
1073
        }
1074
    }
1075
1076
    /**
1077
     * Get the necessary JavaScript for some answers.
1078
     *
1079
     * @return string
1080
     */
1081
    public function getJs()
1082
    {
1083
        return "<script>
1084
                $(window).on('load', function() {
1085
                    jsPlumb.ready(function() {
1086
                        if ($('#drag{$this->questionId}_question').length > 0) {
1087
                            MatchingDraggable.init('{$this->questionId}');
1088
                        }
1089
                    });
1090
                });
1091
            </script>";
1092
    }
1093
1094
    /**
1095
     * Check if a answer is correct by an answer auto id.
1096
     *
1097
     * @param int $needle The answer auto id
1098
     *
1099
     * @return bool
1100
     */
1101
    public function isCorrectByAutoId($needle)
1102
    {
1103
        $key = 0;
1104
        if (is_array($this->autoId)) {
1105
            foreach ($this->autoId as $autoIdKey => $autoId) {
1106
                if ($autoId == $needle) {
1107
                    $key = $autoIdKey;
1108
                }
1109
            }
1110
        }
1111
1112
        if (!$key) {
1113
            return false;
1114
        }
1115
1116
        return $this->isCorrect($key) ? true : false;
1117
    }
1118
}
1119