/**
  * Set the identifier of the template variable to be set.
  * 
  * @param string $identifier A valid QTI identifier.
  */
 public function setIdentifier($identifier)
 {
     if (Format::isIdentifier($identifier, false) === true) {
         $this->identifier = $identifier;
     } else {
         $msg = "The 'identifier' argument must be a valid QTI identifier, '" . $identifier . "' given.";
         throw new InvalidArgumentException($msg);
     }
 }
Esempio n. 2
0
 /**
  * Set the assessment section identifier to match.
  *
  * @param string $sectionIdentifier A QTI Identifier.
  * @throws \InvalidArgumentException If $sectionIdentifier is not a valid QTI Identifier.
  */
 public function setSectionIdentifier($sectionIdentifier)
 {
     if (Format::isIdentifier($sectionIdentifier) || empty($sectionIdentifier)) {
         $this->sectionIdentifier = $sectionIdentifier;
     } else {
         $msg = "'{$sectionIndentifier}' is not a valid QTI Identifier.";
         throw new InvalidArgumentException($msg);
     }
 }
 /**
  * Set the fieldIdentifier attribute.
  * 
  * @param string $fieldIdentifier A QTI Identifier.
  * @throws InvalidArgumentException If $fieldIdentifier is not a valid QTI Identifier.
  */
 public function setFieldIdentifier($fieldIdentifier)
 {
     if (Format::isIdentifier($fieldIdentifier)) {
         $this->fieldIdentifier = $fieldIdentifier;
     } else {
         $msg = "'{$fieldIdentifier}' is not a valid QTI Identifier.";
         throw new InvalidArgumentException($msg);
     }
 }
Esempio n. 4
0
 /**
  * Set the identifier of the associated mapping.
  *
  * @param string $identifier A QTI Identifier.
  * @throws \InvalidArgumentException If $identifier is not a valid QTI Identifier.
  */
 public function setIdentifier($identifier)
 {
     if (Format::isIdentifier($identifier, false)) {
         $this->identifier = $identifier;
     } else {
         $msg = "{$identifier} is not a valid QTI Identifier.";
         throw new InvalidArgumentException($identifier);
     }
 }
Esempio n. 5
0
 /**
  * Check if $value is a valid QTI Identifier.
  *
  * @throws \InvalidArgumentException If $value is not a valid QTI Identifier.
  */
 protected function checkType($value)
 {
     if (gettype($value) !== 'string') {
         $msg = "IdentifierCollection class only accept string values, '" . gettype($value) . "' given.";
         throw new InvalidArgumentException($msg);
     } elseif (!Format::isIdentifier($value)) {
         $msg = "IdentifierCollection class only accept valid QTI Identifiers, '{$value}' given.";
         throw new InvalidArgumentException($msg);
     }
 }
Esempio n. 6
0
 public function convert(BaseQuestionType $questionType, $interactionIdentifier, $interactionLabel)
 {
     /** @var mcq $question */
     $question = $questionType;
     // Build <choiceInteraction>
     $valueIdentifierMap = [];
     $simpleChoiceCollection = new SimpleChoiceCollection();
     foreach ($question->get_options() as $index => $option) {
         /** @var mcq_options_item $option */
         $choiceContent = new FlowStaticCollection();
         foreach (QtiMarshallerUtil::unmarshallElement($option->get_label()) as $component) {
             $choiceContent->attach($component);
         }
         // Use option['value'] as choice `identifier` if it has the correct format,
         // Otherwise, generate a valid using index such `CHOICE_1`, `CHOICE_2`, etc
         $originalOptionValue = $option->get_value();
         $choiceIdentifier = Format::isIdentifier($originalOptionValue, false) ? $originalOptionValue : 'CHOICE_' . $index;
         // Store this reference in a map
         $valueIdentifierMap[$originalOptionValue] = $choiceIdentifier;
         $choice = new SimpleChoice($choiceIdentifier);
         $choice->setContent($choiceContent);
         $simpleChoiceCollection->attach($choice);
     }
     // Build final interaction and its corresponding <responseDeclaration>, and its <responseProcessingTemplate>
     $interaction = new ChoiceInteraction($interactionIdentifier, $simpleChoiceCollection);
     $interaction->setLabel($interactionLabel);
     $interaction->setMinChoices(1);
     $interaction->setMaxChoices($question->get_multiple_responses() ? $simpleChoiceCollection->count() : 1);
     // Build the prompt
     $interaction->setPrompt($this->convertStimulusForPrompt($question->get_stimulus()));
     // Set shuffle options
     $interaction->setShuffle($question->get_shuffle_options() ? true : false);
     // Set the layout
     if ($question->get_ui_style() instanceof mcq_ui_style && $question->get_ui_style()->get_type() === 'horizontal' && intval($question->get_ui_style()->get_columns()) === count($question->get_options())) {
         $interaction->setOrientation(Orientation::HORIZONTAL);
     } else {
         $interaction->setOrientation(Orientation::VERTICAL);
         LogService::log('ui_style` is ignored and `choiceInteraction` is assumed and set as `vertical`');
     }
     if (empty($question->get_validation())) {
         return [$interaction, null, null];
     }
     $builder = new McqValidationBuilder($question->get_multiple_responses(), $valueIdentifierMap);
     list($responseDeclaration, $responseProcessing) = $builder->buildValidation($interactionIdentifier, $question->get_validation());
     return [$interaction, $responseDeclaration, $responseProcessing];
 }
