Esempio n. 1
0
 /**
  * This function analyzes the manifest. In order to perform faster, manifest entities are analyzed one-by-one (on the fly)
  * during parsing and not stored into memory
  * Algorithm:
  * 1. Detect organization elements. Each one will consist a separate units structure inside efront
  * 2. Dive inside an organization and detect item elements. Each <item> corresponds to a "unit" in efront
  *
  *
  *
  *
  * @param $manifest
  * @return unknown_type
  */
 public static function import2($lesson, $manifest)
 {
     //@todo: parse $lesson
     //foreach ($namespaces as $prefix => $ns) {
     //$xml->registerXPathNamespace($prefix, $ns);
     //}
     //pr($xml -> xpath("$dfn:organizations/$dfn:organization/$dfn:item/adlcp:timeLimitAction"));
     $xml = simplexml_load_file(G_SCORMPATH . 'imsmanifest.xml', 'SimpleXMLIterator');
     $namespaces = $xml->getNamespaces(true);
     if (isset($namespaces[""])) {
         //See notes for xpath() in php.net site
         $dfn = "default";
         $xml->registerXPathNamespace($dfn, $namespaces[""]);
         // register a prefix for that default namespace:
         //$xml -> organizations -> registerXPathNamespace($dfn, $namespaces[""]);  	// register a prefix for that default namespace:
     }
     /**
      * Manifest (1/1): may contain the following elements:
      * - metadata (1/1)
      * - organizations (1/1)
      * - resources (1/1)
      * - manifest
      * - imsss:sequencingCollection (0/1)
      * And the following attributes
      * - identifier (xs:ID, m): unique identifier
      * - version (xs:string, o): manifest version
      * - xml:base (xs:anyURI, o): provides a relative path offset for the content file(s) contained in the manifest
      */
     $manifest['identifier'] = (string) $xml->attributes()->identifier;
     $manifest['version'] = (string) $xml->attributes()->version;
     //@todo: handle 'xml:base'
     //$manifest['xml:base']	= (string)$xml -> attributes() -> xml:base;
     /**
      * Metadata: may contain the following elements:
      * - schema (1/1)
      * - schemaversion (1/1)
      * - {metadata} (0/1)
      */
     $metadata['schema'] = (string) $xml->metadata->schema;
     $metadata['schemaversion'] = (string) $xml->metadata->schemaversion;
     //@todo: handle metadata
     /*
      * Organizations: may contain the following elements:
      * - organization (1/M)
      * And the following attributes:
      * - default (xs:IDREF, m): The id of the default organization
      */
     $organizations['default'] = (string) $xml->organizations->attributes();
     //@todo: check that default is actually an existing organization
     /*
      * Organization: may contain the following elements:
      * - title (1/1)
      * - item (1/M)
      * - metadata (0/1)
      * - imsss:sequencing
      * And the following attributes:
      * - identifier (xs:ID, m): identifier (unique within the manifest)
      * - structure (xs:string, o): Describes the shape of the organization (default: hierarchical)
      * - adlseq:objectivesGlobalToSystem (xs:boolean, o): self-explanatory ;)
      */
     foreach ($xml->organizations->organization as $org) {
         $org->registerXPathNamespace($dfn, $namespaces[""]);
         // register a prefix for that default namespace:
         $id = (string) $org->attributes()->identifier;
         $org->attributes()->structure ? $organization[$id]['structure'] = $org->attributes()->structure : ($organization[$id]['structure'] = 'hierarchical');
         $organization[$id]['title'] = $org->attributes()->title;
         //@todo: the importing may be done below existing elements, take this into account when considering $previousContentId (its initial value may not be 0)
         $contentTree = new EfrontContentTree($lesson);
         $previousContent = $contentTree->getLastNode() or $previousContent = array('id' => 0);
         //Create the "holding" unit, an empty unit that will hold this organization's elements
         $previousContent = $parentContent = EfrontUnit::createUnit(array('name' => $organization[$id]['title'], 'parent_content_ID' => 0, 'previous_content_ID' => $previousContent['id'], 'lessons_ID' => $lesson));
         //Get contents of the organization
         foreach ($org as $key => $value) {
             /*
              * Item: may contain the following elements:
              * - title (1/1)
              * - item 0/M
              * - metadata 0/1
              * - adlcp: timeLimitAction 0/1
              * - adlcp: dataFromLMS 0/1
              * - adlcp: completionThreshold 0/1
              * - imsss:sequencing
              * - adlnav:presentation
              * And the following attributes:
              * - identifier (xs:ID, m): a unique identifier
              * - identifierref (xs:string, o): a reference to a resource
              * - isvisible (xs:boolean, o): whether this item is displayed when the structure of the package is displayed or rendered (Default true)
              * - parameters (xs:string, o): static parameters to be passed to the resource at launch time (max 1000 chars)
              */
             if ($key == 'item') {
                 $itemId = (string) $value->attributes()->identifier;
                 //pr($value -> attributes() -> identifier);
                 $item = array('identifier' => $itemId, 'identifierref' => (string) $value->attributes()->identifierref, 'isvisible' => (string) $value->attributes()->isvisible, 'parameters' => (string) $value->attributes()->parameters, 'title' => (string) $value->title, 'timeLimitAction' => (string) reset($org->xpath("{$dfn}:item[@identifier='{$itemId}']/adlcp:timeLimitAction")), 'dataFromLMS' => (string) reset($org->xpath("{$dfn}:item[@identifier='{$itemId}']/adlcp:dataFromLMS")), 'completionThreshold' => (string) reset($org->xpath("{$dfn}:item[@identifier='{$itemId}']/adlcp:completionThreshold")));
                 //@todo:<imsss:sequencing>, <adlnav:presentation>
                 //@todo: nested items
                 //@todo: metadata
                 $previousContent = EfrontUnit::createUnit(array('name' => $item['title'], 'parent_content_ID' => $parentContent['id'], 'previous_content_ID' => $previousContent['id'], 'lessons_ID' => $lesson));
                 $items[$itemId] = $item['identifierref'];
             }
         }
         //@todo: handle adlseq:objectivesGlobalToSystem
     }
     /*
      * Resources: may contain the following elements:
      * - resource (0/M)
      * And the following attributes:
      * - xml:base (xs:anyURI, o): provides a relative path offset for the content file(s)
      */
     $resources = $xml->resources;
     $resources->registerXPathNamespace($dfn, $namespaces[""]);
     // register a prefix for that default namespace:
     /*
      * Resource: may contain the following elements:
      * - metadata (0/1)
      * - file (0/M)
      * - dependency (0/M)
      * And the following attributes:
      * - identifier (xs:ID, m): a unique identifier
      * - type (xs:string, m): the type of the resource
      * - href (xs:string, o): the �entry point� or �launching point� of this resource
      * - xml:base (xs:anyURI, o): a relative path offset for the files contained in the manifest
      * - adlcp:scormType (xs:string, m): the type of SCORM resource ("sco" or "asset")
      */
     foreach ($resources->resource as $key => $value) {
         $resourceId = (string) $value->attributes()->identifier;
         $resource = array('identifier' => $resourceId, 'type' => (string) $value->attributes()->type, 'href' => (string) $value->attributes()->href, 'base' => (string) $value->attributes($namespaces['xml'])->base, 'scormType' => (string) $value->attributes($namespaces['adlcp'])->scormType);
         /**
          * File: may contain the following elements:
          * - metadata (0/1)
          * And the following attributes:
          * - href (xs:string, m): identifies the location of the file
          */
         foreach ($value->file as $f) {
             $file = array('href' => (string) $f->attributes()->href);
         }
         /**
          * Dependency: may contain the following elements:
          * <none>
          * And the following attributes:
          * - identifierref (xs:string, m): an identifier attribute of a resource
          */
         foreach ($value->dependency as $d) {
             $dependency = array('identifierref' => (string) $d->attributes()->identifierref);
         }
     }
     //@todo: sequencingCollection
     //pr($organization);
     //    	$result = $xml -> xpath("//$dfn:manifest/$dfn:organizations/$dfn:organization");
     /*
     $iterator = new SimpleXMLIterator($xml -> asXML());
     foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST) as $key => $value) {
     
     }
     */
     /*
              //$iterator = new SimpleXMLIterator($data);
              //$iterator = simplexml_load_string($data, 'SimpleXMLIterator');
     */
 }
