Reportez-vous au tableau de compatibilité des plugins et incrémentez les versions de vos plugins (prendre pour chaque plugin la version la plus récente compatible 4.2)
Dans le runtime.xml, supprimez les lignes les lignes suivantes:
<org.ametys.cms.source.ContentView>org.ametys.web.source.WebContentView</org.ametys.cms.source.ContentView> <org.ametys.cms.source.ViewSelector>org.ametys.web.source.WebViewSelector</org.ametys.cms.source.ViewSelector>
Dans vos modèles de recherche (les fichiers XML sous WEB-INF/param/search), remplacer les occurrences de IndexingStringFieldAggregatorSearchUICriterion par IndexingFieldAggregatorSearchUICriterion
Les options de configuration du mode d'authentification par formulaire (FormsCredentialProvider) ont été modifiées:
Le fichier $AMETYS_HOME/config/user-population.xml doit être modifié manuellement.
Remplacez :
<runtime.authentication.form.security.level>low</runtime.authentication.form.security.level>
par
<runtime.authentication.form.cookies>true</runtime.authentication.form.cookies> <runtime.authentication.form.captcha>false</runtime.authentication.form.captcha> <runtime.authentication.form.login-by-email>false</runtime.authentication.form.login-by-email>
Remplacez :
<runtime.authentication.form.security.level>high</runtime.authentication.form.security.level>
par
<runtime.authentication.form.cookies>false</runtime.authentication.form.cookies> <runtime.authentication.form.captcha>true</runtime.authentication.form.captcha> <runtime.authentication.form.login-by-email>false</runtime.authentication.form.login-by-email>
Le paramètre "tri des résultats" a été remonté des populations de type "Annuaire LDAP" directement dans la source de données, notamment pour être aussi utilisé par les répertoires de groupes.
Dans vos fichiers $AMETYS_HOME/config/user-populations.xml, supprimez toutes les occurrences du paramètre suivant, si présent :
<runtime.users.ldap.serverSideSorting>true</runtime.users.ldap.serverSideSorting>
Et dans vos fichiers $AMETYS_HOME/config/datasources-ldap.xml, ajoutez à chaque source de données le paramètre suivant :
<serverSideSorting>true</serverSideSorting>
La valeur par défaut est "true". Cependant, si vous aviez décochés "Tri des résultats", c-à-d que vous aviez un "runtime.users.ldap.serverSideSorting" à false dans vos ou votre population(s) annuaire LDAP pour des raisons de performances, alors mettez la valeur à "false" au lieu de "true" dans le $AMETYS_HOME/config/datasources-ldap.xml aux sources de données correspondantes
Le fichier WEB-INF/param/workflows.xml est devenu facultatif. Les workflows disponible sont automatiquement lus à partir du contenu du dossier WEB-INF/param/workflows.
En général, il suffit d'enlever le préfixe "workflow-" devant le nom du fichier, mais attention il y a quelques pièges... par exemple "worfklow.xml" qui devient "content.xml" ; ou "workflow-coursepart.xml" qui devient "course-part.xml". Soyez attentif à l'attribut "name" du fichier workflows.xml
Dans le fichier workflows/reference-table.xml pour les tables de référence, rajoutez l'action suivante dans les <common-actions> :
<action id="220" name="plugin.default-workflow:WORKFLOW_ACTION_ADD_CONTENTTYPE"> <restrict-to> <conditions type="AND"> <condition type="avalon"> <arg name="role">org.ametys.cms.workflow.LockCondition</arg> </condition> </conditions> </restrict-to> <results> <unconditional-result old-status=" " status=" " step="1" /> </results> <post-functions> <function type="avalon"> <arg name="role">org.ametys.cms.workflow.SetCurrentStepIdAndNotifyFunction</arg> </function> <function type="avalon"> <arg name="role">org.ametys.cms.workflow.CreateVersionFunction</arg> </function> </post-functions> </action>
et rajoutez la référence à cette nouvelle action, dans les états (step) 1 et 3
<actions> <common-action id="2" /> <common-action id="220" /> <common-action id="222" /> </actions>
Sur tous les workflows utilisés en synchronisation (c'est à dire utilisant l'action 800), ajoutez à l'action de synchronisation 800 la post-fonction org.ametys.cms.workflow.ExtractOutgoingReferencesFunction :
<action id="800" name="plugin.contentio:WORKFLOW_ACTION_SYNCHRONIZE"> <restrict-to> [...] </restrict-to> <results> [...] </results> <post-functions> <function type="avalon"> <arg name="role">org.ametys.cms.workflow.ExtractOutgoingReferencesFunction</arg> </function> </post-functions> </action>
Pour simplifier l'installation de certains plugins, il y a maintenant un point d'extension pour les fonctions 'après enregistrement' et 'après validation'.
Les endroits où vous aviez la fonction de workflow du plugin forms ou du plugin translation-flagging seront remplacés par des fonctions génériques.
Par exemple, la fonction : org.ametys.plugins.forms.workflow.FormEditionFunction devient
<function type="avalon"> <arg name="role">org.ametys.cms.workflow.extensions.ExtensibleFunction</arg> <arg name="extension-point">org.ametys.cms.workflow.extensions.PostContentEditionFunctionsExtensionPoint</arg> </function>
et la fonction org.ametys.plugins.translationflagging.TranslationAlertFunction devient :
<function type="avalon"> <arg name="role">org.ametys.cms.workflow.extensions.ExtensibleFunction</arg> <arg name="extension-point">org.ametys.cms.workflow.extensions.PostContentValidationFunctionsExtensionPoint</arg> </function>
Les tokens pouvaient être à usage infini ou à usage unique.
Maintenant ils peuvent avoir un nombre limité d'utilisation, avoir leur durée renouvelable et avoir un contexte d'utilisation.
Des scripts de migration SQL sont à exécuter afin de pouvoir mettre à jour le format des tables (en fonction de votre type de base de données.
#Derby ALTER TABLE APP.Authentication_Token ADD nb_uses_left int; ALTER TABLE APP.Authentication_Token ADD auto_renew_duration bigint; ALTER TABLE APP.Authentication_Token ADD context VARCHAR(200); UPDATE APP.Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL; RENAME COLUMN APP.Authentication_Token.comment TO token_comment; #HsqlDb ALTER TABLE Authentication_Token ADD nb_uses_left INTEGER NULL BEFORE context; ALTER TABLE Authentication_Token ADD auto_renew_duration NUMERIC(13) NULL BEFORE context; ALTER TABLE Authentication_Token ADD context VARCHAR(200) NULL BEFORE context; UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL; ALTER TABLE Authentication_Token ALTER COLUMN comment RENAME TO token_comment; #MySQL ALTER TABLE Authentication_Token ADD nb_uses_left INT NULL AFTER last_update_date, ADD auto_renew_duration BIGINT NULL AFTER nb_uses_left, ADD context VARCHAR(200) NULL AFTER auto_renew_duration; UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL; ALTER TABLE Authentication_Token CHANGE comment token_comment LONGBLOB; #Oracle ALTER TABLE Authentication_Token ADD ( nb_uses_left NUMBER, auto_renew_duration NUMBER(13), context VARCHAR(200) ); UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL; ALTER TABLE Authentication_Token RENAME COLUMN comment TO token_comment; #PostgreSql ALTER TABLE Authentication_Token ADD nb_uses_left INTEGER NULL, ADD auto_renew_duration BIGINT NULL, ADD context VARCHAR(200) NULL; UPDATE Authentication_Token SET nb_uses_left = 1 WHERE end_date IS NOT NULL; ALTER TABLE Authentication_Token RENAME COLUMN comment TO token_comment;
Lors de la demande de création de compte, on ne demande plus les nom et prénoms (qui seront demandées plus tard).
Exécutez les scripts suivants sur votre base de données :
alter table Users_Temp drop lastname; alter table Users_Temp drop firstname;
Dans vos fichiers java et plugin.xml, recherchez et remplacez les occurrences de la 1ere colonne du tableau par leur équivalent dans la 2e colonne:
|
Remplacez |
Par |
|---|---|
|
org.ametys.cms.clientsideelement.SmartContentClientSideElement |
org.ametys.core.ui.StaticClientSideElement |
|
org.ametys.cms.clientsideelement.SmartContentTypesGallery |
org.ametys.cms.clientsideelement.ContentTypesGallery |
|
org.ametys.cms.clientsideelement.DeleteContentClientSideElement |
org.ametys.core.ui.StaticClientSideElement |
|
org.ametys.cms.clientsideelement.ArchiveMenuClientSideElement |
org.ametys.cms.clientsideelement.SmartContentMenu |
|
org.ametys.web.clientsideelement.DeleteContentClientSideElement |
org.ametys.core.ui.StaticClientSideElement |
|
org.ametys.web.clientsideelement.TagClientSideElement |
org.ametys.core.ui.StaticClientSideElement |
|
org.ametys.web.clientsideelement.PageVisibilityClientSideElement |
org.ametys.core.ui.StaticClientSideElement |
|
org.ametys.web.clientsideelement.PreviewPageClientSideElement |
org.ametys.core.ui.StaticClientSideElement |
|
org.ametys.web.clientsideelement.LivePageClientSideElement |
org.ametys.core.ui.StaticClientSideElement |
|
org.ametys.web.clientsideelement.BlankPageClientSideElement |
org.ametys.core.ui.StaticClientSideElement |
|
org.ametys.web.clientsideelement.LinkPageClientSideElement |
org.ametys.core.ui.SimpleMenu |
La gestion des paramètres de service a été complètement modifiée. Lors de la migration d'un projet en 4.2, si ce projet contient des services spécifiques ou surcharge des services du noyau (sauf s'il ne surcharge que le rendu), cette migration risque de nécessiter des modifications de code.
Dans certains projets (principalement ODF) les pipelines faisant appel à des PDF ont été modifiés pour intégrer des fonts personnalisées. Les pipelines personnalisés dans ce but ne sont donc plus utiles, il faut supprimer leurs appels et leurs déclarations. Vous pouvez les détecter en cherchant les serializers (sitemap.xmap) org.ametys.core.cocoon.FOPNGSerializer ayant une balise <user-config>. Les pipelines noyaux font désormais correctement l'appel à la configuration personnalisée.
Vérifier qu'il n'existe pas d'autres serializers spécifique au projet en cherchant <map:serialize type="fo2pdf"/>.
Cependant, il est possible que vous deviez modifier votre projet si le fichier n'est pas bien positionné. Se référer à la page Mettre une font personnalisée dans un PDF pour de plus amples informations.
Dans les paramètres de configuration générale, l'url du CMS ne peut plus se terminer par / ou par /index.html.
Vous devez modifiez ce paramètre si c'est le cas.
Serveur éteint, commencez par supprimer le fichier $AMETYS_HOME/data/repository/repository/custom_nodetypes.xml puis redémarrer.
Dans la console d'administration exécutez les scripts suivants :
function copyTagNode(originalNode, newNode)
{
setPropertyFromNode(originalNode, newNode, "ametys-internal:target");
setPropertyFromNode(originalNode, newNode, "ametys-internal:description");
setPropertyFromNode(originalNode, newNode, "ametys-internal:visibility");
setPropertyFromNode(originalNode, newNode, "ametys-internal:title");
}
function setPropertyFromNode(originalNode, newNode, propertyName)
{
if (originalNode.hasProperty(propertyName))
{
newNode.setProperty(propertyName, originalNode.getProperty(propertyName).getString());
}
}
function createNodesFromNode(rootNode, sourceNode)
{
var nbTag = 0;
var childNodes = sourceNode.getNodes();
while (childNodes.hasNext())
{
var childNode = childNodes.next();
var createdNode = rootNode.addNode(childNode.getName(), "ametys:cmstag");
copyTagNode(childNode, createdNode);
nbTag++;
nbTag += createNodesFromNode(createdNode, childNode);
}
return nbTag;
}
var totalNbTag = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:tags)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var tagsNode = nodes.next();
if (!tagsNode.getParent().hasNode("cmstags"))
{
tagsNode.getParent().addNode("cmstags", "ametys:cmstags");
}
var newTagsNode = tagsNode.getParent().getNode("cmstags");
totalNbTag += createNodesFromNode(newTagsNode, tagsNode);
tagsNode.remove();
}
session.save();
print(totalNbTag + " tag(s) have been migrated"); Les paramètres du service ont été modifiés :
Exécutez le script JCR suivant pour modifier les services existants:
var count = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:zoneItem)[@ametys-internal:service = 'org.ametys.web.service.UserSignup']", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var node = nodes.next();
var page = node.getParent().getParent().getParent().getParent();
var sitemap = page.getProperty("ametys:sitemap").getString();
print("Found a signup service for language " + sitemap + " at path " + page.getPath());
count++;
var params = node.getNode("ametys:service_parameters");
if (params.hasProperty("ametys:terms-of-service-page"))
{
var pageId = params.getProperty("ametys:terms-of-service-page").getString();
if (pageId != '')
{
params.setProperty("ametys:terms-of-service-mode", "PAGE");
}
else
{
params.setProperty("ametys:terms-of-service-mode", "NONE");
}
}
else
{
params.setProperty("ametys:terms-of-service-mode", "NONE");
}
query = qm.createQuery("//element(*, ametys:page)[@ametys-internal:tags = 'USER_PREFS_MAIN' and @ametys:sitemap= " + sitemap + "]", javax.jcr.query.Query.XPATH);
var pages = query.execute().getNodes();
if (pages.hasNext())
{
var successPage = pages.next();
params.setProperty("ametys:success-page", "page://" + successPage.getUUID());
params.setProperty("ametys:success-mode", "PAGE");
}
// TO UNCOMMENT ONLY IF YOU USE USER-DIRECTORY PLUGIN
// params.setProperty("ametys:xslt", pages/services/user-signup/signup.xsl);
}
session.save();
print(count + " signup services have been migrated"); var fieldsByContent = new java.util.HashMap();
fillFieldsToMigrateMap();
var migratedFields = 0;
var migratedContents = 0;
// Migrate the multilingual nodes content by content
fieldsByContent.forEach(
function(contentId)
{
var content = ametysResolver.resolveById("content://" + contentId);
migrateContent(content,
[renameMultilingualString],
true /* old versions have to be marked incompatible */,
null /* tag new versions */,
false /* not verbose - DO NOT ACTIVATE IN THIS CASE !! */
);
}
);
print(migratedFields + " multilingual fields have been migrated in " + migratedContents + " contents.");
// Get all the multilingual nodes
function fillFieldsToMigrateMap()
{
var fieldsToMigrate = 0;
var qm = session.getWorkspace().getQueryManager();
var query = qm.createQuery("//element(*, ametys:multilingualString)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
while (nodes.hasNext())
{
var node = nodes.next();
// Get the path of the multilingual metadata to migrate
var metadataPath = "";
var contentNode = node;
while (!contentNode.getPrimaryNodeType().isNodeType("ametys:content"))
{
metadataPath += node.getName() + "/";
contentNode = node.getParent();
}
metadataPath = metadataPath.slice(0, -1);
// Store the metadataPath to migrate by content ID
var contentId = contentNode.getIdentifier();
var fields = fieldsByContent.getOrDefault(contentId, new java.util.HashSet());
fields.add(metadataPath);
fieldsByContent.put(contentId, fields);
fieldsToMigrate++;
}
print(fieldsToMigrate + " multilingual fields to migrate potentially in " + fieldsByContent.keySet().size() + " contents.");
}
// Migrate the multilingual strings of the content and increment the global counter
function renameMultilingualString(content)
{
var migratedContent = false;
var contentId = content.getNode().getIdentifier();
// Get all metadata to migrate for the current content
var fields = fieldsByContent.get(contentId);
fields.forEach(
function(fieldName)
{
var migratedField = false;
var fieldNode = content.getNode().getNode(fieldName);
var properties = fieldNode.getProperties();
while (properties.hasNext())
{
var property = properties.nextProperty();
// If the current property name doesn't starts with "ametys:" ...
var propertyName = property.getName();
if (propertyName.indexOf(":") == -1)
{
// ... move it to "ametys:[propertyName]"
fieldNode.setProperty("ametys:" + propertyName, property.getValue());
property.remove();
migratedField = true;
}
}
if (migratedField)
{
migratedFields++;
migratedContent = true;
}
}
);
if (migratedContent)
{
migratedContents++;
}
} Le service de moteur de recherche principal a été renommé en "Recherche de pages".
L'url de service associée a été changée de "service/search.html" vers "service/search-pages.html". Vérifiez dans vos XSL que vous n'aviez pas cette url qui apparaissait.
La classe du service a changé. Si le moteur de recherche a été dupliqué, cherchez dans les fichiers xml de votre projet et remplacez "org.ametys.web.frontoffice.SearchService" par "org.ametys.web.frontoffice.SearchPagesService".
L'emplacement des XSL du service à changé (voir migration graphique) il faut donc exécuter le script suivant (et reconstruire le live s'il y a des modifications):
var count = 0;
var done = 0;
jcrXPathQuery("//element(*, ametys:zoneItem)[@ametys-internal:service='org.ametys.web.service.FrontSearchService']").forEach(function(zi) {
print("Found " + zi.getPath());
var parameters = zi.getServiceParameters();
var xsltParam = parameters.getValue("xslt");
print(" " + xsltParam);
count++;
var toReplace = "pages/services/search/";
if (xsltParam.startsWith(toReplace))
{
var newValue = "pages/services/search-pages/" + xsltParam.substring(toReplace.length);
print(" => " + newValue)
parameters.setValue("xslt", newValue);
zi.saveChanges();
done++;
}
else
{
print(" => ok")
}
})
print("...");
print(done + " services modifiés sur " + count)
if (done > 0)
{
print("PENSEZ A RECONSTRUIRE LE LIVE")
} Suite à une modification d'API et de stockages des données, les services existants doivent être migrés.
Exécutez le script sur la page dédiée à la migration des services.
Si votre application est une application Ametys ODF, suivez le guide de migration technique et graphique de la version 4.0 à la version 4.1 de l'ODF
Suivant les plugins Ametys que vous utilisez, vous devez suivre les migrations techniques et/ou graphiques propres à chaque plugin :
Le droit "Modifier la recherche Solr" a été retiré au profit de l'autre droit déjà existant "Outil de recherche Solr".
Le serveur Solr doit être réinstallé.
Télécharger la version 4.2 http://releases.ametys.org/release/org.ametys/solr-app/4.2.x/4.2.0/zips/
Ne conservez pas les anciennes données indéxées (supprimez tout le contenu du "solr home" (sauf le dossier logs éventuellement), par défaut il se trouve dans solr/server/solr, puis copiez-collez les données par défaut issues de la livraison du ametys-solr-config-*.zip)
Après redémarrage du serveur Solr puis Ametys, lancez une indexation totale.