Esempio n. 7
0
 public function convert(item $item, array $questions)
 {
     // Make sure we clean up the log
     LogService::flush();
     // Try to build the identifier using item `reference`
     // Otherwise, generate an alternative identifier and store the original reference as `label`
     $itemReference = $item->get_reference();
     $itemIdentifier = Format::isIdentifier($itemReference, false) ? $itemReference : 'ITEM_' . StringUtil::generateRandomString(12);
     if ($itemReference !== $itemIdentifier) {
         LogService::log("The item `reference` ({$itemReference}) is not a valid identifier, thus can not be used for `assessmentItem` identifier. " . "Replaced it with randomly generated `{$itemIdentifier}` and stored the original `reference` as `label` attribute");
     }
     $builder = new AssessmentItemBuilder();
     $assessmentItem = $builder->build($itemIdentifier, $itemReference, $questions, $item->get_content());
     $xml = new XmlDocument();
     $xml->setDocumentComponent($assessmentItem);
     // Flush out all the error messages stored in this static class, also ensure they are unique
     $messages = array_values(array_unique(LogService::flush()));
     return [$xml->saveToString(true), $messages];
 }
 /**
  * Get the categories of an item
  *
  * @param RdfResource $item the item
  *
  * @return string[] the list of categories
  */
 public function getItemCategories(RdfResource $item)
 {
     $categories = [];
     foreach ($item->getTypes() as $class) {
         $eligibleProperties = $this->getElligibleProperties($class);
         $propertiesValues = $item->getPropertiesValues(array_keys($eligibleProperties));
         foreach ($propertiesValues as $property => $propertyValues) {
             foreach ($propertyValues as $value) {
                 if ($value instanceof RdfResource) {
                     $sanitizedIdentifier = self::sanitizeCategoryName($value->getLabel());
                 } else {
                     $sanitizedIdentifier = self::sanitizeCategoryName((string) $value);
                 }
                 if (Format::isIdentifier($sanitizedIdentifier)) {
                     $categories[] = $sanitizedIdentifier;
                 }
             }
         }
     }
     return $categories;
 }
 /**
  * Set the response variable associated with the interaction. 
  * 
  * @param string $responseIdentifier A QTI identifier.
  * @throws InvalidArgumentException If $responseIdentifier is not a valid QTI identifier.
  */
 public function setResponseIdentifier($responseIdentifier)
 {
     if (Format::isIdentifier($responseIdentifier, false) === true) {
         $this->responseIdentifier = $responseIdentifier;
     } else {
         $msg = "The 'responseIdentifier' argument must be a valid QTI identifier.";
         throw new InvalidArgumentException($msg);
     }
 }
Esempio n. 10
0
 /**
  * Set the unique identifier of the body element.
  *
  * @param string $id A QTI Identifier.
  * @throws \InvalidArgumentException If $id is not a valid QTI identifier.
  */
 public function setId($id = '')
 {
     if (is_string($id) && (empty($id) === true || Format::isIdentifier($id, false) === true)) {
         $this->id = $id;
     } else {
         $msg = "The 'id' argument of a body element must be a valid identifier or an empty string";
         throw new InvalidArgumentException($msg);
     }
 }
 /**
  * If the interaction is bound to a numeric response variable, set the identifier of the response variable where the
  * plain text entered by the candidate will be stored. If $stringIdentifier is an empty string, it means that
  * there is no value for the stringIdentifier attribute.
  *
  * @param string $stringIdentifier A QTI Identifier or an empty string.
  * @throws InvalidArgumentException If $stringIdentifier is not a valid QTIIdentifier nor an empty string.
  */
 public function setStringIdentifier($stringIdentifier)
 {
     if (Format::isIdentifier($stringIdentifier, false) === true || is_string($stringIdentifier) && empty($stringIdentifier) === true) {
         $this->stringIdentifier = $stringIdentifier;
     } else {
         $msg = "The 'stringIdentifier' argument must be a valid QTI identifier or an empty string, '" . $stringIdentifier . "' given.";
         throw new InvalidArgumentException($msg);
     }
 }
