Manuel de migration technique de la version 2.1.x vers la version 2.2.x ou 2.3.x

  1. Modèle de données
    1. Organisation de l'enseignement
    2. Pièces jointes multiples sur les parcours
  2. Workflow
  3. Export CDM-fr des stages

Modèle de données

Organisation de l'enseignement

Par cohérence avec les Eléments Pédagogiques, les 5 cases à cocher des contenus Formation : Formation initialeFormation continueFormation continue non diplômanteFormation en alternance et Formation professionnelle ont été regroupées en une liste à choix multiple "Organisation de l'enseignement" présentant les 5 options.

Pour migrer les contenus existants, le script suivant doit être exécuté dans la console du workspace repository :

importClass(org.ametys.plugins.repository.RepositoryConstants);
var unlock = function(node)
{
    var lockToken = node.getProperty(RepositoryConstants.METADATA_LOCKTOKEN).getString();
      
    var lockManager = node.getSession().getWorkspace().getLockManager();
      
    lockManager.addLockToken(lockToken);
      
    lockManager.unlock(node.getPath());
      
    // Remove residual properties
    node["setProperty(java.lang.String,javax.jcr.Value)"](RepositoryConstants.METADATA_LOCKTOKEN, null);
    node["setProperty(java.lang.String,javax.jcr.Value)"](RepositoryConstants.METADATA_LOCKOWNER, null);
      
    node.getSession().save();
}
var migrate = function(node, propName, value, values, values_remote)
{
    var sync = false;
    
    var localValue = null;
    var remoteValue = null;
    
    if (node.hasProperty(propName) && node.getProperty(propName).getBoolean())
    {
    	// Stocker la valeur locale.
        localValue = value;
    }
    if (node.hasProperty(propName + '_remote') && node.getProperty(propName + '_remote').getBoolean())
    {
    	// Remplir le tableau des valeurs synchro et stocker la valeur synchro.
        values_remote.push(value);
        remoteValue = value;
    }
    if (node.hasProperty(propName + '_sync') && node.getProperty(propName + '_sync').getBoolean())
    {
    	// Le champ est synchronisé : mettre dans la nouvelle valeur locale la valeur synchronisée.
        if (remoteValue != null)
        {
        	values.push(remoteValue);
    	}
        
        sync = true;
    }
    else
    {
    	// Le champ n'est pas synchronisé : recopier la valeur locale.
        if (localValue != null)
        {
        	values.push(localValue);
    	}
    }
     
    return sync;
}
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:content)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.program' or @ametys-internal:contentType = 'org.ametys.plugins.odf.Content.subProgram']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
var all_synchronized_props = [];
var nodeCount = 0;
while (nodes.hasNext())
{
    var node = nodes.next();
     
    var values = [];
    var values_remote = [];
    var sync = true;
    
    // On synchronise le nouveau champ si les 5 champs étaient synchronisés.
    sync = migrate(node, 'ametys:initialEducation', '1', values, values_remote) && sync;
    sync = migrate(node, 'ametys:continuingEducation', '2', values, values_remote) && sync;
    sync = migrate(node, 'ametys:noDegreeContinuingEducation', '3', values, values_remote) && sync;
    sync = migrate(node, 'ametys:apprenticeship', '4', values, values_remote) && sync;
    sync = migrate(node, 'ametys:vocationalEducation', '5', values, values_remote) && sync;
     
    if (node.isLocked())
    {
        unlock(node);
    }
     
    node["setProperty(java.lang.String,java.lang.String[])"]('ametys:formofteachingOrg', values);
    node["setProperty(java.lang.String,java.lang.String[])"]('ametys:formofteachingOrg_remote', values_remote);
    node["setProperty(java.lang.String,boolean)"]('ametys:formofteachingOrg_sync', sync);
     
    nodeCount++;
}
session.save();
println(nodeCount + " contenus formation ont été migrés.\n");

Pour les contenus dont toutes les cases à cocher n'étaient pas synchronisées, le statut de synchronisation sera perdu. A la fin de la migration, le script affichera les contenus concernés dans l'onglet "Sortie standard".

