public function convert(BaseQuestionType $questionType, $interactionIdentifier, $interactionLabel)
 {
     /** @var shorttext $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();
     $interaction = new TextEntryInteraction($interactionIdentifier);
     $interaction->setLabel($interactionLabel);
     // Build placeholder
     $placeholderText = $question->get_placeholder();
     if (!empty($placeholderText)) {
         $interaction->setPlaceholderText($placeholderText);
     }
     // Use 15 as default
     $interaction->setExpectedLength($question->get_max_length() ? $question->get_max_length() : 15);
     // Build those validation
     $isCaseSensitive = $question->get_case_sensitive() === null ? true : $question->get_case_sensitive();
     $validationBuilder = new ShorttextValidationBuilder($isCaseSensitive);
     list($responseDeclaration, $responseProcessing) = $validationBuilder->buildValidation($interactionIdentifier, $question->get_validation(), $isCaseSensitive);
     // TODO: This is a freaking hack
     // Wrap this interaction in a block since our `shorttext` meant to be blocky and not inline
     $div = new Div();
     $content = new FlowCollection();
     $content->attach($interaction);
     $div->setContent($content);
     return [$div, $responseDeclaration, $responseProcessing];
 }
 public static function buildFlowCollectionContent(QtiComponentCollection $content)
 {
     $collection = new FlowCollection();
     foreach ($content as $component) {
         $collection->attach($component);
     }
     return $collection;
 }
 public function buildContentCollection(QtiComponentCollection $contentCollection)
 {
     $areBlockComponents = array_reduce($contentCollection->getArrayCopy(), function ($initial, $component) {
         return $initial && $component instanceof Block;
     }, true);
     // Check whether the content could all be attached as is
     if ($areBlockComponents) {
         $blockCollection = new BlockCollection();
         foreach ($contentCollection as $component) {
             $blockCollection->attach($component);
         }
         return $blockCollection;
     }
     // Otherwise, build a `div` wrapper around it
     $divCollection = new FlowCollection();
     foreach ($contentCollection as $component) {
         $divCollection->attach($component);
     }
     $div = new Div();
     $div->setContent($divCollection);
     $blockCollection = new BlockCollection();
     $blockCollection->attach($div);
     return $blockCollection;
 }
 private function buildItemBodyWithItemContent(array $interactions, $content)
 {
     // Map <itemBody>
     // TODO: Wrap these `content` stuff in a div
     // TODO: to avoid QtiComponentIterator bug ignoring 2nd element with empty content
     $contentCollection = QtiMarshallerUtil::unmarshallElement($content);
     $wrapperCollection = new FlowCollection();
     foreach ($contentCollection as $component) {
         $wrapperCollection->attach($component);
     }
     $divWrapper = new Div();
     $divWrapper->setContent($wrapperCollection);
     // Iterate through these elements and try to replace every single question `span` with its interaction equivalent
     $iterator = $divWrapper->getIterator();
     foreach ($iterator as $component) {
         if ($component instanceof Span && StringUtil::contains($component->getClass(), 'learnosity-response')) {
             $currentContainer = $iterator->getCurrentContainer();
             $questionReference = trim(str_replace('learnosity-response', '', $component->getClass()));
             $questionReference = trim(str_replace('question-', '', $questionReference));
             // Build the actual interaction
             $interaction = $interactions[$questionReference]['interaction'];
             $content = new FlowCollection();
             if (isset($interactions[$questionReference]['extraContent'])) {
                 $content->attach($interactions[$questionReference]['extraContent']);
             }
             $content->attach($interaction);
             $replacement = ContentCollectionBuilder::buildContent($currentContainer, $content)->current();
             $currentContainer->getComponents()->replace($component, $replacement);
         }
     }
     // Extract the actual content from the div wrapper and add that to our <itemBody>
     $componentsWithinDiv = $divWrapper->getComponents();
     $itemBody = new ItemBody();
     $itemBody->setContent(ContentCollectionBuilder::buildBlockCollectionContent($componentsWithinDiv));
     return $itemBody;
 }