Esempio n. 2
0
 /**
  * Insert unit to tree
  *
  * This function is used to insert a new unit to the content tree
  * <br/>Example:
  * <code>
  * $unit = array("id"                  => 99,                           //Create the array of the new unit
  *               "name"                => "Test Insert Unit",
  *               "lessons_ID"          => 1,
  *               "timestamp"           => time(),
  *               "ctg_type"            => "theory",
  *               "active"              => 1,
  *               "parent_content_ID"   => 5,
  *               "previous_content_ID" => 5);
  *
  * $content = new EfrontContentTree(4);                                 //Initialize content tree for lesson with id 4
  * $content -> insertNode($unit);                                       //Insert the new unit
  * </code>
  *
  * @param array $unit The unit array
  * @param int $parentUnit The parent of the specified node, if it is not set inside the node (not used for the moment)
  * @param int $previousUnit The previous of the specified node, if it is not set inside the node (not used for the moment)
  * @return EfrontUnit The new unit
  * @since 3.5.0
  * @access public
  * @todo implement $parentUnit/$previousUnit functionality, when not present inside $unit
  */
 public function insertNode($unit, $parentUnit = false, $previousUnit = false)
 {
     if (!isset($unit['id'])) {
         if (!isset($unit['previous_content_ID'])) {
             $unit['parent_content_ID'] ? $children = $this->getNodeChildren($unit['parent_content_ID']) : ($children = $this->tree);
             //Get the new unit's parent children. If the parent unit is 0, then we will append it to the end of the tree
             foreach ($iterator = new EfrontAttributeFilterIterator(new RecursiveIteratorIterator($children, RecursiveIteratorIterator::SELF_FIRST), 'id') as $lastUnitId) {
             }
             //Iterate through the parent's children until you reach the last one
             $lastUnitId ? $unit['previous_content_ID'] = $lastUnitId : ($unit['previous_content_ID'] = 0);
             //The new unit's parent last unit
         }
         $unit = EfrontUnit::createUnit($unit);
     }
     $iterator = new EfrontNodeFilterIterator(new RecursiveIteratorIterator($this->tree, RecursiveIteratorIterator::SELF_FIRST));
     //Get an iterator for the current tree. This iterator returns only whole unit arrays and not unit members separately (such as id, timestamp etc)
     $iterator->rewind();
     //Initialize iterator
     while ($iterator->valid() && $iterator->key() != $unit['previous_content_ID']) {
         //Forward iterator index until you reach the unit's previous unit
         $iterator->next();
     }
     $iterator->next();
     //Advance iterator once more to get the next unit
     if ($iterator->valid()) {
         //If there is a next unit
         $lastUnit = $unit;
         //Set the current last unit to be the inserted unit
         foreach (new EfrontNodeFilterIterator(new RecursiveIteratorIterator(new RecursiveArrayIterator($unit), RecursiveIteratorIterator::SELF_FIRST)) as $lastUnit) {
         }
         //If the inserted unit is actually a tree branch with children, advance to the last one
         $iterator->current()->offsetSet('previous_content_ID', $lastUnit['id']);
         //The current unit will have the $lastUnit as previous
         $iterator->current()->persist();
         //Store value to the database
     }
     $this->reset();
     //Rebuild content tree, so that the unit may appear to the right place
     return $this->seekNode($unit['id']);
 }
