Example #1
0
 /**
  * Test searching for a child term.
  */
 public function testSearchChildTerm()
 {
     $terms = array();
     $root = new PerTerm('type', 'uuid0');
     for ($i = 5; $i > 0; $i--) {
         $term = new PerTerm('type', "uuid{$i}", "Child {$i}");
         $root->addChild($term);
         $terms["uuid{$i}"] = $term;
         for ($j = 5; $j > 0; $j--) {
             $childTerm = new PerTerm('type', "uuid{$i}.{$j}", "Child {$i}.{$j}", "{$i}.{$j}");
             $term->addChild($childTerm);
             $terms["uuid{$i}.{$j}"] = $childTerm;
         }
     }
     $this->assertEquals(null, $root->findChildByCode('4.2'), "Searching by code one level for a child that's located deeper returns null.");
     $this->assertEquals($terms['uuid4.1'], $terms['uuid4']->findChildByCode('4.1'), "Searching by code one level for a child that exists works.");
     $this->assertEquals($terms['uuid4.2'], $root->findChildByCodeRecursive('4.2'), "Recursively searching by code works.");
 }
Example #2
0
 /**
  * Load the curriculum definition from the BDPER API.
  *
  * By passing the official curriculum definition file (XML), this method
  * will parse it and return a curriculum definition it can understand and
  * treat. It mainly needs a "dictionary" of term types.
  *
  * @param string $url
  *    The curriculum definition endpoint URL.
  *
  * @return array
  *    An object with 2 properties:
  *    - curriculum: A parsed and prepared curriculum tree. It uses
  *      Educa\DSB\Client\Curriculum\Term\PerTerm elements to define
  *      the curriculum tree.
  *    - dictionary: A dictionary of term identifiers, with name and type
  *      information for each one of them.
  *
  * @see \Educa\DSB\Client\Curriculum\PerCurriculum::setCurriculumDictionary()
  */
 public static function fetchCurriculumData($url)
 {
     if (preg_match('/\\/$/', $url)) {
         $url = rtrim($url, '/');
     }
     $dictionary = array();
     // First, we want to prepare our 3 cycle base terms. In the Per logic,
     // the cycles are at the root of the tree. That is why we
     // prepare them here, and we will add relevant trees underneath when
     // needed. There are, technically, no cycle elements provided by the
     // PER API. But, to remain consistent, we create them anyway, and make
     // their type plural, as with all the other elements.
     $cycle1 = new PerTerm('cycles', 1, array('fr' => "Cycle 1"));
     $cycle2 = new PerTerm('cycles', 2, array('fr' => "Cycle 2"));
     $cycle3 = new PerTerm('cycles', 3, array('fr' => "Cycle 3"));
     // Prepare our root element, and add our cycles to it.
     $root = new PerTerm('root', 'root');
     $root->addChild($cycle1)->addChild($cycle2)->addChild($cycle3);
     foreach ($root->getChildren() as $child) {
         $description = $child->describe();
         $id = $description->id;
         unset($description->id);
         $dictionary["cycles:{$id}"] = $description;
     }
     $objectives = json_decode(@file_get_contents(defined('RUNNING_PHPUNIT') && RUNNING_PHPUNIT ? "{$url}/objectifs_all" : "{$url}/objectifs"), true);
     $themes = array();
     $domains = array();
     $disciplines = array();
     // Prepare a little function for reducing school year lists.
     $reduceSchoolYears = function ($schoolYears) {
         return array_values(array_filter(array_map(function ($item) {
             switch ($item) {
                 case 1:
                     return '1-2';
                 case 3:
                     return '3-4';
                 case 5:
                     return '5-6';
                 case 7:
                     return '7-8';
                 case 9:
                 case 10:
                 case 11:
                     return (string) $item;
             }
             return null;
         }, array_unique($schoolYears))));
     };
     if (!empty($objectives)) {
         foreach ($objectives as $objectiveData) {
             $objectiveId = $objectiveData['id'];
             $cycleNum = (string) $objectiveData['cycle'];
             // To which cycle does it apply?
             switch ($cycleNum) {
                 case '1':
                     $cycle = $cycle1;
                     break;
                 case '2':
                     $cycle = $cycle2;
                     break;
                 case '3':
                     $cycle = $cycle3;
                     break;
                 default:
                     throw new CurriculumInvalidDataStructureException(sprintf("Couldn't find valid cycle information for the objectif with ID %d", $objectiveId));
                     break;
             }
             // What is the domain ID?
             $domainId = $objectiveData['domaine']['id'];
             // Contrary to objectives and progressions, domains are shared.
             // Check if we already created this domain. If we did, re-use
             // the old one.
             if (isset($domains[$cycleNum][$domainId])) {
                 $domain = $domains[$cycleNum][$domainId];
             } else {
                 $domain = new PerTerm('domaines', $domainId, array('fr' => $objectiveData['domaine']['nom']));
                 $cycle->addChild($domain);
                 // Store it.
                 $domains[$cycleNum][$domainId] = $domain;
                 // Store the description in the dictionary.
                 $description = $domain->describe();
                 unset($description->id);
                 $dictionary["domaines:{$domainId}"] = $description;
             }
             // Prepare all theme names.
             foreach ($objectiveData['thematiques'] as $themeData) {
                 if (!isset($themes[$themeData['id']])) {
                     $themes[$themeData['id']] = $themeData['nom'];
                 }
             }
             // Treat all disciplines.
             foreach ($objectiveData['disciplines'] as $disciplineData) {
                 $disciplineId = $disciplineData['id'];
                 // Contrary to objectives and progressions, disciplines are
                 // shared. Check if we already created this discipline. If
                 // we did, re-use the old one.
                 if (isset($disciplines[$cycleNum][$domainId][$disciplineId])) {
                     $discipline = $disciplines[$cycleNum][$domainId][$disciplineId];
                 } else {
                     $discipline = new PerTerm('disciplines', $disciplineId, array('fr' => $disciplineData['nom']));
                     $domain->addChild($discipline);
                     // Store it.
                     $disciplines[$cycleNum][$domainId][$disciplineId] = $discipline;
                     // Store the description in the dictionary.
                     $description = $discipline->describe();
                     unset($description->id);
                     $dictionary["disciplines:{$disciplineId}"] = $description;
                 }
                 // We can now set the objectives. Prepare the names. They
                 // are based on the Thématiques, as they make more sense.
                 $names = array();
                 foreach ($objectiveData['thematiques'] as $themeData) {
                     $names[] = sprintf('%s (%s)', $themes[$themeData['id']], $objectiveData['code']);
                 }
                 // Objectives are not unique. They can be "shared" by
                 // disciplines, meaning we actually have to duplicate them.
                 $objective = new PerTerm('objectifs', $objectiveId, array('fr' => implode("\n", $names)));
                 $discipline->addChild($objective);
                 // Prepare a list for the objective's school years.
                 $objectiveSchoolYears = array();
                 // Load the raw objective data, we need it for the school
                 // years information, which is not provided in the global
                 // call.
                 $rawData = json_decode(@file_get_contents("{$url}/objectifs/" . $objectiveId), true);
                 if (empty($rawData)) {
                     continue;
                 }
                 foreach ($rawData['progressions'] as $progressionGroup) {
                     $objectiveSchoolYears = array_merge($objectiveSchoolYears, $progressionGroup['annees']);
                     // Fetch the "progressions".
                     foreach ($progressionGroup['items'] as $item) {
                         if (!empty($item['contenus'])) {
                             foreach ($item['contenus'] as $content) {
                                 $progression = new PerTerm('progressions', $content['id'], array('fr' => $content['texte']));
                                 $progression->setSchoolYears($reduceSchoolYears($progressionGroup['annees']));
                                 $objective->addChild($progression);
                                 $description = $progression->describe();
                                 $description->schoolYears = $progression->getSchoolYears();
                                 unset($description->id);
                                 $dictionary["progressions:{$content['id']}"] = $description;
                             }
                         }
                     }
                 }
                 $objective->setSchoolYears($reduceSchoolYears($objectiveSchoolYears));
                 $objective->setCode($objectiveData['code']);
                 $description = $objective->describe();
                 $description->code = $objectiveData['code'];
                 $description->schoolYears = $objective->getSchoolYears();
                 unset($description->id);
                 $dictionary["objectifs:{$objectiveId}"] = $description;
             }
         }
     }
     // Return the parsed data.
     return (object) array('curriculum' => $root, 'dictionary' => $dictionary);
 }