Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 40 |
|
0.00% |
0 / 7 |
CRAP | |
0.00% |
0 / 1 |
QtiItemPacker | |
0.00% |
0 / 40 |
|
0.00% |
0 / 7 |
272 | |
0.00% |
0 / 1 |
setQtiParser | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
packItem | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
packQtiItem | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
20 | |||
createQtiItemPackWithAssets | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
20 | |||
resolveAsset | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
setReplaceXinclude | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getXmlByItem | |
0.00% |
0 / 1 |
|
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 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT); |
19 | * |
20 | * |
21 | */ |
22 | |
23 | namespace oat\taoQtiItem\model\pack; |
24 | |
25 | use oat\oatbox\filesystem\Directory; |
26 | use oat\taoItems\model\pack\ItemPack; |
27 | use oat\taoItems\model\pack\ItemPacker; |
28 | use oat\taoQtiItem\model\pack\QtiAssetPacker\PackedAsset; |
29 | use oat\taoQtiItem\model\qti\Item; |
30 | use oat\taoQtiItem\model\qti\Parser as QtiParser; |
31 | use oat\taoQtiItem\model\qti\AssetParser; |
32 | use core_kernel_classes_Resource; |
33 | use InvalidArgumentException; |
34 | use common_Exception; |
35 | use oat\taoQtiItem\model\qti\XIncludeLoader; |
36 | use oat\taoItems\model\media\ItemMediaResolver; |
37 | use oat\taoQtiItem\model\qti\Service; |
38 | use Throwable; |
39 | |
40 | /** |
41 | * This class pack a QTI Item. Packing instead of compiling, aims |
42 | * to extract the only data of an item. Those data are used by the |
43 | * item runner to render the item. |
44 | * |
45 | * @package taoQtiItem |
46 | * @author Bertrand Chevrier <bertrand@taotesting.com> |
47 | */ |
48 | class QtiItemPacker extends ItemPacker |
49 | { |
50 | /** |
51 | * The item type identifier |
52 | * @var string |
53 | */ |
54 | protected static $itemType = 'qti'; |
55 | |
56 | /** |
57 | * XInclude expressions are replaced and not treated as assets |
58 | * @var boolean |
59 | */ |
60 | protected $replaceXinclude = true; |
61 | |
62 | /** @var QtiParser|null */ |
63 | private $qtiParser; |
64 | |
65 | public function setQtiParser(QtiParser $parser): void |
66 | { |
67 | $this->qtiParser = $parser; |
68 | } |
69 | |
70 | /** |
71 | * packItem implementation for QTI |
72 | * @inheritdoc |
73 | * @see {@link ItemPacker} |
74 | * @throws InvalidArgumentException |
75 | * @throws common_Exception |
76 | */ |
77 | public function packItem(core_kernel_classes_Resource $item, $lang, Directory $directory) |
78 | { |
79 | //use the QtiParser to transform the QTI XML into an assoc array representation |
80 | $content = $this->getXmlByItem($item, $lang); |
81 | //load content |
82 | $qtiParser = $this->qtiParser ?? new QtiParser($content); |
83 | |
84 | if ($this->skipValidation === false && !$qtiParser->validate()) { |
85 | throw new common_Exception('Invalid QTI content : ' . $qtiParser->displayErrors(false)); |
86 | } |
87 | |
88 | //parse |
89 | $qtiItem = $qtiParser->load(); |
90 | |
91 | return $this->packQtiItem($item, $lang, $qtiItem, $directory); |
92 | } |
93 | |
94 | /** |
95 | * @param core_kernel_classes_Resource $item the item to pack |
96 | * @param string $lang |
97 | * @param Item $qtiItem |
98 | * @param \oat\oatbox\filesystem\Directory $directory |
99 | * @return ItemPack $itemPack |
100 | * @throws common_Exception |
101 | */ |
102 | public function packQtiItem($item, $lang, $qtiItem, Directory $directory) |
103 | { |
104 | //use the QtiParser to transform the QTI XML into an assoc array representation |
105 | try { |
106 | //build the ItemPack from the parsed data |
107 | $resolver = new ItemMediaResolver($item, $lang); |
108 | if ($this->replaceXinclude) { |
109 | $xincludeLoader = new XIncludeLoader($qtiItem, $resolver); |
110 | $xincludeLoader->load(true); |
111 | } |
112 | |
113 | $itemPack = new ItemPack(self::$itemType, $qtiItem->toArray()); |
114 | |
115 | $itemPack->setAssetEncoders($this->getAssetEncoders()); |
116 | |
117 | $assetParser = new AssetParser($qtiItem, $directory); |
118 | $assetParser->setDeepParsing($this->isNestedResourcesInclusion()); |
119 | $assetParser->setGetXinclude(!$this->replaceXinclude); |
120 | |
121 | $storageDirectory = new \tao_models_classes_service_StorageDirectory( |
122 | $item->getUri(), |
123 | $directory->getFileSystemId(), |
124 | $directory->getPrefix() . '/' . $lang |
125 | ); |
126 | $storageDirectory->setServiceLocator($directory->getServiceLocator()); |
127 | |
128 | foreach ($assetParser->extract($itemPack) as $type => $assets) { |
129 | $itemPack->setAssets($type, $this->resolveAsset($assets, $resolver), $storageDirectory, true); |
130 | } |
131 | } catch (common_Exception $e) { |
132 | throw new common_Exception('Unable to pack item ' . $item->getUri() . ' : ' . $e->getMessage()); |
133 | } |
134 | |
135 | return $itemPack; |
136 | } |
137 | |
138 | /** |
139 | * @param $item |
140 | * @param $qtiItem |
141 | * @param Directory $directory |
142 | * @param PackedAsset[] $packedAssets |
143 | * @return ItemPack |
144 | * @throws common_Exception |
145 | */ |
146 | public function createQtiItemPackWithAssets($item, $qtiItem, array $packedAssets): ItemPack |
147 | { |
148 | try { |
149 | $itemPack = new ItemPack(self::$itemType, $qtiItem->toArray()); |
150 | $itemPack->setAssetEncoders($this->getAssetEncoders()); |
151 | |
152 | /** @var PackedAsset $packedAsset */ |
153 | foreach ($packedAssets as $packedAsset) { |
154 | if ($packedAsset->getType() != 'xinclude') { |
155 | $itemPack->setAsset($packedAsset->getType(), $packedAsset->getMediaAsset()); |
156 | } |
157 | } |
158 | } catch (Throwable $e) { |
159 | throw new common_Exception('Unable to pack item ' . $item->getUri() . ' : ' . $e->getMessage()); |
160 | } |
161 | |
162 | return $itemPack; |
163 | } |
164 | |
165 | /** |
166 | * @param string[] $assets |
167 | * @param ItemMediaResolver $resolver |
168 | * @return string[] |
169 | */ |
170 | private function resolveAsset($assets, ItemMediaResolver $resolver) |
171 | { |
172 | foreach ($assets as &$asset) { |
173 | $asset = $resolver->resolve($asset); |
174 | } |
175 | return $assets; |
176 | } |
177 | |
178 | /** |
179 | * @param boolean $replaceXinclude |
180 | */ |
181 | public function setReplaceXinclude($replaceXinclude) |
182 | { |
183 | $this->replaceXinclude = $replaceXinclude; |
184 | } |
185 | |
186 | /** |
187 | * @param core_kernel_classes_Resource $item |
188 | * @param string $lang |
189 | * @return string |
190 | */ |
191 | protected function getXmlByItem(core_kernel_classes_Resource $item, $lang = '') |
192 | { |
193 | return Service::singleton()->getXmlByRdfItem($item, $lang); |
194 | } |
195 | } |