/**
  * Compile an item.
  * 
  * @param core_kernel_file_File $destinationDirectory
  * @throws taoItems_models_classes_CompilationFailedException
  * @return tao_models_classes_service_ServiceCall
  */
 public function compile()
 {
     $destinationDirectory = $this->spawnPublicDirectory();
     $item = $this->getResource();
     $itemUri = $item->getUri();
     $report = new common_report_Report(common_report_Report::TYPE_SUCCESS, __('Published %s', $item->getLabel()));
     if (!taoItems_models_classes_ItemsService::singleton()->isItemModelDefined($item)) {
         return $this->fail(__('Item \'%s\' has no model', $item->getLabel()));
     }
     $langs = $this->getContentUsedLanguages();
     foreach ($langs as $compilationLanguage) {
         $compiledFolder = $this->getLanguageCompilationPath($destinationDirectory, $compilationLanguage);
         if (!is_dir($compiledFolder)) {
             if (!@mkdir($compiledFolder)) {
                 common_Logger::e('Could not create directory ' . $compiledFolder, 'COMPILER');
                 return $this->fail(__('Could not create language specific directory for item \'%s\'', $item->getLabel()));
             }
         }
         $langReport = $this->deployItem($item, $compilationLanguage, $compiledFolder);
         $report->add($langReport);
         if ($langReport->getType() == common_report_Report::TYPE_ERROR) {
             $report->setType(common_report_Report::TYPE_ERROR);
             break;
         }
     }
     if ($report->getType() == common_report_Report::TYPE_SUCCESS) {
         $report->setData($this->createService($item, $destinationDirectory));
     } else {
         $report->setMessage(__('Failed to publish %s', $item->getLabel()));
     }
     return $report;
 }
 public function testCompile()
 {
     //test with items
     $config = array('previous' => true);
     $items = array($this->item->getUri());
     $this->testModel->save($this->test, array('itemUris' => $items, 'config' => $config));
     $waitingReport = new \common_report_Report(\common_report_Report::TYPE_SUCCESS);
     $serviceCall = $this->getMockBuilder('tao_models_classes_service_ServiceCall')->disableOriginalConstructor()->setMethods(array('serializeToString'))->getMock();
     $serviceCall->expects($this->once())->method('serializeToString')->willReturn('greatString');
     $waitingReport->setData($serviceCall);
     $testCompiler = $this->getMockBuilder('oat\\taoTestLinear\\model\\TestCompiler')->setConstructorArgs(array($this->test, $this->storage))->setMethods(array('subCompile', 'spawnPrivateDirectory'))->getMock();
     $testCompiler->expects($this->once())->method('subCompile')->willReturn($waitingReport);
     //will spawn a new directory and store the content file
     $directoryMock = $this->getMockBuilder('tao_models_classes_service_StorageDirectory')->disableOriginalConstructor()->setMethods(array('getPath'))->getMock();
     if (!file_exists(sys_get_temp_dir() . '/sample/compile/')) {
         mkdir(sys_get_temp_dir() . '/sample/compile/', 0777, true);
     }
     $directoryMock->expects($this->once())->method('getPath')->willReturn(sys_get_temp_dir() . '/sample/compile/');
     $testCompiler->expects($this->once())->method('spawnPrivateDirectory')->willReturn($directoryMock);
     $report = $testCompiler->compile();
     $this->assertEquals(__('Test Compilation'), $report->getMessage(), __('Compilation should work'));
     $this->assertFileExists(sys_get_temp_dir() . '/sample/compile/data.json', __('Compilation file not created'));
     $compile = '{"items":{"http:\\/\\/myFancyDomain.com\\/myGreatResourceUriForItem":"greatString"},"previous":true}';
     $this->assertEquals($compile, file_get_contents(sys_get_temp_dir() . '/sample/compile/data.json', __('File content error')));
 }
 /**
  * (non-PHPdoc)
  * @see tao_models_classes_Compiler::compile()
  */
 public function compile()
 {
     $report = new common_report_Report(common_report_Report::TYPE_SUCCESS, __('Published test "%s"', $this->getResource()->getLabel()));
     common_ext_ExtensionsManager::singleton()->getExtensionById('taoWfTest');
     // loads the extension
     $test = $this->getResource();
     common_Logger::i('Compiling test ' . $test->getLabel() . ' items');
     $process = $test->getUniquePropertyValue(new core_kernel_classes_Property(TEST_TESTCONTENT_PROP));
     if (count(wfEngine_models_classes_ProcessDefinitionService::singleton()->getAllActivities($process)) == 0) {
         return new common_report_Report(common_report_Report::TYPE_ERROR, __('An empty test cannot be published.'));
     }
     $processCloner = new wfAuthoring_models_classes_ProcessCloner();
     try {
         $processClone = $processCloner->cloneProcess($process);
         $report->add(new common_report_Report(common_report_Report::TYPE_SUCCESS, __('Cloned the process %s', $process->getLabel())));
         $itemsServiceReport = $this->process($processClone);
         foreach ($itemsServiceReport as $subReport) {
             $report->add($subReport);
         }
         if ($itemsServiceReport->getType() == common_report_Report::TYPE_SUCCESS) {
             $serviceCall = new tao_models_classes_service_ServiceCall(new core_kernel_classes_Resource(INSTANCE_SERVICE_PROCESSRUNNER));
             $param = new tao_models_classes_service_ConstantParameter(new core_kernel_classes_Resource(INSTANCE_FORMALPARAM_PROCESSDEFINITION), $processClone->getUri());
             $serviceCall->addInParameter($param);
             $report->setData($serviceCall);
         } else {
             $report->setType(common_report_Report::TYPE_ERROR);
         }
     } catch (common_Exception $e) {
         $report->add(new common_report_Report(common_report_Report::TYPE_ERROR, __('Failed to clone the process')));
         $report->setType(common_report_Report::TYPE_ERROR);
     }
     if ($report->getType() != common_report_Report::TYPE_SUCCESS) {
         $report->setMessage(__('Failed to publish test "%s".', $this->getResource()->getLabel()));
     }
     return $report;
 }
 /**
  * Compile a QTI Test and the related QTI Items.
  * 
  * The compilation process occurs as follows:
  * 
  * * 1. The resources composing the test are copied into the private compilation directory.
  * * 2. The test definition is packed (test and items put together in a single definition).
  * * 3. The items composing the test are compiled.
  * * 4. The rubric blocks are rendered into PHP templates.
  * * 5. The test definition is compiled into PHP source code for maximum performance.
  * * 6. The resources composing the test that have to be accessed at delivery time are compied into the public compilation directory.
  * * 7. The Service Call definition enabling TAO to run the compiled test is built.
  * 
  * @param core_kernel_file_File $destinationDirectory The directory where the compiled files must be put.
  * @return tao_models_classes_service_ServiceCall A ServiceCall object that represent the way to call the newly compiled test.
  * @throws taoQtiTest_models_classes_QtiTestCompilationFailedException If an error occurs during the compilation.
  */
 public function compile()
 {
     $report = new common_report_Report(common_report_Report::TYPE_INFO);
     try {
         // 0. Initialize compilation (compilation directories, renderers, ...).
         $this->initCompilation();
         // 1. Copy the resources composing the test into the private complilation directory.
         $this->copyPrivateResources();
         // 2. Compact the test definition itself.
         $compiledDoc = $this->compactTest();
         // 3. Compile the items of the test.
         $itemReport = $this->compileItems($compiledDoc);
         $report->add($itemReport);
         if ($itemReport->getType() != common_report_Report::TYPE_SUCCESS) {
             $msg = 'Failed item compilation.';
             $code = taoQtiTest_models_classes_QtiTestCompilationFailedException::ITEM_COMPILATION;
             throw new taoQtiTest_models_classes_QtiTestCompilationFailedException($msg, $this->getResource(), $code);
         }
         // 4. Explode the rubric blocks in the test into rubric block refs.
         $this->explodeRubricBlocks($compiledDoc);
         // 5. Update test definition with additional runtime info.
         $assessmentTest = $compiledDoc->getDocumentComponent();
         $this->updateTestDefinition($assessmentTest);
         // 6. Compile rubricBlocks and serialize on disk.
         $this->compileRubricBlocks($assessmentTest);
         // 7. Copy the needed files into the public directory.
         $this->copyPublicResources();
         // 8. Compile the test definition into PHP source code and put it
         // into the private directory.
         $this->compileTest($assessmentTest);
         // 9. Compile the test meta data into PHP array source code and put it
         // into the private directory.
         $this->compileMeta($assessmentTest);
         // 10. Build the service call.
         $serviceCall = $this->buildServiceCall();
         common_Logger::t("QTI Test successfully compiled.");
         $report->setType(common_report_Report::TYPE_SUCCESS);
         $report->setMessage(__('QTI Test "%s" successfully published.', $this->getResource()->getLabel()));
         $report->setData($serviceCall);
     } catch (XmlStorageException $e) {
         $details[] = $e->getMessage();
         while (($previous = $e->getPrevious()) != null) {
             $details[] = $previous->getMessage();
             $e = $e->getPrevious();
         }
         common_Logger::e(implode("\n", $details));
         $subReport = new common_report_Report(common_report_Report::TYPE_ERROR, __('The QTI Test XML or one of its dependencies is malformed or empty.'));
         $report->add($subReport);
         $report->setType(common_report_Report::TYPE_ERROR);
         $report->setMessage(__('QTI Test "%s" publishing failed.', $this->getResource()->getLabel()));
     } catch (Exception $e) {
         common_Logger::e($e->getMessage());
         // All exception that were not catched in the compilation steps
         // above have a last chance here.
         $report->setType(common_report_Report::TYPE_ERROR);
         $report->setMessage(__('QTI Test "%s" publishing failed.', $this->getResource()->getLabel()));
     }
     // Reset time outs to initial value.
     helpers_TimeOutHelper::reset();
     return $report;
 }
 /**
  * Import a QTI Test and its dependent Items into the TAO Platform.
  *
  * @param core_kernel_classes_Class $targetClass The RDFS Class where Ontology resources must be created.
  * @param oat\taoQtiItem\model\qti\Resource $qtiTestResource The QTI Test Resource representing the IMS QTI Test to be imported.
  * @param taoQtiTest_models_classes_ManifestParser $manifestParser The parser used to retrieve the IMS Manifest.
  * @param string $folder The absolute path to the folder where the IMS archive containing the test content
  * @return common_report_Report A report about how the importation behaved.
  */
 protected function importTest(core_kernel_classes_Class $targetClass, Resource $qtiTestResource, taoQtiTest_models_classes_ManifestParser $manifestParser, $folder)
 {
     $itemImportService = ImportService::singleton();
     $itemService = taoItems_models_classes_ItemsService::singleton();
     $testClass = $targetClass;
     // Create an RDFS resource in the knowledge base that will hold
     // the information about the imported QTI Test.
     $testResource = $this->createInstance($testClass);
     $qtiTestModelResource = new core_kernel_classes_Resource(INSTANCE_TEST_MODEL_QTI);
     $modelProperty = new core_kernel_classes_Property(PROPERTY_TEST_TESTMODEL);
     $testResource->editPropertyValues($modelProperty, $qtiTestModelResource);
     // Create the report that will hold information about the import
     // of $qtiTestResource in TAO.
     $report = new common_report_Report(common_report_Report::TYPE_INFO);
     // The class where the items that belong to the test will be imported.
     $itemClass = new core_kernel_classes_Class(TAO_ITEM_CLASS);
     $targetClass = $itemClass->createSubClass($testResource->getLabel());
     // Load and validate the manifest
     $qtiManifestParser = new taoQtiTest_models_classes_ManifestParser($folder . 'imsmanifest.xml');
     $qtiManifestParser->validate();
     // Prepare Metadata mechanisms.
     $metadataMapping = oat\taoQtiItem\model\qti\Service::singleton()->getMetadataRegistry()->getMapping();
     $metadataInjectors = array();
     $metadataGuardians = array();
     $metadataClassLookups = array();
     $metadataValues = array();
     $domManifest = new DOMDocument('1.0', 'UTF-8');
     $domManifest->load($folder . 'imsmanifest.xml');
     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));
     }
     // Set up $report with useful information for client code (especially for rollback).
     $reportCtx = new stdClass();
     $reportCtx->manifestResource = $qtiTestResource;
     $reportCtx->rdfsResource = $testResource;
     $reportCtx->itemClass = $targetClass;
     $reportCtx->items = array();
     $report->setData($reportCtx);
     // Expected test.xml file location.
     $expectedTestFile = $folder . str_replace('/', DIRECTORY_SEPARATOR, $qtiTestResource->getFile());
     // Already imported test items (qti xml file paths).
     $alreadyImportedTestItemFiles = array();
     // -- Check if the file referenced by the test QTI resource exists.
     if (is_readable($expectedTestFile) === false) {
         $report->add(common_report_Report::createFailure(__('No file found at location "%s".', $qtiTestResource->getFile())));
     } else {
         // -- Load the test in a QTISM flavour.
         $testDefinition = new XmlDocument();
         try {
             $testDefinition->load($expectedTestFile, true);
             // -- Load all items related to test.
             $itemError = false;
             // discover test's base path.
             $dependencies = taoQtiTest_helpers_Utils::buildAssessmentItemRefsTestMap($testDefinition, $manifestParser, $folder);
             if (count($dependencies['items']) > 0) {
                 foreach ($dependencies['items'] as $assessmentItemRefId => $qtiDependency) {
                     if ($qtiDependency !== false) {
                         if (Resource::isAssessmentItem($qtiDependency->getType())) {
                             $resourceIdentifier = $qtiDependency->getIdentifier();
                             // Check if the item is already stored in the bank.
                             foreach ($metadataGuardians as $guardian) {
                                 if (isset($metadataValues[$resourceIdentifier]) === true) {
                                     if (($guard = $guardian->guard($metadataValues[$resourceIdentifier])) !== false) {
                                         common_Logger::i("Item with identifier '{$resourceIdentifier}' already in Item Bank.");
                                         $msg = __('The IMS QTI Item referenced as "%s" in the IMS Manifest file was already stored in the Item Bank.', $resourceIdentifier);
                                         $report->add(common_report_Report::createInfo($msg, $guard));
                                         $reportCtx->items[$assessmentItemRefId] = $guard;
                                         // Simply do not import again.
                                         continue 2;
                                     }
                                 }
                             }
                             // Determine target class from metadata, if possible.
                             // This is applied to items, not for test definitions.
                             // The test definitions' target class will not be affected
                             // by class lookups.
                             $lookupTargetClass = false;
                             foreach ($metadataClassLookups as $classLookup) {
                                 if (isset($metadataValues[$resourceIdentifier]) === true) {
                                     if (($lookupTargetClass = $classLookup->lookup($metadataValues[$resourceIdentifier])) !== false) {
                                         break;
                                     }
                                 }
                             }
                             $qtiFile = $folder . str_replace('/', DIRECTORY_SEPARATOR, $qtiDependency->getFile());
                             // Skip if $qtiFile already imported (multiple assessmentItemRef "hrefing" the same file).
                             if (array_key_exists($qtiFile, $alreadyImportedTestItemFiles) === false) {
                                 $isApip = $qtiDependency->getType() === 'imsqti_apipitem_xmlv2p1';
                                 $itemReport = $itemImportService->importQtiItem($folder, $qtiDependency, $lookupTargetClass !== false ? $lookupTargetClass : $targetClass, $isApip, $dependencies['dependencies']);
                                 $rdfItem = $itemReport->getData();
                                 if ($rdfItem) {
                                     $reportCtx->items[$assessmentItemRefId] = $rdfItem;
                                     $alreadyImportedTestItemFiles[$qtiFile] = $rdfItem;
                                     $itemReport->setMessage(__('IMS QTI Item referenced as "%s" in the IMS Manifest file successfully imported.', $qtiDependency->getIdentifier()));
                                 } else {
                                     $itemReport->setType(common_report_Report::TYPE_ERROR);
                                     $itemReport->setMessage(__('IMS QTI Item referenced as "%s" in the IMS Manifest file could not be imported.', $qtiDependency->getIdentifier()));
                                     $itemError = $itemError === false ? true : $itemError;
                                 }
                                 $report->add($itemReport);
                             } else {
                                 $reportCtx->items[$assessmentItemRefId] = $alreadyImportedTestItemFiles[$qtiFile];
                             }
                         }
                     } else {
                         $msg = __('The dependency to the IMS QTI AssessmentItemRef "%s" in the IMS Manifest file could not be resolved.', $assessmentItemRefId);
                         $report->add(common_report_Report::createFailure($msg));
                         $itemError = $itemError === false ? true : $itemError;
                     }
                 }
                 // If items did not produce errors, we import the test definition.
                 if ($itemError === false) {
                     common_Logger::i('Importing test...');
                     // Second step is to take care of the test definition and the related media (auxiliary files).
                     // 1. Import test definition (i.e. the QTI-XML Test file).
                     $testContent = $this->importTestDefinition($testResource, $testDefinition, $qtiTestResource, $reportCtx->items, $folder, $report);
                     if ($testContent !== false) {
                         // 2. Import test auxilliary files (e.g. stylesheets, images, ...).
                         $this->importTestAuxiliaryFiles($testContent, $qtiTestResource, $folder, $report);
                         // 3. Give meaningful names to resources.
                         $testTitle = $testDefinition->getDocumentComponent()->getTitle();
                         $testResource->setLabel($testDefinition->getDocumentComponent()->getTitle());
                         $targetClass->setLabel($testDefinition->getDocumentComponent()->getTitle());
                         // 4. if $targetClass does not contain any instances (because everything resolved by class lookups),
                         // Just delete it.
                         if ($targetClass->countInstances() == 0) {
                             $targetClass->delete();
                         }
                     }
                 } else {
                     $msg = __("One or more dependent IMS QTI Items could not be imported.");
                     $report->add(common_report_Report::createFailure($msg));
                 }
             } else {
                 // No depencies found (i.e. no item resources bound to the test).
                 $msg = __("No reference to any IMS QTI Item found.");
                 $report->add(common_report_Report::createFailure($msg));
             }
         } catch (StorageException $e) {
             // Source of the exception = $testDefinition->load()
             // What is the reason ?
             $finalErrorString = '';
             $eStrs = array();
             if (($libXmlErrors = $e->getErrors()) !== null) {
                 foreach ($libXmlErrors as $libXmlError) {
                     $eStrs[] = __('XML error at line %1$d column %2$d "%3$s".', $libXmlError->line, $libXmlError->column, trim($libXmlError->message));
                 }
             }
             $finalErrorString = implode("\n", $eStrs);
             if (empty($finalErrorString) === true) {
                 // Not XML malformation related. No info from LibXmlErrors extracted.
                 if (($previous = $e->getPrevious()) != null) {
                     // Useful information could be found here.
                     $finalErrorString = $previous->getMessage();
                     if ($previous instanceof UnmarshallingException) {
                         $domElement = $previous->getDOMElement();
                         $finalErrorString = __('Inconsistency at line %1d:', $domElement->getLineNo()) . ' ' . $previous->getMessage();
                     }
                 } else {
                     $finalErrorString = __("Unknown error.");
                 }
             }
             $msg = __("Error found in the IMS QTI Test:\n%s", $finalErrorString);
             $report->add(common_report_Report::createFailure($msg));
         }
     }
     if ($report->containsError() === false) {
         $report->setType(common_report_Report::TYPE_SUCCESS);
         $msg = __("IMS QTI Test referenced as \"%s\" in the IMS Manifest file successfully imported.", $qtiTestResource->getIdentifier());
         $report->setMessage($msg);
     } else {
         $report->setType(common_report_Report::TYPE_ERROR);
         $msg = __("The IMS QTI Test referenced as \"%s\" in the IMS Manifest file could not be imported.", $qtiTestResource->getIdentifier());
         $report->setMessage($msg);
     }
     return $report;
 }
 /**
  * 
  * @param unknown $xhtml
  * @param unknown $destination
  * @return common_report_Report
  */
 public static function retrieveExternalResources($xhtml, $destination)
 {
     if (!file_exists($destination)) {
         if (!mkdir($destination)) {
             common_Logger::e('Folder ' . $destination . ' could not be created');
             return new common_report_Report(common_report_Report::TYPE_ERROR, __('Unable to create deployement directory'), $xhtml);
         }
     }
     $authorizedMedia = self::$defaultMedia;
     $mediaList = array();
     $expr = "/http[s]?:(\\\\)?\\/(\\\\)?\\/[^<'\"&?]+\\.(" . implode('|', $authorizedMedia) . ")/mi";
     //take into account json encoded url
     preg_match_all($expr, $xhtml, $mediaList, PREG_PATTERN_ORDER);
     $uniqueMediaList = array_unique($mediaList[0]);
     $report = new common_report_Report(common_report_Report::TYPE_SUCCESS, __('Retrieving external resources'));
     foreach ($uniqueMediaList as $mediaUrl) {
         // This is a file that has to be stored in the item compilation folder itself...
         // I do not get why they are all copied. They are all there they were copied from the item module...
         // But I agree that remote resources (somewhere on the Internet) should be copied via curl.
         // So if the URL does not matches a place where the TAO server is, we curl the resource and store it.
         // FileManager files should be considered as remote resources to avoid 404 issues. Indeed, a backoffice
         // user might delete an image in the filemanager during a delivery campain. This is dangerous.
         $decodedMediaUrl = str_replace('\\/', '/', $mediaUrl);
         $mediaPath = self::retrieveFile($decodedMediaUrl, $destination);
         if (!empty($mediaPath) && $mediaPath !== false) {
             $xhtml = str_replace($mediaUrl, basename($mediaPath), $xhtml, $replaced);
             //replace only when copyFile is successful
         } else {
             $report->add(new common_report_Report(common_report_Report::TYPE_ERROR, __('Failed retrieving %s', $decodedMediaUrl)));
             $report->setType(common_report_Report::TYPE_ERROR);
         }
     }
     if ($report->getType() == common_report_Report::TYPE_SUCCESS) {
         $report->setData($xhtml);
     }
     return $report;
 }
 /**
  * Import a QTI Test and its dependent Items into the TAO Platform.
  *
  * @param core_kernel_classes_Class $targetClass The RDFS Class where Ontology resources must be created.
  * @param oat\taoQtiItem\model\qti\Resource $qtiTestResource The QTI Test Resource representing the IMS QTI Test to be imported.
  * @param taoQtiTest_models_classes_ManifestParser $manifestParser The parser used to retrieve the IMS Manifest.
  * @param string $folder The absolute path to the folder where the IMS archive containing the test content
  * @return common_report_Report A report about how the importation behaved.
  */
 protected function importTest(core_kernel_classes_Class $targetClass, Resource $qtiTestResource, taoQtiTest_models_classes_ManifestParser $manifestParser, $folder)
 {
     $itemImportService = ImportService::singleton();
     $itemService = taoItems_models_classes_ItemsService::singleton();
     $testClass = $targetClass;
     // Create an RDFS resource in the knowledge base that will hold
     // the information about the imported QTI Test.
     $testResource = $this->createInstance($testClass);
     $qtiTestModelResource = new core_kernel_classes_Resource(INSTANCE_TEST_MODEL_QTI);
     $modelProperty = new core_kernel_classes_Property(PROPERTY_TEST_TESTMODEL);
     $testResource->editPropertyValues($modelProperty, $qtiTestModelResource);
     // Create the report that will hold information about the import
     // of $qtiTestResource in TAO.
     $report = new common_report_Report(common_report_Report::TYPE_INFO);
     // The class where the items that belong to the test will be imported.
     $itemClass = new core_kernel_classes_Class(TAO_ITEM_CLASS);
     $targetClass = $itemClass->createSubClass($testResource->getLabel());
     // Load and validate the manifest
     $qtiManifestParser = new taoQtiTest_models_classes_ManifestParser($folder . 'imsmanifest.xml');
     $qtiManifestParser->validate();
     // Set up $report with useful information for client code (especially for rollback).
     $reportCtx = new stdClass();
     $reportCtx->manifestResource = $qtiTestResource;
     $reportCtx->rdfsResource = $testResource;
     $reportCtx->itemClass = $targetClass;
     $reportCtx->items = array();
     $report->setData($reportCtx);
     // Expected test.xml file location.
     $expectedTestFile = $folder . str_replace('/', DIRECTORY_SEPARATOR, $qtiTestResource->getFile());
     // Already imported test items (qti xml file paths).
     $alreadyImportedTestItemFiles = array();
     // -- Check if the file referenced by the test QTI resource exists.
     if (is_readable($expectedTestFile) === false) {
         $report->add(common_report_Report::createFailure(__('No file found at location "%s".', $qtiTestResource->getFile())));
     } else {
         // -- Load the test in a QTISM flavour.
         $testDefinition = new XmlDocument();
         try {
             $testDefinition->load($expectedTestFile, true);
             // -- Load all items related to test.
             $itemError = false;
             // discover test's base path.
             $dependencies = taoQtiTest_helpers_Utils::buildAssessmentItemRefsTestMap($testDefinition, $manifestParser, $folder);
             if (count($dependencies) > 0) {
                 foreach ($dependencies as $assessmentItemRefId => $qtiDependency) {
                     if ($qtiDependency !== false) {
                         if (Resource::isAssessmentItem($qtiDependency->getType())) {
                             $qtiFile = $folder . str_replace('/', DIRECTORY_SEPARATOR, $qtiDependency->getFile());
                             // Skip if $qtiFile already imported (multiple assessmentItemRef "hrefing" the same file).
                             if (array_key_exists($qtiFile, $alreadyImportedTestItemFiles) === false) {
                                 $itemReport = $itemImportService->importQTIFile($qtiFile, $targetClass);
                                 $rdfItem = $itemReport->getData();
                                 if ($rdfItem) {
                                     $itemPath = taoItems_models_classes_ItemsService::singleton()->getItemFolder($rdfItem);
                                     foreach ($qtiDependency->getAuxiliaryFiles() as $auxResource) {
                                         // $auxResource is a relativ URL, so we need to replace the slashes with directory separators
                                         $auxPath = $folder . str_replace('/', DIRECTORY_SEPARATOR, $auxResource);
                                         // does the file referenced by $auxPath exist?
                                         if (is_readable($auxPath) === true) {
                                             $relPath = helpers_File::getRelPath($qtiFile, $auxPath);
                                             $destPath = $itemPath . $relPath;
                                             tao_helpers_File::copy($auxPath, $destPath, true);
                                         } else {
                                             $msg = __('Auxiliary file not found at location "%s".', $auxResource);
                                             $itemReport->add(new common_report_Report(common_report_Report::TYPE_WARNING, $msg));
                                         }
                                     }
                                     $reportCtx->items[$assessmentItemRefId] = $rdfItem;
                                     $alreadyImportedTestItemFiles[$qtiFile] = $rdfItem;
                                     $itemReport->setMessage(__('IMS QTI Item referenced as "%s" in the IMS Manifest file successfully imported.', $qtiDependency->getIdentifier()));
                                 } else {
                                     $itemReport->setType(common_report_Report::TYPE_ERROR);
                                     $itemReport->setMessage(__('IMS QTI Item referenced as "%s" in the IMS Manifest file could not be imported.', $qtiDependency->getIdentifier()));
                                     $itemError = $itemError === false ? true : $itemError;
                                 }
                                 $report->add($itemReport);
                             } else {
                                 $reportCtx->items[$assessmentItemRefId] = $alreadyImportedTestItemFiles[$qtiFile];
                             }
                         }
                     } else {
                         $msg = __('The dependency to the IMS QTI AssessmentItemRef "%s" in the IMS Manifest file could not be resolved.', $assessmentItemRefId);
                         $report->add(common_report_Report::createFailure($msg));
                         $itemError = $itemError === false ? true : $itemError;
                     }
                 }
                 // If items did not produce errors, we import the test definition.
                 if ($itemError === false) {
                     common_Logger::i('Importing test...');
                     // Second step is to take care of the test definition and the related media (auxiliary files).
                     // 1. Import test definition (i.e. the QTI-XML Test file).
                     $testContent = $this->importTestDefinition($testResource, $testDefinition, $qtiTestResource, $reportCtx->items, $folder, $report);
                     if ($testContent !== false) {
                         // 2. Import test auxilliary files (e.g. stylesheets, images, ...).
                         $this->importTestAuxiliaryFiles($testContent, $qtiTestResource, $folder, $report);
                         // 3. Give meaningful names to resources.
                         $testTitle = $testDefinition->getDocumentComponent()->getTitle();
                         $testResource->setLabel($testDefinition->getDocumentComponent()->getTitle());
                         $targetClass->setLabel($testDefinition->getDocumentComponent()->getTitle());
                     }
                 } else {
                     $msg = __("One or more dependent IMS QTI Items could not be imported.");
                     $report->add(common_report_Report::createFailure($msg));
                 }
             } else {
                 // No depencies found (i.e. no item resources bound to the test).
                 $msg = __("No reference to any IMS QTI Item found.");
                 $report->add(common_report_Report::createFailure($msg));
             }
         } catch (StorageException $e) {
             // Source of the exception = $testDefinition->load()
             // What is the reason ?
             $finalErrorString = '';
             $eStrs = array();
             if (($libXmlErrors = $e->getErrors()) !== null) {
                 foreach ($libXmlErrors as $libXmlError) {
                     $eStrs[] = __('XML error at line %1$d column %2$d "%3$s".', $libXmlError->line, $libXmlError->column, trim($libXmlError->message));
                 }
             }
             $finalErrorString = implode("\n", $eStrs);
             if (empty($finalErrorString) === true) {
                 // Not XML malformation related. No info from LibXmlErrors extracted.
                 if (($previous = $e->getPrevious()) != null) {
                     // Useful information could be found here.
                     $finalErrorString = $previous->getMessage();
                     if ($previous instanceof UnmarshallingException) {
                         $domElement = $previous->getDOMElement();
                         $finalErrorString = __('Inconsistency at line %1d:', $domElement->getLineNo()) . ' ' . $previous->getMessage();
                     }
                 } else {
                     $finalErrorString = __("Unknown error.");
                 }
             }
             $msg = __("Error found in the IMS QTI Test:\n%s", $finalErrorString);
             $report->add(common_report_Report::createFailure($msg));
         }
     }
     if ($report->containsError() === false) {
         $report->setType(common_report_Report::TYPE_SUCCESS);
         $msg = __("IMS QTI Test referenced as \"%s\" in the IMS Manifest file successfully imported.", $qtiTestResource->getIdentifier());
         $report->setMessage($msg);
     } else {
         $report->setType(common_report_Report::TYPE_ERROR);
         $msg = __("The IMS QTI Test referenced as \"%s\" in the IMS Manifest file could not be imported.", $qtiTestResource->getIdentifier());
         $report->setMessage($msg);
     }
     return $report;
 }
 /**
  * @param core_kernel_classes_Resource $instance
  * @param $tmpFile
  *
  * @return \common_report_Report
  */
 public function updateInstanceAttachment($instance, $tmpFile)
 {
     $report = new \common_report_Report(\common_report_Report::TYPE_SUCCESS);
     StorageService::removeAttachedFile($instance);
     $fileResource = StorageService::storeFile($tmpFile);
     $property = new \core_kernel_classes_Property(self::PROPERTY_FILE_CONTENT);
     $instance->editPropertyValues($property, $fileResource);
     $report->setMessage(__('%s updated', $instance->getLabel()));
     $report->setData($instance);
     return $report;
 }