Passed
Push — master ( 251179...3b9d17 )
by Julito
09:58
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\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