Completed
Push — master ( 6c6efe...024a20 )
by Julito
09:28
created

Answer::read()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 30
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

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