Pièces jointes multiples sur les parcours

Les fichiers à télécharger sur un parcours deviennent multiple.

Exécutez le script suivant pour migrer les pièces jointes existantes:

var query = session.getWorkspace().getQueryManager().createQuery("//element(*, ametys:defaultContent)[@ametys-internal:contentType = 'org.ametys.plugins.odf.Content.subProgram']", javax.jcr.query.Query.XPATH);
  
var nodes = query.execute().getNodes();
   
var count = 0;
while (nodes.hasNext())
{
   var program = nodes.next();
   
   if (program.hasNode("ametys:attachment") && !program.hasNode("ametys:attachments"))
   {
       var attachNode = program.getNode("ametys:attachment");
       var entryNode = program.addNode("ametys:attachments", "ametys:compositeMetadata").addNode("ametys:1", "ametys:compositeMetadata");
       // Move node
       attachNode.getSession().move(attachNode.getPath(), entryNode.getPath() + "/ametys:attachment");
      
       program.save();
       count++;
   } 
}
 
println(count + " attachments have been moved");

Si vous avez surchargé la définition des contenus "subProgram" (WEB-INF/param/content-types/_override/*.xml), pensez à modifier les références à la métadonnée "ametys:attachment" qui devient:

<cms:metadata-ref name="attachments">
    <cms:metadata-ref name="attachment"/>
    <cms:metadata-ref name="attachment-text"/>
</cms:metadata-ref>

 

Workflow

Si votre appplication ODF utilise le plugin ODF-Sync pour la synchronisation des formations avec une base apogée ou avec des fichiers CDMfr / ROF, vous devez rajouter les deux actions de workflow suivantes dans la section <initial-actions> du fichier WEB-INF/params/workflow-program.xml

<initial-actions>
	[...]
    <action id="110" name="plugin.odf:WORKFLOW_ACTION_CREATE">
        <pre-functions>
        	<function type="avalon">
            	<arg name="role">org.ametys.odf.workflow.CreateSubProgramFunction</arg>
            </function>
		</pre-functions>
        <results>
        	<unconditional-result old-status=" " status=" " step="0" />
      	</results>
    </action>
	<action id="120" name="plugin.odf:WORKFLOW_ACTION_CREATE">
         <pre-functions>
         	<function type="avalon">
            	<arg name="role">org.ametys.odf.workflow.CreateContainerFunction</arg>
			</function>
		</pre-functions>
        <results>
        	<unconditional-result old-status=" " status=" " step="0" />
        </results>
	</action>
</initial-actions>

Export CDM-fr des stages

Les informations supplémentaires sur les stages et stages à l'étranger (valeur énumérée sur le caractère obligatoire ou facultatif + durée) sont désormais exporté dans le CDM-fr.

Pour information, voici un exemple d'extrait du CDMfr concernant ces informations:

<infoBlock userDefined="ametys-extension">
   <extension>
        <ametys-cdm:training>
          	<ametys-cdm:trainingInfo value="internship_mandatory">Obligatoire</ametys-cdm:trainingInfo>
          	<ametys-cdm:trainingDuration>6 mois</ametys-cdm:trainingDuration>
          	<ametys-cdm:trainingAbroadInfo value="internship_possible">Possible</ametys-cdm:trainingAbroadInfo>
          	<ametys-cdm:trainingAbroadDuration>3 à 6 mois</ametys-cdm:trainingAbroadDuration>
        </ametys-cdm:training>
	</extension>
</infoBlock>

Afin d'exporter correctement ces informations, veuillez rajouter dans le fichier WEB-INF/param/odf/intership.xml le libellé CDMfr pour chaque valeur énumérée :

<items i18n-catalog="application"> 
    <item code="internship_possible" i18n-key="APPLICATION_ODF_INTERNSHIP_POSSIBLE" cdmValue="Possible"/>
    <item code="internship_mandatory" i18n-key="APPLICATION_ODF_INTERNSHIP_MANDATORY" cdmValue="Obligatoire"/>
</items>