Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
83.33% covered (warning)
83.33%
40 / 48
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
CatUtils
83.33% covered (warning)
83.33%
40 / 48
0.00% covered (danger)
0.00%
0 / 3
16.04
0.00% covered (danger)
0.00%
0 / 1
 getCatInfo
96.67% covered (success)
96.67%
29 / 30
0.00% covered (danger)
0.00%
0 / 1
8
 isAssessmentSectionAdaptive
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 createDomXPath
78.57% covered (warning)
78.57%
11 / 14
0.00% covered (danger)
0.00%
0 / 1
5.25
1<?php
2
3namespace oat\taoQtiTest\models\cat;
4
5use qtism\data\AssessmentTest;
6use qtism\data\AssessmentSection;
7use DOMDocument;
8use DOMXPath;
9
10/**
11 * Computerized Assessment Test Utilities.
12 *
13 * This class provide utility methods for CAT support in TAO.
14 */
15class CatUtils
16{
17    /**
18     * Extract CAT Information from Test Definition.
19     *
20     * This method extracts CAT Information from a given $test defintion. Please find below an example
21     * of return value with an adaptive section with QTI Assessment Section Identifier 'S01'.
22     *
23     * [
24     *      'S01' =>
25     *      [
26     *          'adaptiveEngineRef' => 'http://somewhere.com/api',
27     *          'adaptiveSettingsRef' => 'file.xml'
28     *      ]
29     * ]
30     *
31     * @param \qtism\data\AssessmentTest $test
32     * @param string $namespace (optional) The namespace where to search the "adaptivity" information in the
33     *                          $test definition. If not given, a default namespace will be traversed.
34     * @return array
35     */
36    public static function getCatInfo(AssessmentTest $test, string $namespace = '')
37    {
38        $info = [];
39
40        /** @var AssessmentSection $assessmentSection */
41        foreach ($test->getComponentsByClassName('assessmentSection') as $assessmentSection) {
42            $xpath = self::createDomXPath($assessmentSection, $namespace);
43            if (null === $xpath) {
44                continue;
45            }
46
47            // Reference QTI assessmentSection identifier.
48            $sectionIdentifier = $assessmentSection->getIdentifier();
49            $sectionInfo = [];
50
51            // Get the adaptiveEngineRef.
52            foreach (
53                $xpath->query(
54                    './/ais:adaptiveItemSelection/ais:adaptiveEngineRef',
55                    $xpath->document
56                ) as $adaptiveEngineRef
57            ) {
58                $sectionInfo['adaptiveEngineRef'] = $adaptiveEngineRef->getAttribute('href');
59            }
60
61            // Get the adaptiveSettingsRef.
62            foreach (
63                $xpath->query(
64                    './/ais:adaptiveItemSelection/ais:adaptiveSettingsRef',
65                    $xpath->document
66                ) as $adaptiveSettingsRef
67            ) {
68                $sectionInfo['adaptiveSettingsRef'] = $adaptiveSettingsRef->getAttribute('href');
69            }
70
71            // Get the qtiUsagedataRef.
72            foreach (
73                $xpath->query(
74                    './/ais:adaptiveItemSelection/ais:qtiUsagedataRef',
75                    $xpath->document
76                ) as $qtiUsagedataRef
77            ) {
78                $sectionInfo['qtiUsagedataRef'] = $qtiUsagedataRef->getAttribute('href');
79            }
80
81            // Get the qtiUsagedataRef.
82            foreach (
83                $xpath->query(
84                    './/ais:adaptiveItemSelection/ais:qtiMetadataRef',
85                    $xpath->document
86                ) as $qtiMetadataRef
87            ) {
88                $sectionInfo['qtiMetadataRef'] = $qtiMetadataRef->getAttribute('href');
89            }
90
91            if (!empty($sectionInfo)) {
92                $info[$sectionIdentifier] = $sectionInfo;
93            }
94        }
95
96        return $info;
97    }
98
99    /**
100     * Is a Given Section Adaptive
101     *
102     * This method checks whether a given AssessmentSection object $section is adaptive.
103     *
104     * @param \qtism\data\AssessmentSection $section
105     * @param string $namespace (optional) The namespace where to search the "adaptivity" information in the
106     *                          $test definition. If not given, a default namespace will be traversed.
107     *
108     * @return boolean
109     */
110    public static function isAssessmentSectionAdaptive(AssessmentSection $section, string $namespace = '')
111    {
112        $xpath = self::createDomXPath($section, $namespace);
113        if (null === $xpath) {
114            return false;
115        }
116
117        return $xpath->query('.//ais:adaptiveItemSelection', $xpath->document)->length > 0;
118    }
119
120    private static function createDomXPath(AssessmentSection $section, string $namespace = ''): ?DOMXPath
121    {
122        if ($namespace === '') {
123            $namespace = CatService::QTI_2X_ADAPTIVE_XML_NAMESPACE;
124        }
125
126        $selection = $section->getSelection();
127        if (null === $selection) {
128            return null;
129        }
130
131        $selectionXml = (string)$selection->getXml();
132        if (empty($selectionXml)) {
133            return null;
134        }
135
136        $xmlExtension = new DOMDocument();
137        if (!$xmlExtension->loadXML($selectionXml)) {
138            return null;
139        }
140
141        $xpath = new DOMXPath($xmlExtension);
142        $xpath->registerNamespace('ais', $namespace);
143
144        return $xpath;
145    }
146}