Technical migration manual from version 2.2.x to version 2.3.0


 

  1. Training catalog
    1. Catalog duplication
    2. New enumerated field "Catalog
    3. Training offer root page
    4. Service migration
  2. New parameter file
  3. Service migration
  4. Dashboards
  5. Nomenclature of terms
  6. ELP research
  7. Change in storage format

Training catalog

To be included in the tree structure, a training course must be linked to a catalog.

Catalogs are managed via a "Catalogues" tool inODF.

The script link below allows you to create catalogs without using the GUI. This may be useful for executing the following scripts in this migration manual.
Customize the table beforehand catalogs based on your own catalogs.

If you have an intermediate version where the catalogs are defined in a file XML (WEB-INF/params/odf/catalog.xml), fill this table with the values of the file so that the formations and the root pages ofODF do not lose their current catalog. You can delete the file and its reference in the file .

// A PERSONNALISER (code, libellé)
var catalogs = [
  ['2013-2017', 'Catalogue 2013-2017'],
  ['2009-2013', 'Catalogue 2009-2013']
]

var pluginsNode = session.getRootNode().getNode('ametys:root');
if (pluginsNode.hasNode('ametys:plugins'))
{
  pluginsNode = pluginsNode.getNode('ametys:plugins');
}
else
{
  pluginsNode = pluginsNode.addNode('ametys:plugins', 'ametys:unstructured');
}
if (!pluginsNode.hasNode('odf'))
{
    pluginsNode.addNode('odf', 'ametys:unstructured');
}
var odfNode = pluginsNode.getNode('odf');
if (!odfNode.hasNode('catalogs'))
{
    odfNode.addNode('catalogs', 'ametys:unstructured');
}
var catalogsNode = odfNode.getNode('catalogs');
println(catalogsNode.getPath());
  
for (var i=0; i < catalogs.length; i++)
{
  var name = catalogs[i][0];
  var title = catalogs[i][1];

  if (!catalogsNode.hasNode(name))
  {
      var node = catalogsNode.addNode(name, 'ametys:catalog');
      node.setProperty('ametys:title', title);
  }
}
  
session.save();

Catalog duplication

It is possible to create a catalog by copying another catalog. In this case, all the training courses linked to the copied catalog will be duplicated and assigned to the new catalog.

For the copy to work, add action 0 to the training workflow file. WEB-INF/param/workflow-program.xml

<initial-actions>
        <action id="0" name="plugin.odf:WORKFLOW_ACTION_CREATE_BY_COPY">
            <results>
                <unconditional-result old-status=" " status=" " step="1" />
            </results>
        </action>
		...
</initial-actions>

 

New enumerated field "Catalog

A course therefore contains a new, mandatory"Catalog" enumerated field. Possible values are those created via the HMI and the "Catalogues" tool, or those created via script above.

Run script in the repository console to link all existing courses to a catalog.

Customize the catalogDefaultValue based on your own catalogs.

importPackage(javax.jcr);

var catalogDefaultValue = "2013-2017"; // A PERSONNALISER

var processProgram = function (program)
{
	if (!program.hasProperty("ametys:catalog"))
   	{
       program.setProperty("ametys:catalog", catalogDefaultValue);
       program.save();
       return true;
   	}
	return false;
}

// Default workspace
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.program']", javax.jcr.query.Query.XPATH);   
var nodes = query.execute().getNodes();
    
var count = 0;
while (nodes.hasNext())
{
	if (processProgram(nodes.next()))
	{
		count++;
	} 
}  
println(count + " formations ont été mises à jour dans le workspace 'default'");

// Live workspace
var credentials = new SimpleCredentials('ametys', []);
var liveSession = repository.login(credentials, 'live');

qm = liveSession.getWorkspace().getQueryManager();
query = qm.createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.program']", javax.jcr.query.Query.XPATH);   
nodes = query.execute().getNodes();

count = 0;
while (nodes.hasNext())
{
   	if (processProgram(nodes.next()))
	{
		count++;
	} 
}
println(count + " formations ont été mises à jour dans le workspace 'live'");

