예제 #1
0
 /**
  * Get the content of an asset.
  * Only LOCAL assets are yet supported.
  *
  * @param string $assetPath the asset path
  * @return null|string the asset content or null if not stored locally
  * @throws common_Exception if the resource cannot be retrieved
  */
 public function getAssetContent($assetPath)
 {
     $resolver = new ItemMediaResolver($this->item, $this->lang);
     $mediaAsset = $resolver->resolve($assetPath);
     $mediaSource = $mediaAsset->getMediaSource();
     $srcPath = $mediaSource->download($mediaAsset->getMediaIdentifier());
     return file_get_contents($srcPath);
 }
 /**
  * Overriden export from QTI items.
  *
  * @param array $options An array of options.
  * @see taoItems_models_classes_ItemExporter::export()
  */
 public function export($options = array())
 {
     $asApip = isset($options['apip']) && $options['apip'] === true;
     $lang = \common_session_SessionManager::getSession()->getDataLanguage();
     $basePath = $this->buildBasePath();
     $dataFile = (string) $this->getItemModel()->getOnePropertyValue(new core_kernel_classes_Property(TAO_ITEM_MODEL_DATAFILE_PROPERTY));
     $content = $this->getItemService()->getItemContent($this->getItem());
     $resolver = new ItemMediaResolver($this->getItem(), $lang);
     // get the local resources and add them
     foreach ($this->getAssets($this->getItem(), $lang) as $assetUrl) {
         $mediaAsset = $resolver->resolve($assetUrl);
         $mediaSource = $mediaAsset->getMediaSource();
         if (get_class($mediaSource) !== 'oat\\tao\\model\\media\\sourceStrategy\\HttpSource') {
             $srcPath = $mediaSource->download($mediaAsset->getMediaIdentifier());
             $fileInfo = $mediaSource->getFileInfo($mediaAsset->getMediaIdentifier());
             $filename = $fileInfo['filePath'];
             $replacement = $mediaAsset->getMediaIdentifier();
             if ($mediaAsset->getMediaIdentifier() !== $fileInfo['uri']) {
                 $replacement = $filename;
             }
             $destPath = ltrim($filename, '/');
             if (file_exists($srcPath)) {
                 $this->addFile($srcPath, $basePath . '/' . $destPath);
                 $content = str_replace($assetUrl, $replacement, $content);
             } else {
                 throw new \Exception('Missing resource ' . $srcPath);
             }
         }
     }
     if ($asApip === true) {
         // 1. let's merge qti.xml and apip.xml.
         // 2. retrieve apip related assets.
         $apipService = ApipService::singleton();
         $apipContentDoc = $apipService->getApipAccessibilityContent($this->getItem());
         if ($apipContentDoc === null) {
             \common_Logger::i("No APIP accessibility content found for item '" . $this->getItem()->getUri() . "', default inserted.");
             $apipContentDoc = $apipService->getDefaultApipAccessibilityContent($this->getItem());
         }
         $qtiItemDoc = new DOMDocument('1.0', 'UTF-8');
         $qtiItemDoc->formatOutput = true;
         $qtiItemDoc->loadXML($content);
         // Let's merge QTI and APIP Accessibility!
         Apip::mergeApipAccessibility($qtiItemDoc, $apipContentDoc);
         $content = $qtiItemDoc->saveXML();
         $fileHrefElts = $qtiItemDoc->getElementsByTagName('fileHref');
         for ($i = 0; $i < $fileHrefElts->length; $i++) {
             $fileHrefElt = $fileHrefElts->item($i);
             $destPath = $basePath . '/' . $fileHrefElt->nodeValue;
             $sourcePath = $this->getItemLocation() . $fileHrefElt->nodeValue;
             $this->addFile($sourcePath, $destPath);
         }
     }
     // add xml file
     $this->getZip()->addFromString($basePath . '/' . $dataFile, $content);
 }
 /**
  * Handle the process to manage shared stimulus files
  *
  * @param $absolutePath
  * @param $relativePath
  * @return array
  * @throws \qtism\data\storage\xml\XmlStorageException
  */
 public function handle($absolutePath, $relativePath)
 {
     $sharedFiles = $this->getSharedFiles();
     $md5 = md5_file($absolutePath);
     if (isset($sharedFiles[$md5])) {
         \common_Logger::i('Auxiliary file \'' . $absolutePath . '\' linked to shared storage.');
         return $sharedFiles[$md5];
     }
     SharedStimulusImporter::isValidSharedStimulus($absolutePath);
     $newXmlFile = SharedStimulusPackageImporter::embedAssets($absolutePath);
     $itemContent = $this->sharedStorage->add($newXmlFile, basename($relativePath), $this->parentPath);
     if (method_exists($this->sharedStorage, 'forceMimeType')) {
         $asset = $this->itemSource->resolve($itemContent['uri']);
         $this->sharedStorage->forceMimeType($asset->getMediaIdentifier(), 'application/qti+xml');
     }
     $this->addSharedFile($md5, $itemContent);
     \common_Logger::i('Auxiliary file \'' . $absolutePath . '\' added to shared storage.');
     return $itemContent;
 }
 /**
  * @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;
 }
 /**
  * Get the media source based on the partial url
  * 
  * @param string $urlPrefix
  * @param core_kernel_classes_resource $item
  * @param string $itemLang
  * @return \oat\tao\model\media\MediaBrowser
  */
 protected function getMediaSource($urlPrefix, $item, $itemLang)
 {
     $resolver = new ItemMediaResolver($item, $itemLang);
     $asset = $resolver->resolve($urlPrefix);
     return $asset->getMediaSource();
 }
