Completed
Push — 1.11.x ( 3033bc...afd08d )
by José
168:58 queued 132:03
created

MoodleImport::readQuizModule()   C

Complexity

Conditions 8
Paths 17

Size

Total Lines 34
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 8
eloc 21
c 2
b 0
f 0
nc 17
nop 1
dl 0
loc 34
rs 5.3846
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * Class MoodleImport
6
 *
7
 * @author José Loguercio <[email protected]>
8
 * @package chamilo.library
9
 */
10
11
class MoodleImport
12
{
13
    /**
14
     * Read and validate the moodleFile
15
     *
16
     * @param resource $uploadedFile *.* mbz file moodle course backup
17
     * @return bool
18
     */
19
    public function readMoodleFile($uploadedFile)
20
    {
21
        $file = $uploadedFile['tmp_name'];
22
23
        if (is_file($file) && is_readable($file)) {
24
            $package = new PclZip($file);
25
            $packageContent = $package->listContent();
26
            $mainFileKey = 0;
27
            foreach ($packageContent as $index => $value) {
28
                if ($value['filename'] == 'moodle_backup.xml') {
29
                    $mainFileKey = $index;
30
                    break;
31
                }
32
            }
33
34
            if (!$mainFileKey) {
35
                Display::addFlash(Display::return_message(get_lang('FailedToImportThisIsNotAMoodleFile'), 'error'));
36
            }
37
38
            $folder = api_get_unique_id();
39
            $destinationDir = api_get_path(SYS_ARCHIVE_PATH).$folder;
40
            $coursePath = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/';
41
            $courseInfo = api_get_course_info();
42
43
            mkdir($destinationDir, api_get_permissions_for_new_directories(), true);
44
45
            $package->extract(
46
                PCLZIP_OPT_PATH,
47
                $destinationDir
48
            );
49
50
            $xml = @file_get_contents($destinationDir.'/moodle_backup.xml');
51
52
            $doc = new DOMDocument();
53
            $res = @$doc->loadXML($xml);
54
            if ($res) {
55
                $activities = $doc->getElementsByTagName('activity');
56
                foreach ($activities as $activity) {
57
                    if ($activity->childNodes->length) {
58
                        $currentItem = [];
59
60
                        foreach ($activity->childNodes as $item) {
61
                            $currentItem[$item->nodeName] = $item->nodeValue;
62
                        }
63
64
                        $moduleName = isset($currentItem['modulename']) ? $currentItem['modulename'] : false;
65
                        switch ($moduleName) {
66
                            case 'forum':
67
                                require_once '../forum/forumfunction.inc.php';
68
                                $catForumValues = [];
69
70
                                // Read the current forum module xml.
71
                                $moduleDir = $currentItem['directory'];
72
                                $moduleXml = @file_get_contents($destinationDir.'/'.$moduleDir.'/'.$moduleName.'.xml');
73
                                $moduleValues = $this->readForumModule($moduleXml);
74
75
                                // Create a Forum category based on Moodle forum type.
76
                                $catForumValues['forum_category_title'] = $moduleValues['type'];
77
                                $catForumValues['forum_category_comment'] = '';
78
                                $catId = store_forumcategory($catForumValues);
79
                                $forumValues = [];
80
                                $forumValues['forum_title'] = $moduleValues['name'];
81
                                $forumValues['forum_image'] = '';
82
                                $forumValues['forum_comment'] = $moduleValues['intro'];
83
                                $forumValues['forum_category'] = $catId;
84
85
                                store_forum($forumValues);
86
                                break;
87
                            case 'quiz':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
88
89
                                // Read the current quiz module xml.
90
                                // The quiz case is the very complicate process of all the import.
91
                                // Please if you want to review the script, try to see the readingXML functions.
92
                                // The readingXML functions in this clases do all the mayor work here.
93
94
                                $moduleDir = $currentItem['directory'];
95
                                $moduleXml = @file_get_contents($destinationDir.'/'.$moduleDir.'/'.$moduleName.'.xml');
96
                                $questionsXml = @file_get_contents($destinationDir.'/questions.xml');
97
                                $moduleValues = $this->readQuizModule($moduleXml);
98
99
                                // At this point we got all the prepared resources from Moodle file
100
                                // $moduleValues variable contains all the necesary info to the quiz import
101
                                // var_dump($moduleValues); // <-- uncomment this to see the final array
102
103
                                // Lets do this ...
104
                                $exercise = new Exercise();
105
                                $exercise->updateTitle(Exercise::format_title_variable($moduleValues['name']));
106
                                $exercise->updateDescription($moduleValues['intro']);
107
                                $exercise->updateAttempts($moduleValues['attempts_number']);
108
                                $exercise->updateFeedbackType(0);
109
110
                                // Match shuffle question with chamilo
111
                                switch ($moduleValues['shufflequestions']) {
112
                                    case '0':
113
                                        $exercise->setRandom(0);
114
                                        break;
115
                                    case '1':
116
                                        $exercise->setRandom(-1);
117
                                        break;
118
                                    default:
119
                                        $exercise->setRandom(0);
120
                                }
121
                                $exercise->updateRandomAnswers($moduleValues['shuffleanswers']);
122
                                // @todo divide to minutes
123
                                $exercise->updateExpiredTime($moduleValues['timelimit']);
124
125
                                if ($moduleValues['questionsperpage'] == 1) {
126
                                    $exercise->updateType(2);
127
                                } else {
128
                                    $exercise->updateType(1);
129
                                }
130
131
                                // Create the new Quiz
132
                                $exercise->save();
133
134
                                // Ok, we got the Quiz and create it, now its time to add the Questions
135
                                foreach ($moduleValues['question_instances'] as $index => $question) {
136
                                    $questionsValues = $this->readMainQuestionsXml($questionsXml, $question['questionid']);
137
                                    $moduleValues['question_instances'][$index] = $questionsValues;
138
                                    // Set Question Type from Moodle XML element <qtype>
139
                                    $qType = $moduleValues['question_instances'][$index]['qtype'];
140
                                    // Add the matched chamilo question type to the array
141
                                    $moduleValues['question_instances'][$index]['chamilo_qtype'] = $this->matchMoodleChamiloQuestionTypes($qType);
142
                                    $questionInstance = Question::getInstance($moduleValues['question_instances'][$index]['chamilo_qtype']);
143
                                    if ($questionInstance) {
144
                                        $questionInstance->updateTitle($moduleValues['question_instances'][$index]['name']);
145
                                        $questionInstance->updateDescription($moduleValues['question_instances'][$index]['questiontext']);
146
                                        $questionInstance->updateLevel(1);
147
                                        $questionInstance->updateCategory(0);
148
149
                                        //Save normal question if NOT media
150
                                        if ($questionInstance->type != MEDIA_QUESTION) {
151
                                            $questionInstance->save($exercise->id);
152
153
                                            // modify the exercise
154
                                            $exercise->addToList($questionInstance->id);
155
                                            $exercise->update_question_positions();
156
                                        }
157
158
                                        $questionList = $moduleValues['question_instances'][$index]['plugin_qtype_'.$qType.'_question'];
159
                                        $currentQuestion = $moduleValues['question_instances'][$index];
160
161
                                        $result = $this->processAnswers($questionList, $qType, $questionInstance, $currentQuestion);
162
                                    }
163
                                }
164
165
                                break;
166
                            case 'resource':
167
                                // Read the current resource module xml.
168
                                $moduleDir = $currentItem['directory'];
169
                                $moduleXml = @file_get_contents($destinationDir.'/'.$moduleDir.'/'.$moduleName.'.xml');
170
                                $filesXml = @file_get_contents($destinationDir.'/files.xml');
171
                                $moduleValues = $this->readResourceModule($moduleXml);
172
                                $mainFileModuleValues = $this->readMainFilesXml($filesXml, $moduleValues['contextid']);
173
                                $fileInfo = array_merge($moduleValues, $mainFileModuleValues, $currentItem);
174
                                $documentPath = $coursePath.'document/';
175
                                $currentResourceFilePath = $destinationDir.'/files/';
176
                                $dirs = new RecursiveDirectoryIterator($currentResourceFilePath);
177
                                foreach (new RecursiveIteratorIterator($dirs) as $file) {
178
                                    if (is_file($file) && strpos($file, $fileInfo['contenthash']) !== false) {
179
                                        $files = [];
180
                                        $files['file']['name'] = $fileInfo['filename'];
181
                                        $files['file']['tmp_name'] = $file->getPathname();
182
                                        $files['file']['type'] = $fileInfo['mimetype'];
183
                                        $files['file']['error'] = 0;
184
                                        $files['file']['size'] = $fileInfo['filesize'];
185
                                        $files['file']['from_file'] = true;
186
                                        $files['file']['move_file'] = true;
187
                                        $_POST['language'] = $courseInfo['language'];
188
                                        $_POST['moodle_import'] = true;
189
190
                                        DocumentManager::upload_document(
191
                                            $files,
192
                                            '/',
193
                                            $fileInfo['title'],
194
                                            '',
195
                                            null,
196
                                            null,
197
                                            true,
198
                                            true
199
                                        );
200
                                    }
201
                                }
202
203
                                break;
204
                            case 'url':
205
                                // Read the current url module xml.
206
                                $moduleDir = $currentItem['directory'];
207
                                $moduleXml = @file_get_contents($destinationDir.'/'.$moduleDir.'/'.$moduleName.'.xml');
208
                                $moduleValues = $this->readUrlModule($moduleXml);
209
                                $_POST['title'] = $moduleValues['name'];
210
                                $_POST['url'] = $moduleValues['externalurl'];
211
                                $_POST['description'] = $moduleValues['intro'];
212
                                $_POST['category_id'] = 0;
213
                                $_POST['target'] = '_blank';
214
215
                                Link::addlinkcategory("link");
216
                                break;
217
                        }
218
                    }
219
                }
220
            } else {
221
                removeDir($destinationDir);
222
                return false;
223
            }
224
        } else {
225
            return false;
226
        }
227
228
        removeDir($destinationDir);
229
        return $packageContent[$mainFileKey];
230
    }
231
232
    /**
233
     * Read and validate the forum module XML
234
     *
235
     * @param resource $moduleXml XML file
236
     * @return mixed | array if is a valid xml file, false otherwise
237
     */
238 View Code Duplication
    public function readForumModule($moduleXml)
239
    {
240
        $moduleDoc = new DOMDocument();
241
        $moduleRes = @$moduleDoc->loadXML($moduleXml);
242
        if ($moduleRes) {
243
            $activities = $moduleDoc->getElementsByTagName('forum');
244
            $currentItem = [];
245
            foreach ($activities as $activity) {
246
                if ($activity->childNodes->length) {
247
                    foreach ($activity->childNodes as $item) {
248
                        $currentItem[$item->nodeName] = $item->nodeValue;
249
                    }
250
                }
251
            }
252
253
            return $currentItem;
254
        }
255
256
        return false;
257
    }
258
259
    /**
260
     * Read and validate the resource module XML
261
     *
262
     * @param resource $moduleXml XML file
263
     * @return mixed | array if is a valid xml file, false otherwise
264
     */
265
    public function readResourceModule($moduleXml)
266
    {
267
        $moduleDoc = new DOMDocument();
268
        $moduleRes = @$moduleDoc->loadXML($moduleXml);
269
        if ($moduleRes) {
270
            $activities = $moduleDoc->getElementsByTagName('resource');
271
            $mainActivity = $moduleDoc->getElementsByTagName('activity');
272
            $contextId = $mainActivity->item(0)->getAttribute('contextid');
273
            $currentItem = [];
274
            foreach ($activities as $activity) {
275
                if ($activity->childNodes->length) {
276
                    foreach ($activity->childNodes as $item) {
277
                        $currentItem[$item->nodeName] = $item->nodeValue;
278
                    }
279
                }
280
            }
281
282
            $currentItem['contextid'] = $contextId;
283
            return $currentItem;
284
        }
285
286
        return false;
287
    }
288
289
    /**
290
     * Read and validate the url module XML
291
     *
292
     * @param resource $moduleXml XML file
293
     * @return mixed | array if is a valid xml file, false otherwise
294
     */
295 View Code Duplication
    public function readUrlModule($moduleXml)
296
    {
297
        $moduleDoc = new DOMDocument();
298
        $moduleRes = @$moduleDoc->loadXML($moduleXml);
299
        if ($moduleRes) {
300
            $activities = $moduleDoc->getElementsByTagName('url');
301
            $currentItem = [];
302
            foreach ($activities as $activity) {
303
                if ($activity->childNodes->length) {
304
                    foreach ($activity->childNodes as $item) {
305
                        $currentItem[$item->nodeName] = $item->nodeValue;
306
                    }
307
                }
308
            }
309
310
            return $currentItem;
311
        }
312
313
        return false;
314
    }
315
316
    /**
317
     * Read and validate the quiz module XML
318
     *
319
     * @param resource $moduleXml XML file
320
     * @return mixed | array if is a valid xml file, false otherwise
321
     */
322
    public function readQuizModule($moduleXml)
323
    {
324
        $moduleDoc = new DOMDocument();
325
        $moduleRes = @$moduleDoc->loadXML($moduleXml);
326
        if ($moduleRes) {
327
            $activities = $moduleDoc->getElementsByTagName('quiz');
328
            $currentItem = [];
329
            foreach ($activities as $activity) {
330
                if ($activity->childNodes->length) {
331
                    foreach ($activity->childNodes as $item) {
332
                        $currentItem[$item->nodeName] = $item->nodeValue;
333
                    }
334
                }
335
            }
336
337
            $questions = $moduleDoc->getElementsByTagName('question_instance');
338
339
            $questionList = [];
340
            $counter = 0;
341
            foreach ($questions as $question) {
342
                if ($question->childNodes->length) {
343
                    foreach ($question->childNodes as $item) {
344
                        $questionList[$counter][$item->nodeName] = $item->nodeValue;
345
                    }
346
                    $counter++;
347
                }
348
349
            }
350
            $currentItem['question_instances'] = $questionList;
351
            return $currentItem;
352
        }
353
354
        return false;
355
    }
356
357
    /**
358
     * Search the current file resource in main Files XML
359
     *
360
     * @param resource $filesXml XML file
361
     * @param int $contextId
362
     * @return mixed | array if is a valid xml file, false otherwise
363
     */
364
    public function readMainFilesXml($filesXml, $contextId)
365
    {
366
        $moduleDoc = new DOMDocument();
367
        $moduleRes = @$moduleDoc->loadXML($filesXml);
368
        if ($moduleRes) {
369
            $activities = $moduleDoc->getElementsByTagName('file');
370
            $currentItem = [];
371
            foreach ($activities as $activity) {
372
                if ($activity->childNodes->length) {
373
                    $isThisItemThatIWant = false;
374
                    foreach ($activity->childNodes as $item) {
375
                        if (!$isThisItemThatIWant && $item->nodeName == 'contenthash') {
376
                            $currentItem['contenthash'] = $item->nodeValue;
377
                        }
378
                        if ($item->nodeName == 'contextid' && intval($item->nodeValue) == intval($contextId) && !$isThisItemThatIWant) {
379
                            $isThisItemThatIWant = true;
380
                            continue;
381
                        }
382
383
                        if ($isThisItemThatIWant && $item->nodeName == 'filename') {
384
                            $currentItem['filename'] = $item->nodeValue;
385
                        }
386
387
                        if ($isThisItemThatIWant && $item->nodeName == 'filesize') {
388
                            $currentItem['filesize'] = $item->nodeValue;
389
                        }
390
391
                        if ($isThisItemThatIWant && $item->nodeName == 'mimetype' && $item->nodeValue == 'document/unknown') {
392
                            break;
393
                        }
394
395
                        if ($isThisItemThatIWant && $item->nodeName == 'mimetype' && $item->nodeValue !== 'document/unknown') {
396
                            $currentItem['mimetype'] = $item->nodeValue;
397
                            break 2;
398
                        }
399
                    }
400
                }
401
            }
402
403
            return $currentItem;
404
        }
405
406
        return false;
407
    }
408
409
    /**
410
     * Search the current quiestion resource in main Questions XML
411
     *
412
     * @param resource $questionsXml XML file
413
     * @param int $questionId
414
     * @return mixed | array if is a valid xml file, false otherwise
415
     */
416
    public function readMainQuestionsXml($questionsXml, $questionId)
417
    {
418
        $moduleDoc = new DOMDocument();
419
        $moduleRes = @$moduleDoc->loadXML($questionsXml);
420
        if ($moduleRes) {
421
            $questions = $moduleDoc->getElementsByTagName('question');
422
            $currentItem = [];
423
            foreach ($questions as $question) {
424
                if (intval($question->getAttribute('id')) == $questionId) {
425
                    if ($question->childNodes->length) {
426
                        $currentItem['questionid'] = $questionId;
427
                        $questionType = '';
428
                        foreach ($question->childNodes as $item) {
429
                            $currentItem[$item->nodeName] = $item->nodeValue;
430
                            if ($item->nodeName == 'qtype') {
431
                                $questionType = $item->nodeValue;
432
                            }
433
434
                            if ($item->nodeName == 'plugin_qtype_'.$questionType.'_question') {
435
                                $answer = $item->getElementsByTagName($this->getQuestionTypeAnswersTag($questionType));
436
                                $currentItem['plugin_qtype_'.$questionType.'_question'] = [];
437
                                for ($i = 0; $i <= $answer->length - 1; $i++) {
438
                                    $currentItem['plugin_qtype_'.$questionType.'_question'][$i]['answerid'] = $answer->item($i)->getAttribute('id');
439
                                    foreach ($answer->item($i)->childNodes as $properties) {
440
                                        $currentItem['plugin_qtype_'.$questionType.'_question'][$i][$properties->nodeName] = $properties->nodeValue;
441
                                    }
442
                                }
443
444
                                $typeValues = $item->getElementsByTagName($this->getQuestionTypeOptionsTag($questionType));
445
                                for ($i = 0; $i <= $typeValues->length - 1; $i++) {
446
                                    foreach ($typeValues->item($i)->childNodes as $properties) {
447
                                        $currentItem[$questionType.'_values'][$properties->nodeName] = $properties->nodeValue;
448
                                        if ($properties->nodeName == 'sequence') {
449
                                            $sequence = $properties->nodeValue;
450
                                            $sequenceIds = explode(',', $sequence);
451
                                            foreach ($sequenceIds as $qId) {
452
                                                $questionMatch = $this->readMainQuestionsXml($questionsXml, $qId);
453
                                                $currentItem['plugin_qtype_'.$questionType.'_question'][] = $questionMatch;
454
                                            }
455
                                        }
456
                                    }
457
                                }
458
                            }
459
                        }
460
                    }
461
                }
462
            }
463
464
            $this->traverseArray($currentItem, ['#text', 'question_hints', 'tags']);
465
            return $currentItem;
466
        }
467
468
        return false;
469
    }
470
471
    /**
472
     * return the correct question type options tag
473
     *
474
     * @param string $questionType name
475
     * @return string question type tag
476
     */
477
    public function getQuestionTypeOptionsTag($questionType)
478
    {
479
        switch ($questionType) {
480
            case 'match':
481
            case 'ddmatch':
482
                return 'matchoptions';
483
                break;
484
            default:
485
                return $questionType;
486
                break;
487
        }
488
    }
489
490
    /**
491
     * return the correct question type answers tag
492
     *
493
     * @param string $questionType name
494
     * @return string question type tag
495
     */
496
    public function getQuestionTypeAnswersTag($questionType)
497
    {
498
        switch ($questionType) {
499
            case 'match':
500
            case 'ddmatch':
501
                return 'match';
502
                break;
503
            default:
504
                return 'answer';
505
                break;
506
        }
507
    }
508
509
    /**
510
     *
511
     * @param string $moodleQuestionType
512
     * @return integer Chamilo question type
513
     */
514
    public function matchMoodleChamiloQuestionTypes($moodleQuestionType)
515
    {
516
        switch ($moodleQuestionType) {
517
            case 'multichoice':
518
                return UNIQUE_ANSWER;
519
                break;
520
            case 'multianswer':
521
            case 'shortanswer':
522
            case 'match':
523
                return FILL_IN_BLANKS;
524
                break;
525
            case 'match':
526
            case 'essay':
527
                return FREE_ANSWER;
528
                break;
529
            case 'truefalse':
530
                return UNIQUE_ANSWER_NO_OPTION;
531
            break;
532
        }
533
    }
534
535
    /**
536
     * Process Moodle Answers to Chamilo
537
     *
538
     * @param array $questionList
539
     * @param string $questionType
540
     * @param object $questionInstance Question/Answer instance
541
     * @param array $currentQuestion
542
     * @return integer db response
543
     */
544
    public function processAnswers($questionList, $questionType, $questionInstance, $currentQuestion)
545
    {
546
        switch ($questionType) {
547 View Code Duplication
            case 'multichoice':
548
                $objAnswer = new Answer($questionInstance->id);
549
                $questionWeighting = 0;
550
                foreach ($questionList as $slot => $answer) {
551
                    $this->processUniqueAnswer($objAnswer, $answer, $slot + 1, $questionWeighting);
552
                }
553
554
                // saves the answers into the data base
555
                $objAnswer->save();
556
                // sets the total weighting of the question
557
                $questionInstance->updateWeighting($questionWeighting);
558
                $questionInstance->save();
559
560
                return true;
561
                break;
562
            case 'multianswer':
563
                $objAnswer = new Answer($questionInstance->id);
564
565
                $placeholder = $currentQuestion['questiontext'];
566
567
                $optionsValues = [];
568
569
                foreach ($questionList as $slot => $subQuestion) {
570
                    $qtype = $subQuestion['qtype'];
571
                    $optionsValues[] = $this->processFillBlanks($objAnswer, $qtype, $subQuestion['plugin_qtype_'.$qtype.'_question'], $placeholder, $slot + 1);
572
                }
573
574
                $answerOptionsWeight = '::';
575
                $answerOptionsSize = '';
576
                $questionWeighting = 0;
577 View Code Duplication
                foreach ($optionsValues as $index => $value) {
578
                    $questionWeighting += $value['weight'];
579
                    $answerOptionsWeight .= $value['weight'].',';
580
                    $answerOptionsSize .= $value['size'].',';
581
                }
582
583
                $answerOptionsWeight = substr($answerOptionsWeight, 0, -1);
584
                $answerOptionsSize = substr($answerOptionsSize, 0, -1);
585
586
                $answerOptions = $answerOptionsWeight.':'.$answerOptionsSize.':0@';
587
588
                $placeholder = $placeholder.PHP_EOL.$answerOptions;
589
590
                // This is a minor trick to clean the question description that in a multianswer is the main placeholder
591
                $questionInstance->updateDescription('');
592
                // sets the total weighting of the question
593
                $questionInstance->updateWeighting($questionWeighting);
594
                $questionInstance->save();
595
                // saves the answers into the data base
596
                $objAnswer->createAnswer($placeholder, 0, '', 0, 1);
597
                $objAnswer->save();
598
599
                return true;
600
            case 'match':
601
                $objAnswer = new Answer($questionInstance->id);
602
                $placeholder = '';
603
604
                $optionsValues = $this->processFillBlanks($objAnswer, 'match', $questionList, $placeholder, 0);
605
606
                $answerOptionsWeight = '::';
607
                $answerOptionsSize = '';
608
                $questionWeighting = 0;
609 View Code Duplication
                foreach ($optionsValues as $index => $value) {
0 ignored issues
show
Bug introduced by
The expression $optionsValues of type array|null|false is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
610
                    $questionWeighting += $value['weight'];
611
                    $answerOptionsWeight .= $value['weight'].',';
612
                    $answerOptionsSize .= $value['size'].',';
613
                }
614
615
                $answerOptionsWeight = substr($answerOptionsWeight, 0, -1);
616
                $answerOptionsSize = substr($answerOptionsSize, 0, -1);
617
618
                $answerOptions = $answerOptionsWeight.':'.$answerOptionsSize.':0@';
619
620
                $placeholder = $placeholder.PHP_EOL.$answerOptions;
621
622
                // sets the total weighting of the question
623
                $questionInstance->updateWeighting($questionWeighting);
624
                $questionInstance->save();
625
                // saves the answers into the data base
626
                $objAnswer->createAnswer($placeholder, 0, '', 0, 1);
627
                $objAnswer->save();
628
629
                return true;
630
                break;
631
            case 'shortanswer':
632
            case 'ddmatch':
633
                $questionWeighting = $currentQuestion['defaultmark'];
634
                $questionInstance->updateWeighting($questionWeighting);
635
                $questionInstance->updateDescription(get_lang('ThisQuestionIsNotSupportedYet'));
636
                $questionInstance->save();
637
                return false;
638
                break;
639
            case 'essay':
640
                $questionWeighting = $currentQuestion['defaultmark'];
641
                $questionInstance->updateWeighting($questionWeighting);
642
                $questionInstance->save();
643
                return true;
644
                break;
645 View Code Duplication
            case 'truefalse':
646
                $objAnswer = new Answer($questionInstance->id);
647
                $questionWeighting = 0;
648
                foreach ($questionList as $slot => $answer) {
649
                    $this->processTrueFalse($objAnswer, $answer, $slot + 1, $questionWeighting);
650
                }
651
652
                // saves the answers into the data base
653
                $objAnswer->save();
654
                // sets the total weighting of the question
655
                $questionInstance->updateWeighting($questionWeighting);
656
                $questionInstance->save();
657
                return false;
658
                break;
659
            default:
660
                return false;
661
                break;
662
        }
663
    }
664
665
    /**
666
     * Process Chamilo Unique Answer
667
     *
668
     * @param object $objAnswer
669
     * @param array $answerValues
670
     * @param integer $position
671
     * @param integer $questionWeighting
672
     * @return integer db response
673
     */
674 View Code Duplication
    public function processUniqueAnswer($objAnswer, $answerValues, $position, &$questionWeighting)
675
    {
676
        $correct = intval($answerValues['fraction']) ? intval($answerValues['fraction']) : 0;
677
        $answer = $answerValues['answertext'];
678
        $comment = $answerValues['feedback'];
679
        $weighting = $answerValues['fraction'];
680
        $weighting = abs($weighting);
681
        if ($weighting > 0) {
682
            $questionWeighting += $weighting;
683
        }
684
        $goodAnswer =  $correct ? true : false;
685
686
        $objAnswer->createAnswer(
687
            $answer,
688
            $goodAnswer,
689
            $comment,
690
            $weighting,
691
            $position,
692
            null,
693
            null,
694
            ''
695
        );
696
    }
697
698
    /**
699
     * Process Chamilo True False
700
     *
701
     * @param object $objAnswer
702
     * @param array $answerValues
703
     * @param integer $position
704
     * @param integer $questionWeighting
705
     * @return integer db response
706
     */
707 View Code Duplication
    public function processTrueFalse($objAnswer, $answerValues, $position, &$questionWeighting)
708
    {
709
        $correct = intval($answerValues['fraction']) ? intval($answerValues['fraction']) : 0;
710
        $answer = $answerValues['answertext'];
711
        $comment = $answerValues['feedback'];
712
        $weighting = $answerValues['fraction'];
713
        $weighting = abs($weighting);
714
        if ($weighting > 0) {
715
            $questionWeighting += $weighting;
716
        }
717
        $goodAnswer =  $correct ? true : false;
718
719
        $objAnswer->createAnswer(
720
            $answer,
721
            $goodAnswer,
722
            $comment,
723
            $weighting,
724
            $position,
725
            null,
726
            null,
727
            ''
728
        );
729
    }
730
731
    /**
732
     * Process Chamilo FillBlanks
733
     *
734
     * @param object $objAnswer
735
     * @param array $questionType
736
     * @param array $answerValues
737
     * @param string $placeholder
738
     * @param integer $position
739
     * @return integer db response
740
     */
741
    public function processFillBlanks($objAnswer, $questionType, $answerValues, &$placeholder, $position)
742
    {
743
        switch ($questionType) {
744
            case 'multichoice':
745
                $optionsValues = [];
746
747
                $correctAnswer = '';
748
                $othersAnswer = '';
749
                foreach ($answerValues as $answer) {
750
                    $correct = intval($answer['fraction']);
751
                    if ($correct) {
752
                        $correctAnswer .= $answer['answertext'].'|';
753
                        $optionsValues['weight'] = $answer['fraction'];
754
                        $optionsValues['size'] = '200';
755
                    } else {
756
                        $othersAnswer .= $answer['answertext'].'|';
757
                    }
758
                }
759
                $currentAnswers = $correctAnswer.$othersAnswer;
760
                $currentAnswers = '['.substr($currentAnswers, 0, -1).']';
761
                $placeholder = str_replace("{#$position}", $currentAnswers, $placeholder);
762
763
                return $optionsValues;
764
765
                break;
766
            case 'shortanswer':
767
                $optionsValues = [];
768
769
                $correctAnswer = '';
770
771
                foreach ($answerValues as $answer) {
772
                    $correct = intval($answer['fraction']);
773
                    if ($correct) {
774
                        $correctAnswer .= $answer['answertext'];
775
                        $optionsValues['weight'] = $answer['fraction'];
776
                        $optionsValues['size'] = '200';
777
                    }
778
                }
779
780
                $currentAnswers = '['.$correctAnswer.']';
781
                $placeholder = str_replace("{#$position}", $currentAnswers, $placeholder);
782
783
                return $optionsValues;
784
785
                break;
786
            case 'match':
787
                $answers = [];
788
                // Here first we need to extract all the possible answers
789
                foreach ($answerValues as $slot => $answer) {
790
                    $answers[$slot] = $answer['answertext'];
791
                }
792
793
                // Now we set the order of the values matching the correct answer and set it to the first element
794
                $optionsValues = [];
795
                foreach ($answerValues as $slot => $answer) {
796
                    $correctAnswer = '';
797
                    $othersAnswers = '';
798
                    $correctAnswer .= $answer['answertext'].'|';
799
800
                    foreach ($answers as $other) {
801
                        if ($other !== $answer['answertext']) {
802
                            $othersAnswers .= $other.'|';
803
                        }
804
                    }
805
806
                    $optionsValues[$slot]['weight'] = 1;
807
                    $optionsValues[$slot]['size'] = '200';
808
809
                    $currentAnswers = $correctAnswer.$othersAnswers;
810
                    $currentAnswers = '['.substr($currentAnswers, 0, -1).'] ';
811
812
                    $placeholder .= '<p> ' . strip_tags($answer['questiontext']).' '.$currentAnswers . ' </p>';
813
                }
814
815
                return $optionsValues;
816
817
                break;
818
            default:
819
                return false;
820
                break;
821
        }
822
    }
823
824
825
    /**
826
     * Litle utility to delete the unuseful tags
827
     *
828
     * @param $array
829
     * @param $keys
830
     */
831
    public function traverseArray(&$array, $keys)
832
    {
833
        foreach ($array as $key => &$value) {
834
            if (is_array($value)) {
835
                $this->traverseArray($value, $keys);
836
            } else {
837
                if (in_array($key, $keys)){
838
                    unset($array[$key]);
839
                }
840
            }
841
        }
842
    }
843
844
}