tao-test/app/taoQtiItem/views/js/portableElementRegistry/provider/localManifestProvider.js

157 lines
6.1 KiB
JavaScript

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2016 (original work) Open Assessment Technologies SA;
*
*/
define(['lodash', 'context', 'core/promise'], function(_, context, Promise){
'use strict';
var _portableElementManifests = {};
var _registry = {};
var _moduleName = 'taoQtiItem/portableElementRegistry/provider/localManifestProvider';
/**
* Recursively set the prefix of portable element path
* e.g. transform a relative local path "./runtime/entrypoint.js" to "prefix/runtime/entrypoint.js"
*
* @param {Object|String|Array} obj
* @param {String} prefix
* @returns {Object|String|Array}
*/
function setPortableElementPrefix(obj, prefix){
var ret;
if(_.isArray(obj)){
ret = _.map(obj, function(v){
return setPortableElementPrefix(v, prefix);
});
}else if(_.isPlainObject(obj)){
ret = {};
_.forIn(obj, function(v, k){
ret[k] = setPortableElementPrefix(v, prefix);
});
}else if(_.isString(obj)){
ret = obj.replace('./', prefix+'/');
}
return ret;
}
/**
* Use portable element source if exists
*
* @param {Object} manifest - the manifest of the pci to be modified
* @returns {Object} the modified manifest
*/
function useSource(manifest){
var runtimeModules,
runtimeSrc,
typeIdentifier;
// Make sure that we use the unbundled runtime
if (manifest.model === "IMSPCI") {
runtimeModules = (manifest.runtime || {}).modules;
runtimeSrc = (manifest.runtime || {}).src || [];
// in case of a TAO bundled PCI (= we have a "src" entry),
// we redirect the module to the entry point of the PCI instead of its minified version
if (runtimeSrc.length) {
_.forOwn(runtimeModules, function(allModulesFiles, moduleKey) {
if (moduleKey.indexOf('.min') === (moduleKey.length - '.min'.length)) {
runtimeModules[moduleKey] = allModulesFiles.map(function(filePath) {
return filePath.replace('.min.js', '.js');
});
}
});
}
} else {
if(manifest.runtime && _.isArray(manifest.runtime.src)){
delete manifest.runtime.hook;//hook is going to be removed with the support of IMS PCI v1
manifest.runtime.libraries = manifest.runtime.src;
}
if(manifest.creator && _.isArray(manifest.creator.src)){
delete manifest.creator.hook;//hook is going to be removed with the support of IMS PCI v1
manifest.creator.libraries = manifest.creator.src;
}
}
return manifest;
}
/**
* Generic portable element provider than loads portable elements from their manifest.
* It is useful for testing if the portable element source location is easily accessible.
*
* Sample usage :
*
* localManifestProvider.addManifestPath('pci_A', 'qtiItemPci/pciCreator/dev/pci_A/pciCreator.json');
* localManifestProvider.addManifestPath('pci_B', 'taoExtB/pciCreator/dev/pci_B/pciCreator.json');
* localManifestProvider.addManifestPath('pci_C', 'qtiSamples/some/path/pci_C/pciCreator.json');
* ciRegistry.registerProvider(pciTestProvider.getModuleName());
*
*/
return {
/**
* Add testing
* @param id
* @param pathToManifest
*/
addManifestPath : function addManifestPath(id, pathToManifest){
_portableElementManifests[id] = pathToManifest;
return this;
},
/**
* Get the amd module name
* @returns {string}
*/
getModuleName : function getModuleName(){
return _moduleName;
},
/**
* Implementation of the mandatory method load() of a portable element provider
*
* @returns {Promise} resolved when the added pci registered through their manifest are loaded
*/
load : function load(){
return new Promise(function(resolve, reject){
var _requiredManifests = _.map(_portableElementManifests, function(manifest){
return 'json!'+manifest;
});
require(_requiredManifests, function(){
var ok = true;
_.each([].slice.call(arguments), function(manifest){
var id;
if(manifest && manifest.typeIdentifier){
id = manifest.typeIdentifier;
if(!_portableElementManifests[id]){
reject('typeIdentifier mismatch');
ok = false;
return false;
}
manifest = useSource(manifest);
manifest.baseUrl = window.location.origin + '/' +
_portableElementManifests[id].replace(/^([a-zA-Z]*)\/(.*)\/([a-zA-Z]*)(Creator.json$)/, '$1/views/js/$2');
_registry[id] = [setPortableElementPrefix(manifest, id)];
}
});
if(ok){
resolve(_registry);
}
}, reject);
});
}
};
});