/** * Load a QTI_Item from an, RDF Item using the itemContent property of the * Item as the QTI xml * * @access public * @author Somsack Sipasseuth, <*****@*****.**> * @param Resource item * @throws \common_Exception If $item is not representing an item with a QTI item model. * @return oat\taoQtiItem\model\qti\Item An item as a business object. */ public function getDataItemByRdfItem(core_kernel_classes_Resource $item, $langCode = '', $resolveXInclude = false) { $returnValue = null; $itemService = taoItems_models_classes_ItemsService::singleton(); //check if the item is QTI item if ($itemService->hasItemModel($item, array(ItemModel::MODEL_URI))) { //get the QTI xml $itemContent = $itemService->getItemContent($item, $langCode); if (!empty($itemContent)) { //Parse it and build the QTI_Data_Item $qtiParser = new Parser($itemContent); $returnValue = $qtiParser->load(); if ($resolveXInclude && !empty($langCode)) { //loadxinclude $resolver = new ItemMediaResolver($item, $langCode); $xincludeLoader = new XIncludeLoader($returnValue, $resolver); $xincludeLoader->load(true); } if (!$returnValue->getAttributeValue('xml:lang')) { $returnValue->setAttribute('xml:lang', \common_session_SessionManager::getSession()->getDataLanguage()); } } else { // fail silently, since file might not have been created yet // $returnValue is then NULL. common_Logger::d('item(' . $item->getUri() . ') is empty, newly created?'); } } else { throw new common_Exception('Non QTI item(' . $item->getUri() . ') opened via QTI Service'); } return $returnValue; }
/** * Load a QTI_Item from an, RDF Item using the itemContent property of the * Item as the QTI xml * * @access public * @author Somsack Sipasseuth, <*****@*****.**> * @param Resource item * @throws \common_Exception If $item is not representing an item with a QTI item model. * @return Item An item as a business object. */ public function getDataItemByRdfItem(core_kernel_classes_Resource $item, $langCode = '', $resolveXInclude = false) { $returnValue = null; try { //Parse it and build the QTI_Data_Item $file = $this->getXmlByRdfItem($item, $langCode); $qtiParser = new Parser($file); $returnValue = $qtiParser->load(); if ($resolveXInclude && !empty($langCode)) { try { //loadxinclude $resolver = new ItemMediaResolver($item, $langCode); $xincludeLoader = new XIncludeLoader($returnValue, $resolver); $xincludeLoader->load(true); } catch (XIncludeException $exception) { common_Logger::e($exception->getMessage()); } } if (!$returnValue->getAttributeValue('xml:lang')) { $returnValue->setAttribute('xml:lang', \common_session_SessionManager::getSession()->getDataLanguage()); } } catch (FileNotFoundException $e) { // fail silently, since file might not have been created yet // $returnValue is then NULL. common_Logger::d('item(' . $item->getUri() . ') is empty, newly created?'); } return $returnValue; }
/** * Test that xincludes are correctly loaded into pci elements */ public function testLoadxincludeInPci() { $file = dirname(__FILE__) . '/samples/xml/qtiv2p1/xinclude/pci_include.xml'; $href1 = 'stimulus.xml'; $file1 = dirname(__FILE__) . '/samples/xml/qtiv2p1/xinclude/stimulus.xml'; $mediaSource1 = $this->prophesize('oat\\taoMediaManager\\model\\MediaSource'); $mediaSource1->download($href1)->willReturn($file1); $asset1 = $this->prophesize('oat\\tao\\model\\media\\MediaAsset'); $asset1->getMediaSource()->willReturn($mediaSource1->reveal()); $asset1->getMediaIdentifier()->willReturn($href1); $asset1Revealed = $asset1->reveal(); $resolver = $this->prophesize('oat\\taoItems\\model\\media\\ItemMediaResolver'); $resolver->resolve($href1)->willReturn($asset1Revealed); $this->assertEquals($file1, $asset1Revealed->getMediaSource()->download($asset1Revealed->getMediaIdentifier())); //load item model $qtiParser = new Parser($file); $item = $qtiParser->load(); $this->assertTrue($item instanceof Item); //find the unique pci in the sample $pci = null; foreach ($item->getComposingElements() as $element) { if ($element instanceof PortableCustomInteraction) { $pci = $element; break; } } $this->assertNotNull($pci); //check inital markup $markupXml = simplexml_load_string($pci->getMarkup()); $this->assertEquals(1, count($markupXml->xpath(".//*[name(.)='include']")), 'the pci markup has an include element'); $this->assertEquals(0, count($markupXml->xpath(".//*[name(.)='img']"))); $this->assertEquals(0, count($markupXml->xpath(".//*[name(.)='m:math']"))); //load xinclude $xincludeLoader = new XIncludeLoader($item, $resolver->reveal()); $xincludes = $xincludeLoader->load(); //check markup after loading $markupXml = simplexml_load_string($pci->getMarkup()); $this->assertEquals(1, count($xincludes)); $this->assertEquals(0, count($markupXml->xpath(".//*[name(.)='include']")), 'the include element has been replaced'); $this->assertEquals(1, count($markupXml->xpath(".//*[name(.)='img']"))); $this->assertEquals(1, count($markupXml->xpath(".//*[name(.)='m:math']"))); }
/** * @param core_kernel_classes_Resource $item * @param string $lang * @param Directory $publicDirectory * @return qti\Item * @throws taoItems_models_classes_CompilationFailedException */ protected function retrieveAssets(core_kernel_classes_Resource $item, $lang, Directory $publicDirectory) { $qtiItem = Service::singleton()->getDataItemByRdfItem($item, $lang); $assetParser = new AssetParser($qtiItem, $publicDirectory); $assetParser->setGetSharedLibraries(false); $assetParser->setGetXinclude(false); $resolver = new ItemMediaResolver($item, $lang); $replacementList = array(); foreach ($assetParser->extract() as $type => $assets) { foreach ($assets as $assetUrl) { foreach (self::$BLACKLIST as $blacklist) { if (preg_match($blacklist, $assetUrl) === 1) { continue 2; } } $mediaAsset = $resolver->resolve($assetUrl); $mediaSource = $mediaAsset->getMediaSource(); $basename = $mediaSource->getBaseName($mediaAsset->getMediaIdentifier()); $replacement = $basename; $count = 0; while (in_array($replacement, $replacementList)) { $dot = strrpos($basename, '.'); $replacement = $dot !== false ? substr($basename, 0, $dot) . '_' . $count . substr($basename, $dot) : $basename . $count; $count++; } $replacementList[$assetUrl] = $replacement; $tmpfile = $mediaSource->download($mediaAsset->getMediaIdentifier()); $fh = fopen($tmpfile, 'r'); $publicDirectory->writeStream($lang . '/' . $replacement, $fh); fclose($fh); unlink($tmpfile); //$fileStream = $mediaSource->getFileStream($mediaAsset->getMediaIdentifier()); //$publicDirectory->writeStream($lang.'/'.$replacement, $fileStream); } } $dom = new \DOMDocument('1.0', 'UTF-8'); if ($dom->loadXML($qtiItem->toXml()) === true) { $xpath = new \DOMXPath($dom); $attributeNodes = $xpath->query('//@*'); foreach ($attributeNodes as $node) { if (isset($replacementList[$node->value])) { $node->value = $replacementList[$node->value]; } } $attributeNodes = $xpath->query("//*[local-name()='entry']") ?: []; unset($xpath); foreach ($attributeNodes as $node) { $node->nodeValue = strtr(htmlentities($node->nodeValue, ENT_XML1), $replacementList); } } else { throw new taoItems_models_classes_CompilationFailedException('Unable to load XML'); } $qtiParser = new Parser($dom->saveXML()); $assetRetrievedQtiItem = $qtiParser->load(); //loadxinclude $xincludeLoader = new XIncludeLoader($assetRetrievedQtiItem, $resolver); $xincludeLoader->load(true); return $assetRetrievedQtiItem; }
/** * * @param core_kernel_classes_Resource $item * @param string $lang * @param string $destination * @return \oat\taoQtiItem\model\qti\Item */ protected function retrieveAssets(core_kernel_classes_Resource $item, $lang, $destination) { $xml = taoItems_models_classes_ItemsService::singleton()->getItemContent($item); $qtiParser = new Parser($xml); $qtiItem = $qtiParser->load(); $assetParser = new AssetParser($qtiItem); $assetParser->setGetSharedLibraries(false); $assetParser->setGetXinclude(false); $resolver = new ItemMediaResolver($item, $lang); foreach ($assetParser->extract() as $type => $assets) { foreach ($assets as $assetUrl) { foreach (self::$BLACKLIST as $blacklist) { if (preg_match($blacklist, $assetUrl) === 1) { continue 2; } } $mediaAsset = $resolver->resolve($assetUrl); $mediaSource = $mediaAsset->getMediaSource(); $srcPath = $mediaSource->download($mediaAsset->getMediaIdentifier()); $filename = \tao_helpers_File::getSafeFileName(ltrim($mediaAsset->getMediaIdentifier(), '/'), $destination); $replacement = $mediaAsset->getMediaIdentifier(); if (get_class($mediaSource) !== 'oat\\tao\\model\\media\\sourceStrategy\\HttpSource') { $fileInfo = $mediaSource->getFileInfo($mediaAsset->getMediaIdentifier()); $filename = $fileInfo['filePath']; if ($mediaAsset->getMediaIdentifier() !== $fileInfo['uri']) { $replacement = $filename; } } $destPath = ltrim($filename, '/'); tao_helpers_File::copy($srcPath, $destination . $destPath, false); $xml = str_replace($assetUrl, $replacement, $xml); } } $qtiParser = new Parser($xml); $assetRetrievedQtiItem = $qtiParser->load(); //loadxinclude $xincludeLoader = new XIncludeLoader($assetRetrievedQtiItem, $resolver); $xincludeLoader->load(true); return $assetRetrievedQtiItem; }
/** * @param core_kernel_classes_Resource $item the item to pack * @param string $lang * @param Item $qtiItem * @param \oat\oatbox\filesystem\Directory $directory * @return ItemPack $itemPack * @throws common_Exception */ public function packQtiItem($item, $lang, $qtiItem, Directory $directory) { //use the QtiParser to transform the QTI XML into an assoc array representation try { //build the ItemPack from the parsed data if ($this->replaceXinclude) { $resolver = new ItemMediaResolver($item, $lang); $xincludeLoader = new XIncludeLoader($qtiItem, $resolver); $xincludeLoader->load(true); } $itemPack = new ItemPack(self::$itemType, $qtiItem->toArray()); $itemPack->setAssetEncoders($this->getAssetEncoders()); $assetParser = new AssetParser($qtiItem, $directory); $assetParser->setDeepParsing($this->isNestedResourcesInclusion()); $assetParser->setGetXinclude(!$this->replaceXinclude); $storageDirectory = new \tao_models_classes_service_StorageDirectory($item->getUri(), $directory->getFileSystemId(), $directory->getPrefix() . '/' . $lang); $storageDirectory->setServiceLocator($directory->getServiceLocator()); foreach ($assetParser->extract($itemPack) as $type => $assets) { $resolver = new ItemMediaResolver($item, $lang); foreach ($assets as &$asset) { $mediaAsset = $resolver->resolve($asset); $mediaSource = $mediaAsset->getMediaSource(); $asset = $mediaSource->getBaseName($mediaAsset->getMediaIdentifier()); } $itemPack->setAssets($type, $assets, $storageDirectory); } } catch (common_Exception $e) { throw new common_Exception('Unable to pack item ' . $item->getUri() . ' : ' . $e->getMessage()); } return $itemPack; }