Passed
Push — master ( 251179...3b9d17 )
by Julito
09:58
created

Answer::getAnswers()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 20
rs 9.9332

1 Method

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