Esempio n. 12
0
 /**
  * Transform a custom operator class e.g. 'org.qtism.custom.explode' into a PHP
  * fully qualified class name e.g. 'org\qtism\custom\Explode'.
  * 
  * @param string $class A custom operator class name where namespace separator is '.' (dot).
  * @return boolean|string A fully qualified PHP class name corresponding to $class or false if the transformation failed.
  */
 public static function customOperatorClassToPhpClass($class)
 {
     if (is_string($class) === false) {
         return false;
     } else {
         if (Format::isIdentifier($class, false) === false) {
             return false;
         }
     }
     $class = strval($class);
     $tokens = explode('.', $class);
     if ($tokens === false) {
         return $tokens;
     } else {
         $tokenCount = count($tokens);
         if ($tokenCount <= 1) {
             return false;
         }
         // ucfirst on last token (i.e. The actual class name)
         $lastPosition = $tokenCount - 1;
         $lastToken = ucfirst($tokens[$lastPosition]);
         $tokens[$lastPosition] = $lastToken;
         return implode("\\", $tokens);
     }
 }
Esempio n. 13
0
 /**
  * Set the template identifier of the choice.
  * 
  * @param string $templateIdentifier An empty string if no identifier is provided or a QTI identifier.
  * @throws InvalidArgumentException If the given $templateIdentifier is not a valid QTI identifier.
  */
 public function setTemplateIdentifier($templateIdentifier)
 {
     if (is_string($templateIdentifier) === true && empty($templateIdentifier) === true || Format::isIdentifier($templateIdentifier, false) === true) {
         $this->templateIdentifier = $templateIdentifier;
     } else {
         $msg = "The 'templateIdentifier' must be an empty string or a valid QTI identifier, '" . gettype($templateIdentifier) . "' given.";
         throw new InvalidArgumentException($msg);
     }
 }
Esempio n. 14
0
 /**
  * Get the target identifier of the BranchRule.
  *
  * @param string $target A QTI Identifier.
  * @throws \InvalidArgumentException If $target is not a valid QTI Identifier.
  */
 public function setTarget($target)
 {
     if (Format::isIdentifier($target)) {
         $this->target = $target;
     } else {
         $msg = "'Target' must be a valid QTI Identifier.";
         throw new InvalidArgumentException($msg);
     }
 }
