/**
  * Handle the process to add file from $itemSource->add()
  *
  * @param $absolutePath
  * @param $relativePath
  * @return array
  * @throws \common_Exception
  * @throws \common_exception_Error
  */
 public function handle($absolutePath, $relativePath)
 {
     if (!$this->itemSource) {
         throw new \common_Exception('Missing required parameter: item source');
     }
     // store locally, in a safe directory
     $safePath = '';
     if (dirname($relativePath) !== '.') {
         $safePath = str_replace('../', '', dirname($relativePath)) . '/';
     }
     $info = $this->itemSource->add($absolutePath, basename($absolutePath), $safePath);
     \common_Logger::i('Asset file \'' . $absolutePath . '\' copied.');
     return $info;
 }
 public function testAdd()
 {
     $itemService = \taoItems_models_classes_ItemsService::singleton();
     $item = $itemService->createInstance($itemService->getRootClass(), 'testItem');
     $source = new LocalItemSource(array('item' => $item, 'lang' => DEFAULT_LANG));
     $sampleFile = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . 'asset' . DIRECTORY_SEPARATOR . 'sample.css';
     $info = $source->add($sampleFile, 'example.txt', '/');
     $this->assertEquals('example.txt', $info['name']);
     $this->assertEquals('/example.txt', $info['uri']);
     $this->assertEquals('/example.txt', $info['filePath']);
     // this is only true for local item source
     $link = $info['uri'];
     $asset = new MediaAsset($source, $link);
     return $asset;
 }
 public function testResourceManager()
 {
     $itemClass = taoItems_models_classes_ItemsService::singleton()->getRootClass();
     $report = ImportService::singleton()->importQTIPACKFile(dirname(__FILE__) . '/samples/package/QTI/package.zip', $itemClass);
     $items = array();
     foreach ($report as $itemReport) {
         $data = $itemReport->getData();
         if (!is_null($data)) {
             $items[] = $data;
         }
     }
     $this->assertEquals(1, count($items));
     $item = current($items);
     $this->assertIsA($item, 'core_kernel_classes_Resource');
     $this->assertTrue($item->exists());
     $rm = new LocalItemSource(array('item' => $item, 'lang' => DEFAULT_LANG));
     $data = $rm->getDirectory();
     $this->assertTrue(is_array($data));
     $this->assertTrue(isset($data['path']));
     $this->assertEquals('/', $data['path']);
     $this->assertTrue(isset($data['children']));
     $children = $data['children'];
     $this->assertEquals(2, count($children));
     $file = null;
     $dir = null;
     foreach ($children as $child) {
         if (isset($child['path'])) {
             $dir = $child;
         }
         if (isset($child['name'])) {
             $file = $child;
         }
     }
     $this->assertEquals("qti.xml", $file['name']);
     $this->assertTrue(strpos($file['mime'], '/xml') !== false);
     //can be 'application/xml' or 'text/xml'
     $this->assertTrue($file['size'] > 0);
     $this->assertEquals("/images/", $dir['path']);
     taoItems_models_classes_ItemsService::singleton()->deleteItem($item);
     $this->assertFalse($item->exists());
 }
 /**
  * @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;
 }
 public function testImport()
 {
     $itemClass = $this->itemService->getRootClass();
     $report = $this->importService->importQTIPACKFile($this->getSamplePath('/package/QTI/package.zip'), $itemClass);
     $items = array();
     foreach ($report as $itemReport) {
         $data = $itemReport->getData();
         if (!is_null($data)) {
             $items[] = $data;
         }
     }
     $this->assertEquals(1, count($items));
     $item = current($items);
     $this->assertInstanceOf('\\core_kernel_classes_Resource', $item);
     $this->assertTrue($item->exists());
     $resourceManager = new LocalItemSource(array('item' => $item, 'lang' => DEFAULT_LANG));
     $data = $resourceManager->getDirectory();
     $this->assertTrue(is_array($data));
     $this->assertTrue(isset($data['path']));
     $this->assertEquals('/', $data['path']);
     $this->assertTrue(isset($data['children']));
     $children = $data['children'];
     $this->assertEquals(2, count($children));
     $file = null;
     $dir = null;
     foreach ($children as $child) {
         if (isset($child['path'])) {
             $dir = $child;
         }
         if (isset($child['name'])) {
             $file = $child;
         }
     }
     $this->assertEquals("qti.xml", $file['name']);
     $this->assertContains("/xml", $file['mime']);
     $this->assertTrue($file['size'] > 0);
     $this->assertEquals("/images/", $dir['path']);
     $this->assertEquals("/images/", $dir['parent']);
     return $item;
 }