Browse Source

getMapInfos : recupéation de plusieurs mapinfo

frederic 3 years ago
parent
commit
b97ba0920e
2 changed files with 88 additions and 203 deletions
  1. 86
    138
      LearningModels/DOMSCORM2004.php
  2. 2
    65
      Tests/LearningModels/SCORM2004/DOMSCORM2004Test.php

+ 86
- 138
LearningModels/DOMSCORM2004.php View File

@@ -307,7 +307,7 @@ class DOMSCORM2004 extends DOMSCORM
307 307
      * query(//item) pour tout les tags du namespace de base; faire query(//*name="item))
308 308
      * Exemples :
309 309
      * ( '//*[name()="item" or name()="organization"][@identifier="T-01b"]/imsss:sequencing/imsss:controlMode' ,'flow' )
310
-     * 
310
+     *
311 311
      * @param string $item Par exemples (valeurs/defaut):
312 312
      * * imsss:deliveryControls.tracked
313 313
      * @param string $path chemin de l'attribut
@@ -695,82 +695,6 @@ class DOMSCORM2004 extends DOMSCORM
695 695
         return $values;
696 696
     }
697 697
 
698
-    /**
699
-     * l'organization racine de l'item (ou de l'organization c'est à dire elle meme dans ce cas)
700
-     *
701
-     * @param string $item
702
-     * @return string identifer de l'organization mere de l'item
703
-     */
704
-    public function getOrganizationByItem(string $item) : string
705
-    {
706
-        $value ="";
707
-        $query = '//*[name()="item" or name()="organization"][@identifier="'.
708
-            $item.'"]/ancestor-or-self::*[name()="organization"]';
709
-        $nodeList = $this->xpath->query($query);
710
-        if ($nodeList->length > 0) {
711
-            $node = $nodeList->item(0);
712
-            $attributeNode = $node->attributes->getNamedItem('identifier');
713
-            if ($attributeNode !=null) {
714
-                $value = $attributeNode->nodeValue;
715
-            }
716
-        }
717
-        return $value;
718
-    }
719
-
720
-    /**
721
-     * évalue si l'item est present dans la branche constituée de la listes des items partant de
722
-     * l'item racine (l'organization) jusqu'à l'item itemBranche
723
-     *
724
-     * @param string $item
725
-     * @param string $itemBranche
726
-     * @return boolean true si item est dans la branche
727
-     */
728
-    public function isItemInBranch(string $item, string $itemBranche) : bool
729
-    {
730
-        // on remonte jusqu'à trouver l'item ou jusqu'au noeud mere
731
-        $currentNode = $this->getElementById($itemBranche);
732
-        do {
733
-            $current = $currentNode->attributes->getNamedItem("identifier")->nodeValue;
734
-            if ($current == $item) {
735
-                return true;
736
-            }
737
-            $currentNode = $currentNode->parentNode;
738
-        } while (($currentNode->nodeName == 'item')||($currentNode->nodeName == 'organization'));
739
-        return false;
740
-    }
741
-
742
-    /**
743
-     * @deprecated use getItemBranch
744
-     *
745
-     * @param string $item
746
-     * @return array
747
-     */
748
-    public function getNodeBranch(string $item) : array
749
-    {
750
-        return getItemBranch($item);
751
-    }
752
-
753
-    /**
754
-     * renvoie la liste ordonnée de la racine (l'organization) à l'item de fin de branche
755
-     *
756
-     * @param string $item fin de branche
757
-     * @return array tableau associatif demarrant à l' "item" organization
758
-     */
759
-    public function getItemBranch(string $item) : array
760
-    {
761
-        // remontée de la branche jusqu'à la racine puis inversion du tableau
762
-        $branche = array();
763
-        $currentNode = $this->getElementById($item);
764
-        do {
765
-            $current = $currentNode->attributes->getNamedItem("identifier")->nodeValue;
766
-            $branche[] = $current;
767
-            $currentNode = $currentNode->parentNode;
768
-        } while (($currentNode->nodeName == 'item') || ($currentNode->nodeName == 'organization'));
769
-
770
-        $branche = array_reverse($branche);
771
-        return $branche;
772
-    }
773
-
774 698
     /**
775 699
      * renvoi la liste des objectif (objectiveID) d'un item
776 700
      * la forme d'un objective est le triplet (identifier (item),objectiveID, isPrimary)
@@ -887,9 +811,9 @@ class DOMSCORM2004 extends DOMSCORM
887 811
      * tous les objectives tag : "objective"  porteurs
888 812
      * d'une  mapInfo ont obligatoirement un objectiveID associé (CAM5-26 )
889 813
      * les tags "primaryObjective" n'ont pas pas forcement un objectiveID
890
-     *
891
-     * IMPORTANT : apparement un objective peut avoir plusieurs mapInfo
892
-     * ce cas n'est pas traité  et génère une exception!!!
814
+     * Un ims.mapinfo peut avoir un complement adl (lien via attribut targetObjectiveID)
815
+     * un adl.mapinfo peut ne pas etre lié à un ims.mapinfo, dans ce cas c'est un mapinfo en soi (et
816
+     * non un complement)
893 817
      *
894 818
      * @param string $item
895 819
      * @param string $objectiveID peut etre chaine vide si et seulement $isPrimary = true
@@ -899,31 +823,18 @@ class DOMSCORM2004 extends DOMSCORM
899 823
     
900 824
     public function getMapInfos(string $item, string $objectiveID, bool $isPrimary) : ?array
901 825
     {
826
+        $mapInfos = array(); // initialisation du tableau de retour
902 827
         if (($objectiveID=='') && ($isPrimary==false)) {
903 828
             throw new \Exception('SCORM 2004: objectiveID cannot be void for a non primary mapInfo tag. Item :'.$item);
904 829
         }
905
-        $mapInfo = array( // tous les attributs que nous souhaitons retourner obligatoirement...
906
-            'targetObjectiveID' => null,
907
-            'readSatisfiedStatus' => null,
908
-            'readNormalizedMeasure' => null,
909
-            'writeSatisfiedStatus' => null,
910
-            'writeNormalizedMeasure' => null,
911
-            'readRawScore' => null,
912
-            'readMinScore' => null,
913
-            'readMaxScore' => null,
914
-            'readCompletionStatus' => null,
915
-            'readProgressMeasure' => null,
916
-            'writeRawScore' => null,
917
-            'writeMinScore' => null,
918
-            'writeMaxScore' => null,
919
-            'writeCompletionStatus' => null,
920
-            'writeProgressMeasure' => null
921
-        );
830
+        $mapInfo = $this->initNullMapinfo();
831
+        $targetObjectiveIDs = array(); // tableau local pour mémoriser ces IDs, utile ppour l'algo
832
+        // 1) récupération des nodes mapinfo ims
922 833
         if ($isPrimary == false) {
923 834
             $query = '//*[name()="item" or name()="organization"][@identifier="'.
924 835
             $item.'"]/imsss:sequencing/imsss:objectives/imsss:objective[@objectiveID="'.$objectiveID.'"]/imsss:mapInfo | '.
925 836
             '//imsss:sequencingCollection/imsss:sequencing/imsss:objectives/imsss:objective[@objectiveID="'.$objectiveID.'"]/imsss:mapInfo';
926
-        } else {
837
+        } else { // quand c'est un primaire, il n'y a pas d'objectiveID
927 838
             $refSeqCol = $this->getAttributeByName($item, 'IDRef');
928 839
             $query2='';
929 840
             if ($refSeqCol != null) {
@@ -932,64 +843,101 @@ class DOMSCORM2004 extends DOMSCORM
932 843
             $query = '//*[name()="item" or name()="organization"][@identifier="'.
933 844
             $item.'"]/imsss:sequencing/imsss:objectives/imsss:primaryObjective/imsss:mapInfo'.$query2;
934 845
         }
935
-
936
-        $listNodes = $this->xpath->query($query);
937
-
938
-        if ($listNodes->length > 1) { // on ne sait pas gérer le cas de plusieurs mapinfo pour 1 objectif
939
-            throw new \Exception('SCORM 2004: Several mapInfos imsss tags found for item '.$item);
940
-        }
941
-
942
-        if ($listNodes->length == 1) {
943
-            $attributes = $listNodes->item(0)->attributes;
944
-            for ($i=0; $i<$attributes->length; $i++) {
945
-                $a = $attributes->item($i);
846
+        $imsNodes = $this->xpath->query($query); // recupération des nodes map infos
847
+
848
+        // 2) recuperation des complements de l'adl
849
+        for ($i=0; $i < $imsNodes->length; $i++) {
850
+            $mapInfo = $this->initNullMapinfo();
851
+            $attributes = $imsNodes->item($i)->attributes;
852
+            for ($j=0; $j<$attributes->length; $j++) {
853
+                $a = $attributes->item($j);
946 854
                 $mapInfo[$a->nodeName] = $a->nodeValue;
947 855
             }
948
-        }
949
-
950
-        if ($mapInfo['targetObjectiveID'] == null) { // pas d'imsss ? alors il faut tenter adlseq
951
-            $query = '//*[name()="item" or name()="organization"][@identifier="'.
952
-            $item.'"]/imsss:sequencing/adlseq:objectives/*[@objectiveID="'.$objectiveID.'"]/adlseq:mapInfo | '.
953
-            '//imsss:sequencingCollection/imsss:sequencing/adlseq:objectives/*[@objectiveID="'.$objectiveID.'"]/adlseq:mapInfo';
954
-        } else {
955
-        // recherche du complement adlseq
856
+            // recuperation complement
956 857
             $query = '//*[name()="item" or name()="organization"][@identifier="'.
957 858
             $item.'"]/imsss:sequencing/adlseq:objectives/child::*/adlseq:mapInfo[@targetObjectiveID="'.$mapInfo['targetObjectiveID'].'"] | '.
