public function __invoke($params)
 {
     $service = new PortableElementService();
     $service->setServiceLocator(ServiceManager::getServiceManager());
     $sourceDirectory = $this->getSourceDirectory();
     if (empty($sourceDirectory)) {
         return $this->createFailure('the source directory is empty');
     }
     if (!is_readable($sourceDirectory)) {
         return $this->createFailure('the source directory does not exists or is not readable ' . $sourceDirectory);
     }
     try {
         $model = $service->getValidPortableElementFromDirectorySource($sourceDirectory);
         if (!empty($params)) {
             $minRequiredVersion = $params[0];
             // if the minimal required version number string "x.y.z" is given in the parameter, the new target version should be equal or higher than it
             if (version_compare($model->getVersion(), $minRequiredVersion) < 0) {
                 return $this->createFailure('the version in manifest "' . $model->getVersion() . '" cannot be lower than the given minimum required version "' . $minRequiredVersion . '"', $model);
             }
         }
         $service->registerFromDirectorySource($sourceDirectory);
     } catch (PortableElementVersionIncompatibilityException $e) {
         return $this->createFailure('incompatible version: ' . $e->getMessage(), $model);
     }
     return Report::createSuccess('registered portable element "' . $model->getTypeIdentifier() . '" in version "' . $model->getVersion() . '""');
 }
 /**
  * @dataProvider validImportProvider
  */
 public function testValidImport($model, $name, $version, $package)
 {
     $result = $this->instance->import($package);
     $portableElements = $this->getPortableElements($model);
     $this->assertEquals(ksort($result->toArray()), ksort($portableElements[$name][$version]));
     $pciRegistry = $this->getRegistry($model);
     //        $this->assertTrue($pciRegistry->unregister($result));
 }
 protected function getService()
 {
     if (!$this->service) {
         $this->service = new PortableElementService();
         $this->service->setServiceLocator($this->getServiceManager());
     }
     return $this->service;
 }
 /**
  * @return PortableElementService
  */
 public function getService()
 {
     if (!$this->service) {
         $this->service = new PortableElementService();
         $this->service->setServiceLocator($this->getServiceLocator());
     }
     return $this->service;
 }
 /**
 * Re-register a portable element from its source directory
 * The list of portable elements to re-register is configure in the config file {TAO_ROOT}/config/taoQtiItem/debug_portable_element.conf.php
 * e.g.
    return [
        'myPci1' => 'qtiItemPci/views/js/pciCreator/dev/myPci1/',
        'myPci2' => '/home/sam/dev/pcis/myPci2/'
    ];
 *
 * @param ItemCreatorLoad $event
 * @throws \common_Exception
 * @throws \common_ext_ExtensionException
 */
 public static function reloadPortableDevDirectory(ItemCreatorLoad $event)
 {
     $customInteractionDirs = \common_ext_ExtensionsManager::singleton()->getExtensionById('taoQtiItem')->getConfig('debug_portable_element');
     if (is_array($customInteractionDirs)) {
         $service = new PortableElementService();
         $service->setServiceLocator(ServiceManager::getServiceManager());
         foreach ($customInteractionDirs as $path) {
             if (is_dir(ROOT_PATH . $path)) {
                 $sourceDir = ROOT_PATH . $path;
             } else {
                 if (is_dir($path)) {
                     $sourceDir = $path;
                 } else {
                     throw new \common_Exception('No directory found on path ' . $path);
                 }
             }
             $service->registerFromDirectorySource($sourceDir);
             \common_Logger::i('Re-registered portable element from the source ' . $sourceDir);
         }
     }
 }
 public function testExport()
 {
     $packageValid = dirname(__FILE__) . '/samples/package/likertScaleInteraction_v1.0.0';
     $pciModel = new PciModel('likertScaleInteraction', '1.0.0');
     $pciModel->exchangeArray(json_decode(file_get_contents($packageValid . DIRECTORY_SEPARATOR . PciModel::PCI_MANIFEST), true));
     $service = new PortableElementService();
     $service->setServiceLocator(ServiceManager::getServiceManager());
     $reflectionClass = new \ReflectionClass(PortableElementService::class);
     $reflectionMethod = $reflectionClass->getMethod('getRegistry');
     $reflectionMethod->setAccessible(true);
     $registry = $reflectionMethod->invoke($service, new PciModel());
     $registry->setSource($packageValid);
     $registry->register($pciModel);
     $exportDirectory = $registry->export($pciModel);
     $parser = new PortableElementPackageParser($exportDirectory);
     $parser->setModel(new PciModel());
     $source = $parser->extract();
     $original = $this->fillArrayWithFileNodes(new \DirectoryIterator($packageValid));
     $exported = $this->fillArrayWithFileNodes(new \DirectoryIterator($source));
     $this->assertEquals(preg_replace('/\\s+/', '', file_get_contents($packageValid . DIRECTORY_SEPARATOR . PciModel::PCI_MANIFEST)), preg_replace('/\\s+/', '', file_get_contents($source . DIRECTORY_SEPARATOR . PciModel::PCI_MANIFEST)));
     $this->assertTrue(empty($this->array_diff_assoc_recursive($original, $exported)));
     $registry->unregister($pciModel);
     \tao_helpers_File::delTree($source);
 }
 /**
  * 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;
 }