If you have overloaded the program content definition(WEB-INF/param/content-types/_override/*.xml), you must add the reference to the "catalog" metadata in the "main" view in edit mode and in the "index" view in view mode. You can also add it in the main view in visualization mode if you wish to display the catalog name in the course rendering.

<cms:metadata-set name="main" type="edition">
       <cms:metadata-ref name="title" />
       <cms:metadata-ref name="catalog" />
	   <!-- // etc .. -->
</cms:metadata-set>

<cms:metadata-set name="main" type="view">
       <cms:metadata-ref name="title" />
       <cms:metadata-ref name="catalog" />
	   <!-- // etc .. -->
</cms:metadata-set>

<cms:metadata-set name="index" type="view">
       <cms:metadata-ref name="title" />
       <cms:metadata-ref name="catalog" />
	   <!-- // etc .. -->
</cms:metadata-set>

 

Training offer root page

Each training offer root page must be linked to a catalog. In this way, there can be as many training offer roots as there are catalogs.

In addition, the classification of courses in the site tree structure is now configurable. By default, courses are sorted by degree(Licence, Master, DUT, ...) then by domain(Art Lettres & Langues, Sciences et Technologies, ...).

The following script allows you to configure the catalog and the 1st and 2nd level tree structure of the training offer root page. Customize variables catalog, firstLevel and secondLevel at the start of script before executing script in the repository console.

importPackage(javax.jcr);

var catalog = "2013-2017"; // A PERSONNALISER
var firstLevel = "degree"; // A PERSONNALISER
var secondLevel = "domain"; // A PERSONNALISER

var processRootPage = function (page)
{
	var needSave = false;
	if (!page.hasProperty("ametys:odf-root-catalog"))
    {
        page.setProperty("ametys:odf-root-catalog", catalog);
		needSave = true; 
	}
    if (!page.hasProperty("ametys:firstLevel"))
    {
        page.setProperty("ametys:firstLevel", firstLevel);
        needSave = true;
    }
    if (!page.hasProperty("ametys:secondLevel"))
    {
        page.setProperty("ametys:secondLevel", secondLevel);
        needSave = true;
    }
	if (needSave)
    {
        page.save();
		return true;
	}
	return false;
}

// Default workspace
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:page)[@ametys-internal:virtual = 'org.ametys.plugins.odfweb.repository.VirtualPageFactory']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
    
var count = 0;
while (nodes.hasNext())
{
    if (processRootPage(nodes.next()))
	{
		count++;
	} 
}
println(count + " pages racines de l'ODF ont été modifiées dans le workspace 'default'");

// Live workspace
var credentials = new SimpleCredentials('ametys', []);
var liveSession = repository.login(credentials, 'live');

qm = liveSession.getWorkspace().getQueryManager();
query = qm.createQuery("//element(*, ametys:page)[@ametys-internal:virtual = 'org.ametys.plugins.odfweb.repository.VirtualPageFactory']", javax.jcr.query.Query.XPATH);
nodes = query.execute().getNodes();
    
count = 0;
while (nodes.hasNext())
{
    if (processRootPage(nodes.next()))
	{
		count++;
	} 
}
println(count + " pages racines de l'ODF ont été modifiées dans le workspace 'live'");

 

Service migration

To function, the 2 services "List of training courses" and "Search for a training course" require knowledge of the training catalog to which they are linked. Run the following script to set the catalog identifier to be used as a service parameter.

importPackage(javax.jcr);

var catalog = "2013-2017"; // A PERSONNALISER

var processService = function (node)
{
	var paramsNode = node.getNode('ametys:service_parameters');
    if (!paramsNode.hasProperty("ametys:catalog"))
    {
        paramsNode.setProperty('ametys:catalog', catalog);
        return true;
    } 
	return false;
}

// Default workspace
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:type='SERVICE' and (@ametys-internal:service='org.ametys.odf.service.ProgramList' or @ametys-internal:service='org.ametys.odf.service.SearchService')]", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
 
var migrated = 0;
while (nodes.hasNext())
{
	if (processService(nodes.next()))
	{
		migrated++;
	} 
}
session.save();
println(migrated + " services ODF ont été mis à jour dans le workspace 'default'");

// Live workspace
var credentials = new SimpleCredentials('ametys', []);
var liveSession = repository.login(credentials, 'live');

qm = liveSession.getWorkspace().getQueryManager();
query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:type='SERVICE' and (@ametys-internal:service='org.ametys.odf.service.ProgramList' or @ametys-internal:service='org.ametys.odf.service.SearchService')]", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
 
var migrated = 0;
while (nodes.hasNext())
{
	if (processService(nodes.next()))
	{
		migrated++;
	} 
}
liveSession.save();
println(migrated + " services ODF ont été mis à jour dans le workspace 'live'");

 

New parameter file

Create a new file WEB-INF/param/odf-enumeration.xml and copy and paste the following lines:

<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item key="DOMAIN" location="context://WEB-INF/param/odf/domain.xml"/>
    <item key="DEGREE" location="context://WEB-INF/param/odf/degree.xml"/>
    <item key="LEVEL" location="context://WEB-INF/param/odf/level.xml"/>
    <item key="PROGRAM_TYPE" location="context://WEB-INF/param/odf/program_type.xml"/>
    <item key="FORMOFTEACHING_METHOD" location="context://WEB-INF/param/odf/formofteaching_method.xml"/>
    <item key="FORMOFTEACHING_ORG" location="context://WEB-INF/param/odf/formofteaching_org.xml"/>
    <item key="TEACHING_ACTIVITY" location="context://WEB-INF/param/odf/teaching_activity.xml"/>
    <item key="INTERNSHIP" location="context://WEB-INF/param/odf/internship.xml"/>
    <item key="DISTANCE_LEARNING_MODALITIES" location="context://WEB-INF/param/odf/distance_learning_modalities.xml"/>
    <item key="PLACE" location="context://WEB-INF/param/odf/place.xml"/>
    <item key="TEACHING_TERM" location="context://WEB-INF/param/odf/teaching_term.xml"/>
    <item key="TIME_SLOT" location="context://WEB-INF/param/odf/time_slot.xml"/>
    <item key="CODE_DGESIP" location="context://WEB-INF/param/odf/code_dgesip.xml"/>
    <item key="CODE_ROME" location="context://WEB-INF/param/odf/code_rome.xml"/>
    <item key="CODE_SISE" location="context://WEB-INF/param/odf/code_sise.xml"/>
    <item key="CODE_ERASMUS" location="context://WEB-INF/param/odf/code_erasmus.xml"/>
    <item key="CODE_CITE97" location="context://WEB-INF/param/odf/code_cite97.xml"/>
    <item key="CODE_FAP" location="context://WEB-INF/param/odf/code_fap.xml"/>
    <item key="JOIN_ORGUNIT" location="context://WEB-INF/param/odf/join_orgunit.xml"/>
</items>

This file lists the enumerated lists available atODF.

Service migration

The parameters of the "course list" and "course search" services have been modified: all the metadata listed for the course content type can now be used.

The following scripts must be passed to the workspace repository console to migrate existing service parameters.

 List of courses :

var enumToMeta = {
    code_dgesip: 'dgesipCode',
    code_sise: 'siseCode',
    orgunit: 'orgUnit'
}

var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:type='SERVICE' and @ametys-internal:service='org.ametys.odf.service.ProgramList']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();

var migrated = 0;
while (nodes.hasNext())
{
    var node = nodes.next();
    var paramsNode = node.getNode('ametys:service_parameters');
    
    var firstLevel = paramsNode.getProperty('ametys:firstLevel').getString();
    var secondLevel = paramsNode.getProperty('ametys:secondLevel').getString();
    
    if (enumToMeta[firstLevel] != null)
    {
        paramsNode.setProperty('ametys:firstLevel', enumToMeta[firstLevel]);
    }
    if (enumToMeta[secondLevel] != null)
    {
        paramsNode.setProperty('ametys:secondLevel', enumToMeta[secondLevel]);
    }
    
    migrated++;
}

session.save();
println(migrated + ' program list service(s) have been migrated.');
 

Training search :

var enumToMeta = {
    type: 'educationKind',
    level: 'educationLevel',
    orgunit: 'orgUnit'
}
 
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:type='SERVICE' and @ametys-internal:service='org.ametys.odf.service.SearchService']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
 
var migrated = 0;
while (nodes.hasNext())
{
    var node = nodes.next();
    var paramsNode = node.getNode('ametys:service_parameters');
     
    var fieldsParam = paramsNode.getProperty('ametys:search-fields').getString();
    var fields = fieldsParam.split(',');
    var newFields = [];
    
    for (var i = 0; i < fields.length; i++)
    {
        if (enumToMeta[fields[i]]  != null)
        {
            newFields[i] = enumToMeta[fields[i]] ;
        }
        else
        {
            newFields[i] = fields[i];
        }
    }
    
    paramsNode.setProperty('ametys:search-fields', newFields.join(','));
     
    migrated++;
}
 
session.save();
println(migrated + ' search service(s) have been migrated.');

Live rebuilds must be performed after the migration scripts have been run.

Dashboards

Version 2.3.x of plugin includes two dashboards: one for training courses, the other for ELPs.

For these to work, you need to add two parameter files to the WEB-INF/params directory of your ODF application:

These files are example files, adapted to theODF demo application. They should be adapted to your own workflow files (workflow-program.xml, workflow-course.xml)

 

Nomenclature of terms

Since early 2014, a decree has set the nomenclature of mentions according to the type of degree: bachelor's, master's or professional license.

The "Mention" field is now an enumerated field. The list of possible mentions depends on the type of diploma, and only bachelor's degrees, master's degrees and professional bachelor's degrees can have a mention.

  • If you wish to switch to the new nomenclature

3 files XML contain the possible values and wordings of the endorsements for each diploma. Download the 3 files and copy them into your application's WEB-INF/param/odf directory:

Add/replace the associated i18n keys in your application catalog(WEB-INF/i18n /application.xml and WEB-INF/i18n/application_en .xml).

Finally, in the file WEB-INF/param/odf-enumeration.xml, add the following 3 lines:

<item key="MENTION_LICENCE" location="context://WEB-INF/param/odf/mention_licence.xml"/>
<item key="MENTION_LICENCEPRO" location="context://WEB-INF/param/odf/mention_licencepro.xml"/>
<item key="MENTION_MASTER" location="context://WEB-INF/param/odf/mention_master.xml"/>

Please note that if you have already overloaded the "mention" and/or "diploma" fields, you will need to modify the widgets used.

In the file org.ametys.plugins.odf.Content.program.xml in the WEB-INF\param\content-types\_override directory, you should have the following lines

<cms:metadata name="degree" type="string">
	<label i18n="true">...</label>
	<description i18n="true">...</description>
	<validation>
    	<mandatory/>
    </validation>
    <widget>degree-enumeration</widget>
    <widget-params>
    	<param name="enumerationName">degree</param>
   	</widget-params>
    <enumeration>
    	<custom-enumerator class="org.ametys.odf.enumeration.DegreesEnumerator"/>
    </enumeration>
</cms:metadata>

<cms:metadata name="mention" type="string">
	<label i18n="true">...</label>
	<description i18n="true">...</description>
	<widget>mention-enumeration</widget>
	<enumeration>
		<custom-enumerator class="org.ametys.odf.enumeration.MentionsEnumerator"/>
	</enumeration>
</cms:metadata>


  • If you wish to keep the existing system

If you want the mention field to remain a free text field, you need to override the definition of the "mention" field. To do this, create an org.ametys.plugins.odf.Content.program.xml file in the WEB-INF\param\content-types\_override directory (if you haven't already overloaded the fields of a course).

The file must contain the following lines:

<?xml version="1.0" encoding="UTF-8"?>
<cms:content-type xmlns:cms="http://www.ametys.org/schema/cms">
	<cms:metadata name="mention" type="string">
        <label i18n="true">PLUGINS_ODF_PROGRAM_MENTION</label>
        <description i18n="true">PLUGINS_ODF_PROGRAM_MENTION_DESC</description>
    </cms:metadata> 

	<!-- Autres surcharges éventuelles -->

</cms:content-type>

ELP research

A new service allows you to search for ELPs.

If your ODF application uses plugin odf-web, you must exclude the "odf/odf-content-indexer" feature in the WEB-INF/param/runtime file. xml

<plugins>
        <locations>
            <location>modules</location>
        </locations>
        <exclude>
			<!-- .... -->
			<feature>odf/init</feature>
            <feature>odf/odf-content-indexer</feature>
        </exclude>
</plugins>

Change in storage format

Changes have been made to theODF storage format to enable the reordering of ELP lists contained in an ELP (https://issues.ametys.org/browse/ODF-924). After updating CMS and before the first start-up, the file custom_nodetypes.xml (located in the <chemin_repository>/repository/nodetypes) must be deleted. The file will be automatically recreated when the server is restarted.

 

 

Back to top