예제 #6
0
 private function renderFile($item, $path, $lang)
 {
     if (tao_helpers_File::securityCheck($path, true)) {
         $resolver = new ItemMediaResolver($item, $lang);
         $asset = $resolver->resolve($path);
         $filePath = $asset->getMediaSource()->download($asset->getMediaIdentifier());
         \tao_helpers_Http::returnFile($filePath);
     } else {
         throw new common_exception_Error('invalid item preview file path');
     }
 }
 /**
  * @param $folder
  * @param \taoQtiTest_models_classes_QtiResource $qtiItemResource
  * @param $itemClass
  * @param bool|false $extractApip
  * @param array $dependencies
  * @return common_report_Report
  * @throws common_exception_Error
  */
 public function importQtiItem($folder, Resource $qtiItemResource, $itemClass, $extractApip = false, $dependencies = array())
 {
     try {
         //load the information about resources in the manifest
         $itemService = taoItems_models_classes_ItemsService::singleton();
         $qtiService = Service::singleton();
         // The metadata import feature needs a DOM representation of the manifest.
         $domManifest = new DOMDocument('1.0', 'UTF-8');
         $domManifest->load($folder . 'imsmanifest.xml');
         $metadataMapping = $qtiService->getMetadataRegistry()->getMapping();
         $metadataInjectors = array();
         $metadataGuardians = array();
         $metadataClassLookups = array();
         $metadataValues = array();
         foreach ($metadataMapping['injectors'] as $injector) {
             $metadataInjectors[] = new $injector();
         }
         foreach ($metadataMapping['guardians'] as $guardian) {
             $metadataGuardians[] = new $guardian();
         }
         foreach ($metadataMapping['classLookups'] as $classLookup) {
             $metadataClassLookups[] = new $classLookup();
         }
         foreach ($metadataMapping['extractors'] as $extractor) {
             $metadataExtractor = new $extractor();
             $metadataValues = array_merge($metadataValues, $metadataExtractor->extract($domManifest));
         }
         $sources = MediaService::singleton()->getWritableSources();
         $sharedStorage = array_shift($sources);
         $sharedFiles = array();
         try {
             $resourceIdentifier = $qtiItemResource->getIdentifier();
             // Use the guardians to check whether or not the item has to be imported.
             foreach ($metadataGuardians as $guardian) {
                 if (isset($metadataValues[$resourceIdentifier]) === true) {
                     if (($guard = $guardian->guard($metadataValues[$resourceIdentifier])) !== false) {
                         $msg = __('The IMS QTI Item referenced as "%s" in the IMS Manifest file was already stored in the Item Bank.', $qtiItemResource->getIdentifier());
                         $report = common_report_Report::createInfo($msg, $guard);
                         // Simply do not import again.
                         return $report;
                     }
                 }
             }
             $targetClass = false;
             // Use the classLookups to determine where the item has to go.
             foreach ($metadataClassLookups as $classLookup) {
                 if (isset($metadataValues[$resourceIdentifier]) === true) {
                     if (($targetClass = $classLookup->lookup($metadataValues[$resourceIdentifier])) !== false) {
                         break;
                     }
                 }
             }
             $qtiFile = $folder . $qtiItemResource->getFile();
             $qtiModel = $this->createQtiItemModel($qtiFile);
             $rdfItem = $this->createRdfItem($targetClass !== false ? $targetClass : $itemClass, $qtiModel);
             $name = $rdfItem->getLabel();
             $itemContent = $itemService->getItemContent($rdfItem);
             $xincluded = array();
             foreach ($qtiModel->getBody()->getComposingElements('oat\\taoQtiItem\\model\\qti\\Xinclude') as $xincludeEle) {
                 $xincluded[] = $xincludeEle->attr('href');
             }
             $local = new LocalItemSource(array('item' => $rdfItem));
             foreach ($qtiItemResource->getAuxiliaryFiles() as $auxResource) {
                 // file on FS
                 $auxFile = $folder . str_replace('/', DIRECTORY_SEPARATOR, $auxResource);
                 // rel path in item
                 $auxPath = str_replace(DIRECTORY_SEPARATOR, '/', helpers_File::getRelPath($qtiFile, $auxFile));
                 if (!empty($sharedStorage) && in_array($auxPath, $xincluded)) {
                     $md5 = md5_file($auxFile);
                     if (isset($sharedFiles[$md5])) {
                         $info = $sharedFiles[$md5];
                         \common_Logger::i('Auxiliary file \'' . $auxPath . '\' linked to shared storage.');
                     } else {
                         // TODO cleanup sharedstimulus import/export
                         // move to taoQti item or library
                         // validate the shared stimulus
                         SharedStimulusImporter::isValidSharedStimulus($auxFile);
                         // embed assets in the shared stimulus
                         $newXmlFile = SharedStimulusPackageImporter::embedAssets($auxFile);
                         $info = $sharedStorage->add($newXmlFile, basename($auxFile), $name);
                         if (method_exists($sharedStorage, 'forceMimeType')) {
                             // add() does not return link, so we need to parse it
                             $resolver = new ItemMediaResolver($rdfItem, '');
                             $asset = $resolver->resolve($info['uri']);
                             $sharedStorage->forceMimeType($asset->getMediaIdentifier(), 'application/qti+xml');
                         }
                         $sharedFiles[$md5] = $info;
                         \common_Logger::i('Auxiliary file \'' . $auxPath . '\' added to shared storage.');
                     }
                 } else {
                     // store locally, in a safe directory
                     $safePath = '';
                     if (dirname($auxPath) !== '.') {
                         $safePath = str_replace('../', '', dirname($auxPath)) . '/';
                     }
                     $info = $local->add($auxFile, basename($auxFile), $safePath);
                     \common_Logger::i('Auxiliary file \'' . $auxPath . '\' copied.');
                 }
                 // replace uri if changed
                 if ($auxPath != ltrim($info['uri'], '/')) {
                     $itemContent = str_replace($auxPath, $info['uri'], $itemContent);
                 }
             }
             foreach ($qtiItemResource->getDependencies() as $dependency) {
                 // file on FS
                 if (isset($dependencies[$dependency])) {
                     $auxFile = $dependencies[$dependency]->getFile();
                     $auxFile = $folder . str_replace('/', DIRECTORY_SEPARATOR, $auxFile);
                     // rel path in item
                     $auxPath = str_replace(DIRECTORY_SEPARATOR, '/', helpers_File::getRelPath($qtiFile, $auxFile));
                     if (!empty($sharedStorage) && in_array($auxPath, $xincluded)) {
                         $md5 = md5_file($auxFile);
                         if (isset($sharedFiles[$md5])) {
                             $info = $sharedFiles[$md5];
                             \common_Logger::i('Auxiliary file \'' . $auxPath . '\' linked to shared storage.');
                         } else {
                             // TODO cleanup sharedstimulus import/export
                             // move to taoQti item or library
                             // validate the shared stimulus
                             SharedStimulusImporter::isValidSharedStimulus($auxFile);
                             // embed assets in the shared stimulus
                             $newXmlFile = SharedStimulusPackageImporter::embedAssets($auxFile);
                             $info = $sharedStorage->add($newXmlFile, basename($auxFile), $name);
                             if (method_exists($sharedStorage, 'forceMimeType')) {
                                 // add() does not return link, so we need to parse it
                                 $resolver = new ItemMediaResolver($rdfItem, '');
                                 $asset = $resolver->resolve($info['uri']);
                                 $sharedStorage->forceMimeType($asset->getMediaIdentifier(), 'application/qti+xml');
                             }
                             $sharedFiles[$md5] = $info;
                             \common_Logger::i('Auxiliary file \'' . $auxPath . '\' added to shared storage.');
                         }
                     } else {
                         // store locally, in a safe directory
                         $safePath = '';
                         if (dirname($auxPath) !== '.') {
                             $safePath = str_replace('../', '', dirname($auxPath)) . '/';
                         }
                         $info = $local->add($auxFile, basename($auxFile), $safePath);
                         \common_Logger::i('Auxiliary file \'' . $auxPath . '\' copied.');
                     }
                     // replace uri if changed
                     if ($auxPath != ltrim($info['uri'], '/')) {
                         $itemContent = str_replace($auxPath, $info['uri'], $itemContent);
                     }
                 }
             }
             // Finally, import metadata.
             $this->importItemMetadata($metadataValues, $qtiItemResource, $rdfItem, $metadataInjectors);
             // And Apip if wanted
             if ($extractApip) {
                 $this->storeApip($qtiFile, $rdfItem);
             }
             $itemService->setItemContent($rdfItem, $itemContent);
             $msg = __('The IMS QTI Item referenced as "%s" in the IMS Manifest file was successfully imported.', $qtiItemResource->getIdentifier());
             $report = common_report_Report::createSuccess($msg, $rdfItem);
         } catch (ParsingException $e) {
             $report = new common_report_Report(common_report_Report::TYPE_ERROR, $e->getUserMessage());
         } catch (ValidationException $ve) {
             $report = \common_report_Report::createFailure(__('IMS QTI Item referenced as "%s" in the IMS Manifest file could not be imported.', $qtiItemResource->getIdentifier()));
             $report->add($ve->getReport());
         } catch (Exception $e) {
             // an error occured during a specific item
             $report = new common_report_Report(common_report_Report::TYPE_ERROR, __("An unknown error occured while importing the IMS QTI Package."));
             common_Logger::e($e->getMessage());
         }
     } catch (ValidationException $ve) {
         $validationReport = \common_report_Report::createFailure("The IMS Manifest file could not be validated");
         $validationReport->add($ve->getReport());
         $report->setMessage(__("No Items could be imported from the given IMS QTI package."));
         $report->setType(common_report_Report::TYPE_ERROR);
         $report->add($validationReport);
     } catch (common_exception_UserReadableException $e) {
         $report = new common_report_Report(common_report_Report::TYPE_ERROR, __($e->getUserMessage()));
         $report->add($e);
     }
     return $report;
 }
 private function renderResource($item, $path)
 {
     $lang = common_session_SessionManager::getSession()->getDataLanguage();
     $resolver = new ItemMediaResolver($item, $lang);
     $asset = $resolver->resolve($path);
     if ($asset->getMediaSource() instanceof HttpSource) {
         throw new common_Exception('Only tao files available for rendering through item preview');
     }
     $info = $asset->getMediaSource()->getFileInfo($asset->getMediaIdentifier());
     $stream = $asset->getMediaSource()->getFileStream($asset->getMediaIdentifier());
     \tao_helpers_Http::returnStream($stream, $info['mime']);
 }
 /**
  * 
  * @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;
 }
예제 #10
0
 /**
  * @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;
 }
 /**
  * Overriden export from QTI items.
  *
  * @see taoItems_models_classes_ItemExporter::export()
  * @param array $options An array of options.
  * @return \common_report_Report
  * @throws ExportException
  * @throws \common_Exception
  * @throws \common_exception_Error
  * @throws \core_kernel_persistence_Exception
  * @throws PortableElementInvalidAssetException
  */
 public function export($options = array())
 {
     $report = \common_report_Report::createSuccess();
     $asApip = isset($options['apip']) && $options['apip'] === true;
     $lang = \common_session_SessionManager::getSession()->getDataLanguage();
     $basePath = $this->buildBasePath();
     if (is_null($this->getItemModel())) {
         throw new ExportException('', 'No Item Model found for item : ' . $this->getItem()->getUri());
     }
     $dataFile = (string) $this->getItemModel()->getOnePropertyValue(new core_kernel_classes_Property(TAO_ITEM_MODEL_DATAFILE_PROPERTY));
     $resolver = new ItemMediaResolver($this->getItem(), $lang);
     $replacementList = array();
     $modelsAssets = $this->getPortableElementAssets($this->getItem(), $lang);
     $service = new PortableElementService();
     $service->setServiceLocator(ServiceManager::getServiceManager());
     $portableElementsToExport = $portableAssetsToExport = [];
     foreach ($modelsAssets as $key => $portableElements) {
         /** @var  $element */
         foreach ($portableElements as $element) {
             if (!$element instanceof Element) {
                 continue;
             }
             try {
                 $object = $service->retrieve($key, $element->getTypeIdentifier());
             } catch (PortableElementException $e) {
                 $message = __('Fail to export item') . ' (' . $this->getItem()->getLabel() . '): ' . $e->getMessage();
                 return \common_report_Report::createFailure($message);
             }
             $portableElementsToExport[$element->getTypeIdentifier()] = $object;
             $files = $object->getModel()->getValidator()->getAssets($object, 'runtime');
             $baseUrl = $basePath . DIRECTORY_SEPARATOR . $object->getTypeIdentifier();
             $portableAssetsToExport[$object->getTypeIdentifier()] = [];
             foreach ($files as $url) {
                 try {
                     // Skip shared libraries into portable element
                     if (strpos($url, './') !== 0) {
                         \common_Logger::i('Shared libraries skipped : ' . $url);
                         $portableAssetsToExport[$object->getTypeIdentifier()][$url] = $url;
                         continue;
                     }
                     $stream = $service->getFileStream($object, $url);
                     $replacement = $this->copyAssetFile($stream, $baseUrl, $url, $replacementList);
                     $portableAssetToExport = preg_replace('/^(.\\/)(.*)/', $object->getTypeIdentifier() . "/\$2", $replacement);
                     $portableAssetsToExport[$object->getTypeIdentifier()][$url] = $portableAssetToExport;
                     \common_Logger::i('File copied: "' . $url . '" for portable element ' . $object->getTypeIdentifier());
                 } catch (\tao_models_classes_FileNotFoundException $e) {
                     \common_Logger::i($e->getMessage());
                     $report->setMessage('Missing resource for ' . $url);
                     $report->setType(\common_report_Report::TYPE_ERROR);
                 }
             }
         }
     }
     $assets = $this->getAssets($this->getItem(), $lang);
     foreach ($assets as $assetUrl) {
         try {
             $mediaAsset = $resolver->resolve($assetUrl);
             $mediaSource = $mediaAsset->getMediaSource();
             if (!$mediaSource instanceof HttpSource) {
                 $link = $mediaAsset->getMediaIdentifier();
                 $stream = $mediaSource->getFileStream($link);
                 $baseName = $mediaSource instanceof LocalItemSource ? $link : 'assets/' . $mediaSource->getBaseName($link);
                 $replacement = $this->copyAssetFile($stream, $basePath, $baseName, $replacementList);
                 $replacementList[$assetUrl] = $replacement;
             }
         } catch (\tao_models_classes_FileNotFoundException $e) {
             $replacementList[$assetUrl] = '';
             $report->setMessage('Missing resource for ' . $assetUrl);
             $report->setType(\common_report_Report::TYPE_ERROR);
         }
     }
     $xml = Service::singleton()->getXmlByRdfItem($this->getItem());
     $dom = new DOMDocument('1.0', 'UTF-8');
     $dom->preserveWhiteSpace = false;
     $dom->formatOutput = true;
     if ($dom->loadXML($xml) === true) {
         $xpath = new \DOMXPath($dom);
         $attributeNodes = $xpath->query('//@*');
         $portableEntryNodes = $xpath->query("//*[local-name()='entry']") ?: [];
         unset($xpath);
         foreach ($attributeNodes as $node) {
             if (isset($replacementList[$node->value])) {
                 $node->value = $replacementList[$node->value];
             }
         }
         foreach ($portableEntryNodes as $node) {
             $node->nodeValue = strtr(htmlentities($node->nodeValue, ENT_XML1), $replacementList);
         }
         $this->exportPortableAssets($dom, 'portableCustomInteraction', 'customInteractionTypeIdentifier', 'pci', $portableElementsToExport, $portableAssetsToExport);
         $this->exportPortableAssets($dom, 'portableInfoControl', 'infoControlTypeIdentifier', 'pic', $portableElementsToExport, $portableAssetsToExport);
     } else {
         throw new ExportException($this->getItem()->getLabel(), 'Unable to load XML');
     }
     $dom->preserveWhiteSpace = true;
     $dom->formatOutput = true;
     if (($content = $dom->saveXML()) === false) {
         throw new ExportException($this->getItem()->getLabel(), 'Unable to save XML');
     }
     // Possibility to delegate (if necessary) some item content post-processing to sub-classes.
     $content = $this->itemContentPostProcessing($content);
     // add xml file
     $this->getZip()->addFromString($basePath . '/' . $dataFile, $content);
     if (!$report->getMessage()) {
         $report->setMessage(__('Item ' . $this->getItem()->getLabel() . ' exported.'));
     }
     return $report;
 }
 private function renderResource($item, $path)
 {
     $lang = common_session_SessionManager::getSession()->getDataLanguage();
     $resolver = new ItemMediaResolver($item, $lang);
     $asset = $resolver->resolve($path);
     $filePath = $asset->getMediaSource()->download($asset->getMediaIdentifier());
     \tao_helpers_Http::returnFile($filePath);
 }