Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
62.50% covered (warning)
62.50%
25 / 40
40.00% covered (danger)
40.00%
2 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
Exporter
62.50% covered (warning)
62.50%
25 / 40
40.00% covered (danger)
40.00%
2 / 5
6.32
0.00% covered (danger)
0.00%
0 / 1
 renderManifest
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
2
 getQTIVersion
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 itemContentPostProcessing
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
1
 setTransformationService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTransformationService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2024 (original work) Open Assessment Technologies SA;
19 */
20
21declare(strict_types=1);
22
23namespace oat\taoQtiItem\model\Export\Qti3Package;
24
25use common_ext_ExtensionException;
26use common_ext_ExtensionsManager;
27use DOMDocument;
28use DOMException;
29use Exception;
30use oat\taoQtiItem\model\Export\QTIPackedItemExporter;
31use tao_helpers_Display as Display;
32use taoItems_models_classes_TemplateRenderer as TemplateRenderer;
33
34class Exporter extends QTIPackedItemExporter
35{
36    private const QTI_SCHEMA_NAMESPACE = 'http://www.imsglobal.org/xsd/imsqtiasi_v3p0';
37    private const XML_SCHEMA_INSTANCE = 'http://www.w3.org/2001/XMLSchema-instance';
38    private const XSI_SCHEMA_LOCATION = 'http://www.imsglobal.org/xsd/imsqtiasi_v3p0';
39    // phpcs:ignore Generic.Files.LineLength.TooLong
40    private const XSI_SCHEMA_LOCATION_XSD = 'https://purl.imsglobal.org/spec/qti/v3p0/schema/xsd/imsqti_asiv3p0_v1p0.xsd';
41    private const IMSMANIFEST_QTI_30_TEMPLATE_PATH = 'model/qti/templates/imsmanifestQti30.tpl.php';
42    private const IMSMANIFEST_QTI_30_MATHML = 'http://www.w3.org/1998/Math/MathML';
43    private const IMSMANIFEST_QTI_30_XSD_MATHML = 'https://purl.imsglobal.org/spec/mathml/v3p0/schema/xsd/mathml3.xsd';
44
45    private ?TransformationService $transformationService = null;
46
47    /**
48     * @throws common_ext_ExtensionException
49     * @throws Exception
50     */
51    protected function renderManifest(array $options, array $qtiItemData): DOMDocument
52    {
53        $tpl = common_ext_ExtensionsManager::singleton()->getExtensionById('taoQtiItem')->getDir()
54            . self::IMSMANIFEST_QTI_30_TEMPLATE_PATH;
55
56        $templateRenderer = new TemplateRenderer(
57            $tpl,
58            [
59                'qtiItems' => [$qtiItemData],
60                'manifestIdentifier' => 'MANIFEST-' .
61                    Display::textCleaner(uniqid('tao', true), '-')
62            ]
63        );
64
65        $newManifest = new DOMDocument('1.0', TAO_DEFAULT_ENCODING);
66        $newManifest->loadXML($templateRenderer->render());
67
68        return $newManifest;
69    }
70
71    public function getQTIVersion(): string
72    {
73        return '3p0';
74    }
75
76
77    /**
78     * @throws DOMException
79     */
80    protected function itemContentPostProcessing($content): string
81    {
82        $transformationService = $this->getTransformationService();
83        $dom = new DOMDocument('1.0', 'UTF-8');
84        $dom->loadXML($content);
85
86        $newDom = new DOMDocument('1.0', 'UTF-8');
87        $newDom->preserveWhiteSpace = false;
88        $newDom->formatOutput = true;
89
90        $oldRoot = $dom->documentElement;
91        $newRoot = $newDom->createElement($transformationService->createQtiElementName($oldRoot->nodeName));
92
93        //QTI3 namespace
94        $newRoot->setAttribute('xmlns', self::QTI_SCHEMA_NAMESPACE);
95        $newRoot->setAttribute('xmlns:xsi', self::XML_SCHEMA_INSTANCE);
96        $newRoot->setAttribute(
97            'xsi:schemaLocation',
98            sprintf(
99                '%s %s %s %s',
100                self::XSI_SCHEMA_LOCATION,
101                self::XSI_SCHEMA_LOCATION_XSD,
102                self::IMSMANIFEST_QTI_30_MATHML,
103                self::IMSMANIFEST_QTI_30_XSD_MATHML
104            )
105        );
106
107        $transformationService->transformAttributes($oldRoot, $newRoot);
108
109        $newDom->appendChild($newRoot);
110
111        $transformationService->transformChildren($oldRoot, $newRoot, $newDom);
112
113        return $newDom->saveXML();
114    }
115
116    public function setTransformationService(TransformationService $service): void
117    {
118        $this->transformationService = $service;
119    }
120
121    public function getTransformationService(): TransformationService
122    {
123        return $this->transformationService;
124    }
125}