/**
  * Register files associated to a PCI track by $typeIdentifier
  *
  * @refactor improve response
  *
  * @param PortableElementObject $object
  * @param string[] $files Relative path of portable element files
  * @param string $source Location of temporary directory
  * @return bool
  * @throws PortableElementFileStorageException
  */
 public function registerFiles(PortableElementObject $object, $files, $source)
 {
     $registered = false;
     $fileSystem = $this->getFileStorage();
     $source = $this->sanitizeSourceAsDirectory($source);
     foreach ($files as $file) {
         if (substr($file, 0, 2) != './' && !preg_match('/^' . $object->getTypeIdentifier() . '/', $file)) {
             // File is not relative, it's a shared libraries
             // Ignore this file, front have fallBack
             continue;
         }
         $filePath = $source . ltrim($file, DIRECTORY_SEPARATOR);
         if (!file_exists($filePath) || ($resource = fopen($filePath, 'r')) === false) {
             throw new PortableElementFileStorageException('File cannot be opened : ' . $filePath);
         }
         $fileId = $this->getPrefix($object) . preg_replace('/^' . $object->getTypeIdentifier() . '/', '.', $file);
         //Adjust file resource entries where {QTI_NS}/xxx/yyy.js is equivalent to ./xxx/yyy.js
         if ($fileSystem->has($fileId)) {
             $registered = $fileSystem->updateStream($fileId, $resource);
         } else {
             $registered = $fileSystem->writeStream($fileId, $resource);
         }
         fclose($resource);
         \common_Logger::i('Portable element asset file "' . $fileId . '" copied.');
     }
     return $registered;
 }
 /**
  * Return all assets of a portable element in a array of string
  * Path is relative to Portable Element location
  *
  * @param PortableElementObject $object
  * @param null $type Object key to focus
  * @return array List of file relative path
  * @throws PortableElementInvalidAssetException
  */
 public function getAssets(PortableElementObject $object, $type = null)
 {
     $assets = [];
     if (is_null($type) || $type == 'runtime') {
         $assets = ['runtime' => $object->getRuntimePath()];
     }
     if (is_null($type) || $type == 'creator') {
         if (!empty($object->getCreator())) {
             $assets['creator'] = $object->getCreatorPath();
         }
     }
     $files = [];
     foreach ($assets as $key => $asset) {
         $constraints = $this->getAssetConstraints($key);
         foreach ($constraints as $constraint) {
             if (!isset($asset[$constraint])) {
                 if ($this->isOptionalConstraint($key, $constraint)) {
                     continue;
                 }
                 throw new PortableElementInvalidAssetException('Missing asset file for ' . $key . ':' . $constraint);
             }
             if (is_array($asset[$constraint])) {
                 $files = array_merge($files, $asset[$constraint]);
             } else {
                 $files[] = $asset[$constraint];
             }
         }
     }
     return $files;
 }
 /**
  * Validate a model using associated validator
  *
  * @param PortableElementObject $object
  * @param null $source Directory of portable element, if not null it will be checked
  * @param array $validationGroup Fields to be checked, empty=$validator->getConstraints()
  * @return bool
  * @throws PortableElementInconsistencyModelException
  */
 public function validate(PortableElementObject $object, $source = null, $validationGroup = array())
 {
     $validator = $object->getModel()->getValidator();
     Validator::validate($object, $validator, $validationGroup);
     if ($source) {
         $validator->validateAssets($object, $source);
     }
 }
 /**
  * Get manifest representation of Pci Model
  *
  * @param PortableElementObject $object
  * @return string
  */
 public function getManifest(PortableElementObject $object)
 {
     return json_encode($object->toArray(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
 }
 protected function getMinifiedModel(PortableElementObject $object)
 {
     $data = $object->toArray(array('typeIdentifier', 'label'));
     $data['version'] = $object->getVersion();
     return $data;
 }
 /**
  * Replace the libs aliases with their relative url before saving into the registry
  * This format is consistent with the format of TAO portable package manifest
  *
  * @param PortableElementObject $object
  * @return PortableElementObject
  */
 private function replaceLibAliases(PortableElementObject $object)
 {
     $id = $object->getTypeIdentifier();
     $object->setRuntimeKey('libraries', array_map(function ($lib) use($id) {
         if (preg_match('/^' . $id . '/', $lib)) {
             return $lib . '.js';
         }
         return $lib;
     }, $object->getRuntimeKey('libraries')));
     return $object;
 }