/**
  * Unmarshall a DOMElement object corresponding to a QTI variableDeclaration element.
  *
  * @param \DOMElement $element A DOMElement object.
  * @return \qtism\data\QtiComponent A VariableDeclaration object.
  * @throws \qtism\data\storage\xml\marshalling\UnmarshallingException
  */
 protected function unmarshall(DOMElement $element)
 {
     try {
         // identifier is a mandatory value for the variableDeclaration element.
         if (($identifier = static::getDOMElementAttributeAs($element, 'identifier')) !== null) {
             // cardinality is a mandatory value too.
             if (($cardinality = static::getDOMElementAttributeAs($element, 'cardinality')) !== null) {
                 $object = new VariableDeclaration($identifier, -1, Cardinality::getConstantByName($cardinality));
                 // deal with baseType.
                 $baseType = static::getDOMElementAttributeAs($element, 'baseType');
                 if (!empty($baseType)) {
                     $object->setBaseType(BaseType::getConstantByName($baseType));
                 }
                 // set up optional default value.
                 $defaultValueElements = $element->getElementsByTagName('defaultValue');
                 if ($defaultValueElements->length == 1) {
                     $defaultValueElement = $defaultValueElements->item(0);
                     $defaultValueMarshaller = $this->getMarshallerFactory()->createMarshaller($defaultValueElements->item(0), array($object->getBaseType()));
                     $object->setDefaultValue($defaultValueMarshaller->unmarshall($defaultValueElement));
                 }
                 return $object;
             } else {
                 $msg = "The mandatory attribute 'cardinality' is missing from element '" . $element->localName . "'.";
                 throw new UnmarshallingException($msg, $element);
             }
         } else {
             $msg = "The mandatory attribute 'identifier' is missing from element '" . $element->localName . "'.";
             throw new UnmarshallingException($msg, $element);
         }
     } catch (InvalidArgumentException $e) {
         $msg = "An unexpected error occured while unmarshalling the variableDeclaration.";
         throw new UnmarshallingException($msg, $element, $e);
     }
 }
Exemplo n.º 2
0
 /**
  * Unmarshall a DOMElement object corresponding to a QTI baseValue element.
  *
  * @param \DOMElement $element A DOMElement object.
  * @return \qtism\data\QtiComponent A BaseValue object.
  * @throws \qtism\data\storage\xml\marshalling\UnmarshallingException
  */
 protected function unmarshall(DOMElement $element)
 {
     if (($baseType = static::getDOMElementAttributeAs($element, 'baseType', 'string')) !== null) {
         $value = $element->nodeValue;
         $baseTypeCst = BaseType::getConstantByName($baseType);
         $object = new BaseValue($baseTypeCst, Utils::stringToDatatype($value, $baseTypeCst));
         return $object;
     } else {
         $msg = "The mandatory attribute 'baseType' is missing from element '" . $element->localName . "'.";
         throw new UnmarshallingException($msg, $element);
     }
 }
