Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
QtiTestExporter
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 5
110
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 export
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
6
 getAssessmentData
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
30
 getHeaders
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getItemExporter
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) 2015-2022 (original work) Open Assessment Technologies SA;
19 */
20
21declare(strict_types=1);
22
23namespace oat\taoQtiTest\models\export\Formats\Metadata;
24
25use core_kernel_classes_Resource as Resource;
26use oat\generis\model\OntologyAwareTrait;
27use oat\oatbox\log\LoggerAwareTrait;
28use oat\oatbox\reporting\Report;
29use oat\oatbox\service\ServiceManager;
30use oat\taoQtiItem\model\flyExporter\simpleExporter\SimpleExporter;
31use oat\taoQtiTest\models\export\QtiTestExporterInterface;
32use qtism\data\AssessmentItemRef;
33use qtism\data\AssessmentSection;
34use qtism\data\storage\xml\XmlDocument;
35use qtism\data\TestPart;
36use tao_helpers_Uri as Uri;
37use taoQtiTest_models_classes_QtiTestService as QtiTestService;
38use ZipArchive;
39
40class QtiTestExporter implements QtiTestExporterInterface
41{
42    use OntologyAwareTrait;
43    use LoggerAwareTrait;
44
45    public const TEST_PART = 'testPart';
46    public const TEST_SECTION = 'section';
47    public const TEST_ITEM = 'assessmentItemRef';
48
49    public const ITEM_SHUFFLE = 'shuffle';
50    public const ITEM_ORDER = 'section-order';
51    public const ITEM_URI = 'uri';
52
53    /** Resource object of the test, defined for export */
54    protected Resource $instance;
55
56    /** Archive object, which contains exported CSV files */
57    protected ZipArchive $archive;
58
59    public function __construct(Resource $instance, ZipArchive $archive)
60    {
61        $this->archive = $archive;
62        $this->instance = $instance;
63    }
64
65    public function export(array $options = []): Report
66    {
67        $report = Report::createSuccess(__('Export successful for the test "%s"', $this->instance->getLabel()));
68
69        $metadata = [];
70
71        foreach ($this->getAssessmentData(QtiTestService::singleton()->getDoc($this->instance)) as $data) {
72            $itemData = $this->getItemExporter()->getDataByItem($this->getResource($data[static::ITEM_URI]));
73            unset($data[static::ITEM_URI]);
74
75            $metadata[] = array_map(fn ($v) => array_merge($v, $data), $itemData);
76        }
77
78        $temporaryFilePath = $this->getItemExporter()->save(
79            array_merge($this->getItemExporter()->getHeaders(), $this->getHeaders()),
80            $metadata
81        );
82
83        $this->archive->addFromString(
84            sprintf('%s_%s.csv', $this->instance->getLabel(), Uri::getUniqueId($this->instance->getUri())),
85            file_get_contents($temporaryFilePath)
86        );
87
88        return $report;
89    }
90
91    protected function getAssessmentData(XmlDocument $xml): array
92    {
93        $assessmentItemData = [];
94
95        $testPartCollection = $xml->getDocumentComponent()->getComponentsByClassName(static::TEST_PART);
96
97        /** @var TestPart $testPart */
98        foreach ($testPartCollection as $testPart) {
99            $sectionCollection = $testPart->getAssessmentSections();
100            /** @var AssessmentSection $section */
101            foreach ($sectionCollection as $section) {
102                $itemCollection = $section->getComponentsByClassName(static::TEST_ITEM);
103                $order = 1;
104                /** @var AssessmentItemRef $item */
105                foreach ($itemCollection as $item) {
106                    $assessmentItemData[$item->getIdentifier()] = [
107                        static::ITEM_URI     => $item->getHref(),
108                        static::TEST_PART    => $testPart->getIdentifier(),
109                        static::TEST_SECTION => $section->getIdentifier(),
110                        static::ITEM_SHUFFLE => !is_null($section->getOrdering())
111                            ? (int)$section->getOrdering()->getShuffle()
112                            : 0,
113                        static::ITEM_ORDER   => $order,
114                    ];
115                    $order++;
116                }
117            }
118        }
119
120        return $assessmentItemData;
121    }
122
123    /** Get headers of additional data for assessment items */
124    protected function getHeaders(): array
125    {
126        return [
127            static::TEST_PART,
128            static::TEST_SECTION,
129            static::ITEM_SHUFFLE,
130            static::ITEM_ORDER
131        ];
132    }
133
134    protected function getItemExporter(): SimpleExporter
135    {
136        /** @noinspection PhpIncompatibleReturnTypeInspection */
137        return ServiceManager::getServiceManager()->get(SimpleExporter::SERVICE_ID);
138    }
139}