Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
77.19% covered (warning)
77.19%
44 / 57
42.86% covered (danger)
42.86%
3 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
QtiResultXmlImporter
77.19% covered (warning)
77.19%
44 / 57
42.86% covered (danger)
42.86%
3 / 7
15.00
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 importByResultInput
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 importQtiResultXml
74.07% covered (warning)
74.07%
20 / 27
0.00% covered (danger)
0.00%
0 / 1
2.07
 storeItemVariables
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
3.01
 storeTestVariables
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getItem
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
3.14
 getItems
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
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) 2023 (original work) Open Assessment Technologies SA.
19 */
20
21declare(strict_types=1);
22
23namespace oat\taoResultServer\models\Import\Service;
24
25use common_exception_Error;
26use common_exception_InvalidArgumentType;
27use common_exception_NotFound;
28use common_exception_NotImplemented;
29use core_kernel_classes_Resource;
30use core_kernel_persistence_Exception;
31use oat\generis\model\data\Ontology;
32use oat\taoDelivery\model\execution\DeliveryExecutionService;
33use oat\taoDeliveryRdf\model\DeliveryAssemblyService;
34use oat\taoResultServer\models\classes\ResultServerService;
35use oat\taoResultServer\models\Import\Exception\ImportResultException;
36use oat\taoResultServer\models\Import\Factory\QtiResultXmlFactory;
37use oat\taoResultServer\models\Import\Input\ImportResultInput;
38use oat\taoResultServer\models\Parser\QtiResultParser;
39use qtism\data\AssessmentItemRef;
40use qtism\data\AssessmentTest;
41use qtism\data\QtiComponentCollection;
42use qtism\data\storage\xml\XmlStorageException;
43use taoQtiTest_models_classes_QtiTestService;
44use taoResultServer_models_classes_WritableResultStorage;
45
46class QtiResultXmlImporter
47{
48    private Ontology $ontology;
49    private ResultServerService $resultServerService;
50    private QtiResultXmlFactory $qtiResultXmlFactory;
51    private QtiResultParser $qtiResultParser;
52    private taoQtiTest_models_classes_QtiTestService $qtiTestService;
53    private DeliveryExecutionService $deliveryExecutionService;
54
55    public function __construct(
56        Ontology $ontology,
57        ResultServerService $resultServerService,
58        QtiResultXmlFactory $qtiResultXmlFactory,
59        QtiResultParser $qtiResultParser,
60        taoQtiTest_models_classes_QtiTestService $qtiTestService,
61        DeliveryExecutionService $deliveryExecutionService
62    ) {
63        $this->ontology = $ontology;
64        $this->resultServerService = $resultServerService;
65        $this->qtiResultXmlFactory = $qtiResultXmlFactory;
66        $this->qtiResultParser = $qtiResultParser;
67        $this->qtiTestService = $qtiTestService;
68        $this->deliveryExecutionService = $deliveryExecutionService;
69    }
70
71    /**
72     * @throws ImportResultException
73     * @throws XmlStorageException
74     * @throws common_exception_Error
75     * @throws common_exception_InvalidArgumentType
76     * @throws common_exception_NotFound
77     * @throws common_exception_NotImplemented
78     * @throws core_kernel_persistence_Exception
79     */
80    public function importByResultInput(ImportResultInput $input): void
81    {
82        $this->importQtiResultXml(
83            $input->getDeliveryExecutionId(),
84            $this->qtiResultXmlFactory->createByImportResult($input)
85        );
86    }
87
88    /**
89     * @throws ImportResultException
90     * @throws XmlStorageException
91     * @throws common_exception_NotFound
92     * @throws common_exception_Error
93     * @throws common_exception_InvalidArgumentType
94     * @throws common_exception_NotImplemented
95     * @throws core_kernel_persistence_Exception
96     */
97    public function importQtiResultXml(
98        string $deliveryExecutionId,
99        string $xmlContent
100    ): void {
101        $resultStorage = $this->resultServerService->getResultStorage();
102
103        if (!$resultStorage instanceof taoResultServer_models_classes_WritableResultStorage) {
104            throw new ImportResultException(
105                sprintf(
106                    'ResultStorage must be an instance of %s. Instance of %s provided',
107                    taoResultServer_models_classes_WritableResultStorage::class,
108                    get_class($resultStorage)
109                )
110            );
111        }
112
113        $resultMapper = $this->qtiResultParser->parse($xmlContent);
114        $deliveryExecution = $this->deliveryExecutionService->getDeliveryExecution($deliveryExecutionId);
115        $delivery = $deliveryExecution->getDelivery();
116        $test = $this->ontology->getResource($delivery->getUri())
117            ->getOnePropertyValue($this->ontology->getProperty(DeliveryAssemblyService::PROPERTY_ORIGIN));
118
119        $this->storeTestVariables(
120            $resultStorage,
121            $test->getUri(),
122            $deliveryExecutionId,
123            $resultMapper->getTestVariables()
124        );
125        $this->storeItemVariables(
126            $resultStorage,
127            $test->getUri(),
128            $this->getItems($test),
129            $deliveryExecutionId,
130            $resultMapper->getItemVariables()
131        );
132    }
133
134    private function storeItemVariables(
135        taoResultServer_models_classes_WritableResultStorage $resultStorage,
136        string $testUri,
137        QtiComponentCollection $items,
138        string $deliveryExecutionId,
139        array $itemVariablesByItemResult
140    ): void {
141        foreach ($itemVariablesByItemResult as $itemResultIdentifier => $itemVariables) {
142            $item = $this->getItem($itemResultIdentifier, $items);
143
144            if (null === $item) {
145                continue;
146            }
147
148            $resultStorage->storeItemVariables(
149                $deliveryExecutionId,
150                $testUri,
151                $item->getHref(),
152                $itemVariables,
153                sprintf('%s.%s.0', $deliveryExecutionId, $itemResultIdentifier)
154            );
155        }
156    }
157
158    private function storeTestVariables(
159        taoResultServer_models_classes_WritableResultStorage $resultStorage,
160        string $testId,
161        string $deliveryExecutionId,
162        array $itemVariablesByTestResult
163    ): void {
164        foreach ($itemVariablesByTestResult as $test => $testVariables) {
165            $resultStorage->storeTestVariables($deliveryExecutionId, $testId, $testVariables, $deliveryExecutionId);
166        }
167    }
168
169    private function getItem(string $identifier, QtiComponentCollection $items): ?AssessmentItemRef
170    {
171        /** @var AssessmentItemRef $item */
172        foreach ($items as $item) {
173            if ($item->getIdentifier() === $identifier) {
174                return $item;
175            }
176        }
177
178        return null;
179    }
180
181    private function getItems(core_kernel_classes_Resource $test): QtiComponentCollection
182    {
183        $testDoc = $this->qtiTestService->getDoc($test);
184        /** @var AssessmentTest $test */
185        $assessmentTest = $testDoc->getDocumentComponent();
186
187        return $assessmentTest->getComponentsByClassName('assessmentItemRef');
188    }
189}