Manuel de migration technique de la version 2.2.x vers la version 2.3.0

 

  1. Catalogue de formations
    1. Duplication de catalogue
    2. Nouveau champ énuméré "Catalogue"
    3. Page racine de l'offre de formation
    4. Migration des services
  2. Nouveau fichier de paramètres
  3. Migration de services
  4. Tableaux de bord
  5. Nomenclature des mentions
  6. Recherche sur les ELP
  7. Modification dans le format de stockage

Catalogue de formations

Pour prendre place dans l'arborescence, une formation doit obligatoirement être liée à un catalogue.

Les catalogues sont gérés au travers d'un outil "Catalogues" dans l'ODF.

Le script ci-dessous permet de créer des catalogues sans passer par l'IHM. Ceci peut être utile pour exécuter les scripts suivants de ce manuel de migration.
Personnalisez au préalable le tableau catalogs en fonction de vos propres catalogues.

Si vous posséder une version intermédiaire où les catalogues sont définis dans un fichier XML (WEB-INF/params/odf/catalog.xml), remplissez ce tableau par les valeurs du fichier afin que les formations et les pages racines de l'ODF ne perdent pas leur catalogue actuel.Vous pouvez supprimer le fichier et sa référence dans le fichier .

// 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();

Duplication de catalogue

Il est possible de créer un catalogue par copie d'un autre catalogue. Dans ce cas l'ensemble des formations liées au catalogue copié seront dupliquées puis affectées au nouveau catalogue.

Pour que la copie fonctionne, rajouter l'action 0 dans le fichier de workflow des formations 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>

 

Nouveau champ énuméré "Catalogue"

Une formation contient donc un nouveau champ énuméré "Catalogue", obligatoire. Les valeurs possibles sont celles créées via l'IHM et l'outil "Catalogues" ou celles créées via le script ci-dessus.

Exécutez le script ci-dessous dans la console du repository afin de lier toutes les formations existantes à un catalogue.

Personnalisez au préalable la variable catalogDefaultValue en fonction de vos propres catalogues.

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'");

Si vous avez surchargé la définition du contenus program (WEB-INF/param/content-types/_override/*.xml) vous devez ajouter la référence à la métadonnée "catalog"  dans la vue "main" en mode édition et dans la vue "index" en mode visualisation. Vous pouvez aussi l'ajouter dans la vue main en visualisation si vous souhaitez afficher le nom du catalogue dans le rendu de la formation.

<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>

 

Page racine de l'offre de formation

Chaque page racine de l'offre de formation est obligatoirement liée à un catalogue. Il peut ainsi y avoir autant de racines de l'offre de formation que de catalogues.

Par ailleurs le classement des formations dans l'arborescence du site est désormais paramétrable. Par défaut, les formations sont classées par type de diplôme "degree" (Licence, Master, DUT, ...) puis par domaine "domain" (Art Lettres & Langues, Sciences et Technologies, ...).

Le script suivant permet de paramétrer le catalogue et le 1er niveau et 2e niveau d'arborescence de la page racine de l'offre de formation. Personnalisez les variables catalog, firstLevel et secondLevel en début de script avant d'exécuter le script dans la console du repository.

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'");

 

Migration des services

Pour fonctionner, les 2 services "Liste de formations" et "Rechercher une formation" nécessitent de connaitre le catalogue de formation auquel ils sont liés. Exécutez le script suivant pour positionner l'identifiant du catalogue à utiliser en tant que paramètre du service.

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'");

 

Nouveau fichier de paramètres

Créez un nouveau fichier WEB-INF/param/odf-enumeration.xml et copier-coller y les lignes suivantes:

<?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>

Ce fichier répertorie les listes énumérées disponibles dans l'ODF.

Migration de services

Les paramètres des services "liste de formations" et "recherche de formation" ont été modifiés : toutes les métadonnées énumérées du type de contenu Formation peuvent désormais être utilisées.

Les scripts suivants doivent être passés dans la console du workspace repository pour migrer les paramètres des services existants.

 Liste de formations :

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.');
 

Recherche de formation :

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.');

La reconstruction du live doit être effectuée après le passage des scripts de migration.

Tableaux de bord

Dans sa version 2.3.x, le plugin d'offre de formation comprend deux tableaux de bord: un pour les formations, un pour les ELPs.

Pour le fonctionnement de ces derniers, il est nécessaire d'ajouter deux fichiers de paramétrages dans le répertoire WEB-INF/params de votre application ODF:

Ces fichiers sont des fichiers d'exemple, adaptés à l'application de démonstration de l'ODF. Ils doivent être adaptés à vos propres fichiers de workflow (workflow-program.xml, workflow-course.xml)

 

Nomenclature des mentions

Depuis début 2014, un décret fixe la nomenclature des mentions en fonction du type de diplôme: licence, master ou licence professionnelle.

Le champ "Mention" est donc maintenant un champ énuméré. La liste des mentions possibles dépend du type de diplôme et seules les licences, masters et les licences professionnelles peuvent avoir une mention.

  • Si vous souhaitez passer à la nouvelle nomenclature

3 fichiers XML contiennent les valeurs et libellés possibles des mentions pour chaque diplôme. Télécharger les 3 fichiers et copier-les dans le répertoire WEB-INF/param/odf de votre application:

Ajoutez/remplacez les clés i18n associées  dans votre catalogue application (WEB-INF/i18n/application.xml et WEB-INF/i18n/application_en.xml).

Enfin, dans le fichier WEB-INF/param/odf-enumeration.xml, ajoutez les 3 lignes suivantes:

<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"/>

Attention, si vous aviez déjà surchargé les champs "mention" et/ou "diplôme", il vous faut modifier les widgets utilisés.

Dans le fichier org.ametys.plugins.odf.Content.program.xml du répertoire WEB-INF\param\content-types\_override,vous devez avoir les lignes suivantes

<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>


  • Si vous souhaitez garder le système existant

Si vous souhaitez que le champ mention reste un champ texte libre, il vous faut surcharger la définition du champ "mention". Pour cela, créez un fichier org.ametys.plugins.odf.Content.program.xml dans le répertoire WEB-INF\param\content-types\_override (si vous n'avez pas déjà surcharger les champs d'une formation).

Le fichier doit contenir les lignes suivantes:

<?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>

Recherche sur les ELP

Un nouveau service permet de recherche des ELPs.

Si votre application ODF utilise le plugin odf-web, vous devez exclure la feature "odf/odf-content-indexer" dans le fichier WEB-INF/param/runtime.xml

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

Modification dans le format de stockage

Des modifications ont été apportées au format de stockage de l'ODF afin de permettre de ré-ordonner des listes d'ELP contenues dans un ELP (https://issues.ametys.org/browse/ODF-924). Après mise à jour du CMS et avant le premier démarrage, le fichier custom_nodetypes.xml (qui se trouve dans le dossier <chemin_repository>/repository/nodetypes) doit être effacé. Le fichier sera automatiquement recréé au redémarrage du serveur.