Esempio n. 15
0
 /**
  * Transform a string representing a QTI valueType value in a
  * the correct datatype.
  *
  * @param string $string The QTI valueType value as a string.
  * @param integer $baseType The QTI baseType that defines the datatype of $string.
  * @return mixed A converted object/primitive type.
  * @throws \InvalidArgumentException If $baseType is not a value from the BaseType enumeration.
  * @throws \UnexpectedValueException If $string cannot be transformed in a Value expression with the given $baseType.
  */
 public static function stringToDatatype($string, $baseType)
 {
     if (in_array($baseType, BaseType::asArray())) {
         $value = null;
         switch ($baseType) {
             case BaseType::BOOLEAN:
                 if (Format::isBoolean($string)) {
                     $value = Format::toLowerTrim($string) == 'true' ? true : false;
                     return $value;
                 } else {
                     $msg = "'{$string}' cannot be transformed into boolean.";
                     throw new UnexpectedValueException($msg);
                 }
                 break;
             case BaseType::INTEGER:
                 if (Format::isInteger($string)) {
                     $value = intval($string);
                     return $value;
                 } else {
                     $msg = "'{$string}' cannot be transformed into integer.";
                     throw new UnexpectedValueException($msg);
                 }
                 break;
             case BaseType::FLOAT:
                 if (Format::isFloat($string)) {
                     $value = floatval($string);
                     return $value;
                 } else {
                     $msg = "'{$string}' cannot be transformed into float.";
                     throw new UnexpectedValueException($msg);
                 }
                 break;
             case BaseType::URI:
                 if (Format::isUri($string)) {
                     return $string;
                 } else {
                     $msg = "'{$string}' is not a valid URI.";
                     throw new UnexpectedValueException($msg);
                 }
                 break;
             case BaseType::IDENTIFIER:
                 if (Format::isIdentifier($string)) {
                     return $string;
                 } else {
                     $msg = "'{$string}' is not a valid QTI Identifier.";
                     throw new UnexpectedValueException($msg);
                 }
                 break;
             case BaseType::INT_OR_IDENTIFIER:
                 if (Format::isIdentifier($string)) {
                     return $string;
                 } elseif (Format::isInteger($string)) {
                     return intval($string);
                 } else {
                     $msg = "'{$string}' is not a valid QTI Identifier nor a valid integer.";
                     throw new UnexpectedValueException($msg);
                 }
                 break;
             case BaseType::PAIR:
                 if (Format::isPair($string)) {
                     $pair = explode(" ", $string);
                     return new Pair($pair[0], $pair[1]);
                 } else {
                     $msg = "'{$string}' is not a valid pair.";
                     throw new UnexpectedValueException($msg);
                 }
                 break;
             case BaseType::DIRECTED_PAIR:
                 if (Format::isDirectedPair($string)) {
                     $pair = explode(" ", $string);
                     return new DirectedPair($pair[0], $pair[1]);
                 } else {
                     $msg = "'{$string}' is not a valid directed pair.";
                     throw new UnexpectedValueException($msg);
                 }
                 break;
             case BaseType::DURATION:
                 if (Format::isDuration($string)) {
                     return new Duration($string);
                 } else {
                     $msg = "'{$string}' is not a valid duration.";
                     throw new UnexpectedValueException($msg);
                 }
                 break;
             case BaseType::FILE:
                 throw new \RuntimeException("Unsupported baseType: file.");
                 break;
             case BaseType::STRING:
                 return '' . $string;
                 break;
             case BaseType::POINT:
                 if (Format::isPoint($string)) {
                     $parts = explode(" ", $string);
                     return new Point(intval($parts[0]), intval($parts[1]));
                 } else {
                     $msg = "'{$string}' is not valid point.";
                     throw new UnexpectedValueException($msg);
                 }
                 break;
             default:
                 throw new \RuntimeException("Unknown baseType.");
                 break;
         }
     } else {
         $msg = "BaseType must be a value from the BaseType enumeration.";
         throw new InvalidArgumentException($msg);
     }
 }
 private function map(Question $question)
 {
     $type = $question->get_type();
     if (!in_array($type, Constants::$supportedQuestionTypes)) {
         throw new MappingException("Question type `{$type}` not yet supported to be mapped to QTI");
     }
     $clazz = new \ReflectionClass(self::MAPPER_CLASS_BASE . ucfirst($type . 'Mapper'));
     $questionTypeMapper = $clazz->newInstance();
     // Try to use question `reference` as identifier
     // Otherwise, generate an alternative identifier and store the original reference as `label` to be passed in
     $questionReference = $question->get_reference();
     $interactionIdentifier = Format::isIdentifier($questionReference, false) ? $questionReference : strtoupper($type) . '_' . StringUtil::generateRandomString(12);
     if ($interactionIdentifier !== $questionReference) {
         LogService::log("The question `reference` ({$questionReference}) is not a valid identifier. " . "Replaced it with randomly generated `{$interactionIdentifier}` and stored the original `reference` as `label` attribute");
     }
     $result = $questionTypeMapper->convert($question->get_data(), $interactionIdentifier, $questionReference);
     $result[] = $questionTypeMapper->getExtraContent();
     return $result;
 }
 /**
  * Set the weight identifier. Can be '' (empty string) if no weight specified.
  * 
  * @param string $weightIdentifier A QTI Identifier or '' (empty string) if not specified.
  * @throws InvalidArgumentException If $weightIdentifier is not a valid QTI Identifier nor '' (empty string).
  */
 public function setWeightIdentifier($weightIdentifier)
 {
     if (Format::isIdentifier($weightIdentifier) || $weightIdentifier == '') {
         $this->weightIdentifier = $weightIdentifier;
     } else {
         $msg = "'{$weightIdentifier}' is not a valid QTI Identifier.";
         throw new InvalidArgumentException($msg);
     }
 }
 /**
  * @dataProvider invalidIdentifierFormatProvider
  */
 public function testInvalidIdentifierFormat($string)
 {
     $this->assertFalse(Format::isIdentifier($string));
 }
Esempio n. 19
0
 /**
  * Set the second identifier of the pair.
  *
  * @param string $second A QTI Identifier.
  * @throws \InvalidArgumentException If $identifier is not a valid QTI Identifier.
  */
 public function setSecond($second)
 {
     if (Format::isIdentifier($second)) {
         $this->second = $second;
     } else {
         $msg = "'{$second}' is an invalid QTI identifier.";
         throw new InvalidArgumentException($msg);
     }
 }