Passed
Push — 1.11.x ( 69d982...5f02d6 )
by Yannick
10:37
created

Cc13Quiz::getDefaultgrade()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 3
nop 2
dl 0
loc 15
rs 9.6111
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
class Cc13Quiz extends Cc13Entities
5
{
6
    /**
7
     * Get all data from the object instance (coming from the xml file) into a clean array
8
     * @return array
9
     */
10
    public function generateData()
11
    {
12
        $data = [];
13
        $instances = $this->generateInstances();
14
        if (!empty($instances)) {
15
            foreach ($instances as $instance) {
16
                if ($instance['is_question_bank'] == 0) {
17
                    $data[] = $this->getQuizData($instance);
18
                }
19
            }
20
        }
21
22
        return $data;
23
    }
24
25
    /**
26
     * Create a quiz based on the information available in the assessment structure
27
     * @param $quiz
28
     * @return void
29
     */
30
    public function storeQuiz($quiz)
31
    {
32
        $token = '/\$(?:IMS|1EdTech)[-_]CC[-_]FILEBASE\$\.\.\//';
33
        $courseInfo = api_get_course_info();
34
        // Replace by the path in documents in which we place all relevant CC files
35
        $replacementPath = '/courses/'.$courseInfo['directory'].'/document/commoncartridge/';
36
        $exercise = new Exercise($courseInfo['real_id']);
37
        $title = Exercise::format_title_variable($quiz['title']);
38
        $exercise->updateTitle($title);
39
        $description = preg_replace($token, $replacementPath, $quiz['description']);
40
        $exercise->updateDescription($description);
41
        $exercise->updateAttempts($quiz['max_attempts']);
42
        $exercise->updateFeedbackType(0);
43
44
        $exercise->setRandom(0);
45
        $exercise->updateRandomAnswers(!empty($moduleValues['shuffleanswers']));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $moduleValues seems to never exist and therefore empty should always be true.
Loading history...
46
        $exercise->updateExpiredTime((int) $quiz['timelimit']);
47
        $exercise->updateType(1);
48
49
        // Create the new Quiz
50
        $exercise->save();
51
52
        if (!empty($quiz['questions'])) {
53
            foreach ($quiz['questions'] as $question) {
54
                $qtype = $question['type'];
55
56
                $types = [
57
                    'unique_answer' => UNIQUE_ANSWER,
58
                    'multiple_answer' => MULTIPLE_ANSWER,
59
                    'fib' => FILL_IN_BLANKS,
60
                    'essay' => FREE_ANSWER,
61
                ];
62
                $questionType = $types[$qtype];
63
64
                $questionInstance = Question::getInstance($questionType);
65
                if (empty($questionInstance)) {
66
                    continue;
67
                }
68
69
                $questionInstance->updateTitle(substr(Security::remove_XSS(strip_tags_blacklist($question['title'], ['br', 'p'])), 0, 20));
70
                $questionText = Security::remove_XSS(strip_tags_blacklist($question['title'], ['br', 'p']));
71
                // Replace the path from $1EdTech-CC-FILEBASE$ to a correct chamilo path
72
                $questionText = preg_replace($token, $replacementPath, $questionText);
73
                $questionInstance->updateDescription($questionText);
74
75
                $questionInstance->updateLevel(1);
76
                $questionInstance->updateCategory(0);
77
78
                //Save normal question if NOT media
79
                if ($questionInstance->type != MEDIA_QUESTION) {
80
                    $questionInstance->save($exercise);
81
                    // modify the exercise
82
                    $exercise->addToList($questionInstance->iid);
83
                    $exercise->update_question_positions();
84
                }
85
86
                if ($qtype == 'unique_answer') {
87
                    $objAnswer = new Answer($questionInstance->iid);
88
                    $questionWeighting = 0;
89
                    foreach ($question['answers'] as $slot => $answerValues) {
90
                        $correct = $answerValues['score'] ? (int) $answerValues['score'] : 0;
91
                        $answer = Security::remove_XSS(preg_replace($token, $replacementPath, $answerValues['title']));
92
                        $comment = Security::remove_XSS(preg_replace($token, $replacementPath, $answerValues['feedback']));
93
                        $weighting = $answerValues['score'];
94
                        $weighting = abs($weighting);
95
                        if ($weighting > 0) {
96
                            $questionWeighting += $weighting;
97
                        }
98
                        $goodAnswer = $correct ? true : false;
99
100
                        $objAnswer->createAnswer(
101
                            $answer,
102
                            $goodAnswer,
103
                            $comment,
104
                            $weighting,
105
                            $slot + 1,
106
                            null,
107
                            null,
108
                            ''
109
                        );
110
                    }
111
                    // saves the answers into the database
112
                    $objAnswer->save();
113
                    // sets the total weighting of the question
114
                    $questionInstance->updateWeighting($questionWeighting);
115
                    $questionInstance->save($exercise);
116
                } else {
117
                    $objAnswer = new Answer($questionInstance->iid);
118
                    $questionWeighting = 0;
119
                    if (is_array($question['answers'])) {
120
                        foreach ($question['answers'] as $slot => $answerValues) {
121
                            $answer = Security::remove_XSS(preg_replace($token, $replacementPath, $answerValues['title']));
122
                            $comment = Security::remove_XSS(preg_replace($token, $replacementPath, $answerValues['feedback']));
123
                            $weighting = $answerValues['score'];
124
                            if ($weighting > 0) {
125
                                $questionWeighting += $weighting;
126
                            }
127
                            $goodAnswer = $weighting > 0;
128
129
                            $objAnswer->createAnswer(
130
                                $answer,
131
                                $goodAnswer,
132
                                $comment,
133
                                $weighting,
134
                                $slot + 1,
135
                                null,
136
                                null,
137
                                ''
138
                            );
139
                        }
140
                    } elseif ($qtype == 'essay') {
141
                        $questionWeighting = $question['ponderation'];
142
                    }
143
144
                    // saves the answers into the database
145
                    $objAnswer->save();
146
                    // sets the total weighting of the question
147
                    $questionInstance->updateWeighting($questionWeighting);
148
                    $questionInstance->save($exercise);
149
                }
150
            }
151
        }
152
    }
153
154
    public function storeQuizzes($quizzes)
155
    {
156
        if (!empty($quizzes)) {
157
            foreach ($quizzes as $quiz) {
158
                $this->storeQuiz($quiz);
159
            }
160
        }
161
    }
162
163
    public function getQuizData($instance)
164
    {
165
        $values = [];
166
        if (!empty($instance)) {
167
            $questions = [];
168
            if (!empty($instance['questions'])) {
169
                foreach ($instance['questions'] as $question) {
170
                    $questions[$question['id']] = [
171
                        'title' => $question['title'],
172
                        'type' => $question['qtype'],
173
                        'ponderation' => $question['defaultgrade'],
174
                        'answers' => $question['answers'],
175
                    ];
176
                }
177
            }
178
            $values = [
179
                'id' => $instance['id'],
180
                'title' => $instance['title'],
181
                'description' => $instance['description'],
182
                'timelimit' => $instance['options']['timelimit'],
183
                'max_attempts' => $instance['options']['max_attempts'],
184
                'questions' => $questions,
185
            ];
186
        }
187
188
        return $values;
189
    }
190
191
    private function generateInstances()
192
    {
193
        $lastInstanceId = 0;
194
        $lastQuestionId = 0;
195
        $lastAnswerId = 0;
196
197
        $instances = [];
198
199
        $types = [TOOL_TYPE_QUIZ];
200
201
        foreach ($types as $type) {
202
            if (!empty(Cc1p3Convert::$instances['instances'][$type])) {
203
                foreach (Cc1p3Convert::$instances['instances'][$type] as $instance) {
204
                    if ($type == TOOL_TYPE_QUIZ) {
205
                        $is_question_bank = 0;
206
                    } else {
207
                        $is_question_bank = 1;
208
                    }
209
210
                    // Get the path of the assessment.xml file
211
                    $assessmentFile = $this->getExternalXml($instance['resource_identifier']);
212
213
                    if (!empty($assessmentFile)) {
214
                        $assessment = $this->loadXmlResource(Cc1p3Convert::$pathToManifestFolder.DIRECTORY_SEPARATOR.$assessmentFile);
215
216
                        if (!empty($assessment)) {
217
                            $replaceValues = ['unlimited' => 0];
218
219
                            $questions = $this->getQuestions($assessment, $lastQuestionId, $lastAnswerId, dirname($assessmentFile), $is_question_bank);
220
                            $questionCount = count($questions);
221
222
                            if (!empty($questionCount)) {
223
                                $lastInstanceId++;
224
225
                                $instances[$instance['resource_identifier']]['questions'] = $questions;
226
                                $instances[$instance['resource_identifier']]['id'] = $lastInstanceId;
227
                                $instances[$instance['resource_identifier']]['title'] = $instance['title'];
228
                                $instances[$instance['resource_identifier']]['description'] = $this->getQuizDescription($assessment);
229
                                $instances[$instance['resource_identifier']]['is_question_bank'] = $is_question_bank;
230
                                $instances[$instance['resource_identifier']]['options']['timelimit'] = $this->getGlobalConfig($assessment, 'qmd_timelimit', 0);
231
                                $instances[$instance['resource_identifier']]['options']['max_attempts'] = $this->getGlobalConfig($assessment, 'cc_maxattempts', 0, $replaceValues);
232
                            }
233
                        }
234
                    }
235
                }
236
            }
237
        }
238
239
        return $instances;
240
    }
241
242
    private function getGlobalConfig($assessment, $option, $defaultValue, $replaceValues = '')
243
    {
244
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
245
        $metadata = $xpath->query('/xmlns:questestinterop/xmlns:assessment/xmlns:qtimetadata/xmlns:qtimetadatafield');
246
247
        foreach ($metadata as $field) {
248
            $fieldLabel = $xpath->query('xmlns:fieldlabel', $field);
249
            $fieldLabel = !empty($fieldLabel->item(0)->nodeValue) ? $fieldLabel->item(0)->nodeValue : '';
250
251
            if (strtolower($fieldLabel) == strtolower($option)) {
252
                $fieldEntry = $xpath->query('xmlns:fieldentry', $field);
253
                $response = !empty($fieldEntry->item(0)->nodeValue) ? $fieldEntry->item(0)->nodeValue : '';
254
            }
255
        }
256
257
        $response = !empty($response) ? trim($response) : '';
258
259
        if (!empty($replaceValues)) {
260
            foreach ($replaceValues as $key => $value) {
261
                $response = ($key == $response) ? $value : $response;
262
            }
263
        }
264
265
        $response = empty($response) ? $defaultValue : $response;
266
267
        return $response;
268
    }
269
270
    private function getQuizDescription(DOMDocument $assessment): string
271
    {
272
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
273
        $fieldEntry = $xpath->query('/xmlns:questestinterop/xmlns:assessment/xmlns:rubric/xmlns:material/xmlns:mattext');
274
        $response = !empty($fieldEntry->item(0)->nodeValue) ? $fieldEntry->item(0)->nodeValue : '';
275
        return $response;
276
    }
277
278
    private function getQuestions($assessment, &$lastQuestionId, &$last_answer_id, $rootPath, $is_question_bank)
279
    {
280
        $questions = [];
281
282
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
283
284
        if (!$is_question_bank) {
285
            $questionsItems = $xpath->query('/xmlns:questestinterop/xmlns:assessment/xmlns:section/xmlns:item');
286
        } else {
287
            $questionsItems = $xpath->query('/xmlns:questestinterop/xmlns:objectbank/xmlns:item');
288
        }
289
290
        foreach ($questionsItems as $question_item) {
291
            $countQuestions = $xpath->evaluate('count(xmlns:presentation/xmlns:flow/xmlns:material/xmlns:mattext)', $question_item);
292
293
            if ($countQuestions == 0) {
294
                $questionTitle = $xpath->query('xmlns:presentation/xmlns:material/xmlns:mattext', $question_item);
295
            } else {
296
                $questionTitle = $xpath->query('xmlns:presentation/xmlns:flow/xmlns:material/xmlns:mattext', $question_item);
297
            }
298
299
            $questionTitle = !empty($questionTitle->item(0)->nodeValue) ? $questionTitle->item(0)->nodeValue : '';
300
301
            $questionIdentifier = $xpath->query('@ident', $question_item);
302
            $questionIdentifier = !empty($questionIdentifier->item(0)->nodeValue) ? $questionIdentifier->item(0)->nodeValue : '';
303
304
            if (!empty($questionIdentifier)) {
305
                $questionType = $this->getQuestionType($questionIdentifier, $assessment);
306
307
                if (!empty($questionType['qtype'])) {
308
                    $lastQuestionId++;
309
310
                    $questions[$questionIdentifier]['id'] = $lastQuestionId;
311
312
                    $questionTitle = $this->updateSources($questionTitle, $rootPath);
313
                    $questionTitle = !empty($questionTitle) ? str_replace("%24", "\$", $this->includeTitles($questionTitle)) : '';
314
315
                    $questionname = $xpath->query('@title', $question_item);
316
                    $questionname = !empty($questionname->item(0)->nodeValue) ? $questionname->item(0)->nodeValue : '';
317
318
                    $questions[$questionIdentifier]['title'] = $questionTitle;
319
                    $questions[$questionIdentifier]['name'] = $questionname;
320
                    $questions[$questionIdentifier]['identifier'] = $questionIdentifier;
321
                    $questions[$questionIdentifier]['qtype'] = $questionType['qtype'];
322
                    $questions[$questionIdentifier]['cc_type'] = $questionType['cc'];
323
                    $questions[$questionIdentifier]['feedback'] = $this->getGeneralFeedback($assessment, $questionIdentifier);
324
                    $questions[$questionIdentifier]['defaultgrade'] = $this->getDefaultgrade($assessment, $questionIdentifier);
325
                    $questions[$questionIdentifier]['answers'] = $this->getAnswers($questionIdentifier, $assessment, $lastAnswerId);
326
                }
327
            }
328
        }
329
330
        $questions = !empty($questions) ? $questions : '';
331
332
        return $questions;
333
    }
334
335
    private function getDefaultgrade($assessment, $questionIdentifier)
336
    {
337
        $result = 1;
338
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
339
        $query = '//xmlns:item[@ident="'.$questionIdentifier.'"]';
340
        $query .= '//xmlns:qtimetadatafield[xmlns:fieldlabel="cc_weighting"]/xmlns:fieldentry';
341
        $defgrade = $xpath->query($query);
342
        if (!empty($defgrade) && ($defgrade->length > 0)) {
343
            $resp = (int) $defgrade->item(0)->nodeValue;
344
            if ($resp >= 0 && $resp <= 99) {
345
                $result = $resp;
346
            }
347
        }
348
349
        return $result;
350
    }
351
352
    private function getGeneralFeedback($assessment, $questionIdentifier)
353
    {
354
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
355
356
        $respconditions = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition');
357
358
        if (!empty($respconditions)) {
359
            foreach ($respconditions as $respcondition) {
360
                $continue = $respcondition->getAttributeNode('continue');
361
                $continue = !empty($continue->nodeValue) ? strtolower($continue->nodeValue) : '';
362
363
                if ($continue == 'yes') {
364
                    $displayFeedback = $xpath->query('xmlns:displayfeedback', $respcondition);
365
366
                    if (!empty($displayFeedback)) {
367
                        foreach ($displayFeedback as $feedback) {
368
                            $feedbackIdentifier = $feedback->getAttributeNode('linkrefid');
369
                            $feedbackIdentifier = !empty($feedbackIdentifier->nodeValue) ? $feedbackIdentifier->nodeValue : '';
370
371
                            if (!empty($feedbackIdentifier)) {
372
                                $feedbackIdentifiers[] = $feedbackIdentifier;
373
                            }
374
                        }
375
                    }
376
                }
377
            }
378
        }
379
380
        $feedback = '';
381
        $feedbackIdentifiers = empty($feedbackIdentifiers) ? '' : $feedbackIdentifiers;
382
383
        if (!empty($feedbackIdentifiers)) {
384
            foreach ($feedbackIdentifiers as $feedbackIdentifier) {
385
                $feedbacks = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:itemfeedback[@ident="'.$feedbackIdentifier.'"]/xmlns:flow_mat/xmlns:material/xmlns:mattext');
386
                $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue.' ' : '';
387
            }
388
        }
389
390
        return $feedback;
391
    }
392
393
    private function getFeedback($assessment, $identifier, $itemIdentifier, $questionType)
394
    {
395
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
396
397
        $resourceProcessing = $xpath->query('//xmlns:item[@ident="'.$itemIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition');
398
399
        if (!empty($resourceProcessing)) {
400
            foreach ($resourceProcessing as $response) {
401
                $varequal = $xpath->query('xmlns:conditionvar/xmlns:varequal', $response);
402
                $varequal = !empty($varequal->item(0)->nodeValue) ? $varequal->item(0)->nodeValue : '';
403
404
                if (strtolower($varequal) == strtolower($identifier) || ($questionType == CC_QUIZ_ESSAY)) {
405
                    $displayFeedback = $xpath->query('xmlns:displayfeedback', $response);
406
407
                    if (!empty($displayFeedback)) {
408
                        foreach ($displayFeedback as $feedback) {
409
                            $feedbackIdentifier = $feedback->getAttributeNode('linkrefid');
410
                            $feedbackIdentifier = !empty($feedbackIdentifier->nodeValue) ? $feedbackIdentifier->nodeValue : '';
411
412
                            if (!empty($feedbackIdentifier)) {
413
                                $feedbackIdentifiers[] = $feedbackIdentifier;
414
                            }
415
                        }
416
                    }
417
                }
418
            }
419
        }
420
421
        $feedback = '';
422
        $feedbackIdentifiers = empty($feedbackIdentifiers) ? '' : $feedbackIdentifiers;
423
424
        if (!empty($feedbackIdentifiers)) {
425
            foreach ($feedbackIdentifiers as $feedbackIdentifier) {
426
                $feedbacks = $xpath->query('//xmlns:item[@ident="'.$itemIdentifier.'"]/xmlns:itemfeedback[@ident="'.$feedbackIdentifier.'"]/xmlns:flow_mat/xmlns:material/xmlns:mattext');
427
                $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue.' ' : '';
428
            }
429
        }
430
431
        return $feedback;
432
    }
433
434
    private function getAnswersFib($questionIdentifier, $identifier, $assessment, &$lastAnswerId)
435
    {
436
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
437
438
        $correctanswersfib = [];
439
        $incorrectanswersfib = [];
440
441
        $responseItems = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition');
442
443
        $correctrespcond = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition/xmlns:setvar[text()="100"]/..');
444
        $correctanswers = $xpath->query('xmlns:conditionvar/xmlns:varequal', $correctrespcond->item(0));
445
446
        // Correct answers.
447
        foreach ($correctanswers as $correctans) {
448
            $answertitle = !empty($correctans->nodeValue) ? $correctans->nodeValue : '';
449
            if (empty($answertitle)) {
450
                continue;
451
            }
452
453
            $lastAnswerId++;
454
455
            $correctanswersfib[$answertitle] = [
456
                'id' => $lastAnswerId,
457
                'title' => $answertitle,
458
                'score' => 1,
459
                'feedback' => '',
460
                'case' => 0, ];
461
        }
462
463
        // Handle incorrect answers and feedback for all items.
464
        foreach ($responseItems as $response_item) {
465
            $setvar = $xpath->query('xmlns:setvar', $response_item);
466
            if (!empty($setvar->length) && $setvar->item(0)->nodeValue == '100') {
467
                // Skip the correct answer responsecondition.
468
                continue;
469
            }
470
471
            $varequal = $xpath->query('xmlns:conditionvar/xmlns:varequal', $response_item);
472
            if (empty($varequal->length)) {
473
                // Skip respcondition elements that don't have varequal containing an answer
474
                continue;
475
            }
476
            $answerTitle = !empty($varequal->item(0)->nodeValue) ? $varequal->item(0)->nodeValue : '';
477
478
            $displayFeedback = $xpath->query('xmlns:displayfeedback', $response_item);
479
480
            unset($feedbackIdentifiers);
481
482
            if (!empty($displayFeedback)) {
483
                foreach ($displayFeedback as $feedback) {
484
                    $feedbackIdentifier = $feedback->getAttributeNode('linkrefid');
485
                    $feedbackIdentifier = !empty($feedbackIdentifier->nodeValue) ? $feedbackIdentifier->nodeValue : '';
486
487
                    if (!empty($feedbackIdentifier)) {
488
                        $feedbackIdentifiers[] = $feedbackIdentifier;
489
                    }
490
                }
491
            }
492
493
            $feedback = '';
494
            $feedbackIdentifiers = empty($feedbackIdentifiers) ? '' : $feedbackIdentifiers;
495
496
            if (!empty($feedbackIdentifiers)) {
497
                foreach ($feedbackIdentifiers as $feedbackIdentifier) {
498
                    $feedbacks = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:itemfeedback[@ident="'.$feedbackIdentifier.'"]/xmlns:flow_mat/xmlns:material/xmlns:mattext');
499
                    $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue.' ' : '';
500
                }
501
            }
502
503
            if (array_key_exists($answerTitle, $correctanswersfib)) {
504
                // Already a correct answer, just need the feedback for the correct answer.
505
                $correctanswerfib[$answerTitle]['feedback'] = $feedback;
506
            } else {
507
                // Need to add an incorrect answer.
508
                $lastAnswerId++;
509
                $incorrectanswersfib[] = [
510
                    'id' => $lastAnswerId,
511
                    'title' => $answerTitle,
512
                    'score' => 0,
513
                    'feedback' => $feedback,
514
                    'case' => 0, ];
515
            }
516
        }
517
518
        $answersFib = array_merge($correctanswersfib, $incorrectanswersfib);
519
        $answersFib = empty($answersFib) ? '' : $answersFib;
520
521
        return $answersFib;
522
    }
523
524
    private function getAnswersPatternMatch($questionIdentifier, $identifier, $assessment, &$lastAnswerId)
525
    {
526
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
527
528
        $answersFib = [];
529
530
        $responseItems = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition');
531
532
        foreach ($responseItems as $response_item) {
533
            $setvar = $xpath->query('xmlns:setvar', $response_item);
534
            $setvar = is_object($setvar->item(0)) ? $setvar->item(0)->nodeValue : '';
535
536
            if ($setvar != '') {
537
                $lastAnswerId++;
538
539
                $answerTitle = $xpath->query('xmlns:conditionvar/xmlns:varequal[@respident="'.$identifier.'"]', $response_item);
540
                $answerTitle = !empty($answerTitle->item(0)->nodeValue) ? $answerTitle->item(0)->nodeValue : '';
541
542
                if (empty($answerTitle)) {
543
                    $answerTitle = $xpath->query('xmlns:conditionvar/xmlns:varsubstring[@respident="'.$identifier.'"]', $response_item);
544
                    $answerTitle = !empty($answerTitle->item(0)->nodeValue) ? '*'.$answerTitle->item(0)->nodeValue.'*' : '';
545
                }
546
547
                if (empty($answerTitle)) {
548
                    $answerTitle = '*';
549
                }
550
551
                $case = $xpath->query('xmlns:conditionvar/xmlns:varequal/@case', $response_item);
552
                $case = is_object($case->item(0)) ? $case->item(0)->nodeValue : 'no'
553
                                    ;
554
                $case = strtolower($case) == 'yes' ? 1 :
555
                            0;
556
557
                $displayFeedback = $xpath->query('xmlns:displayfeedback', $response_item);
558
559
                unset($feedbackIdentifiers);
560
561
                if (!empty($displayFeedback)) {
562
                    foreach ($displayFeedback as $feedback) {
563
                        $feedbackIdentifier = $feedback->getAttributeNode('linkrefid');
564
                        $feedbackIdentifier = !empty($feedbackIdentifier->nodeValue) ? $feedbackIdentifier->nodeValue : '';
565
566
                        if (!empty($feedbackIdentifier)) {
567
                            $feedbackIdentifiers[] = $feedbackIdentifier;
568
                        }
569
                    }
570
                }
571
572
                $feedback = '';
573
                $feedbackIdentifiers = empty($feedbackIdentifiers) ? '' : $feedbackIdentifiers;
574
575
                if (!empty($feedbackIdentifiers)) {
576
                    foreach ($feedbackIdentifiers as $feedbackIdentifier) {
577
                        $feedbacks = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:itemfeedback[@ident="'.$feedbackIdentifier.'"]/xmlns:flow_mat/xmlns:material/xmlns:mattext');
578
                        $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue.' ' : '';
579
                    }
580
                }
581
582
                $answersFib[] = ['id' => $lastAnswerId,
583
                                       'title' => $answerTitle,
584
                                       'score' => $setvar,
585
                                       'feedback' => $feedback,
586
                                       'case' => $case, ];
587
            }
588
        }
589
590
        $answersFib = empty($answersFib) ? '' : $answersFib;
591
592
        return $answersFib;
593
    }
594
595
    private function getAnswers($identifier, $assessment, &$lastAnswerId)
596
    {
597
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
598
599
        $answers = [];
600
601
        $questionCcType = $this->getQuestionType($identifier, $assessment);
602
        $questionCcType = $questionCcType['cc'];
603
        $isMultiresponse = ($questionCcType == CC_QUIZ_MULTIPLE_RESPONSE);
604
605
        if ($questionCcType == CC_QUIZ_MULTIPLE_CHOICE || $isMultiresponse || $questionCcType == CC_QUIZ_TRUE_FALSE) {
606
            $queryAnswers = '//xmlns:item[@ident="'.$identifier.'"]/xmlns:presentation/xmlns:response_lid/xmlns:render_choice/xmlns:response_label';
607
            $queryAnswersWithFlow = '//xmlns:item[@ident="'.$identifier.'"]/xmlns:presentation/xmlns:flow/xmlns:response_lid/xmlns:render_choice/xmlns:response_label';
608
609
            $queryIndentifer = '@ident';
610
            $queryTitle = 'xmlns:material/xmlns:mattext';
611
        }
612
613
        if ($questionCcType == CC_QUIZ_ESSAY) {
614
            $queryAnswers = '//xmlns:item[@ident="'.$identifier.'"]/xmlns:presentation/xmlns:response_str';
615
            $queryAnswersWithFlow = '//xmlns:item[@ident="'.$identifier.'"]/xmlns:presentation/xmlns:flow/xmlns:response_str';
616
617
            $queryIndentifer = '@ident';
618
            $queryTitle = 'xmlns:render_fib';
619
        }
620
621
        if ($questionCcType == CC_QUIZ_FIB || $questionCcType == CC_QUIZ_PATTERN_MACHT) {
622
            $xpathQuery = '//xmlns:item[@ident="'.$identifier.'"]/xmlns:presentation/xmlns:response_str/@ident';
623
            $xpathQueryWithFlow = '//xmlns:item[@ident="'.$identifier.'"]/xmlns:presentation/xmlns:flow/xmlns:response_str/@ident';
624
625
            $countResponse = $xpath->evaluate('count('.$xpathQueryWithFlow.')');
626
627
            if ($countResponse == 0) {
628
                $answerIdentifier = $xpath->query($xpathQuery);
629
            } else {
630
                $answerIdentifier = $xpath->query($xpathQueryWithFlow);
631
            }
632
633
            $answerIdentifier = !empty($answerIdentifier->item(0)->nodeValue) ? $answerIdentifier->item(0)->nodeValue : '';
634
635
            if ($questionCcType == CC_QUIZ_FIB) {
636
                $answers = $this->getAnswersFib($identifier, $answerIdentifier, $assessment, $lastAnswerId);
637
            } else {
638
                $answers = $this->getAnswersPatternMatch($identifier, $answerIdentifier, $assessment, $lastAnswerId);
639
            }
640
        } else {
641
            $countResponse = $xpath->evaluate('count('.$queryAnswersWithFlow.')');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $queryAnswersWithFlow does not seem to be defined for all execution paths leading up to this point.
Loading history...
642
643
            if ($countResponse == 0) {
644
                $responseItems = $xpath->query($queryAnswers);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $queryAnswers does not seem to be defined for all execution paths leading up to this point.
Loading history...
645
            } else {
646
                $responseItems = $xpath->query($queryAnswersWithFlow);
647
            }
648
649
            if (!empty($responseItems)) {
650
                if ($isMultiresponse) {
651
                    $correctAnswerScore = 0;
652
                    //get the correct answers count
653
                    $canswers_query = "//xmlns:item[@ident='{$identifier}']//xmlns:setvar[@varname='SCORE'][.=100]/../xmlns:conditionvar//xmlns:varequal[@case='Yes'][not(parent::xmlns:not)]";
654
                    $canswers = $xpath->query($canswers_query);
655
                    if ($canswers->length > 0) {
656
                        $correctAnswerScore = round(1.0 / (float) $canswers->length, 7); //weird
657
                        $correctAanswersIdent = [];
658
                        foreach ($canswers as $cnode) {
659
                            $correctAanswersIdent[$cnode->nodeValue] = true;
660
                        }
661
                    }
662
                }
663
664
                foreach ($responseItems as $response_item) {
665
                    $lastAnswerId++;
666
667
                    $answerIdentifier = $xpath->query($queryIndentifer, $response_item);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $queryIndentifer does not seem to be defined for all execution paths leading up to this point.
Loading history...
668
                    $answerIdentifier = !empty($answerIdentifier->item(0)->nodeValue) ? $answerIdentifier->item(0)->nodeValue : '';
669
670
                    $answerTitle = $xpath->query($queryTitle, $response_item);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $queryTitle does not seem to be defined for all execution paths leading up to this point.
Loading history...
671
                    $answerTitle = !empty($answerTitle->item(0)->nodeValue) ? $answerTitle->item(0)->nodeValue : '';
672
673
                    $answerFeedback = $this->getFeedback($assessment, $answerIdentifier, $identifier, $questionCcType);
674
675
                    $answer_score = $this->getScore($assessment, $answerIdentifier, $identifier);
676
677
                    if ($isMultiresponse && isset($correctAanswersIdent[$answerIdentifier])) {
678
                        $answer_score = $correctAnswerScore;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $correctAnswerScore does not seem to be defined for all execution paths leading up to this point.
Loading history...
679
                    }
680
681
                    $answers[] = ['id' => $lastAnswerId,
682
                                       'title' => $answerTitle,
683
                                       'score' => $answer_score,
684
                                       'identifier' => $answerIdentifier,
685
                                       'feedback' => $answerFeedback, ];
686
                }
687
            }
688
        }
689
690
        $answers = empty($answers) ? '' : $answers;
691
692
        return $answers;
693
    }
694
695
    private function getScore($assessment, $identifier, $questionIdentifier)
696
    {
697
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
698
699
        $resourceProcessing = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition');
700
701
        if (!empty($resourceProcessing)) {
702
            foreach ($resourceProcessing as $response) {
703
                $questionCcType = $this->getQuestionType($questionIdentifier, $assessment);
704
                $questionCcType = $questionCcType['cc'];
705
706
                $varequal = $xpath->query('xmlns:conditionvar/xmlns:varequal', $response);
707
                $varequal = !empty($varequal->item(0)->nodeValue) ? $varequal->item(0)->nodeValue : '';
708
709
                if (strtolower($varequal) == strtolower($identifier)) {
710
                    $score = $xpath->query('xmlns:setvar', $response);
711
                    $score = !empty($score->item(0)->nodeValue) ? $score->item(0)->nodeValue : '';
712
                }
713
            }
714
        }
715
716
        $score = empty($score) ? "0.0000000" : '1.0000000';
717
718
        return $score;
719
    }
720
721
    private function getQuestionType($identifier, $assessment)
722
    {
723
        $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
724
725
        $metadata = $xpath->query('//xmlns:item[@ident="'.$identifier.'"]/xmlns:itemmetadata/xmlns:qtimetadata/xmlns:qtimetadatafield');
726
727
        foreach ($metadata as $field) {
728
            $fieldLabel = $xpath->query('xmlns:fieldlabel', $field);
729
            $fieldLabel = !empty($fieldLabel->item(0)->nodeValue) ? $fieldLabel->item(0)->nodeValue : '';
730
731
            if ($fieldLabel == 'cc_profile') {
732
                $fieldEntry = $xpath->query('xmlns:fieldentry', $field);
733
                $type = !empty($fieldEntry->item(0)->nodeValue) ? $fieldEntry->item(0)->nodeValue : '';
734
            }
735
        }
736
737
        $returnType = [];
738
739
        $returnType['qtype'] = '';
740
        $returnType['cc'] = $type;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $type does not seem to be defined for all execution paths leading up to this point.
Loading history...
741
742
        switch ($type) {
743
            case CC_QUIZ_MULTIPLE_CHOICE:
744
                $returnType['qtype'] = 'unique_answer';
745
                break;
746
            case CC_QUIZ_MULTIPLE_RESPONSE:
747
                $returnType['qtype'] = 'multiple_answer';
748
                break;
749
            case CC_QUIZ_FIB:
750
                $returnType['qtype'] = 'fib';
751
                break;
752
            case CC_QUIZ_ESSAY:
753
                $returnType['qtype'] = 'essay';
754
                break;
755
        }
756
757
        return $returnType;
758
    }
759
}
760