public function convert(BaseQuestionType $questionType, $interactionIdentifier, $interactionLabel) { /** @var clozetext $question */ $question = $questionType; // Extra text that can't be mapped since we are in textEntryInteraction which does not have prompt $this->extraContent = $question->get_stimulus(); // Replace {{ response }} with `textEntryInteraction` elements $maxLength = !is_null($question->get_max_length()) ? intval($question->get_max_length()) : 15; // Set default to `15` if not set $index = 0; $template = preg_replace_callback('/{{response}}/', function ($match) use(&$index, $interactionIdentifier, $interactionLabel, $maxLength) { $interaction = new TextEntryInteraction($interactionIdentifier . '_' . $index); $interaction->setLabel($interactionLabel); $interaction->setExpectedLength($maxLength); $index++; $replacement = QtiMarshallerUtil::marshall($interaction); return $replacement; }, $question->get_template()); // Wrap this interaction in a block since our `clozetext` `template` meant to be blocky and not inline $div = new Div(); $div->setClass('lrn-template'); $div->setContent(ContentCollectionBuilder::buildFlowCollectionContent(QtiMarshallerUtil::unmarshallElement($template))); // Build validation $isCaseSensitive = is_null($question->get_case_sensitive()) ? true : $question->get_case_sensitive(); $validationBuilder = new ClozetextValidationBuilder($isCaseSensitive); list($responseDeclaration, $responseProcessing) = $validationBuilder->buildValidation($interactionIdentifier, $question->get_validation(), $isCaseSensitive); return [$div, $responseDeclaration, $responseProcessing]; }
private function buildTemplate(QtiGapMatchInteraction $interaction) { $templateCollection = new QtiComponentCollection(); foreach ($interaction->getComponents() as $component) { // Ignore `prompt` and the `gapChoice` since they are going to be mapped somewhere else :) if (!$component instanceof Prompt && !$component instanceof GapChoice) { $templateCollection->attach($component); } } $gapIdentifiers = []; $content = QtiMarshallerUtil::marshallCollection($templateCollection); foreach ($interaction->getComponentsByClassName('gap', true) as $gap) { /** @var Gap $gap */ $gapIdentifiers[] = $gap->getIdentifier(); $gapString = QtiMarshallerUtil::marshall($gap); $content = str_replace($gapString, '{{response}}', $content); } return [$content, $gapIdentifiers]; }
public function convert(BaseQuestionType $questionType, $interactionIdentifier, $interactionLabel) { /** @var clozedropdown $question */ $question = $questionType; // Extra text that can't be mapped since we are in textEntryInteraction which does not have prompt $this->extraContent = $question->get_stimulus(); // Replace {{ response }} with `textEntryInteraction` elements $valueIdentifierMapPerInlineChoices = []; $index = 0; $possibleResponses = $question->get_possible_responses(); $template = preg_replace_callback('/{{response}}/', function ($match) use(&$index, &$valueIdentifierMapPerInlineChoices, $possibleResponses, $interactionIdentifier, $interactionLabel) { $inlineChoiceCollection = new InlineChoiceCollection(); if (!isset($possibleResponses[$index])) { throw new MappingException('Invalid `possible_responses`, missing entries'); } foreach ($possibleResponses[$index] as $choiceIndex => $choiceValue) { $inlineChoiceIdentifier = 'INLINECHOICE_' . $choiceIndex; $valueIdentifierMapPerInlineChoices[$index][$choiceValue] = $inlineChoiceIdentifier; // Update this map so can be used later upon building responseDeclaration objects $inlineChoice = new InlineChoice($inlineChoiceIdentifier); $inlineChoiceContent = new TextOrVariableCollection(); $inlineChoiceContent->attach(new TextRun($choiceValue)); $inlineChoice->setContent($inlineChoiceContent); $inlineChoiceCollection->attach($inlineChoice); } $interaction = new InlineChoiceInteraction($interactionIdentifier . '_' . $index, $inlineChoiceCollection); $interaction->setLabel($interactionLabel); $index++; $replacement = QtiMarshallerUtil::marshall($interaction); return $replacement; }, $question->get_template()); // Wrap this interaction in a block since our `clozedropdown` `template` meant to be blocky and not inline $div = new Div(); $div->setClass('lrn-template'); $div->setContent(ContentCollectionBuilder::buildFlowCollectionContent(QtiMarshallerUtil::unmarshallElement($template))); // Build validation $validationBuilder = new ClozedropdownValidationBuilder($valueIdentifierMapPerInlineChoices); list($responseDeclaration, $responseProcessing) = $validationBuilder->buildValidation($interactionIdentifier, $question->get_validation()); return [$div, $responseDeclaration, $responseProcessing]; }
public function getQuestionType() { $interactionComponents = $this->itemBody->getComponentsByClassName('inlineChoiceInteraction', true); $interactionXmls = []; $possibleResponsesMap = []; foreach ($interactionComponents as $component) { /** @var Interaction $component */ $interactionXmls[] = QtiMarshallerUtil::marshall($component); /** @var InlineChoice $inlineChoice */ foreach ($component->getComponents() as $inlineChoice) { $possibleResponsesMap[$component->getResponseIdentifier()][$inlineChoice->getIdentifier()] = QtiMarshallerUtil::marshallCollection($inlineChoice->getContent()); } } $template = $this->buildTemplate($this->itemBody, $interactionXmls); $clozedropdown = new clozedropdown('clozedropdown', $template, array_values(array_map('array_values', $possibleResponsesMap))); $validationBuilder = new InlineChoiceInteractionValidationBuilder($this->responseDeclarations, $possibleResponsesMap); // Build `validation` $validation = $validationBuilder->buildValidation($this->responseProcessingTemplate); if (!empty($validation)) { $clozedropdown->set_validation($validation); } return $clozedropdown; }
public function getQuestionType() { // we assume the function maintain the order of the xml element $this->interactionComponents = $this->itemBody->getComponentsByClassName('textEntryInteraction', true); $interactionXmls = []; $interactionIdentifiers = []; /** @var TextEntryInteraction $component */ foreach ($this->interactionComponents as $component) { $interactionXmls[] = QtiMarshallerUtil::marshall($component); $interactionIdentifiers[] = $component->getResponseIdentifier(); } $validation = $this->buildValidation($interactionIdentifiers, $isCaseSensitive); $closetext = new clozetext('clozetext', $this->buildTemplate($this->itemBody, $interactionXmls)); if ($validation) { $closetext->set_validation($validation); } $isMultiLine = false; $maxLength = $this->getExpectedLength($isMultiLine); $closetext->set_max_length($maxLength); $closetext->set_multiple_line($isMultiLine); $closetext->set_case_sensitive($isCaseSensitive); return $closetext; }
private function buildTemplate(HottextInteraction $interaction) { $templateCollection = new QtiComponentCollection(); foreach ($interaction->getComponents() as $component) { // Ignore `prompt` since its going to be mapped to `stimulus` if (!$component instanceof Prompt) { $templateCollection->attach($component); } } $content = QtiMarshallerUtil::marshallCollection($templateCollection); foreach ($interaction->getComponentsByClassName('hottext') as $hottext) { /** @var Hottext $hottext */ $hottextString = QtiMarshallerUtil::marshall($hottext); $tokenSpan = new span(); $tokenSpan->setClass('lrn_token'); $inlineCollection = new InlineCollection(); foreach ($hottext->getComponents() as $c) { $inlineCollection->attach($c); } $tokenSpan->setContent($inlineCollection); $content = str_replace($hottextString, QtiMarshallerUtil::marshall($tokenSpan), $content); } return $content; }