Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 39 |
|
0.00% |
0 / 10 |
CRAP | |
0.00% |
0 / 1 |
StimulusHandler | |
0.00% |
0 / 39 |
|
0.00% |
0 / 10 |
342 | |
0.00% |
0 / 1 |
isApplicable | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
handle | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
safePath | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
encodeStimulusImages | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
42 | |||
finalize | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setItemSource | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setQtiItem | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getItemSource | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getQtiItem | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
assertAttribute | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 |
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) 2018 (original work) Open Assessment Technologies SA; |
19 | * |
20 | */ |
21 | |
22 | namespace oat\taoQtiItem\model\qti\asset\handler; |
23 | |
24 | use oat\taoItems\model\media\LocalItemSource; |
25 | use oat\taoQtiItem\model\qti\Element; |
26 | use oat\taoQtiItem\model\qti\Item; |
27 | |
28 | /** |
29 | * Class StimulusHandler |
30 | * |
31 | * The purpose of this handler is to extract xml stimulus from item to copy them |
32 | * If the included stimulus includes images, they should be encoded to avoid file dependencies |
33 | * |
34 | * @package oat\taoQtiItem\model\qti\asset\handler |
35 | */ |
36 | class StimulusHandler implements AssetHandler |
37 | { |
38 | /** |
39 | * The object representation of qti item |
40 | * |
41 | * @var Item |
42 | */ |
43 | protected $qtiItem; |
44 | |
45 | /** |
46 | * The destination of the item directory |
47 | * |
48 | * @var LocalItemSource |
49 | */ |
50 | protected $itemSource; |
51 | |
52 | /** |
53 | * Applicable to all items that contain <xinclude> tag |
54 | * |
55 | * @param $relativePath |
56 | * @return bool |
57 | * @throws \common_exception_MissingParameter |
58 | */ |
59 | public function isApplicable($relativePath) |
60 | { |
61 | $xincluded = []; |
62 | /** @var Element $xincludeElement */ |
63 | foreach ($this->getQtiItem()->getComposingElements('oat\taoQtiItem\model\qti\Xinclude') as $xincludeElement) { |
64 | $xincluded[] = $xincludeElement->attr('href'); |
65 | \common_Logger::i("Xinclude component found in resource '" . |
66 | $this->getQtiItem()->getIdentifier() . "' with href '" . $xincludeElement->attr('href') . "'."); |
67 | } |
68 | |
69 | return in_array($relativePath, $xincluded); |
70 | } |
71 | |
72 | /** |
73 | * Store locally, in a safe directory |
74 | * Encoded all stimulus images to avoid file dependencies |
75 | * |
76 | * @param $absolutePath |
77 | * @param $relativePath |
78 | * @return array|mixed |
79 | * @throws \common_Exception |
80 | */ |
81 | public function handle($absolutePath, $relativePath) |
82 | { |
83 | $safePath = $this->safePath($relativePath); |
84 | $this->encodeStimulusImages($absolutePath); |
85 | |
86 | $info = $this->getItemSource()->add($absolutePath, basename($absolutePath), $safePath); |
87 | \common_Logger::i('Stimulus file \'' . $absolutePath . '\' copied.'); |
88 | |
89 | return $info; |
90 | } |
91 | |
92 | /** |
93 | * Remove ../ to secure path |
94 | * |
95 | * @param $path |
96 | * @return string |
97 | */ |
98 | protected function safePath($path) |
99 | { |
100 | $safePath = ''; |
101 | if (dirname($path) !== '.') { |
102 | $safePath = str_replace('../', '', dirname($path)) . '/'; |
103 | } |
104 | return $safePath; |
105 | } |
106 | |
107 | /** |
108 | * Walk into stimulus file to transform images from path to base64encoded data:image |
109 | * |
110 | * @param $absolutePath |
111 | * @throws \common_Exception |
112 | */ |
113 | protected function encodeStimulusImages($absolutePath) |
114 | { |
115 | if (!is_readable($absolutePath) || !is_writable($absolutePath)) { |
116 | throw new \common_Exception('Stimulus cannot be imported, asset file is not readable/writable.'); |
117 | } |
118 | $dom = new \DOMDocument('1.0', 'UTF-8'); |
119 | $dom->loadXML(file_get_contents($absolutePath)); |
120 | $images = $dom->getElementsByTagName('img'); |
121 | |
122 | for ($i = 0; $i < $images->length; $i++) { |
123 | $imageFile = dirname($absolutePath) . DIRECTORY_SEPARATOR |
124 | . ltrim($images->item($i)->getAttribute('src'), DIRECTORY_SEPARATOR); |
125 | |
126 | if (is_readable($imageFile)) { |
127 | $encodedSrc = 'data:image/png;base64,' . base64_encode(file_get_contents($imageFile)); |
128 | $images->item($i)->setAttribute('src', $encodedSrc); |
129 | } |
130 | } |
131 | if (isset($encodedSrc)) { |
132 | file_put_contents($absolutePath, $dom->saveXML()); |
133 | } |
134 | } |
135 | |
136 | public function finalize() |
137 | { |
138 | // Nothing to do |
139 | } |
140 | |
141 | /** |
142 | * @param LocalItemSource $itemSource |
143 | * @return $this |
144 | */ |
145 | public function setItemSource(LocalItemSource $itemSource) |
146 | { |
147 | $this->itemSource = $itemSource; |
148 | return $this; |
149 | } |
150 | |
151 | /** |
152 | * @param Item $qtiItem |
153 | * @return $this |
154 | */ |
155 | public function setQtiItem(Item $qtiItem) |
156 | { |
157 | $this->qtiItem = $qtiItem; |
158 | return $this; |
159 | } |
160 | |
161 | /** |
162 | * @return LocalItemSource |
163 | * @throws \common_exception_MissingParameter |
164 | */ |
165 | protected function getItemSource() |
166 | { |
167 | $this->assertAttribute('itemSource'); |
168 | return $this->itemSource; |
169 | } |
170 | |
171 | /** |
172 | * @return Item |
173 | * @throws \common_exception_MissingParameter |
174 | */ |
175 | protected function getQtiItem() |
176 | { |
177 | $this->assertAttribute('qtiItem'); |
178 | return $this->qtiItem; |
179 | } |
180 | |
181 | /** |
182 | * @param $attribute |
183 | * @throws \common_exception_MissingParameter |
184 | */ |
185 | private function assertAttribute($attribute) |
186 | { |
187 | if (!isset($this->$attribute)) { |
188 | throw new \common_exception_MissingParameter($attribute, 'stimulusImporter'); |
189 | } |
190 | } |
191 | } |