Commit | Line | Data |
---|---|---|
dc383b6f | 1 | <?php |
f7b5c6aa DM |
2 | // This file is part of Moodle - http://moodle.org/ |
3 | // | |
4 | // Moodle is free software: you can redistribute it and/or modify | |
5 | // it under the terms of the GNU General Public License as published by | |
6 | // the Free Software Foundation, either version 3 of the License, or | |
7 | // (at your option) any later version. | |
8 | // | |
9 | // Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
dc383b6f | 17 | function scorm_get_resources($blocks) { |
18 | $resources = array(); | |
19 | foreach ($blocks as $block) { | |
03c34889 | 20 | if ($block['name'] == 'RESOURCES' && isset($block['children'])) { |
dc383b6f | 21 | foreach ($block['children'] as $resource) { |
22 | if ($resource['name'] == 'RESOURCE') { | |
294ce987 | 23 | $resources[addslashes_js($resource['attrs']['IDENTIFIER'])] = $resource['attrs']; |
dc383b6f | 24 | } |
25 | } | |
26 | } | |
27 | } | |
28 | return $resources; | |
29 | } | |
30 | ||
f7b5c6aa | 31 | function scorm_get_manifest($blocks, $scoes) { |
03c34889 | 32 | global $OUTPUT; |
dc383b6f | 33 | static $parents = array(); |
34 | static $resources; | |
35 | ||
36 | static $manifest; | |
37 | static $organization; | |
38 | ||
03c34889 | 39 | $manifestresourcesnotfound = array(); |
dc383b6f | 40 | if (count($blocks) > 0) { |
41 | foreach ($blocks as $block) { | |
42 | switch ($block['name']) { | |
43 | case 'METADATA': | |
44 | if (isset($block['children'])) { | |
45 | foreach ($block['children'] as $metadata) { | |
46 | if ($metadata['name'] == 'SCHEMAVERSION') { | |
47 | if (empty($scoes->version)) { | |
f7b5c6aa | 48 | if (isset($metadata['tagData']) && (preg_match("/^(1\.2)$|^(CAM )?(1\.3)$/", $metadata['tagData'], $matches))) { |
dc383b6f | 49 | $scoes->version = 'SCORM_'.$matches[count($matches)-1]; |
50 | } else { | |
f7b5c6aa | 51 | if (isset($metadata['tagData']) && (preg_match("/^2004 (3rd|4th) Edition$/", $metadata['tagData'], $matches))) { |
d11b69ff | 52 | $scoes->version = 'SCORM_1.3'; |
53 | } else { | |
54 | $scoes->version = 'SCORM_1.2'; | |
55 | } | |
dc383b6f | 56 | } |
57 | } | |
58 | } | |
59 | } | |
60 | } | |
61 | break; | |
62 | case 'MANIFEST': | |
294ce987 | 63 | $manifest = $block['attrs']['IDENTIFIER']; |
dc383b6f | 64 | $organization = ''; |
65 | $resources = array(); | |
66 | $resources = scorm_get_resources($block['children']); | |
f7b5c6aa | 67 | $scoes = scorm_get_manifest($block['children'], $scoes); |
36149cf0 | 68 | if (empty($scoes->elements) || count($scoes->elements) <= 0) { |
dc383b6f | 69 | foreach ($resources as $item => $resource) { |
70 | if (!empty($resource['HREF'])) { | |
71 | $sco = new stdClass(); | |
72 | $sco->identifier = $item; | |
73 | $sco->title = $item; | |
74 | $sco->parent = '/'; | |
294ce987 | 75 | $sco->launch = $resource['HREF']; |
76 | $sco->scormtype = $resource['ADLCP:SCORMTYPE']; | |
dc383b6f | 77 | $scoes->elements[$manifest][$organization][$item] = $sco; |
78 | } | |
79 | } | |
80 | } | |
81 | break; | |
82 | case 'ORGANIZATIONS': | |
ef7f7453 | 83 | if (!isset($scoes->defaultorg) && isset($block['attrs']['DEFAULT'])) { |
294ce987 | 84 | $scoes->defaultorg = $block['attrs']['DEFAULT']; |
dc383b6f | 85 | } |
36149cf0 | 86 | if (!empty($block['children'])) { |
f7b5c6aa | 87 | $scoes = scorm_get_manifest($block['children'], $scoes); |
36149cf0 | 88 | } |
dc383b6f | 89 | break; |
90 | case 'ORGANIZATION': | |
294ce987 | 91 | $identifier = $block['attrs']['IDENTIFIER']; |
dc383b6f | 92 | $organization = ''; |
93 | $scoes->elements[$manifest][$organization][$identifier]->identifier = $identifier; | |
94 | $scoes->elements[$manifest][$organization][$identifier]->parent = '/'; | |
95 | $scoes->elements[$manifest][$organization][$identifier]->launch = ''; | |
96 | $scoes->elements[$manifest][$organization][$identifier]->scormtype = ''; | |
97 | ||
98 | $parents = array(); | |
99 | $parent = new stdClass(); | |
100 | $parent->identifier = $identifier; | |
101 | $parent->organization = $organization; | |
102 | array_push($parents, $parent); | |
103 | $organization = $identifier; | |
104 | ||
36149cf0 | 105 | if (!empty($block['children'])) { |
f7b5c6aa | 106 | $scoes = scorm_get_manifest($block['children'], $scoes); |
36149cf0 | 107 | } |
309ee089 | 108 | |
dc383b6f | 109 | array_pop($parents); |
110 | break; | |
111 | case 'ITEM': | |
112 | $parent = array_pop($parents); | |
113 | array_push($parents, $parent); | |
114 | ||
294ce987 | 115 | $identifier = $block['attrs']['IDENTIFIER']; |
dc383b6f | 116 | $scoes->elements[$manifest][$organization][$identifier]->identifier = $identifier; |
117 | $scoes->elements[$manifest][$organization][$identifier]->parent = $parent->identifier; | |
118 | if (!isset($block['attrs']['ISVISIBLE'])) { | |
119 | $block['attrs']['ISVISIBLE'] = 'true'; | |
120 | } | |
294ce987 | 121 | $scoes->elements[$manifest][$organization][$identifier]->isvisible = $block['attrs']['ISVISIBLE']; |
dc383b6f | 122 | if (!isset($block['attrs']['PARAMETERS'])) { |
123 | $block['attrs']['PARAMETERS'] = ''; | |
124 | } | |
294ce987 | 125 | $scoes->elements[$manifest][$organization][$identifier]->parameters = $block['attrs']['PARAMETERS']; |
dc383b6f | 126 | if (!isset($block['attrs']['IDENTIFIERREF'])) { |
127 | $scoes->elements[$manifest][$organization][$identifier]->launch = ''; | |
128 | $scoes->elements[$manifest][$organization][$identifier]->scormtype = 'asset'; | |
129 | } else { | |
294ce987 | 130 | $idref = $block['attrs']['IDENTIFIERREF']; |
dc383b6f | 131 | $base = ''; |
132 | if (isset($resources[$idref]['XML:BASE'])) { | |
133 | $base = $resources[$idref]['XML:BASE']; | |
134 | } | |
03c34889 DM |
135 | if (!isset($resources[$idref])) { |
136 | $manifestresourcesnotfound[] = $idref; | |
137 | $scoes->elements[$manifest][$organization][$identifier]->launch = ''; | |
138 | } else { | |
139 | $scoes->elements[$manifest][$organization][$identifier]->launch = $base.$resources[$idref]['HREF']; | |
140 | if (empty($resources[$idref]['ADLCP:SCORMTYPE'])) { | |
141 | $resources[$idref]['ADLCP:SCORMTYPE'] = 'asset'; | |
142 | } | |
143 | $scoes->elements[$manifest][$organization][$identifier]->scormtype = $resources[$idref]['ADLCP:SCORMTYPE']; | |
dc383b6f | 144 | } |
dc383b6f | 145 | } |
146 | ||
147 | $parent = new stdClass(); | |
148 | $parent->identifier = $identifier; | |
149 | $parent->organization = $organization; | |
150 | array_push($parents, $parent); | |
151 | ||
36149cf0 | 152 | if (!empty($block['children'])) { |
f7b5c6aa | 153 | $scoes = scorm_get_manifest($block['children'], $scoes); |
36149cf0 | 154 | } |
309ee089 | 155 | |
dc383b6f | 156 | array_pop($parents); |
157 | break; | |
158 | case 'TITLE': | |
159 | $parent = array_pop($parents); | |
160 | array_push($parents, $parent); | |
161 | if (!isset($block['tagData'])) { | |
162 | $block['tagData'] = ''; | |
163 | } | |
294ce987 | 164 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->title = $block['tagData']; |
dc383b6f | 165 | break; |
166 | case 'ADLCP:PREREQUISITES': | |
167 | if ($block['attrs']['TYPE'] == 'aicc_script') { | |
168 | $parent = array_pop($parents); | |
169 | array_push($parents, $parent); | |
170 | if (!isset($block['tagData'])) { | |
171 | $block['tagData'] = ''; | |
172 | } | |
294ce987 | 173 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->prerequisites = $block['tagData']; |
dc383b6f | 174 | } |
175 | break; | |
176 | case 'ADLCP:MAXTIMEALLOWED': | |
177 | $parent = array_pop($parents); | |
178 | array_push($parents, $parent); | |
179 | if (!isset($block['tagData'])) { | |
180 | $block['tagData'] = ''; | |
181 | } | |
294ce987 | 182 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->maxtimeallowed = $block['tagData']; |
dc383b6f | 183 | break; |
184 | case 'ADLCP:TIMELIMITACTION': | |
185 | $parent = array_pop($parents); | |
186 | array_push($parents, $parent); | |
187 | if (!isset($block['tagData'])) { | |
188 | $block['tagData'] = ''; | |
189 | } | |
294ce987 | 190 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->timelimitaction = $block['tagData']; |
dc383b6f | 191 | break; |
192 | case 'ADLCP:DATAFROMLMS': | |
193 | $parent = array_pop($parents); | |
194 | array_push($parents, $parent); | |
195 | if (!isset($block['tagData'])) { | |
196 | $block['tagData'] = ''; | |
197 | } | |
294ce987 | 198 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->datafromlms = $block['tagData']; |
dc383b6f | 199 | break; |
200 | case 'ADLCP:MASTERYSCORE': | |
201 | $parent = array_pop($parents); | |
202 | array_push($parents, $parent); | |
203 | if (!isset($block['tagData'])) { | |
204 | $block['tagData'] = ''; | |
205 | } | |
294ce987 | 206 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->masteryscore = $block['tagData']; |
dc383b6f | 207 | break; |
b3659259 | 208 | case 'ADLCP:COMPLETIONTHRESHOLD': |
209 | $parent = array_pop($parents); | |
210 | array_push($parents, $parent); | |
b5a26fe1 MG |
211 | if (!isset($block['attrs']['MINPROGRESSMEASURE'])) { |
212 | $block['attrs']['MINPROGRESSMEASURE'] = '1.0'; | |
b3659259 | 213 | } |
b5a26fe1 | 214 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->threshold = $block['attrs']['MINPROGRESSMEASURE']; |
b3659259 | 215 | break; |
216 | case 'ADLNAV:PRESENTATION': | |
217 | $parent = array_pop($parents); | |
218 | array_push($parents, $parent); | |
33b6a8f4 | 219 | if (!empty($block['children'])) { |
220 | foreach ($block['children'] as $adlnav) { | |
221 | if ($adlnav['name'] == 'ADLNAV:NAVIGATIONINTERFACE') { | |
222 | foreach ($adlnav['children'] as $adlnavInterface) { | |
223 | if ($adlnavInterface['name'] == 'ADLNAV:HIDELMSUI') { | |
224 | if ($adlnavInterface['tagData'] == 'continue') { | |
309ee089 | 225 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hidecontinue = 1; |
33b6a8f4 | 226 | } |
227 | if ($adlnavInterface['tagData'] == 'previous') { | |
309ee089 | 228 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideprevious = 1; |
33b6a8f4 | 229 | } |
230 | if ($adlnavInterface['tagData'] == 'exit') { | |
309ee089 | 231 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideexit = 1; |
33b6a8f4 | 232 | } |
233 | if ($adlnavInterface['tagData'] == 'exitAll') { | |
309ee089 | 234 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideexitall = 1; |
33b6a8f4 | 235 | } |
236 | if ($adlnavInterface['tagData'] == 'abandon') { | |
309ee089 | 237 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideabandon = 1; |
33b6a8f4 | 238 | } |
239 | if ($adlnavInterface['tagData'] == 'abandonAll') { | |
309ee089 | 240 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideabandonall = 1; |
33b6a8f4 | 241 | } |
242 | if ($adlnavInterface['tagData'] == 'suspendAll') { | |
309ee089 | 243 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hidesuspendall = 1; |
33b6a8f4 | 244 | } |
b3659259 | 245 | } |
33b6a8f4 | 246 | } |
247 | } | |
248 | } | |
249 | } | |
250 | break; | |
251 | case 'IMSSS:SEQUENCING': | |
252 | $parent = array_pop($parents); | |
253 | array_push($parents, $parent); | |
254 | if (!empty($block['children'])) { | |
255 | foreach ($block['children'] as $sequencing) { | |
256 | if ($sequencing['name']=='IMSSS:CONTROLMODE') { | |
257 | if (isset($sequencing['attrs']['CHOICE'])) { | |
258 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->choice = $sequencing['attrs']['CHOICE'] == 'true'?1:0; | |
259 | } | |
260 | if (isset($sequencing['attrs']['CHOICEEXIT'])) { | |
261 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->choiceexit = $sequencing['attrs']['CHOICEEXIT'] == 'true'?1:0; | |
262 | } | |
263 | if (isset($sequencing['attrs']['FLOW'])) { | |
264 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->flow = $sequencing['attrs']['FLOW'] == 'true'?1:0; | |
265 | } | |
266 | if (isset($sequencing['attrs']['FORWARDONLY'])) { | |
267 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->forwardonly = $sequencing['attrs']['FORWARDONLY'] == 'true'?1:0; | |
268 | } | |
269 | if (isset($sequencing['attrs']['USECURRENTATTEMPTOBJECTINFO'])) { | |
270 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->usecurrentattemptobjectinfo = $sequencing['attrs']['USECURRENTATTEMPTOBJECTINFO'] == 'true'?1:0; | |
271 | } | |
272 | if (isset($sequencing['attrs']['USECURRENTATTEMPTPROGRESSINFO'])) { | |
273 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->usecurrentattemptprogressinfo = $sequencing['attrs']['USECURRENTATTEMPTPROGRESSINFO'] == 'true'?1:0; | |
274 | } | |
275 | } | |
276 | if ($sequencing['name']=='ADLSEQ:CONSTRAINEDCHOICECONSIDERATIONS') { | |
277 | if (isset($sequencing['attrs']['CONSTRAINCHOICE'])) { | |
278 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->constrainChoice = $sequencing['attrs']['CONSTRAINCHOICE'] == 'true'?1:0; | |
279 | } | |
280 | if (isset($sequencing['attrs']['PREVENTACTIVATION'])) { | |
281 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->preventactivation = $sequencing['attrs']['PREVENTACTIVATION'] == 'true'?1:0; | |
282 | } | |
283 | } | |
284 | if ($sequencing['name']=='IMSSS:OBJECTIVES') { | |
285 | $objectives = array(); | |
286 | foreach ($sequencing['children'] as $objective) { | |
287 | $objectivedata = new stdClass(); | |
288 | $objectivedata->primaryobj = 0; | |
289 | switch ($objective['name']) { | |
290 | case 'IMSSS:PRIMARYOBJECTIVE': | |
291 | $objectivedata->primaryobj = 1; | |
292 | case 'IMSSS:OBJECTIVE': | |
293 | $objectivedata->satisfiedbymeasure = 0; | |
294 | if (isset($objective['attrs']['SATISFIEDBYMEASURE'])) { | |
295 | $objectivedata->satisfiedbymeasure = $objective['attrs']['SATISFIEDBYMEASURE']== 'true'?1:0; | |
296 | } | |
297 | $objectivedata->objectiveid = ''; | |
298 | if (isset($objective['attrs']['OBJECTIVEID'])) { | |
299 | $objectivedata->objectiveid = $objective['attrs']['OBJECTIVEID']; | |
300 | } | |
301 | $objectivedata->minnormalizedmeasure = 1.0; | |
302 | if (!empty($objective['children'])) { | |
303 | $mapinfos = array(); | |
304 | foreach ($objective['children'] as $objectiveparam) { | |
305 | if ($objectiveparam['name']=='IMSSS:MINNORMALIZEDMEASURE') { | |
7f4a3293 | 306 | if (isset($objectiveparam['tagData'])) { |
307 | $objectivedata->minnormalizedmeasure = $objectiveparam['tagData']; | |
308 | } else { | |
309 | $objectivedata->minnormalizedmeasure = 0; | |
310 | } | |
33b6a8f4 | 311 | } |
312 | if ($objectiveparam['name']=='IMSSS:MAPINFO') { | |
313 | $mapinfo = new stdClass(); | |
314 | $mapinfo->targetobjectiveid = ''; | |
315 | if (isset($objectiveparam['attrs']['TARGETOBJECTIVEID'])) { | |
316 | $mapinfo->targetobjectiveid = $objectiveparam['attrs']['TARGETOBJECTIVEID']; | |
317 | } | |
318 | $mapinfo->readsatisfiedstatus = 1; | |
319 | if (isset($objectiveparam['attrs']['READSATISFIEDSTATUS'])) { | |
320 | $mapinfo->readsatisfiedstatus = $objectiveparam['attrs']['READSATISFIEDSTATUS'] == 'true'?1:0; | |
321 | } | |
322 | $mapinfo->writesatisfiedstatus = 0; | |
323 | if (isset($objectiveparam['attrs']['WRITESATISFIEDSTATUS'])) { | |
324 | $mapinfo->writesatisfiedstatus = $objectiveparam['attrs']['WRITESATISFIEDSTATUS'] == 'true'?1:0; | |
325 | } | |
326 | $mapinfo->readnormalizemeasure = 1; | |
327 | if (isset($objectiveparam['attrs']['READNORMALIZEDMEASURE'])) { | |
328 | $mapinfo->readnormalizemeasure = $objectiveparam['attrs']['READNORMALIZEDMEASURE'] == 'true'?1:0; | |
329 | } | |
330 | $mapinfo->writenormalizemeasure = 0; | |
331 | if (isset($objectiveparam['attrs']['WRITENORMALIZEDMEASURE'])) { | |
332 | $mapinfo->writenormalizemeasure = $objectiveparam['attrs']['WRITENORMALIZEDMEASURE'] == 'true'?1:0; | |
333 | } | |
f7b5c6aa | 334 | array_push($mapinfos, $mapinfo); |
33b6a8f4 | 335 | } |
336 | } | |
337 | if (!empty($mapinfos)) { | |
338 | $objectivesdata->mapinfos = $mapinfos; | |
339 | } | |
340 | } | |
341 | break; | |
b3659259 | 342 | } |
f7b5c6aa | 343 | array_push($objectives, $objectivedata); |
33b6a8f4 | 344 | } |
345 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->objectives = $objectives; | |
346 | } | |
347 | if ($sequencing['name']=='IMSSS:LIMITCONDITIONS') { | |
348 | if (isset($sequencing['attrs']['ATTEMPTLIMIT'])) { | |
309ee089 | 349 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->attemptLimit = $sequencing['attrs']['ATTEMPTLIMIT']; |
33b6a8f4 | 350 | } |
351 | if (isset($sequencing['attrs']['ATTEMPTABSOLUTEDURATIONLIMIT'])) { | |
309ee089 | 352 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->attemptAbsoluteDurationLimit = $sequencing['attrs']['ATTEMPTABSOLUTEDURATIONLIMIT']; |
33b6a8f4 | 353 | } |
354 | } | |
355 | if ($sequencing['name']=='IMSSS:ROLLUPRULES') { | |
356 | if (isset($sequencing['attrs']['ROLLUPOBJECTIVESATISFIED'])) { | |
357 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->rollupobjectivesatisfied = $sequencing['attrs']['ROLLUPOBJECTIVESATISFIED'] == 'true'?1:0;; | |
358 | } | |
359 | if (isset($sequencing['attrs']['ROLLUPPROGRESSCOMPLETION'])) { | |
309ee089 | 360 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->rollupprogresscompletion = $sequencing['attrs']['ROLLUPPROGRESSCOMPLETION'] == 'true'?1:0; |
33b6a8f4 | 361 | } |
362 | if (isset($sequencing['attrs']['OBJECTIVEMEASUREWEIGHT'])) { | |
309ee089 | 363 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->objectivemeasureweight = $sequencing['attrs']['OBJECTIVEMEASUREWEIGHT']; |
33b6a8f4 | 364 | } |
309ee089 | 365 | |
f7b5c6aa | 366 | if (!empty($sequencing['children'])) { |
33b6a8f4 | 367 | $rolluprules = array(); |
368 | foreach ($sequencing['children'] as $sequencingrolluprule) { | |
369 | if ($sequencingrolluprule['name']=='IMSSS:ROLLUPRULE' ) { | |
370 | $rolluprule = new stdClass(); | |
371 | $rolluprule->childactivityset = 'all'; | |
372 | if (isset($sequencingrolluprule['attrs']['CHILDACTIVITYSET'])) { | |
373 | $rolluprule->childactivityset = $sequencingrolluprule['attrs']['CHILDACTIVITYSET']; | |
374 | } | |
375 | $rolluprule->minimumcount = 0; | |
376 | if (isset($sequencingrolluprule['attrs']['MINIMUMCOUNT'])) { | |
377 | $rolluprule->minimumcount = $sequencingrolluprule['attrs']['MINIMUMCOUNT']; | |
378 | } | |
379 | $rolluprule->minimumpercent = 0.0000; | |
380 | if (isset($sequencingrolluprule['attrs']['MINIMUMPERCENT'])) { | |
381 | $rolluprule->minimumpercent = $sequencingrolluprule['attrs']['MINIMUMPERCENT']; | |
382 | } | |
383 | if (!empty($sequencingrolluprule['children'])) { | |
384 | foreach ($sequencingrolluprule['children'] as $rolluproleconditions) { | |
385 | if ($rolluproleconditions['name']=='IMSSS:ROLLUPCONDITIONS') { | |
386 | $conditions = array(); | |
387 | $rolluprule->conditioncombination = 'all'; | |
388 | if (isset($rolluproleconditions['attrs']['CONDITIONCOMBINATION'])) { | |
389 | $rolluprule->conditioncombination = $rolluproleconditions['attrs']['CONDITIONCOMBINATION']; | |
390 | } | |
391 | foreach ($rolluproleconditions['children'] as $rolluprulecondition) { | |
392 | if ($rolluprulecondition['name']=='IMSSS:ROLLUPCONDITION') { | |
393 | $condition = new stdClass(); | |
394 | if (isset($rolluprulecondition['attrs']['CONDITION'])) { | |
395 | $condition->cond = $rolluprulecondition['attrs']['CONDITION']; | |
396 | } | |
397 | $condition->operator = 'noOp'; | |
398 | if (isset($rolluprulecondition['attrs']['OPERATOR'])) { | |
399 | $condition->operator = $rolluprulecondition['attrs']['OPERATOR']; | |
400 | } | |
f7b5c6aa | 401 | array_push($conditions, $condition); |
33b6a8f4 | 402 | } |
403 | } | |
404 | $rolluprule->conditions = $conditions; | |
405 | } | |
406 | if ($rolluproleconditions['name']=='IMSSS:ROLLUPACTION') { | |
407 | $rolluprule->rollupruleaction = $rolluproleconditions['attrs']['ACTION']; | |
408 | } | |
409 | } | |
410 | } | |
411 | array_push($rolluprules, $rolluprule); | |
412 | } | |
413 | } | |
414 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->rolluprules = $rolluprules; | |
415 | } | |
416 | } | |
309ee089 | 417 | |
33b6a8f4 | 418 | if ($sequencing['name']=='IMSSS:SEQUENCINGRULES') { |
419 | if (!empty($sequencing['children'])) { | |
420 | $sequencingrules = array(); | |
421 | foreach ($sequencing['children'] as $conditionrules) { | |
422 | $conditiontype = -1; | |
423 | switch($conditionrules['name']) { | |
424 | case 'IMSSS:PRECONDITIONRULE': | |
425 | $conditiontype = 0; | |
426 | break; | |
427 | case 'IMSSS:POSTCONDITIONRULE': | |
428 | $conditiontype = 1; | |
429 | break; | |
430 | case 'IMSSS:EXITCONDITIONRULE': | |
431 | $conditiontype = 2; | |
432 | break; | |
433 | } | |
434 | if (!empty($conditionrules['children'])) { | |
435 | $sequencingrule = new stdClass(); | |
436 | foreach ($conditionrules['children'] as $conditionrule) { | |
437 | if ($conditionrule['name']=='IMSSS:RULECONDITIONS') { | |
438 | $ruleconditions = array(); | |
439 | $sequencingrule->conditioncombination = 'all'; | |
440 | if (isset($conditionrule['attrs']['CONDITIONCOMBINATION'])) { | |
441 | $sequencingrule->conditioncombination = $conditionrule['attrs']['CONDITIONCOMBINATION']; | |
442 | } | |
443 | foreach ($conditionrule['children'] as $rulecondition) { | |
444 | if ($rulecondition['name']=='IMSSS:RULECONDITION') { | |
445 | $condition = new stdClass(); | |
446 | if (isset($rulecondition['attrs']['CONDITION'])) { | |
447 | $condition->cond = $rulecondition['attrs']['CONDITION']; | |
448 | } | |
449 | $condition->operator = 'noOp'; | |
450 | if (isset($rulecondition['attrs']['OPERATOR'])) { | |
451 | $condition->operator = $rulecondition['attrs']['OPERATOR']; | |
452 | } | |
453 | $condition->measurethreshold = 0.0000; | |
454 | if (isset($rulecondition['attrs']['MEASURETHRESHOLD'])) { | |
455 | $condition->measurethreshold = $rulecondition['attrs']['MEASURETHRESHOLD']; | |
456 | } | |
457 | $condition->referencedobjective = ''; | |
458 | if (isset($rulecondition['attrs']['REFERENCEDOBJECTIVE'])) { | |
459 | $condition->referencedobjective = $rulecondition['attrs']['REFERENCEDOBJECTIVE']; | |
309ee089 | 460 | } |
f7b5c6aa | 461 | array_push($ruleconditions, $condition); |
33b6a8f4 | 462 | } |
463 | } | |
464 | $sequencingrule->ruleconditions = $ruleconditions; | |
465 | } | |
466 | if ($conditionrule['name']=='IMSSS:RULEACTION') { | |
467 | $sequencingrule->action = $conditionrule['attrs']['ACTION']; | |
468 | } | |
469 | $sequencingrule->type = $conditiontype; | |
470 | } | |
f7b5c6aa | 471 | array_push($sequencingrules, $sequencingrule); |
33b6a8f4 | 472 | } |
473 | } | |
474 | $scoes->elements[$manifest][$parent->organization][$parent->identifier]->sequencingrules = $sequencingrules; | |
b3659259 | 475 | } |
b3659259 | 476 | } |
477 | } | |
478 | } | |
479 | break; | |
dc383b6f | 480 | } |
481 | } | |
482 | } | |
03c34889 DM |
483 | if (!empty($manifestresourcesnotfound)) { |
484 | //throw warning to user to let them know manifest contains references to resources that don't appear to exist. | |
485 | if (!defined('DEBUGGING_PRINTED')) { //prevent redirect and display warning | |
486 | define('DEBUGGING_PRINTED', 1); | |
487 | } | |
488 | echo $OUTPUT->notification(get_string('invalidmanifestresource', 'scorm').' '. implode(', ',$manifestresourcesnotfound)); | |
489 | } | |
dc383b6f | 490 | return $scoes; |
491 | } | |
492 | ||
9528568b | 493 | function scorm_parse_scorm($scorm, $manifest) { |
bf347041 | 494 | global $CFG, $DB; |
dc383b6f | 495 | |
9528568b | 496 | // load manifest into string |
497 | if ($manifest instanceof stored_file) { | |
498 | $xmltext = $manifest->get_content(); | |
499 | } else { | |
f7b5c6aa | 500 | require_once("$CFG->libdir/filelib.php"); |
9528568b | 501 | $xmltext = download_file_content($manifest); |
502 | } | |
309ee089 | 503 | |
9528568b | 504 | $launch = 0; |
b3659259 | 505 | |
9528568b | 506 | $pattern = '/&(?!\w{2,6};)/'; |
507 | $replacement = '&'; | |
508 | $xmltext = preg_replace($pattern, $replacement, $xmltext); | |
b3659259 | 509 | |
9528568b | 510 | $objXML = new xml2Array(); |
511 | $manifests = $objXML->parse($xmltext); | |
9528568b | 512 | $scoes = new stdClass(); |
513 | $scoes->version = ''; | |
f7b5c6aa | 514 | $scoes = scorm_get_manifest($manifests, $scoes); |
9528568b | 515 | if (count($scoes->elements) > 0) { |
516 | $olditems = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id)); | |
517 | foreach ($scoes->elements as $manifest => $organizations) { | |
518 | foreach ($organizations as $organization => $items) { | |
519 | foreach ($items as $identifier => $item) { | |
520 | // This new db mngt will support all SCORM future extensions | |
309ee089 | 521 | $newitem = new stdClass(); |
9528568b | 522 | $newitem->scorm = $scorm->id; |
523 | $newitem->manifest = $manifest; | |
524 | $newitem->organization = $organization; | |
525 | $standarddatas = array('parent', 'identifier', 'launch', 'scormtype', 'title'); | |
526 | foreach ($standarddatas as $standarddata) { | |
527 | if (isset($item->$standarddata)) { | |
528 | $newitem->$standarddata = $item->$standarddata; | |
dc383b6f | 529 | } |
9528568b | 530 | } |
309ee089 | 531 | |
9528568b | 532 | // Insert the new SCO, and retain the link between the old and new for later adjustment |
f7b5c6aa DM |
533 | $id = $DB->insert_record('scorm_scoes', $newitem); |
534 | if (!empty($olditems) && ($olditemid = scorm_array_search('identifier', $newitem->identifier, $olditems))) { | |
9528568b | 535 | $olditems[$olditemid]->newid = $id; |
536 | } | |
309ee089 | 537 | |
f7b5c6aa | 538 | if ($optionaldatas = scorm_optionals_data($item, $standarddatas)) { |
9528568b | 539 | $data = new stdClass(); |
540 | $data->scoid = $id; | |
541 | foreach ($optionaldatas as $optionaldata) { | |
542 | if (isset($item->$optionaldata)) { | |
543 | $data->name = $optionaldata; | |
544 | $data->value = $item->$optionaldata; | |
f7b5c6aa | 545 | $dataid = $DB->insert_record('scorm_scoes_data', $data); |
dc383b6f | 546 | } |
33b6a8f4 | 547 | } |
9528568b | 548 | } |
dc383b6f | 549 | |
9528568b | 550 | if (isset($item->sequencingrules)) { |
f7b5c6aa | 551 | foreach ($item->sequencingrules as $sequencingrule) { |
9528568b | 552 | $rule = new stdClass(); |
553 | $rule->scoid = $id; | |
554 | $rule->ruletype = $sequencingrule->type; | |
555 | $rule->conditioncombination = $sequencingrule->conditioncombination; | |
556 | $rule->action = $sequencingrule->action; | |
f7b5c6aa | 557 | $ruleid = $DB->insert_record('scorm_seq_ruleconds', $rule); |
9528568b | 558 | if (isset($sequencingrule->ruleconditions)) { |
f7b5c6aa | 559 | foreach ($sequencingrule->ruleconditions as $rulecondition) { |
9528568b | 560 | $rulecond = new stdClass(); |
561 | $rulecond->scoid = $id; | |
562 | $rulecond->ruleconditionsid = $ruleid; | |
563 | $rulecond->referencedobjective = $rulecondition->referencedobjective; | |
564 | $rulecond->measurethreshold = $rulecondition->measurethreshold; | |
565 | $rulecond->cond = $rulecondition->cond; | |
f7b5c6aa | 566 | $rulecondid = $DB->insert_record('scorm_seq_rulecond', $rulecond); |
33b6a8f4 | 567 | } |
9528568b | 568 | } |
309ee089 | 569 | } |
9528568b | 570 | } |
309ee089 | 571 | |
9528568b | 572 | if (isset($item->rolluprules)) { |
f7b5c6aa | 573 | foreach ($item->rolluprules as $rolluprule) { |
9528568b | 574 | $rollup = new stdClass(); |
575 | $rollup->scoid = $id; | |
576 | $rollup->childactivityset = $rolluprule->childactivityset; | |
577 | $rollup->minimumcount = $rolluprule->minimumcount; | |
578 | $rollup->minimumpercent = $rolluprule->minimumpercent; | |
579 | $rollup->rollupruleaction = $rolluprule->rollupruleaction; | |
580 | $rollup->conditioncombination = $rolluprule->conditioncombination; | |
33b6a8f4 | 581 | |
f7b5c6aa | 582 | $rollupruleid = $DB->insert_record('scorm_seq_rolluprule', $rollup); |
9528568b | 583 | if (isset($rollup->conditions)) { |
f7b5c6aa | 584 | foreach ($rollup->conditions as $condition) { |
9528568b | 585 | $cond = new stdClass(); |
586 | $cond->scoid = $rollup->scoid; | |
587 | $cond->rollupruleid = $rollupruleid; | |
588 | $cond->operator = $condition->operator; | |
589 | $cond->cond = $condition->cond; | |
f7b5c6aa | 590 | $conditionid = $DB->insert_record('scorm_seq_rolluprulecond', $cond); |
33b6a8f4 | 591 | } |
9528568b | 592 | } |
309ee089 | 593 | } |
9528568b | 594 | } |
33b6a8f4 | 595 | |
9528568b | 596 | if (isset($item->objectives)) { |
f7b5c6aa | 597 | foreach ($item->objectives as $objective) { |
9528568b | 598 | $obj = new stdClass(); |
599 | $obj->scoid = $id; | |
600 | $obj->primaryobj = $objective->primaryobj; | |
601 | $obj->satisfiedbumeasure = $objective->satisfiedbymeasure; | |
602 | $obj->objectiveid = $objective->objectiveid; | |
45999e78 | 603 | $obj->minnormalizedmeasure = trim($objective->minnormalizedmeasure); |
f7b5c6aa | 604 | $objectiveid = $DB->insert_record('scorm_seq_objective', $obj); |
9528568b | 605 | if (isset($objective->mapinfos)) { |
f7b5c6aa | 606 | foreach ($objective->mapinfos as $objmapinfo) { |
9528568b | 607 | $mapinfo = new stdClass(); |
608 | $mapinfo->scoid = $id; | |
609 | $mapinfo->objectiveid = $objectiveid; | |
610 | $mapinfo->targetobjectiveid = $objmapinfo->targetobjectiveid; | |
611 | $mapinfo->readsatisfiedstatus = $objmapinfo->readsatisfiedstatus; | |
612 | $mapinfo->writesatisfiedstatus = $objmapinfo->writesatisfiedstatus; | |
613 | $mapinfo->readnormalizedmeasure = $objmapinfo->readnormalizedmeasure; | |
614 | $mapinfo->writenormalizedmeasure = $objmapinfo->writenormalizedmeasure; | |
f7b5c6aa | 615 | $mapinfoid = $DB->insert_record('scorm_seq_mapinfo', $mapinfo); |
33b6a8f4 | 616 | } |
617 | } | |
618 | } | |
9528568b | 619 | } |
9528568b | 620 | if (($launch == 0) && ((empty($scoes->defaultorg)) || ($scoes->defaultorg == $identifier))) { |
621 | $launch = $id; | |
dc383b6f | 622 | } |
623 | } | |
624 | } | |
9528568b | 625 | } |
626 | if (!empty($olditems)) { | |
f7b5c6aa | 627 | foreach ($olditems as $olditem) { |
9528568b | 628 | $DB->delete_records('scorm_scoes', array('id'=>$olditem->id)); |
f7b5c6aa | 629 | $DB->delete_records('scorm_scoes_data', array('scoid'=>$olditem->id)); |
9528568b | 630 | if (isset($olditem->newid)) { |
631 | $DB->set_field('scorm_scoes_track', 'scoid', $olditem->newid, array('scoid' => $olditem->id)); | |
dc383b6f | 632 | } |
f7b5c6aa | 633 | $DB->delete_records('scorm_scoes_track', array('scoid'=>$olditem->id)); |
9528568b | 634 | $DB->delete_records('scorm_seq_objective', array('scoid'=>$olditem->id)); |
635 | $DB->delete_records('scorm_seq_mapinfo', array('scoid'=>$olditem->id)); | |
636 | $DB->delete_records('scorm_seq_ruleconds', array('scoid'=>$olditem->id)); | |
637 | $DB->delete_records('scorm_seq_rulecond', array('scoid'=>$olditem->id)); | |
638 | $DB->delete_records('scorm_seq_rolluprule', array('scoid'=>$olditem->id)); | |
639 | $DB->delete_records('scorm_seq_rolluprulecond', array('scoid'=>$olditem->id)); | |
dc383b6f | 640 | } |
dc383b6f | 641 | } |
309ee089 | 642 | if (empty($scoes->version)) { |
643 | $scoes->version = 'SCORM_1.2'; | |
644 | } | |
f7b5c6aa | 645 | $DB->set_field('scorm', 'version', $scoes->version, array('id'=>$scorm->id)); |
9528568b | 646 | $scorm->version = $scoes->version; |
647 | } | |
309ee089 | 648 | |
9528568b | 649 | $scorm->launch = $launch; |
650 | ||
651 | return true; | |
dc383b6f | 652 | } |
653 | ||
b3659259 | 654 | function scorm_optionals_data($item, $standarddata) { |
655 | $result = array(); | |
f7b5c6aa | 656 | $sequencingdata = array('sequencingrules', 'rolluprules', 'objectives'); |
b3659259 | 657 | foreach ($item as $element => $value) { |
658 | if (! in_array($element, $standarddata)) { | |
33b6a8f4 | 659 | if (! in_array($element, $sequencingdata)) { |
660 | $result[] = $element; | |
661 | } | |
b3659259 | 662 | } |
663 | } | |
664 | return $result; | |
665 | } | |
666 | ||
10fd330f | 667 | function scorm_is_leaf($sco) { |
bf347041 | 668 | global $DB; |
669 | ||
670 | if ($DB->get_record('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->identifier))) { | |
10fd330f | 671 | return false; |
672 | } | |
673 | return true; | |
674 | } | |
675 | ||
676 | function scorm_get_parent($sco) { | |
bf347041 | 677 | global $DB; |
309ee089 | 678 | |
10fd330f | 679 | if ($sco->parent != '/') { |
f7b5c6aa | 680 | if ($parent = $DB->get_record('scorm_scoes', array('scorm'=>$sco->scorm, 'identifier'=>$sco->parent))) { |
10fd330f | 681 | return scorm_get_sco($parent->id); |
682 | } | |
683 | } | |
684 | return null; | |
685 | } | |
686 | ||
687 | function scorm_get_children($sco) { | |
bf347041 | 688 | global $DB; |
689 | ||
f7b5c6aa | 690 | if ($children = $DB->get_records('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->identifier))) {//originally this said parent instead of childrean |
10fd330f | 691 | return $children; |
692 | } | |
693 | return null; | |
694 | } | |
695 | ||
f7b5c6aa | 696 | function scorm_get_available_children($sco) { // TODO: undefined vars!!! |
bf347041 | 697 | global $DB; |
698 | ||
f7b5c6aa DM |
699 | $res = $DB->get_record('scorm_scoes_track', array('scoid'=>$scoid, |
700 | 'userid'=>$userid, | |
701 | 'element'=>'availablechildren')); | |
702 | if (!$res || $res == null) { | |
a9d71982 | 703 | return false; |
f7b5c6aa | 704 | } else { |
a9d71982 | 705 | return unserialize($res->value); |
706 | } | |
60a3aaf9 | 707 | } |
708 | ||
f7b5c6aa DM |
709 | function scorm_get_available_descendent($descend = array(), $sco) { |
710 | if ($sco == null) { | |
a9d71982 | 711 | return $descend; |
f7b5c6aa | 712 | } else { |
a9d71982 | 713 | $avchildren = scorm_get_available_children($sco); |
f7b5c6aa DM |
714 | foreach ($avchildren as $avchild) { |
715 | array_push($descend, $avchild); | |
a9d71982 | 716 | } |
f7b5c6aa DM |
717 | foreach ($avchildren as $avchild) { |
718 | scorm_get_available_descendent($descend, $avchild); | |
a9d71982 | 719 | } |
720 | } | |
60a3aaf9 | 721 | } |
722 | ||
723 | function scorm_get_siblings($sco) { | |
bf347041 | 724 | global $DB; |
725 | ||
f7b5c6aa | 726 | if ($siblings = $DB->get_records('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->parent))) { |
10fd330f | 727 | unset($siblings[$sco->id]); |
728 | if (!empty($siblings)) { | |
729 | return $siblings; | |
730 | } | |
731 | } | |
732 | return null; | |
733 | } | |
c5a51ed5 | 734 | //get an array that contains all the parent scos for this sco. |
10fd330f | 735 | function scorm_get_ancestors($sco) { |
c5a51ed5 DM |
736 | $ancestors = array(); |
737 | $continue = true; | |
f7b5c6aa | 738 | while ($continue) { |
c5a51ed5 DM |
739 | $ancestor = scorm_get_parent($sco); |
740 | if (!empty($ancestor) && $ancestor->id !== $sco->id) { | |
741 | $sco = $ancestor; | |
742 | $ancestors[] = $ancestor; | |
743 | if ($sco->parent == '/') { | |
744 | $continue = false; | |
745 | } | |
746 | } else { | |
747 | $continue = false; | |
748 | } | |
10fd330f | 749 | } |
c5a51ed5 | 750 | return $ancestors; |
10fd330f | 751 | } |
752 | ||
f7b5c6aa | 753 | function scorm_get_preorder($preorder=array(), $sco) { |
60a3aaf9 | 754 | if ($sco != null) { |
f7b5c6aa | 755 | array_push($preorder, $sco); |
a9d71982 | 756 | $children = scorm_get_children($sco); |
f7b5c6aa | 757 | foreach ($children as $child) { |
a9d71982 | 758 | scorm_get_preorder($sco); |
759 | } | |
60a3aaf9 | 760 | } else { |
761 | return $preorder; | |
762 | } | |
763 | } | |
764 | ||
10fd330f | 765 | function scorm_find_common_ancestor($ancestors, $sco) { |
f7b5c6aa | 766 | $pos = scorm_array_search('identifier', $sco->parent, $ancestors); |
10fd330f | 767 | if ($sco->parent != '/') { |
768 | if ($pos === false) { | |
f7b5c6aa | 769 | return scorm_find_common_ancestor($ancestors, scorm_get_parent($sco)); |
10fd330f | 770 | } |
771 | } | |
772 | return $pos; | |
773 | } | |
774 | ||
dc383b6f | 775 | /* Usage |
776 | Grab some XML data, either from a file, URL, etc. however you want. Assume storage in $strYourXML; | |
777 | ||
778 | $objXML = new xml2Array(); | |
779 | $arrOutput = $objXML->parse($strYourXML); | |
780 | print_r($arrOutput); //print it out, or do whatever! | |
309ee089 | 781 | |
dc383b6f | 782 | */ |
783 | class xml2Array { | |
309ee089 | 784 | |
f7b5c6aa DM |
785 | var $arrOutput = array(); |
786 | var $resParser; | |
787 | var $strXmlData; | |
788 | ||
789 | /** | |
790 | * Convert a utf-8 string to html entities | |
791 | * | |
792 | * @param string $str The UTF-8 string | |
793 | * @return string | |
794 | */ | |
795 | function utf8_to_entities($str) { | |
796 | global $CFG; | |
797 | ||
798 | $entities = ''; | |
799 | $values = array(); | |
800 | $lookingfor = 1; | |
801 | ||
802 | return $str; | |
803 | } | |
804 | ||
805 | /** | |
806 | * Parse an XML text string and create an array tree that rapresent the XML structure | |
807 | * | |
808 | * @param string $strInputXML The XML string | |
809 | * @return array | |
810 | */ | |
811 | function parse($strInputXML) { | |
812 | $this->resParser = xml_parser_create ('UTF-8'); | |
813 | xml_set_object($this->resParser, $this); | |
814 | xml_set_element_handler($this->resParser, "tagOpen", "tagClosed"); | |
815 | ||
816 | xml_set_character_data_handler($this->resParser, "tagData"); | |
817 | ||
818 | $this->strXmlData = xml_parse($this->resParser, $strInputXML ); | |
819 | if (!$this->strXmlData) { | |
820 | die(sprintf("XML error: %s at line %d", | |
821 | xml_error_string(xml_get_error_code($this->resParser)), | |
822 | xml_get_current_line_number($this->resParser))); | |
823 | } | |
824 | ||
825 | xml_parser_free($this->resParser); | |
826 | ||
827 | return $this->arrOutput; | |
828 | } | |
829 | ||
830 | function tagOpen($parser, $name, $attrs) { | |
831 | $tag=array("name"=>$name, "attrs"=>$attrs); | |
832 | array_push($this->arrOutput, $tag); | |
833 | } | |
834 | ||
835 | function tagData($parser, $tagData) { | |
836 | if (trim($tagData)) { | |
837 | if (isset($this->arrOutput[count($this->arrOutput)-1]['tagData'])) { | |
838 | $this->arrOutput[count($this->arrOutput)-1]['tagData'] .= $this->utf8_to_entities($tagData); | |
839 | } else { | |
840 | $this->arrOutput[count($this->arrOutput)-1]['tagData'] = $this->utf8_to_entities($tagData); | |
841 | } | |
842 | } | |
843 | } | |
844 | ||
845 | function tagClosed($parser, $name) { | |
846 | $this->arrOutput[count($this->arrOutput)-2]['children'][] = $this->arrOutput[count($this->arrOutput)-1]; | |
847 | array_pop($this->arrOutput); | |
848 | } | |
dc383b6f | 849 | |
850 | } |