958 859
             '//imsss:sequencingCollection/adlseq:objectives/child::*/adlseq:mapInfo[@targetObjectiveID="'.$mapInfo['targetObjectiveID'].'"]';
959
-        }
960
-
961
-        // on cherche ailleurs que dans le cas ou on n'a un primaryObjective sans objectiveID (seul cas ou objectiveID peut etre null)
962
-        if ($objectiveID != "") {
963
-            $listNodes = $this->xpath->query($query);
964
-
965
-            if ($listNodes->length > 1) { // on ne sait pas gérer le cas de plusieurs mapinfo pour 1 objectif
966
-                throw new \Exception('SCORM 2004: Several mapInfos adlseq tags found for item '.$item);
860
+            $adlNodes =  $this->xpath->query($query); // il ne devrait y avoir qu'un seul complement max
861
+            if ($adlNodes->length > 1) { // on ne sait pas gérer le cas de plusieurs mapinfo pour 1 objectif
862
+                throw new \Exception('SCORM 2004: Several complement mapInfos adlseq tags found for item '.$item);
967 863
             }
968
-
969
-            if ($listNodes->length == 1) {
970
-                $attributes = $listNodes->item(0)->attributes;
971
-                for ($i=0; $i<$attributes->length; $i++) {
972
-                    $a = $attributes->item($i);
864
+            if ($adlNodes->length == 1) {
865
+                $attributes = $adlNodes->item(0)->attributes;
866
+                for ($j=0; $j<$attributes->length; $j++) {
867
+                    $a = $attributes->item($j);
973 868
                     $mapInfo[$a->nodeName] = $a->nodeValue;
974 869
                 }
975 870
             }
871
+            $mapInfo = $this->completeMapinfoWithDefaults($mapInfo);
872
+            $mapInfos[] = $mapInfo;
873
+            $targetObjectiveIDs[$mapInfo['targetObjectiveID']]= true; // on cree une entrée dans le tableau
976 874
         }
977
-        // cet attribut 'targetObjectiveID' doit être...
978
-        if ($mapInfo['targetObjectiveID'] == null) { // s'il ne l'est pas il n'y a pas de mapInfo pour l'item
979
-            return null;
875
+
876
+        //3) recupération des mapinfo de l'adl qui sont isolés (pas de lien via targetObjectiveID)
877
+        $query = '//*[name()="item" or name()="organization"][@identifier="'.
878
+        $item.'"]/imsss:sequencing/adlseq:objectives/*[@objectiveID="'.$objectiveID.'"]/adlseq:mapInfo | '.
879
+        '//imsss:sequencingCollection/imsss:sequencing/adlseq:objectives/*[@objectiveID="'.$objectiveID.'"]/adlseq:mapInfo';
880
+        $adlNodes =  $this->xpath->query($query);
881
+        // on parcours la liste en creant un nouveau mapinfo lorsque targetObjectiveID n'est pas une clef
882
+        for ($i=0; $i < $adlNodes->length; $i++) {
883
+            $attributes = $adlNodes->item($i)->attributes;
884
+            $targetObjectiveID = $attributes->getNamedItem('targetObjectiveID')->nodeValue;
885
+            if (!isset($targetObjectiveIDs[$targetObjectiveID])) { // creation d'un nouveau mapinfo, si iniexsitance
886
+                $mapInfo = $this->initNullMapinfo();
887
+                for ($j=0; $j<$attributes->length; $j++) {
888
+                    $a = $attributes->item($j);
889
+                    $mapInfo[$a->nodeName] = $a->nodeValue;
890
+                }
891
+                $mapInfo = $this->completeMapinfoWithDefaults($mapInfo);
892
+                $mapInfos[] = $mapInfo;
893
+            }
980 894
         }
981 895
 
896
+        return $mapInfos;
897
+    }
898
+
899
+    /**
900
+     * on remplit un tableau mapinfo avec les valeur par défaut
901
+     * (attention : les clefs non spécifiées ne sont pas gérées)
902
+     *
903
+     * @param array $mapInfo
904
+     * @return array
905
+     */
906
+    private function completeMapinfoWithDefaults(array $mapInfo) : array
907
+    {
982 908
         foreach ($mapInfo as $key => $value) {
983 909
             if ($value == null) {
984 910
                 $mapInfo[$key] = SCORMTools::getAttributeDefaultValue($key);
985 911
             }
986 912
         }
913
+        return $mapInfo;
914
+    }
987 915
 
988
-        // Simulation de la gestion de la réception de plusieurs mapInfos
989
-        $mapInfos = array();
990
-        $mapInfos[] = $mapInfo;
991
-
992
-        return $mapInfos;
916
+    /**
917
+     * creation d'un tableau ayant toutes les clef nommées pour un mapinfo
918
+     * avec des valeurs null
919
+     *
920
+     * @return array
921
+     */
922
+    private function initNullMapinfo() : array
923
+    {
924
+        return array( // tous les attributs que nous souhaitons retourner obligatoirement...
925
+            'targetObjectiveID' => null, // ims
926
+            'readSatisfiedStatus' => null,
927
+            'readNormalizedMeasure' => null,
928
+            'writeSatisfiedStatus' => null,
929
+            'writeNormalizedMeasure' => null,
930
+            'readRawScore' => null, //adl
931
+            'readMinScore' => null,
932
+            'readMaxScore' => null,
933
+            'readCompletionStatus' => null,
934
+            'readProgressMeasure' => null,
935
+            'writeRawScore' => null,
936
+            'writeMinScore' => null,
937
+            'writeMaxScore' => null,
938
+            'writeCompletionStatus' => null,
939
+            'writeProgressMeasure' => null
940
+        );
993 941
     }
994 942
 
995 943
     /**

+ 2
- 65
Tests/LearningModels/SCORM2004/DOMSCORM2004Test.php View File

@@ -164,50 +164,6 @@ class DOMSCORM2004Test extends TestCase
164 164
         $this->assertSame(4, sizeof($flat));
165 165
     }
166 166
 
167
-    public function testIsItemInBranch()
168
-    {
169
-         //construction du DOM à partir d'un  paquet test ADL
170
-         $dom = null; // pour ecrase l'ancien dom
171
-         $filename = __DIR__.
172
-         '/../../packages/SCORM2004/LMSTestPackage_T-01b.zip';
173
-         $XMLManifest = DOMLearningModel::getManifest($filename);
174
-         $dom = DOMLearningModel::getInstance(1, $XMLManifest);
175
-
176
-         $isPresent = $dom->isItemInBranch('activity_2', 'activity_31'); // l'item 2 est dans la branche 31
177
-         $this->assertSame(true, $isPresent);
178
-
179
-         $isPresent = $dom->isItemInBranch('activity_1', 'activity_31'); // l'item 1 n' est pas dans la branche 31
180
-         $this->assertSame(false, $isPresent);
181
-
182
-         $isPresent = $dom->isItemInBranch('T-01b', 'activity_1'); // l'organization est dans n'importe quelle branche
183
-         $this->assertSame(true, $isPresent);
184
-
185
-         $isPresent = $dom->isItemInBranch('T-01b', 'activity_31'); // l'organization est dans n'importe quelle branche
186
-         $this->assertSame(true, $isPresent);
187
-    }
188
-
189
-    public function testGetItemBranch()
190
-    {
191
-        //construction du DOM à partir d'un autre paquet test fournit par l'ADL
192
-        $dom = null; // pour ecrase l'ancien dom
193
-        $filename = __DIR__.
194
-        '/../../packages/SCORM2004/LMSTestPackage_T-01b.zip';
195
-        $XMLManifest = DOMLearningModel::getManifest($filename);
196
-        $dom = DOMLearningModel::getInstance(1, $XMLManifest);
197
-
198
-        $branch = $dom->getItemBranch('activity_32');
199
-        $this->assertEquals([
200
-            'T-01b',
201
-            'activity_2',
202
-            'activity_29',
203
-            'activity_30',
204
-            'activity_32'], $branch, true);
205
-
206
-        $branch = $dom->getItemBranch('T-01b'); // branche constituée uniquement par la racine
207
-        $this->assertEquals([
208
-            'T-01b'], $branch, true);
209
-    }
210
-
211 167
     public function testGetSequencingAttribute()
212 168
     {
213 169
         //construction du DOM à partir d'un autre paquet test fournit par l'ADL
@@ -253,25 +209,6 @@ class DOMSCORM2004Test extends TestCase
253 209
         $this->assertSame($result, 'false');
254 210
     }
255 211
 
256
-    public function testGetOrganizationByItem()
257
-    {
258
-        //construction du DOM à partir d'un autre paquet test fournit par l'ADL
259
-        $dom = null; // pour ecrase l'ancien dom
260
-        $filename = __DIR__.
261
-        '/../../packages/SCORM2004/LMSTestPackage_T-01b.zip';
262
-        $XMLManifest = DOMLearningModel::getManifest($filename);
263
-        $dom = DOMLearningModel::getInstance(1, $XMLManifest);
264
-
265
-        $result = $dom->getOrganizationByItem('activity_4');
266
-        $this->assertSame('T-01b', $result);
267
-
268
-        $result = $dom->getOrganizationByItem('activity_10');
269
-        $this->assertSame('T-01b', $result);
270
-
271
-        $result = $dom->getOrganizationByItem('T-01b');
272
-        $this->assertSame('T-01b', $result);
273
-    }
274
-
275 212
     public function testGetAttributeByName()
276 213
     {
277 214
         $dom = null; // pour ecrase l'ancien dom
@@ -564,7 +501,7 @@ class DOMSCORM2004Test extends TestCase
564 501
 
565 502
         $result = $dom->getMapInfos('activity_5', '', true);
566 503
 
567
-        $this->assertSame(null, $result);
504
+        $this->assertSame(array(), $result);
568 505
 
569 506
         $result = $dom->getMapInfos('activity_4', 'PRIMARYOBJ', true);
570 507
  
@@ -592,7 +529,7 @@ class DOMSCORM2004Test extends TestCase
592 529
         $XMLManifest = DOMLearningModel::getManifest($filename);
593 530
         $dom = DOMLearningModel::getInstance(1, $XMLManifest);
594 531
         $result = $dom->getMapInfos('handicapping_item', 'handicapping_completed', true);
595
-
532
+;
596 533
         $this->assertEquals([0 => [
597 534
         'targetObjectiveID' => 'com.scorm.golfsamples.sequencing.forcedsequential.handicapping_completed',
598 535
         'readSatisfiedStatus' => 'true',

Loading…
Cancel
Save