Esempio n. 3
0
 /**
  * Create test
  *
  * This function is used to create a new test.
  * In order to create the test, it firsts creates
  * a unit to hold it.
  * <br/>Example:
  * <code>
  * $contentFields = new array('name' => 'new unit');
  * $testFields    = new array('duration' => 100);
  * $test = EfrontTest :: createTest($contentFields, $testFields);
  * </code>
  *
  * @param mixed $content The content unit fields or an existing unitObject. If it's false, then the test will not be associated to a unit
  * @param array $test The test fields
  * @return EfrontTest the new test object
  * @since 3.5.0
  * @access public
  * @static
  */
 public static function createTest($content, $test)
 {
     if ($content === false) {
         $test['content_ID'] = 0;
     } elseif (!$content instanceof EfrontUnit) {
         $unit = EfrontUnit::createUnit($content);
         $test['content_ID'] = $unit['id'];
         $test['lessons_ID'] = $unit['lessons_ID'];
     } else {
         $unit = $content;
         $test['content_ID'] = $unit['id'];
         $test['lessons_ID'] = $unit['lessons_ID'];
     }
     unset($test['id']);
     if ($newId = eF_insertTableData("tests", $test)) {
         if ($test['lessons_ID'] != 0) {
             EfrontEvent::triggerEvent(array("type" => EfrontEvent::TEST_CREATION, "users_LOGIN" => $GLOBALS['currentUser']->user['login'], "lessons_ID" => $test['lessons_ID']));
         } else {
             // Special treatment for skillgap tests
             EfrontEvent::triggerEvent(array("type" => EfrontEvent::TEST_CREATION, "users_LOGIN" => $GLOBALS['currentUser']->user['login'], "lessons_ID" => 0, "lessons_name" => _SKILLGAPTESTS));
         }
         return new EfrontTest($newId);
     } else {
         return false;
     }
 }