/**
  * @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;
 }
 /**
  * Import dependencies files
  *
  * @param QtiResource $qtiItemResource
  * @param $dependencies
  * @return $this
  * @throws AssetManagerException
  */
 public function importDependencyFiles(QtiResource $qtiItemResource, $dependencies)
 {
     $qtiFile = $this->getSource() . \helpers_File::urlToPath($qtiItemResource->getFile());
     foreach ($qtiItemResource->getDependencies() as $dependenciesFile) {
         if (!isset($dependencies[$dependenciesFile])) {
             continue;
         }
         $absolutePath = $this->getAbsolutePath($dependencies[$dependenciesFile]->getFile());
         $relativePath = $this->getRelativePath($qtiFile, $absolutePath);
         try {
             $this->importAsset($absolutePath, $relativePath);
         } catch (\common_Exception $e) {
             throw new AssetManagerException('Error occurs during dependency assets handling for item: ' . $qtiItemResource->getIdentifier() . ', assetFile: ' . $relativePath, 0, $e);
         }
     }
     return $this;
 }