Exemplo n.º 3
0
 /**
  * Marshall a testVariable QTI element in its TestVariable object equivalent.
  *
  * @param \DOMElement A DOMElement object.
  * @return \qtism\data\QtiComponent The corresponding TestVariable object.
  */
 protected function unmarshall(DOMElement $element)
 {
     $baseComponent = parent::unmarshall($element);
     if (($variableIdentifier = static::getDOMElementAttributeAs($element, 'variableIdentifier')) !== null) {
         $object = new TestVariables($variableIdentifier);
         $object->setSectionIdentifier($baseComponent->getSectionIdentifier());
         $object->setIncludeCategories($baseComponent->getIncludeCategories());
         $object->setExcludeCategories($baseComponent->getExcludeCategories());
         if (($baseType = static::getDOMElementAttributeAs($element, 'baseType')) !== null) {
             $object->setBaseType(BaseType::getConstantByName($baseType));
         }
         if (($weightIdentifier = static::getDOMElementAttributeAs($element, 'weightIdentifier')) !== null) {
             $object->setWeightIdentifier($weightIdentifier);
         }
         return $object;
     } else {
         $msg = "The mandatory attribute 'variableIdentifier' is missing from element '" . $element->localName . "'.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 /**
  * Transform a PCI JSON representation of QTI data into the QTISM runtime model.
  * 
  * @param string|array $json The json data to be transformed.
  * @throws UnmarshallingException If an error occurs while processing $json.
  * @return null|qtism\common\datatypes\QtiDataType|array
  */
 public function unmarshall($json)
 {
     if (is_string($json) === true) {
         $tmpJson = @json_decode($json, true);
         if ($tmpJson === null) {
             // An error occured while decoding.
             $msg = "An error occured while decoding the following JSON data '" . mb_substr($json, 0, 30, 'UTF-8') . "...'.";
             $code = UnmarshallingException::JSON_DECODE;
             throw new UnmarshallingException($msg, $code);
         }
         $json = $tmpJson;
     }
     if (is_array($json) === false || count($json) === 0) {
         $msg = "The '" . get_class($this) . "::unmarshall' method only accepts a JSON string or a non-empty array as argument, '";
         if (is_object($json) === true) {
             $msg .= get_class($json);
         } else {
             $msg .= gettype($json);
         }
         $msg .= "' given.";
         $code = UnmarshallingException::NOT_SUPPORTED;
         throw new UnmarshallingException($msg, $code);
     }
     if (Arrays::isAssoc($json) === false) {
         $msg = "The '" . get_class($this) . "::unmarshall' does not accepts non-associative arrays.";
         $code = UnmarshallingException::NOT_SUPPORTED;
         throw new UnmarshallingException($msg, $code);
     }
     // Check whether or not $json is a state (no 'base' nor 'list' keys found),
     // a base, a list or a record.
     $keys = array_keys($json);
     if (in_array('base', $keys) === true) {
         // This is a base.
         return $this->unmarshallUnit($json);
     } else {
         if (in_array('list', $keys) === true) {
             $keys = array_keys($json['list']);
             if (isset($keys[0]) === false) {
                 $msg = "No baseType provided for list.";
                 throw new UnmarshallingException($msg, UnmarshallingException::NOT_PCI);
             }
             $baseType = BaseType::getConstantByName($keys[0]);
             if ($baseType === false) {
                 $msg = "Unknown QTI baseType '" . $keys[0] . "'.";
                 $code = UnmarshallingException::NOT_PCI;
                 throw new UnmarshallingException($msg, $code);
             }
             $returnValue = new MultipleContainer($baseType);
             // This is a list.
             foreach ($json['list'][$keys[0]] as $v) {
                 try {
                     if ($v === null) {
                         $returnValue[] = $this->unmarshallUnit(array('base' => $v));
                     } else {
                         $returnValue[] = $this->unmarshallUnit(array('base' => array($keys[0] => $v)));
                     }
                 } catch (InvalidArgumentException $e) {
                     $strBaseType = BaseType::getNameByConstant($baseType);
                     $msg = "A value is not compliant with the '{$strBaseType}' baseType.";
                     $code = UnmarshallingException::NOT_PCI;
                     throw new UnmarshallingException($msg, $code);
                 }
             }
             return $returnValue;
         } else {
             if (in_array('record', $keys) === true) {
                 // This is a record.
                 $returnValue = new RecordContainer();
                 if (count($json['record']) === 0) {
                     return $returnValue;
                 }
                 foreach ($json['record'] as $v) {
                     if (isset($v['name']) === false) {
                         $msg = "No 'name' key found in record field.";
                         $code = UnmarshallingException::NOT_PCI;
                         throw new UnmarshallingException($msg, $code);
                     }
                     if (isset($v['base']) === true || array_key_exists('base', $v) && $v['base'] === null) {
                         $unit = array('base' => $v['base']);
                     } else {
                         // No value found, let's go for a null value.
                         $unit = array('base' => null);
                     }
                     $returnValue[$v['name']] = $this->unmarshallUnit($unit);
                 }
                 return $returnValue;
             } else {
                 // This is a state.
                 $state = array();
                 foreach ($json as $k => $j) {
                     $state[$k] = $this->unmarshall($j);
                 }
                 return $state;
             }
         }
     }
 }
Exemplo n.º 5
0
 /**
  * Unmarshall a DOMElement object corresponding to a QTI Value element.
  *
  * @param \DOMElement $element A DOMElement object.
  * @return \qtism\data\QtiComponent A Value object.
  * @throws \qtism\data\storage\xml\marshalling\UnmarshallingException If the 'baseType' attribute is not a valid QTI baseType.
  */
 protected function unmarshall(DOMElement $element)
 {
     $object = null;
     if (($baseType = static::getDOMElementAttributeAs($element, 'baseType', 'string')) !== null) {
         // baseType attribute is set -> part of a record.
         $baseTypeCst = BaseType::getConstantByName($baseType);
         if ($baseTypeCst !== false) {
             $object = new Value(Utils::stringToDatatype(trim($element->nodeValue), $baseTypeCst), $baseTypeCst);
             $object->setPartOfRecord(true);
         } else {
             $msg = "The 'baseType' attribute value ('{$value}') is not a valid QTI baseType in element '" . $element->localName . "'.";
             throw new UnmarshallingException($msg, $element);
         }
     } else {
         // baseType attribute not set -> not part of a record.
         $nodeValue = trim($element->nodeValue);
         if ($nodeValue !== '') {
             // Try to use the marshaller as parametric to know how to unserialize the value.
             if ($this->getBaseType() != -1) {
                 $object = new Value(Utils::stringToDatatype($nodeValue, $this->getBaseType()), $this->getBaseType());
             } else {
                 // value used as plain string (at your own risks).
                 $object = new Value($nodeValue);
             }
         } else {
             $msg = "The element '" . $element->localName . "' has no value.";
             throw new UnmarshallingException($msg, $element);
         }
     }
     if (($value = static::getDOMElementAttributeAs($element, 'fieldIdentifier', 'string')) !== null) {
         $object->setFieldIdentifier($value);
     }
     return $object;
 }
Exemplo n.º 6
0
 /**
  * Transform a TAO serialized result value to its QtiDatatype equivalent.
  * 
  * This method transforms a TAO serialized result $value to a the equivalent QtiDatatype depending
  * on result's $cardinality and $baseType.
  * 
  * Note: at the present time, this implementation only supports 'single', 'multiple', and 'ordered' cardinality in conjunction
  * with the 'identifier', 'boolean', 'pair' or 'directedPair' baseType.
  * 
  * @param string $cardinality i.e. 'ordered', 'multiple' or 'single'.
  * @param string $basetype i.e. 'identifier'
  * @param string $value A TAO serialized result value e.g. '<choice1 choice2 choice3>'
  * @return mixed A QtiDatatype object or null in case of no possibility to transform $value in the appropriate target $cardinality and $basetype.
  */
 public static function toQtiDatatype($cardinality, $basetype, $value)
 {
     // @todo support all baseTypes
     $datatype = null;
     if (is_string($value) && empty($value) === false && $cardinality !== 'record' && ($basetype === 'identifier' || $basetype === 'pair' || $basetype === 'directedPair' || $basetype === 'boolean')) {
         if ($cardinality !== 'simple') {
             $value = trim($value, "<>[]");
             $value = explode(';', $value);
         } else {
             $value = array($value);
         }
         if (count($value) === 1 && empty($value[0]) === true) {
             $value = array();
         }
         $value = array_map(function ($val) {
             return trim($val);
         }, $value);
         $qtiBasetype = BaseType::getConstantByName($basetype);
         $datatype = $cardinality === 'ordered' ? new OrderedContainer($qtiBasetype) : new MultipleContainer($qtiBasetype);
         foreach ($value as $val) {
             try {
                 switch ($basetype) {
                     case 'identifier':
                         $datatype[] = new QtiIdentifier($val);
                         break;
                     case 'pair':
                         $pair = explode(" ", $val);
                         if (count($pair) === 2) {
                             $datatype[] = new QtiPair($pair[0], $pair[1]);
                         }
                         break;
                     case 'directedPair':
                         $pair = explode(" ", $val);
                         if (count($pair) === 2) {
                             $datatype[] = new QtiDirectedPair($pair[0], $pair[1]);
                         }
                         break;
                     case 'boolean':
                         if ($val === 'true') {
                             $datatype[] = new QtiBoolean(true);
                         } elseif ($val === 'false') {
                             $datatype[] = new QtiBoolean(false);
                         } else {
                             $datatype[] = new QtiBoolean($val);
                         }
                         break;
                 }
             } catch (InvalidArgumentException $e) {
                 $datatype = null;
                 break;
             }
         }
         $datatype = $cardinality === 'single' ? isset($datatype[0]) ? $datatype[0] : null : $datatype;
     }
     return $datatype;
 }
Exemplo n.º 7
0
 /**
  * @dataProvider invalidBaseTypeProvider
  */
 public function testGetConstantByNameInvalidBaseType($baseType)
 {
     $this->assertFalse(BaseType::getConstantByName($baseType));
 }