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