For greater flexibility, course, training and ELP contacts have been merged into a single "repeater" of contacts with different roles:
on training courses and itineraries, the "personInCharge" repeater and the "contact" multiple field (administrative contacts) are replaced by the "contacts" repeater. Each repeater entry is made up of a role, and a multiple field for persons.
on ELP, the multiple fields "personInCharge" (managers) and "contact" (administrative contacts) are replaced by the "contacts" repeater. Each repeater entry is made up of a role, and a multiple field for persons.
Run the following script to migrate the contacts for your courses, pathways and ELP. Customize the code and title for the role of administrative contacts and the code and title for the role of course leaders.
Oops!
Copy to clipboard failed. Open the code and copy it manually.
// Administrative role (A PERSONNALISER SI BESOIN)
var administrativeRoleCode = "contact";
var administrativeRoleTitle = new java.util.HashMap();
administrativeRoleTitle.put('fr', 'Contact administratif');
administrativeRoleTitle.put('en', 'Administrative contact');
var StringArray = Java.type("java.lang.String[]");
var administrativeRoleId = _createRoleIfNeeded(administrativeRoleTitle, administrativeRoleCode);
// Responsable pédagogique pour les ELPs (A PERSONNALISER SI BESOIN)
var respPRoleCode = "RespP";
var respPRoleTitle = new java.util.HashMap();
respPRoleTitle.put('fr', 'Responsable pédagogique');
respPRoleTitle.put('en', 'Education manager');
var respPRoleId = _createRoleIfNeeded(respPRoleTitle, respPRoleCode);
var t0 = new java.util.Date().getTime();
java.lang.System.out.println(new java.util.Date() + "----------------------- DEBUT SCRIPT : MIGRATION CONTACTS ----------------------- "
+ " en " +((new java.util.Date().getTime()) - t0)/1000.0 + "seconds "
+ " - le " + (new java.util.Date())
)
function _createRoleIfNeeded(roleTitle, roleCode)
{
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.PersonRole' and @ametys:code='" + roleCode + "']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
if (nodes.hasNext())
{
print("Found role with code '" + roleCode + "'");
return "content://" + nodes.next().getUUID();
}
else
{
var contentWorkflowHelper= serviceManager.lookup('org.ametys.cms.workflow.ContentWorkflowHelper');
var contentTypes = new StringArray(1);
contentTypes[0] = 'odf-enumeration.PersonRole';
var result = contentWorkflowHelper.createContent("reference-table", 1, roleTitle.get('fr'), roleTitle, contentTypes, new StringArray(0), null, null, new java.util.HashMap());
var roleId = result.contentId;
var content = result.get('org.ametys.cms.repository.Content');
content.getNode().setProperty("ametys:code", roleCode);
contentWorkflowHelper.doAction(content, 22);
session.save();
print("Create new role with code '" + roleCode + "'");
return content.getId();
}
}
function _moveContactToRepeater(content, oldPropertyName, newRoleId)
{
if (content.getNode().hasProperty(oldPropertyName))
{
var values = content.getNode().getProperty(oldPropertyName).getValues();
if (values.length > 0)
{
hasChanges = true;
var repeaterNode = null;
if (content.getNode().hasNode("ametys:contacts"))
{
repeaterNode = content.getNode().getNode("ametys:contacts");
}
else
{
repeaterNode = content.getNode().addNode("ametys:contacts", "ametys:compositeMetadata");
}
var size = repeaterNode.getNodes().getSize();
var entryNode = repeaterNode.addNode("ametys:" + (size+1), "ametys:compositeMetadata");
// Move values
entryNode.setProperty("ametys:persons", values);
if (newRoleId)
{
entryNode.setProperty("ametys:role", newRoleId);
}
}
// remove old property
content.getNode().getProperty(oldPropertyName).remove();
return true;
}
return false;
}
function _contactMigration(content)
{
var hasChanges = false;
// Move repeater 'ametys:personInCharge' to 'ametys:contact'
if (content.getNode().hasNode("ametys:personInCharge"))
{
var node = content.getNode().getNode("ametys:personInCharge");
session.move(node.getPath(), node.getParent().getPath() + '/ametys:contacts');
hasChanges = true;
}
// Move 'contact' into a new entry of 'contacts' repeater with the administrative role
hasChanges = _moveContactToRepeater(content, "ametys:contact", administrativeRoleId) || hasChanges;
if (hasChanges) count++;
}
function _contactMigrationForCourses(content)
{
var hasChanges = _moveContactToRepeater(content, "ametys:contact", administrativeRoleId);
hasChanges = _moveContactToRepeater(content, "ametys:personInCharge", respPRoleId) || hasChanges;
if (hasChanges) count++;
}
var outgoingReferencesExtractor = serviceManager.lookup("org.ametys.cms.content.references.OutgoingReferencesExtractor");
function _updateOutgoingReferences(content)
{
var outgoingReferencesByPath = outgoingReferencesExtractor.getOutgoingReferences(content);
content.setOutgoingReferences(outgoingReferencesByPath);
content.saveChanges();
}
var totalCount = 0;
var count = 0;
// Migrate programs
jcrXPathQuery("//element(*, ametys:programContent)").forEach(function (content) {
migrateContent(content, [_contactMigration], true /* old versions incompatible */, null /* no tag */, false /* not verbose */);
_updateOutgoingReferences(content);
});
print(count + " programs have been migrated");
totalCount += count;
// Migrate subprograms
count = 0;
jcrXPathQuery("//element(*, ametys:subProgramContent)").forEach(function (content) {
migrateContent(content, [_contactMigration], true /* old versions incompatible */, null /* no tag */, false /* not verbose */);
_updateOutgoingReferences(content);
});
print(count + " subprograms have been migrated");
totalCount += count;
// Migrate courses
count = 0;
jcrXPathQuery("//element(*, ametys:courseContent)[@ametys:contact or @ametys:personInCharge]").forEach(function (content) {
migrateContent(content, [_contactMigrationForCourses], true /* old versions incompatible */, null /* no tag */, false /* not verbose */);
_updateOutgoingReferences(content);
});
print(count + " courses have been migrated");
totalCount += count;
java.lang.System.out.println(new java.util.Date() + "----------------------- FIN SCRIPT : MIGRATION CONTACTS ----------------------- "
+ " en " +((new java.util.Date().getTime()) - t0)/1000.0 + "seconds "
+ " - le " + (new java.util.Date())
)
if (totalCount > 0)
print(" => BUILD LIVE WORKSPACE");
// Administrative role (A PERSONNALISER SI BESOIN)
var administrativeRoleCode = "contact";
var administrativeRoleTitle = new java.util.HashMap();
administrativeRoleTitle.put('fr', 'Contact administratif');
administrativeRoleTitle.put('en', 'Administrative contact');
var StringArray = Java.type("java.lang.String[]");
var administrativeRoleId = _createRoleIfNeeded(administrativeRoleTitle, administrativeRoleCode);
// Responsable pédagogique pour les ELPs (A PERSONNALISER SI BESOIN)
var respPRoleCode = "RespP";
var respPRoleTitle = new java.util.HashMap();
respPRoleTitle.put('fr', 'Responsable pédagogique');
respPRoleTitle.put('en', 'Education manager');
var respPRoleId = _createRoleIfNeeded(respPRoleTitle, respPRoleCode);
var t0 = new java.util.Date().getTime();
java.lang.System.out.println(new java.util.Date() + "----------------------- DEBUT SCRIPT : MIGRATION CONTACTS ----------------------- "
+ " en " +((new java.util.Date().getTime()) - t0)/1000.0 + "seconds "
+ " - le " + (new java.util.Date())
)
function _createRoleIfNeeded(roleTitle, roleCode)
{
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.PersonRole' and @ametys:code='" + roleCode + "']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
if (nodes.hasNext())
{
print("Found role with code '" + roleCode + "'");
return "content://" + nodes.next().getUUID();
}
else
{
var contentWorkflowHelper= serviceManager.lookup('org.ametys.cms.workflow.ContentWorkflowHelper');
var contentTypes = new StringArray(1);
contentTypes[0] = 'odf-enumeration.PersonRole';
var result = contentWorkflowHelper.createContent("reference-table", 1, roleTitle.get('fr'), roleTitle, contentTypes, new StringArray(0), null, null, new java.util.HashMap());
var roleId = result.contentId;
var content = result.get('org.ametys.cms.repository.Content');
content.getNode().setProperty("ametys:code", roleCode);
contentWorkflowHelper.doAction(content, 22);
session.save();
print("Create new role with code '" + roleCode + "'");
return content.getId();
}
}
function _moveContactToRepeater(content, oldPropertyName, newRoleId)
{
if (content.getNode().hasProperty(oldPropertyName))
{
var values = content.getNode().getProperty(oldPropertyName).getValues();
if (values.length > 0)
{
hasChanges = true;
var repeaterNode = null;
if (content.getNode().hasNode("ametys:contacts"))
{
repeaterNode = content.getNode().getNode("ametys:contacts");
}
else
{
repeaterNode = content.getNode().addNode("ametys:contacts", "ametys:compositeMetadata");
}
var size = repeaterNode.getNodes().getSize();
var entryNode = repeaterNode.addNode("ametys:" + (size+1), "ametys:compositeMetadata");
// Move values
entryNode.setProperty("ametys:persons", values);
if (newRoleId)
{
entryNode.setProperty("ametys:role", newRoleId);
}
}
// remove old property
content.getNode().getProperty(oldPropertyName).remove();
return true;
}
return false;
}
function _contactMigration(content)
{
var hasChanges = false;
// Move repeater 'ametys:personInCharge' to 'ametys:contact'
if (content.getNode().hasNode("ametys:personInCharge"))
{
var node = content.getNode().getNode("ametys:personInCharge");
session.move(node.getPath(), node.getParent().getPath() + '/ametys:contacts');
hasChanges = true;
}
// Move 'contact' into a new entry of 'contacts' repeater with the administrative role
hasChanges = _moveContactToRepeater(content, "ametys:contact", administrativeRoleId) || hasChanges;
if (hasChanges) count++;
}
function _contactMigrationForCourses(content)
{
var hasChanges = _moveContactToRepeater(content, "ametys:contact", administrativeRoleId);
hasChanges = _moveContactToRepeater(content, "ametys:personInCharge", respPRoleId) || hasChanges;
if (hasChanges) count++;
}
var outgoingReferencesExtractor = serviceManager.lookup("org.ametys.cms.content.references.OutgoingReferencesExtractor");
function _updateOutgoingReferences(content)
{
var outgoingReferencesByPath = outgoingReferencesExtractor.getOutgoingReferences(content);
content.setOutgoingReferences(outgoingReferencesByPath);
content.saveChanges();
}
var totalCount = 0;
var count = 0;
// Migrate programs
jcrXPathQuery("//element(*, ametys:programContent)").forEach(function (content) {
migrateContent(content, [_contactMigration], true /* old versions incompatible */, null /* no tag */, false /* not verbose */);
_updateOutgoingReferences(content);
});
print(count + " programs have been migrated");
totalCount += count;
// Migrate subprograms
count = 0;
jcrXPathQuery("//element(*, ametys:subProgramContent)").forEach(function (content) {
migrateContent(content, [_contactMigration], true /* old versions incompatible */, null /* no tag */, false /* not verbose */);
_updateOutgoingReferences(content);
});
print(count + " subprograms have been migrated");
totalCount += count;
// Migrate courses
count = 0;
jcrXPathQuery("//element(*, ametys:courseContent)[@ametys:contact or @ametys:personInCharge]").forEach(function (content) {
migrateContent(content, [_contactMigrationForCourses], true /* old versions incompatible */, null /* no tag */, false /* not verbose */);
_updateOutgoingReferences(content);
});
print(count + " courses have been migrated");
totalCount += count;
java.lang.System.out.println(new java.util.Date() + "----------------------- FIN SCRIPT : MIGRATION CONTACTS ----------------------- "
+ " en " +((new java.util.Date().getTime()) - t0)/1000.0 + "seconds "
+ " - le " + (new java.util.Date())
)
if (totalCount > 0)
print(" => BUILD LIVE WORKSPACE");
// Administrative role (A PERSONNALISER SI BESOIN)
var administrativeRoleCode = "contact";
var administrativeRoleTitle = new java.util.HashMap();
administrativeRoleTitle.put('fr', 'Contact administratif');
administrativeRoleTitle.put('en', 'Administrative contact');
var StringArray = Java.type("java.lang.String[]");
var administrativeRoleId = _createRoleIfNeeded(administrativeRoleTitle, administrativeRoleCode);
// Responsable pédagogique pour les ELPs (A PERSONNALISER SI BESOIN)
var respPRoleCode = "RespP";
var respPRoleTitle = new java.util.HashMap();
respPRoleTitle.put('fr', 'Responsable pédagogique');
respPRoleTitle.put('en', 'Education manager');
var respPRoleId = _createRoleIfNeeded(respPRoleTitle, respPRoleCode);
var t0 = new java.util.Date().getTime();
java.lang.System.out.println(new java.util.Date() + "----------------------- DEBUT SCRIPT : MIGRATION CONTACTS ----------------------- "
+ " en " +((new java.util.Date().getTime()) - t0)/1000.0 + "seconds "
+ " - le " + (new java.util.Date())
)
function _createRoleIfNeeded(roleTitle, roleCode)
{
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.PersonRole' and @ametys:code='" + roleCode + "']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
if (nodes.hasNext())
{
print("Found role with code '" + roleCode + "'");
return "content://" + nodes.next().getUUID();
}
else
{
var contentWorkflowHelper= serviceManager.lookup('org.ametys.cms.workflow.ContentWorkflowHelper');
var contentTypes = new StringArray(1);
contentTypes[0] = 'odf-enumeration.PersonRole';
var result = contentWorkflowHelper.createContent("reference-table", 1, roleTitle.get('fr'), roleTitle, contentTypes, new StringArray(0), null, null, new java.util.HashMap());
var roleId = result.contentId;
var content = result.get('org.ametys.cms.repository.Content');
content.getNode().setProperty("ametys:code", roleCode);
contentWorkflowHelper.doAction(content, 22);
session.save();
print("Create new role with code '" + roleCode + "'");
return content.getId();
}
}
function _moveContactToRepeater(content, oldPropertyName, newRoleId)
{
if (content.getNode().hasProperty(oldPropertyName))
{
var values = content.getNode().getProperty(oldPropertyName).getValues();
if (values.length > 0)
{
hasChanges = true;
var repeaterNode = null;
if (content.getNode().hasNode("ametys:contacts"))
{
repeaterNode = content.getNode().getNode("ametys:contacts");
}
else
{
repeaterNode = content.getNode().addNode("ametys:contacts", "ametys:compositeMetadata");
}
var size = repeaterNode.getNodes().getSize();
var entryNode = repeaterNode.addNode("ametys:" + (size+1), "ametys:compositeMetadata");
// Move values
entryNode.setProperty("ametys:persons", values);
if (newRoleId)
{
entryNode.setProperty("ametys:role", newRoleId);
}
}
// remove old property
content.getNode().getProperty(oldPropertyName).remove();
return true;
}
return false;
}
function _contactMigration(content)
{
var hasChanges = false;
// Move repeater 'ametys:personInCharge' to 'ametys:contact'
if (content.getNode().hasNode("ametys:personInCharge"))
{
var node = content.getNode().getNode("ametys:personInCharge");
session.move(node.getPath(), node.getParent().getPath() + '/ametys:contacts');
hasChanges = true;
}
// Move 'contact' into a new entry of 'contacts' repeater with the administrative role
hasChanges = _moveContactToRepeater(content, "ametys:contact", administrativeRoleId) || hasChanges;
if (hasChanges) count++;
}
function _contactMigrationForCourses(content)
{
var hasChanges = _moveContactToRepeater(content, "ametys:contact", administrativeRoleId);
hasChanges = _moveContactToRepeater(content, "ametys:personInCharge", respPRoleId) || hasChanges;
if (hasChanges) count++;
}
var outgoingReferencesExtractor = serviceManager.lookup("org.ametys.cms.content.references.OutgoingReferencesExtractor");
function _updateOutgoingReferences(content)
{
var outgoingReferencesByPath = outgoingReferencesExtractor.getOutgoingReferences(content);
content.setOutgoingReferences(outgoingReferencesByPath);
content.saveChanges();
}
var totalCount = 0;
var count = 0;
// Migrate programs
jcrXPathQuery("//element(*, ametys:programContent)").forEach(function (content) {
migrateContent(content, [_contactMigration], true /* old versions incompatible */, null /* no tag */, false /* not verbose */);
_updateOutgoingReferences(content);
});
print(count + " programs have been migrated");
totalCount += count;
// Migrate subprograms
count = 0;
jcrXPathQuery("//element(*, ametys:subProgramContent)").forEach(function (content) {
migrateContent(content, [_contactMigration], true /* old versions incompatible */, null /* no tag */, false /* not verbose */);
_updateOutgoingReferences(content);
});
print(count + " subprograms have been migrated");
totalCount += count;
// Migrate courses
count = 0;
jcrXPathQuery("//element(*, ametys:courseContent)[@ametys:contact or @ametys:personInCharge]").forEach(function (content) {
migrateContent(content, [_contactMigrationForCourses], true /* old versions incompatible */, null /* no tag */, false /* not verbose */);
_updateOutgoingReferences(content);
});
print(count + " courses have been migrated");
totalCount += count;
java.lang.System.out.println(new java.util.Date() + "----------------------- FIN SCRIPT : MIGRATION CONTACTS ----------------------- "
+ " en " +((new java.util.Date().getTime()) - t0)/1000.0 + "seconds "
+ " - le " + (new java.util.Date())
)
if (totalCount > 0)
print(" => BUILD LIVE WORKSPACE");
Management workflow does not version
Oops!
Copy to clipboard failed. Open the code and copy it manually.
var ArrayUtils = Java.type("org.apache.commons.lang3.ArrayUtils");
jcrXPathQuery("//element(*, ametys:programContent)").forEach(function(program) {
var currentVersionIsLive = ArrayUtils.contains(program.getLabels(), "Live");
program.checkpoint();
// Move the Live label if the last version was validated.
if (currentVersionIsLive)
{
program.addLabel("Live", true);
}
});
var ArrayUtils = Java.type("org.apache.commons.lang3.ArrayUtils");
jcrXPathQuery("//element(*, ametys:programContent)").forEach(function(program) {
var currentVersionIsLive = ArrayUtils.contains(program.getLabels(), "Live");
program.checkpoint();
// Move the Live label if the last version was validated.
if (currentVersionIsLive)
{
program.addLabel("Live", true);
}
});
var ArrayUtils = Java.type("org.apache.commons.lang3.ArrayUtils");
jcrXPathQuery("//element(*, ametys:programContent)").forEach(function(program) {
var currentVersionIsLive = ArrayUtils.contains(program.getLabels(), "Live");
program.checkpoint();
// Move the Live label if the last version was validated.
if (currentVersionIsLive)
{
program.addLabel("Live", true);
}
});
Period type
The "Period type" field in the "Period" reference table becomes a reference table.
To migrate data from the "Period" reference table, run the following script migration (it transforms the existing strings into entries in the new "Period type" reference table and makes the link with the "Periode" reference table)
Oops!
Copy to clipboard failed. Open the code and copy it manually.
// Imports
var ArrayList = Java.type('java.util.ArrayList');
var HashMap = Java.type('java.util.HashMap');
var AbstractWorkflowComponent = Java.type('org.ametys.plugins.workflow.AbstractWorkflowComponent');
var AbstractContentWorkflowComponent = Java.type('org.ametys.cms.workflow.AbstractContentWorkflowComponent');
// Components
var refTableHelper = serviceManager.lookup("org.ametys.odf.enumeration.OdfReferenceTableHelper");
var workflowHelper = serviceManager.lookup("org.ametys.cms.workflow.ContentWorkflowHelper");
var workflowProvider = serviceManager.lookup("org.ametys.plugins.workflow.support.WorkflowProvider");
var count = 0;
jcrXPathQuery("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.Period']").forEach(function(period)
{
if (updatePeriod(period))
{
count++;
}
});
print("[info] " + count + " periods have been migrated");
// Update the type field of a period entry from String to Content
function updatePeriod(period)
{
var periodNode = period.getNode();
if (periodNode.hasProperty("ametys:type"))
{
var periodTypeCode = periodNode.getProperty("ametys:type").getString();
if (periodTypeCode.length > 0 && !periodTypeCode.startsWith("content://"))
{
var periodType = getOrCreatePeriodType(periodTypeCode);
if (periodType != null)
{
period.setValue("type", periodType);
period.saveChanges();
doAction(period, 2);
return true;
}
else
{
print("[WARN] Impossible to get or create the period type with the code '" + periodeTypeCode + "'.");
}
}
}
return false;
}
// Create an entry in the PeriodType table ref
function getOrCreatePeriodType(code)
{
var periodTypeEntry = refTableHelper.getItemFromCode("odf-enumeration.PeriodType", code);
if (periodTypeEntry != null)
{
return periodTypeEntry.getContent();
}
var result = workflowHelper.createContent("reference-table", 1, code, code, ["odf-enumeration.PeriodType"], [], "fr");
var periodType = result.get(AbstractContentWorkflowComponent.CONTENT_KEY);
periodType.setValue("code", code);
periodType.saveChanges();
doAction(periodType, 22);
print("[INFO] Period type entry '" + code + "' created");
return periodType;
}
// Update the current workflow state
function doAction(content, actionId)
{
var inputs = new HashMap();
inputs.put(AbstractWorkflowComponent.RESULT_MAP_KEY, new HashMap());
inputs.put(AbstractContentWorkflowComponent.CONTENT_KEY, content);
inputs.put(AbstractWorkflowComponent.FAIL_CONDITIONS_KEY, new ArrayList());
inputs.put(AbstractWorkflowComponent.CONTEXT_PARAMETERS_KEY, new HashMap());
try
{
var workflow = workflowProvider.getAmetysObjectWorkflow(content);
workflow.doAction(content.getWorkflowId(), actionId, inputs);
}
catch (e)
{
print("[ERROR] An error occured while do workflow action '" + actionId + "' on content '" + content.getId() + "'", e);
}
}
// Imports
var ArrayList = Java.type('java.util.ArrayList');
var HashMap = Java.type('java.util.HashMap');
var AbstractWorkflowComponent = Java.type('org.ametys.plugins.workflow.AbstractWorkflowComponent');
var AbstractContentWorkflowComponent = Java.type('org.ametys.cms.workflow.AbstractContentWorkflowComponent');
// Components
var refTableHelper = serviceManager.lookup("org.ametys.odf.enumeration.OdfReferenceTableHelper");
var workflowHelper = serviceManager.lookup("org.ametys.cms.workflow.ContentWorkflowHelper");
var workflowProvider = serviceManager.lookup("org.ametys.plugins.workflow.support.WorkflowProvider");
var count = 0;
jcrXPathQuery("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.Period']").forEach(function(period)
{
if (updatePeriod(period))
{
count++;
}
});
print("[info] " + count + " periods have been migrated");
// Update the type field of a period entry from String to Content
function updatePeriod(period)
{
var periodNode = period.getNode();
if (periodNode.hasProperty("ametys:type"))
{
var periodTypeCode = periodNode.getProperty("ametys:type").getString();
if (periodTypeCode.length > 0 && !periodTypeCode.startsWith("content://"))
{
var periodType = getOrCreatePeriodType(periodTypeCode);
if (periodType != null)
{
period.setValue("type", periodType);
period.saveChanges();
doAction(period, 2);
return true;
}
else
{
print("[WARN] Impossible to get or create the period type with the code '" + periodeTypeCode + "'.");
}
}
}
return false;
}
// Create an entry in the PeriodType table ref
function getOrCreatePeriodType(code)
{
var periodTypeEntry = refTableHelper.getItemFromCode("odf-enumeration.PeriodType", code);
if (periodTypeEntry != null)
{
return periodTypeEntry.getContent();
}
var result = workflowHelper.createContent("reference-table", 1, code, code, ["odf-enumeration.PeriodType"], [], "fr");
var periodType = result.get(AbstractContentWorkflowComponent.CONTENT_KEY);
periodType.setValue("code", code);
periodType.saveChanges();
doAction(periodType, 22);
print("[INFO] Period type entry '" + code + "' created");
return periodType;
}
// Update the current workflow state
function doAction(content, actionId)
{
var inputs = new HashMap();
inputs.put(AbstractWorkflowComponent.RESULT_MAP_KEY, new HashMap());
inputs.put(AbstractContentWorkflowComponent.CONTENT_KEY, content);
inputs.put(AbstractWorkflowComponent.FAIL_CONDITIONS_KEY, new ArrayList());
inputs.put(AbstractWorkflowComponent.CONTEXT_PARAMETERS_KEY, new HashMap());
try
{
var workflow = workflowProvider.getAmetysObjectWorkflow(content);
workflow.doAction(content.getWorkflowId(), actionId, inputs);
}
catch (e)
{
print("[ERROR] An error occured while do workflow action '" + actionId + "' on content '" + content.getId() + "'", e);
}
}
// Imports
var ArrayList = Java.type('java.util.ArrayList');
var HashMap = Java.type('java.util.HashMap');
var AbstractWorkflowComponent = Java.type('org.ametys.plugins.workflow.AbstractWorkflowComponent');
var AbstractContentWorkflowComponent = Java.type('org.ametys.cms.workflow.AbstractContentWorkflowComponent');
// Components
var refTableHelper = serviceManager.lookup("org.ametys.odf.enumeration.OdfReferenceTableHelper");
var workflowHelper = serviceManager.lookup("org.ametys.cms.workflow.ContentWorkflowHelper");
var workflowProvider = serviceManager.lookup("org.ametys.plugins.workflow.support.WorkflowProvider");
var count = 0;
jcrXPathQuery("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.Period']").forEach(function(period)
{
if (updatePeriod(period))
{
count++;
}
});
print("[info] " + count + " periods have been migrated");
// Update the type field of a period entry from String to Content
function updatePeriod(period)
{
var periodNode = period.getNode();
if (periodNode.hasProperty("ametys:type"))
{
var periodTypeCode = periodNode.getProperty("ametys:type").getString();
if (periodTypeCode.length > 0 && !periodTypeCode.startsWith("content://"))
{
var periodType = getOrCreatePeriodType(periodTypeCode);
if (periodType != null)
{
period.setValue("type", periodType);
period.saveChanges();
doAction(period, 2);
return true;
}
else
{
print("[WARN] Impossible to get or create the period type with the code '" + periodeTypeCode + "'.");
}
}
}
return false;
}
// Create an entry in the PeriodType table ref
function getOrCreatePeriodType(code)
{
var periodTypeEntry = refTableHelper.getItemFromCode("odf-enumeration.PeriodType", code);
if (periodTypeEntry != null)
{
return periodTypeEntry.getContent();
}
var result = workflowHelper.createContent("reference-table", 1, code, code, ["odf-enumeration.PeriodType"], [], "fr");
var periodType = result.get(AbstractContentWorkflowComponent.CONTENT_KEY);
periodType.setValue("code", code);
periodType.saveChanges();
doAction(periodType, 22);
print("[INFO] Period type entry '" + code + "' created");
return periodType;
}
// Update the current workflow state
function doAction(content, actionId)
{
var inputs = new HashMap();
inputs.put(AbstractWorkflowComponent.RESULT_MAP_KEY, new HashMap());
inputs.put(AbstractContentWorkflowComponent.CONTENT_KEY, content);
inputs.put(AbstractWorkflowComponent.FAIL_CONDITIONS_KEY, new ArrayList());
inputs.put(AbstractWorkflowComponent.CONTEXT_PARAMETERS_KEY, new HashMap());
try
{
var workflow = workflowProvider.getAmetysObjectWorkflow(content);
workflow.doAction(content.getWorkflowId(), actionId, inputs);
}
catch (e)
{
print("[ERROR] An error occured while do workflow action '" + actionId + "' on content '" + content.getId() + "'", e);
}
}
Apogée fields migrated to reference table
4 fields linked to the Apogée export have been changed from enumeration to reference table:
Cycle
Authorized listing plans
CIP list
Stage duration
The following script must therefore be passed (the data in the reference tables can be adapted by modifying the tables at script)
Oops!
Copy to clipboard failed. Open the code and copy it manually.
const filterNameHelper = Java.type("org.ametys.cms.FilterNameHelper");
const odfTableRefHelper = Ametys.serviceManager.lookup("org.ametys.odf.enumeration.OdfReferenceTableHelper");
var cycles = {
'0': 'Pré-universitaire',
'1': 'Premier cycle',
'2': 'Deuxième cycle',
'3': 'Troisième cycle'
};
var inscriptions = {
'1': 'Régime initial',
'2': 'Régime continu'
};
var cips = {
'A': 'CIP Apogée',
'G': 'Eco-Gest'
};
var durations = {
'AN': 'Année',
'PA': 'Pluri-annuelle',
'SE': 'Semestre',
'TR': 'Trimestre'
};
function createTableRef(mapping, contentType)
{
var count = 0;
for (var code in mapping)
{
var item = odfTableRefHelper.getItemFromCode(contentType, code);
if (item == null)
{
var tableRefContent = Content.create({
contentTypes: contentType,
contentTitle: {
fr: mapping[code],
},
contentName: filterNameHelper.filterName(mapping[code]),
workflowName: "reference-table"
});
tableRefContent.setValue("code", code);
tableRefContent.setValue("codeApogee", code);
Content.save(tableRefContent);
count++;
}
}
print(count + " contenu(s) créé(s) pour la table de référence " + contentType);
}
createTableRef(cycles, "odf-enumeration.CycleApogee");
createTableRef(inscriptions, "odf-enumeration.InscriptionType");
createTableRef(cips, "odf-enumeration.Cips");
createTableRef(durations, "odf-enumeration.DurationApogee");
print("Migration des programmes");
migrateContents('org.ametys.plugins.odf.Content.program');
print("Migration des sous-programmes");
migrateContents('org.ametys.plugins.odf.Content.subProgram');
print("Migration des conteneurs");
migrateContents('org.ametys.plugins.odf.Content.container');
print("Migration des ELPs");
migrateContents('org.ametys.plugins.odf.Content.course');
function migrateContents(contentType)
{
var count = {
existing: 0,
done: 0
};
Repository.query("//element(*, ametys:content)[@ametys-internal:contentType = '" + contentType + "']").forEach(function(content) {
count.existing++;
Content.migrate(content,
migrateODFContent,
false,
null,
false);
count.done++;
});
print(count.done + " contents migrated on " + count.existing + " existing contents");
}
function migrateODFContent(content)
{
migrateSingleAttribute(content, "cycleApogee", "odf-enumeration.CycleApogee");
migrateMultipleAttribute(content, "inscription-types", "odf-enumeration.InscriptionType");
migrateMultipleAttribute(content, "cips", "odf-enumeration.Cips");
migrateSingleAttribute(content, "duration-apogee", "odf-enumeration.DurationApogee");
}
function migrateSingleAttribute(content, attributeName, attributeContentType)
{
if (content.hasValue(attributeName))
{
var node = content.getNode();
if (node.isLocked())
{
content.unlock();
}
if (node.hasProperty("ametys:" + attributeName))
{
var property = node.getProperty("ametys:" + attributeName);
var oldVal = property.getString();
var item = odfTableRefHelper.getItemFromCode(attributeContentType, oldVal);
property.remove();
if (item != null)
{
content.setValue(attributeName, item.getId());
}
}
}
}
function migrateMultipleAttribute(content, attributeName, attributeContentType)
{
if (content.hasValue(attributeName))
{
var node = content.getNode();
if (node.isLocked())
{
content.unlock();
}
if (node.hasProperty("ametys:" + attributeName))
{
var newValues = [];
var property = node.getProperty("ametys:" + attributeName);
var values = property.getValues();
for (var i in values)
{
var item = odfTableRefHelper.getItemFromCode(attributeContentType, values[i].getString());
if (item != null)
{
newValues.push(item.getId());
}
}
property.remove();
if (newValues.length != 0)
{
Repository.helper.setProperty(node, attributeName, newValues);
}
}
}
}
const filterNameHelper = Java.type("org.ametys.cms.FilterNameHelper");
const odfTableRefHelper = Ametys.serviceManager.lookup("org.ametys.odf.enumeration.OdfReferenceTableHelper");
var cycles = {
'0': 'Pré-universitaire',
'1': 'Premier cycle',
'2': 'Deuxième cycle',
'3': 'Troisième cycle'
};
var inscriptions = {
'1': 'Régime initial',
'2': 'Régime continu'
};
var cips = {
'A': 'CIP Apogée',
'G': 'Eco-Gest'
};
var durations = {
'AN': 'Année',
'PA': 'Pluri-annuelle',
'SE': 'Semestre',
'TR': 'Trimestre'
};
function createTableRef(mapping, contentType)
{
var count = 0;
for (var code in mapping)
{
var item = odfTableRefHelper.getItemFromCode(contentType, code);
if (item == null)
{
var tableRefContent = Content.create({
contentTypes: contentType,
contentTitle: {
fr: mapping[code],
},
contentName: filterNameHelper.filterName(mapping[code]),
workflowName: "reference-table"
});
tableRefContent.setValue("code", code);
tableRefContent.setValue("codeApogee", code);
Content.save(tableRefContent);
count++;
}
}
print(count + " contenu(s) créé(s) pour la table de référence " + contentType);
}
createTableRef(cycles, "odf-enumeration.CycleApogee");
createTableRef(inscriptions, "odf-enumeration.InscriptionType");
createTableRef(cips, "odf-enumeration.Cips");
createTableRef(durations, "odf-enumeration.DurationApogee");
print("Migration des programmes");
migrateContents('org.ametys.plugins.odf.Content.program');
print("Migration des sous-programmes");
migrateContents('org.ametys.plugins.odf.Content.subProgram');
print("Migration des conteneurs");
migrateContents('org.ametys.plugins.odf.Content.container');
print("Migration des ELPs");
migrateContents('org.ametys.plugins.odf.Content.course');
function migrateContents(contentType)
{
var count = {
existing: 0,
done: 0
};
Repository.query("//element(*, ametys:content)[@ametys-internal:contentType = '" + contentType + "']").forEach(function(content) {
count.existing++;
Content.migrate(content,
migrateODFContent,
false,
null,
false);
count.done++;
});
print(count.done + " contents migrated on " + count.existing + " existing contents");
}
function migrateODFContent(content)
{
migrateSingleAttribute(content, "cycleApogee", "odf-enumeration.CycleApogee");
migrateMultipleAttribute(content, "inscription-types", "odf-enumeration.InscriptionType");
migrateMultipleAttribute(content, "cips", "odf-enumeration.Cips");
migrateSingleAttribute(content, "duration-apogee", "odf-enumeration.DurationApogee");
}
function migrateSingleAttribute(content, attributeName, attributeContentType)
{
if (content.hasValue(attributeName))
{
var node = content.getNode();
if (node.isLocked())
{
content.unlock();
}
if (node.hasProperty("ametys:" + attributeName))
{
var property = node.getProperty("ametys:" + attributeName);
var oldVal = property.getString();
var item = odfTableRefHelper.getItemFromCode(attributeContentType, oldVal);
property.remove();
if (item != null)
{
content.setValue(attributeName, item.getId());
}
}
}
}
function migrateMultipleAttribute(content, attributeName, attributeContentType)
{
if (content.hasValue(attributeName))
{
var node = content.getNode();
if (node.isLocked())
{
content.unlock();
}
if (node.hasProperty("ametys:" + attributeName))
{
var newValues = [];
var property = node.getProperty("ametys:" + attributeName);
var values = property.getValues();
for (var i in values)
{
var item = odfTableRefHelper.getItemFromCode(attributeContentType, values[i].getString());
if (item != null)
{
newValues.push(item.getId());
}
}
property.remove();
if (newValues.length != 0)
{
Repository.helper.setProperty(node, attributeName, newValues);
}
}
}
}
const filterNameHelper = Java.type("org.ametys.cms.FilterNameHelper");
const odfTableRefHelper = Ametys.serviceManager.lookup("org.ametys.odf.enumeration.OdfReferenceTableHelper");
var cycles = {
'0': 'Pré-universitaire',
'1': 'Premier cycle',
'2': 'Deuxième cycle',
'3': 'Troisième cycle'
};
var inscriptions = {
'1': 'Régime initial',
'2': 'Régime continu'
};
var cips = {
'A': 'CIP Apogée',
'G': 'Eco-Gest'
};
var durations = {
'AN': 'Année',
'PA': 'Pluri-annuelle',
'SE': 'Semestre',
'TR': 'Trimestre'
};
function createTableRef(mapping, contentType)
{
var count = 0;
for (var code in mapping)
{
var item = odfTableRefHelper.getItemFromCode(contentType, code);
if (item == null)
{
var tableRefContent = Content.create({
contentTypes: contentType,
contentTitle: {
fr: mapping[code],
},
contentName: filterNameHelper.filterName(mapping[code]),
workflowName: "reference-table"
});
tableRefContent.setValue("code", code);
tableRefContent.setValue("codeApogee", code);
Content.save(tableRefContent);
count++;
}
}
print(count + " contenu(s) créé(s) pour la table de référence " + contentType);
}
createTableRef(cycles, "odf-enumeration.CycleApogee");
createTableRef(inscriptions, "odf-enumeration.InscriptionType");
createTableRef(cips, "odf-enumeration.Cips");
createTableRef(durations, "odf-enumeration.DurationApogee");
print("Migration des programmes");
migrateContents('org.ametys.plugins.odf.Content.program');
print("Migration des sous-programmes");
migrateContents('org.ametys.plugins.odf.Content.subProgram');
print("Migration des conteneurs");
migrateContents('org.ametys.plugins.odf.Content.container');
print("Migration des ELPs");
migrateContents('org.ametys.plugins.odf.Content.course');
function migrateContents(contentType)
{
var count = {
existing: 0,
done: 0
};
Repository.query("//element(*, ametys:content)[@ametys-internal:contentType = '" + contentType + "']").forEach(function(content) {
count.existing++;
Content.migrate(content,
migrateODFContent,
false,
null,
false);
count.done++;
});
print(count.done + " contents migrated on " + count.existing + " existing contents");
}
function migrateODFContent(content)
{
migrateSingleAttribute(content, "cycleApogee", "odf-enumeration.CycleApogee");
migrateMultipleAttribute(content, "inscription-types", "odf-enumeration.InscriptionType");
migrateMultipleAttribute(content, "cips", "odf-enumeration.Cips");
migrateSingleAttribute(content, "duration-apogee", "odf-enumeration.DurationApogee");
}
function migrateSingleAttribute(content, attributeName, attributeContentType)
{
if (content.hasValue(attributeName))
{
var node = content.getNode();
if (node.isLocked())
{
content.unlock();
}
if (node.hasProperty("ametys:" + attributeName))
{
var property = node.getProperty("ametys:" + attributeName);
var oldVal = property.getString();
var item = odfTableRefHelper.getItemFromCode(attributeContentType, oldVal);
property.remove();
if (item != null)
{
content.setValue(attributeName, item.getId());
}
}
}
}
function migrateMultipleAttribute(content, attributeName, attributeContentType)
{
if (content.hasValue(attributeName))
{
var node = content.getNode();
if (node.isLocked())
{
content.unlock();
}
if (node.hasProperty("ametys:" + attributeName))
{
var newValues = [];
var property = node.getProperty("ametys:" + attributeName);
var values = property.getValues();
for (var i in values)
{
var item = odfTableRefHelper.getItemFromCode(attributeContentType, values[i].getString());
if (item != null)
{
newValues.push(item.getId());
}
}
property.remove();
if (newValues.length != 0)
{
Repository.helper.setProperty(node, attributeName, newValues);
}
}
}
}
You can run the following script to position a label according to diploma type. Please note that script is just an example, and the __MAPPING object must be adapted to suit your own diploma types.
Oops!
Copy to clipboard failed. Open the code and copy it manually.
To identify state-controlled training courses, a new boolean "certified" field has been added to the training courses and itineraries. If most of the training courses are state-controlled, it will be tedious to go through all the training courses to change this field to true.
Below is an example of script to position this field at true for training courses and itineraries according to the following rules:
The "certified" field is set to true for all courses other than bachelor's, master's and professional bachelor's degrees.
The "certified" field is set to true for (direct) courses of a bachelor's, master's or professional license type.
You can adapt script to suit your own needs.
Oops!
Copy to clipboard failed. Open the code and copy it manually.
const RefTableHelperType = Java.type("org.ametys.odf.enumeration.OdfReferenceTableHelper");
const refTableHelper = Ametys.serviceManager.lookup(RefTableHelperType.ROLE);
// Licence
const licenceId = refTableHelper.getItemFromCode("odf-enumeration.Degree", "XA").getId();
// Master
const masterId = refTableHelper.getItemFromCode("odf-enumeration.Degree", "XB").getId();
// Licence pro
const licenceProId = refTableHelper.getItemFromCode("odf-enumeration.Degree", "DP").getId()
function _setCertification(content)
{
content.setValue("certified", true);
}
// Itère sur toutes les formations SAUF les licences, master et licences professionnelles
// et positionne le champ "formation controlée par l'état" à true
let nbcontent = 0;
const predicate = "@ametys:degree != '" + licenceId + "' and @ametys:degree != '" + masterId + "' and @ametys:degree != '" + licenceProId + "'";
Repository.query("//element(*, ametys:programContent)[not(@ametys:certified) and " + predicate + "]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_setCertification],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} programs(s) has been marked as certified`);
// Itère sur tous les parcours des licences, master et licences professionnelles
// et positionne le champ "formation controlée par l'état" à true
nbcontent = 0;
const predicate2 = "@ametys:degree = '" + licenceId + "' or @ametys:degree = '" + masterId + "' or @ametys:degree = '" + licenceProId + "'";
Repository.query("//element(*, ametys:programContent)[" + predicate2 + "]")
.forEach(function(program)
{
program.getProgramPartChildren().forEach(function(child){
if (child.getClass().getName() == 'org.ametys.odf.program.SubProgram' && !child.hasValue("certified"))
{
nbcontent++;
Content.migrate(
child,
[_setCertification],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
}
);
});
Ametys.console.info(`${nbcontent} subprograms(s) has been marked as certified`);
Ametys.console.info(`Live workspace has to be rebuilt.`);
const RefTableHelperType = Java.type("org.ametys.odf.enumeration.OdfReferenceTableHelper");
const refTableHelper = Ametys.serviceManager.lookup(RefTableHelperType.ROLE);
// Licence
const licenceId = refTableHelper.getItemFromCode("odf-enumeration.Degree", "XA").getId();
// Master
const masterId = refTableHelper.getItemFromCode("odf-enumeration.Degree", "XB").getId();
// Licence pro
const licenceProId = refTableHelper.getItemFromCode("odf-enumeration.Degree", "DP").getId()
function _setCertification(content)
{
content.setValue("certified", true);
}
// Itère sur toutes les formations SAUF les licences, master et licences professionnelles
// et positionne le champ "formation controlée par l'état" à true
let nbcontent = 0;
const predicate = "@ametys:degree != '" + licenceId + "' and @ametys:degree != '" + masterId + "' and @ametys:degree != '" + licenceProId + "'";
Repository.query("//element(*, ametys:programContent)[not(@ametys:certified) and " + predicate + "]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_setCertification],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} programs(s) has been marked as certified`);
// Itère sur tous les parcours des licences, master et licences professionnelles
// et positionne le champ "formation controlée par l'état" à true
nbcontent = 0;
const predicate2 = "@ametys:degree = '" + licenceId + "' or @ametys:degree = '" + masterId + "' or @ametys:degree = '" + licenceProId + "'";
Repository.query("//element(*, ametys:programContent)[" + predicate2 + "]")
.forEach(function(program)
{
program.getProgramPartChildren().forEach(function(child){
if (child.getClass().getName() == 'org.ametys.odf.program.SubProgram' && !child.hasValue("certified"))
{
nbcontent++;
Content.migrate(
child,
[_setCertification],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
}
);
});
Ametys.console.info(`${nbcontent} subprograms(s) has been marked as certified`);
Ametys.console.info(`Live workspace has to be rebuilt.`);
const RefTableHelperType = Java.type("org.ametys.odf.enumeration.OdfReferenceTableHelper");
const refTableHelper = Ametys.serviceManager.lookup(RefTableHelperType.ROLE);
// Licence
const licenceId = refTableHelper.getItemFromCode("odf-enumeration.Degree", "XA").getId();
// Master
const masterId = refTableHelper.getItemFromCode("odf-enumeration.Degree", "XB").getId();
// Licence pro
const licenceProId = refTableHelper.getItemFromCode("odf-enumeration.Degree", "DP").getId()
function _setCertification(content)
{
content.setValue("certified", true);
}
// Itère sur toutes les formations SAUF les licences, master et licences professionnelles
// et positionne le champ "formation controlée par l'état" à true
let nbcontent = 0;
const predicate = "@ametys:degree != '" + licenceId + "' and @ametys:degree != '" + masterId + "' and @ametys:degree != '" + licenceProId + "'";
Repository.query("//element(*, ametys:programContent)[not(@ametys:certified) and " + predicate + "]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_setCertification],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} programs(s) has been marked as certified`);
// Itère sur tous les parcours des licences, master et licences professionnelles
// et positionne le champ "formation controlée par l'état" à true
nbcontent = 0;
const predicate2 = "@ametys:degree = '" + licenceId + "' or @ametys:degree = '" + masterId + "' or @ametys:degree = '" + licenceProId + "'";
Repository.query("//element(*, ametys:programContent)[" + predicate2 + "]")
.forEach(function(program)
{
program.getProgramPartChildren().forEach(function(child){
if (child.getClass().getName() == 'org.ametys.odf.program.SubProgram' && !child.hasValue("certified"))
{
nbcontent++;
Content.migrate(
child,
[_setCertification],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
}
);
});
Ametys.console.info(`${nbcontent} subprograms(s) has been marked as certified`);
Ametys.console.info(`Live workspace has to be rebuilt.`);
Competency-based approach
The new competency-based approach is leading to changes in models:
added "Acquisition level" reference table
suppression des liens Blocs de compétences <-> Compétences
Training/Course :
requiredSkillSets (multiple value of Skill Blocks) becomes requiredSkills (multiple value of Skills)
acquiredSkillSets is deleted
ELP
requiredSkillSets (multiple value of Skill Blocks) becomes requiredSkills (multiple value of Skills)
acquiredSkillSets (multiple value of Skill Blocks) becomes acquiredSkills, which is a repeater of a Skill Block, itself a repeater of a Skill with an acquisition level.
First, run the following script to migrate skills to your ODF content:
Oops!
Copy to clipboard failed. Open the code and copy it manually.
const RefTableHelperType = Java.type("org.ametys.odf.enumeration.OdfReferenceTableHelper");
const refTableHelper = Ametys.serviceManager.lookup(RefTableHelperType.ROLE);
const ContentDataHelper = Java.type("org.ametys.cms.data.ContentDataHelper");
const ConsoleHelper = Java.type("org.ametys.workspaces.repository.ConsoleHelper");
function _getSkillsId(content, attributeName)
{
var skillIds = [];
if (content.getNode().hasProperty('ametys:' + attributeName))
{
var skillSets = content.getNode().getProperty('ametys:' + attributeName).getValues();
if (skillSets.length > 0)
{
for (var i in skillSets)
{
var skillSetId = skillSets[i].getString();
var skillSet = Repository.resolver.resolveById(skillSetId);
if (skillSet.getNode().hasProperty('ametys:skills'))
{
var skills = skillSet.getNode().getProperty('ametys:skills').getValues();
for (var j in skills)
{
skillIds.push(skills[j].getString());
}
}
}
}
}
return skillIds;
}
function _setSkills(content, attributeName, skillIds)
{
if (skillIds.length > 0)
{
ConsoleHelper.setProperty(content.getNode(), "ametys:" + attributeName, skillIds);
}
}
function _removeSkillSets(content, attributeName)
{
if (content.getNode().hasProperty('ametys:' + attributeName))
{
content.getNode().getProperty('ametys:' + attributeName).remove();
}
}
function _migrateSkills(content)
{
var requiredSkills = _getSkillsId(content, 'requiredSkillSets');
_setSkills(content, 'requiredSkills', requiredSkills);
_removeSkillSets(content, 'requiredSkillSets');
var acquiredSkills = _getSkillsId(content, 'acquiredSkillSets');
_setSkills(content, 'acquiredSkills', acquiredSkills);
_removeSkillSets(content, 'acquiredSkillSets');
}
function _migrateCourseSkills(content)
{
var requiredSkills = _getSkillsId(content, 'requiredSkillSets');
_setSkills(content, 'requiredSkills', requiredSkills);
_removeSkillSets(content, 'requiredSkillSets');
_setRepeaterSkillSet(content, 'acquiredSkillSets', 'acquiredSkills');
_removeSkillSets(content, 'acquiredSkillSets');
}
function _setRepeaterSkillSet(content, attributeName, repeaterName)
{
var node = content.getNode();
if (node.hasProperty('ametys:' + attributeName))
{
var skillSets = node.getProperty('ametys:' + attributeName).getValues();
if (skillSets.length > 0)
{
if (node.hasNode('ametys:' + repeaterName))
{
node.getNode('ametys:' + repeaterName).remove();
}
var repeater = node.addNode('ametys:' + repeaterName, 'ametys:compositeMetadata');
var index1 = 1;
for (var i in skillSets)
{
var skillSetId = skillSets[i].getString();
var entry = repeater.addNode('ametys:' + index1++, 'ametys:compositeMetadata');
entry.setProperty('ametys:skillSet', skillSetId);
var skillSet = Repository.resolver.resolveById(skillSetId);
if (skillSet.getNode().hasProperty('ametys:skills'))
{
var skills = skillSet.getNode().getProperty('ametys:skills').getValues();
var skillRep = entry.addNode('ametys:skills', 'ametys:compositeMetadata');
var index2 = 1;
for (var j in skills)
{
var skillEntry = skillRep.addNode('ametys:' + index2++, 'ametys:compositeMetadata');
skillEntry.setProperty("ametys:skill", skills[j].getString());
}
}
}
}
}
}
let nbcontent = 0;
Repository.query("//element(*, ametys:programContent)[@ametys:requiredSkillSets or @ametys:acquiredSkillSets]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_migrateSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} programs(s) has been migrated`);
nbcontent = 0;
Repository.query("//element(*, ametys:subProgramContent)[@ametys:requiredSkillSets or @ametys:acquiredSkillSets]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_migrateSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} subprograms(s) has been migrated`);
nbcontent = 0;
Repository.query("//element(*, ametys:courseContent)[@ametys:requiredSkillSets or @ametys:acquiredSkillSets]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_migrateCourseSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} course(s) has been migrated`);
Ametys.console.info(`Live workspace has to be rebuilt.`);
const RefTableHelperType = Java.type("org.ametys.odf.enumeration.OdfReferenceTableHelper");
const refTableHelper = Ametys.serviceManager.lookup(RefTableHelperType.ROLE);
const ContentDataHelper = Java.type("org.ametys.cms.data.ContentDataHelper");
const ConsoleHelper = Java.type("org.ametys.workspaces.repository.ConsoleHelper");
function _getSkillsId(content, attributeName)
{
var skillIds = [];
if (content.getNode().hasProperty('ametys:' + attributeName))
{
var skillSets = content.getNode().getProperty('ametys:' + attributeName).getValues();
if (skillSets.length > 0)
{
for (var i in skillSets)
{
var skillSetId = skillSets[i].getString();
var skillSet = Repository.resolver.resolveById(skillSetId);
if (skillSet.getNode().hasProperty('ametys:skills'))
{
var skills = skillSet.getNode().getProperty('ametys:skills').getValues();
for (var j in skills)
{
skillIds.push(skills[j].getString());
}
}
}
}
}
return skillIds;
}
function _setSkills(content, attributeName, skillIds)
{
if (skillIds.length > 0)
{
ConsoleHelper.setProperty(content.getNode(), "ametys:" + attributeName, skillIds);
}
}
function _removeSkillSets(content, attributeName)
{
if (content.getNode().hasProperty('ametys:' + attributeName))
{
content.getNode().getProperty('ametys:' + attributeName).remove();
}
}
function _migrateSkills(content)
{
var requiredSkills = _getSkillsId(content, 'requiredSkillSets');
_setSkills(content, 'requiredSkills', requiredSkills);
_removeSkillSets(content, 'requiredSkillSets');
var acquiredSkills = _getSkillsId(content, 'acquiredSkillSets');
_setSkills(content, 'acquiredSkills', acquiredSkills);
_removeSkillSets(content, 'acquiredSkillSets');
}
function _migrateCourseSkills(content)
{
var requiredSkills = _getSkillsId(content, 'requiredSkillSets');
_setSkills(content, 'requiredSkills', requiredSkills);
_removeSkillSets(content, 'requiredSkillSets');
_setRepeaterSkillSet(content, 'acquiredSkillSets', 'acquiredSkills');
_removeSkillSets(content, 'acquiredSkillSets');
}
function _setRepeaterSkillSet(content, attributeName, repeaterName)
{
var node = content.getNode();
if (node.hasProperty('ametys:' + attributeName))
{
var skillSets = node.getProperty('ametys:' + attributeName).getValues();
if (skillSets.length > 0)
{
if (node.hasNode('ametys:' + repeaterName))
{
node.getNode('ametys:' + repeaterName).remove();
}
var repeater = node.addNode('ametys:' + repeaterName, 'ametys:compositeMetadata');
var index1 = 1;
for (var i in skillSets)
{
var skillSetId = skillSets[i].getString();
var entry = repeater.addNode('ametys:' + index1++, 'ametys:compositeMetadata');
entry.setProperty('ametys:skillSet', skillSetId);
var skillSet = Repository.resolver.resolveById(skillSetId);
if (skillSet.getNode().hasProperty('ametys:skills'))
{
var skills = skillSet.getNode().getProperty('ametys:skills').getValues();
var skillRep = entry.addNode('ametys:skills', 'ametys:compositeMetadata');
var index2 = 1;
for (var j in skills)
{
var skillEntry = skillRep.addNode('ametys:' + index2++, 'ametys:compositeMetadata');
skillEntry.setProperty("ametys:skill", skills[j].getString());
}
}
}
}
}
}
let nbcontent = 0;
Repository.query("//element(*, ametys:programContent)[@ametys:requiredSkillSets or @ametys:acquiredSkillSets]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_migrateSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} programs(s) has been migrated`);
nbcontent = 0;
Repository.query("//element(*, ametys:subProgramContent)[@ametys:requiredSkillSets or @ametys:acquiredSkillSets]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_migrateSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} subprograms(s) has been migrated`);
nbcontent = 0;
Repository.query("//element(*, ametys:courseContent)[@ametys:requiredSkillSets or @ametys:acquiredSkillSets]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_migrateCourseSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} course(s) has been migrated`);
Ametys.console.info(`Live workspace has to be rebuilt.`);
const RefTableHelperType = Java.type("org.ametys.odf.enumeration.OdfReferenceTableHelper");
const refTableHelper = Ametys.serviceManager.lookup(RefTableHelperType.ROLE);
const ContentDataHelper = Java.type("org.ametys.cms.data.ContentDataHelper");
const ConsoleHelper = Java.type("org.ametys.workspaces.repository.ConsoleHelper");
function _getSkillsId(content, attributeName)
{
var skillIds = [];
if (content.getNode().hasProperty('ametys:' + attributeName))
{
var skillSets = content.getNode().getProperty('ametys:' + attributeName).getValues();
if (skillSets.length > 0)
{
for (var i in skillSets)
{
var skillSetId = skillSets[i].getString();
var skillSet = Repository.resolver.resolveById(skillSetId);
if (skillSet.getNode().hasProperty('ametys:skills'))
{
var skills = skillSet.getNode().getProperty('ametys:skills').getValues();
for (var j in skills)
{
skillIds.push(skills[j].getString());
}
}
}
}
}
return skillIds;
}
function _setSkills(content, attributeName, skillIds)
{
if (skillIds.length > 0)
{
ConsoleHelper.setProperty(content.getNode(), "ametys:" + attributeName, skillIds);
}
}
function _removeSkillSets(content, attributeName)
{
if (content.getNode().hasProperty('ametys:' + attributeName))
{
content.getNode().getProperty('ametys:' + attributeName).remove();
}
}
function _migrateSkills(content)
{
var requiredSkills = _getSkillsId(content, 'requiredSkillSets');
_setSkills(content, 'requiredSkills', requiredSkills);
_removeSkillSets(content, 'requiredSkillSets');
var acquiredSkills = _getSkillsId(content, 'acquiredSkillSets');
_setSkills(content, 'acquiredSkills', acquiredSkills);
_removeSkillSets(content, 'acquiredSkillSets');
}
function _migrateCourseSkills(content)
{
var requiredSkills = _getSkillsId(content, 'requiredSkillSets');
_setSkills(content, 'requiredSkills', requiredSkills);
_removeSkillSets(content, 'requiredSkillSets');
_setRepeaterSkillSet(content, 'acquiredSkillSets', 'acquiredSkills');
_removeSkillSets(content, 'acquiredSkillSets');
}
function _setRepeaterSkillSet(content, attributeName, repeaterName)
{
var node = content.getNode();
if (node.hasProperty('ametys:' + attributeName))
{
var skillSets = node.getProperty('ametys:' + attributeName).getValues();
if (skillSets.length > 0)
{
if (node.hasNode('ametys:' + repeaterName))
{
node.getNode('ametys:' + repeaterName).remove();
}
var repeater = node.addNode('ametys:' + repeaterName, 'ametys:compositeMetadata');
var index1 = 1;
for (var i in skillSets)
{
var skillSetId = skillSets[i].getString();
var entry = repeater.addNode('ametys:' + index1++, 'ametys:compositeMetadata');
entry.setProperty('ametys:skillSet', skillSetId);
var skillSet = Repository.resolver.resolveById(skillSetId);
if (skillSet.getNode().hasProperty('ametys:skills'))
{
var skills = skillSet.getNode().getProperty('ametys:skills').getValues();
var skillRep = entry.addNode('ametys:skills', 'ametys:compositeMetadata');
var index2 = 1;
for (var j in skills)
{
var skillEntry = skillRep.addNode('ametys:' + index2++, 'ametys:compositeMetadata');
skillEntry.setProperty("ametys:skill", skills[j].getString());
}
}
}
}
}
}
let nbcontent = 0;
Repository.query("//element(*, ametys:programContent)[@ametys:requiredSkillSets or @ametys:acquiredSkillSets]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_migrateSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} programs(s) has been migrated`);
nbcontent = 0;
Repository.query("//element(*, ametys:subProgramContent)[@ametys:requiredSkillSets or @ametys:acquiredSkillSets]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_migrateSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} subprograms(s) has been migrated`);
nbcontent = 0;
Repository.query("//element(*, ametys:courseContent)[@ametys:requiredSkillSets or @ametys:acquiredSkillSets]")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_migrateCourseSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} course(s) has been migrated`);
Ametys.console.info(`Live workspace has to be rebuilt.`);
Then run the following script (only if the 1st script was successful!) to remove the link between the Skills and Skill Blocks reference tables:
Oops!
Copy to clipboard failed. Open the code and copy it manually.
let nbcontent = 0;
function _removeSkills(content)
{
if (content.hasValue('ametys:skills'))
{
content.getProperty('ametys:skills').remove();
nbcontent++;
}
}
function _removeSkillSets(content)
{
if (content.hasValue('ametys:skillSets'))
{
content.getProperty('ametys:skillSets').remove();
}
}
Repository.query("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.SkillSet']")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_removeSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} skill set(s) has been migrated`);
Repository.query("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.Skill']")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_removeSkillSets],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} skill(s) has been migrated`);
let nbcontent = 0;
function _removeSkills(content)
{
if (content.hasValue('ametys:skills'))
{
content.getProperty('ametys:skills').remove();
nbcontent++;
}
}
function _removeSkillSets(content)
{
if (content.hasValue('ametys:skillSets'))
{
content.getProperty('ametys:skillSets').remove();
}
}
Repository.query("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.SkillSet']")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_removeSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} skill set(s) has been migrated`);
Repository.query("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.Skill']")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_removeSkillSets],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} skill(s) has been migrated`);
let nbcontent = 0;
function _removeSkills(content)
{
if (content.hasValue('ametys:skills'))
{
content.getProperty('ametys:skills').remove();
nbcontent++;
}
}
function _removeSkillSets(content)
{
if (content.hasValue('ametys:skillSets'))
{
content.getProperty('ametys:skillSets').remove();
}
}
Repository.query("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.SkillSet']")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_removeSkills],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} skill set(s) has been migrated`);
Repository.query("//element(*, ametys:content)[@ametys-internal:contentType = 'odf-enumeration.Skill']")
.forEach(function(content) {
nbcontent++;
Content.migrate(
content,
[_removeSkillSets],
false /* old versions are still compatible */,
null /* no tag */,
false /* not verbose */
);
}
);
Ametys.console.info(`${nbcontent} skill(s) has been migrated`);