Migration de Google Analytics en Universal Analytics
A partir de la version 3.8 du CMS, l'intégration du code de suivi Google Analytics a été mis à jour vers Universal Analytics.
Pour pouvoir traiter les données envoyées par le nouveau code de suivi, il est impératif de transférer vos propriétés dans l'interface de Google Analytics.
Pour savoir comment faire, consultez le guide de mise à jour vers Universal Analytics. Il suffit de réaliser l'étape 1 ("transférez vos propriétés"), l'étape 2 étant déjà réalisée au niveau d'Ametys.
Droit de suppression de page
Le droit "Supprimer la page" devient "Supprimer les pages filles".
Autrement dit, pour supprimer une page il faut maintenant avoir le droit "Supprimer les pages filles" sur une page parente. Par conséquent pour pouvoir supprimer une rubrique ou une page racine, il faut le droit "Supprimer les pages filles" sur tout le plan du site.
Attention aucune migration n'est possible, donc c'est à chacun de modifier ses profils de droits en conséquence.
Ajout des observateurs asynchrones
Des informations générales sur les observateurs sont disponibles sur cette page. Vous trouverez aussi la liste des événements ayant un observateur asynchrone.
Cette partie concerne l'API JAVA. L'ajout de la notion d'observateurs asynchrones (via une interface AsyncObserver) impose d'éventuelles modifications de code dans le cas suivants:
Notification (envoi) d'un événement dont au moins un observateur est asynchrone (se reporter à la page cité dans le bloc info).
Observateurs qui utilisent des paramètres, l'ordre des paramètres peut avoir changé.
Pour déterminer les modifications à apporter à vos classes JAVA voici la démarche à suivre.
Faire une recherche sur l'ensemble des classes sur le texte "new Event" et/ou ouvrez la classe ObservationManager, recherchez les appels à la méthode #notify(Event) dans vos classes Java.
Pour chaque Event envoyé il faut regarder si il est marqué comme Asynchrone dans le tableau les recensant (cf. page bloc info), si c'est le cas, il faut s'assurer que le premier argument optionnel est l'identifiant de la cible de l'événement.
Exemple
Oups !
La copie dans le presse papier a échouée. Ouvrez le code et copier-le manuellement.
// Cette ligne
_observationManager.notify(new Event(user, ObservationConstants.CONTENT_UNPUBLISHED, content, new String[]{content.getSiteName()}));
// Deviendra
_observationManager.notify(new Event(user, ObservationConstants.CONTENT_UNPUBLISHED, content, new String[]{content.getId(), content.getSiteName()}));
// Car CONTENT_UNPUBLISHED est marqué comme Asynchrone dans le tableau, il faut ajouter l'identifiant du contenu en premier argument optionnel.
// De même cette ligne
_observationManager.notify(new Event(event.getIssuer(), ObservationConstants.PAGE_UPDATED, page));
// Deviendra
_observationManager.notify(new Event(event.getIssuer(), ObservationConstants.PAGE_UPDATED, page, new Object[]{page.getId()}));
// Cette ligne
_observationManager.notify(new Event(user, ObservationConstants.CONTENT_UNPUBLISHED, content, new String[]{content.getSiteName()}));
// Deviendra
_observationManager.notify(new Event(user, ObservationConstants.CONTENT_UNPUBLISHED, content, new String[]{content.getId(), content.getSiteName()}));
// Car CONTENT_UNPUBLISHED est marqué comme Asynchrone dans le tableau, il faut ajouter l'identifiant du contenu en premier argument optionnel.
// De même cette ligne
_observationManager.notify(new Event(event.getIssuer(), ObservationConstants.PAGE_UPDATED, page));
// Deviendra
_observationManager.notify(new Event(event.getIssuer(), ObservationConstants.PAGE_UPDATED, page, new Object[]{page.getId()}));
// Cette ligne
_observationManager.notify(new Event(user, ObservationConstants.CONTENT_UNPUBLISHED, content, new String[]{content.getSiteName()}));
// Deviendra
_observationManager.notify(new Event(user, ObservationConstants.CONTENT_UNPUBLISHED, content, new String[]{content.getId(), content.getSiteName()}));
// Car CONTENT_UNPUBLISHED est marqué comme Asynchrone dans le tableau, il faut ajouter l'identifiant du contenu en premier argument optionnel.
// De même cette ligne
_observationManager.notify(new Event(event.getIssuer(), ObservationConstants.PAGE_UPDATED, page));
// Deviendra
_observationManager.notify(new Event(event.getIssuer(), ObservationConstants.PAGE_UPDATED, page, new Object[]{page.getId()}));
Si vous avez ajouté des observateurs relatifs à l'indexation dans Lucene (peu probable), ceux-ci devront devenir des AsyncObserver. Un observateur asynchrone ne peut plus utiliser la cible d'un Événement (si il est un AmetysObject). event.getTarget(); devient interdit. Il faut utiliser le premier argument de l'event pour retrouver l'identifiant de l'objet ametys et le résoudre à nouveau, soit _resolver.resolveById(event.getArguments()[0]); Il faut alors s'assurer que tous les événements que recevra cet observateur possèdent bien l'identifiant requis en premier argument.
Il faut aussi vous assurer de mettre à jour les Observers qui ne sont pas asynchrones mais dont les événements reçus ont été modifiés dû à l'ajout de l'identifiant de la cible dans le premier argument.
Exemple
Oups !
La copie dans le presse papier a échouée. Ouvrez le code et copier-le manuellement.
// Ces lignes
String name = (String) event.getArguments()[0];
Integer count = (Integer) event.getArguments()[1];
// Pourront devenir
String name = (String) event.getArguments()[1];
Integer count = (Integer) event.getArguments()[2];
// Si la liste des arguments de l'événement s'est vue ajouter l'identifiant de la cible en premier argument.
// Ces lignes
String name = (String) event.getArguments()[0];
Integer count = (Integer) event.getArguments()[1];
// Pourront devenir
String name = (String) event.getArguments()[1];
Integer count = (Integer) event.getArguments()[2];
// Si la liste des arguments de l'événement s'est vue ajouter l'identifiant de la cible en premier argument.
// Ces lignes
String name = (String) event.getArguments()[0];
Integer count = (Integer) event.getArguments()[1];
// Pourront devenir
String name = (String) event.getArguments()[1];
Integer count = (Integer) event.getArguments()[2];
// Si la liste des arguments de l'événement s'est vue ajouter l'identifiant de la cible en premier argument.
Alertes et rappel (24/12/2015)
La gestion des alertes/rappels sur les contenus a été améliorée pour permettre l'envoi d'un rappel immédiat.
La configuration des alertes/rappels est propre à chaque application et est généralement définie dans le plugin default-workflow. Pour le rappel immédiat, vous devez y rajouter la configuration propre aux alertes immédiates dans la section <instantAlert>: droit + clés i18n.
Le rôle du composant doit être remplacé par org.ametys.cms.alerts.AlertScheduler (au lieu de org.ametys.web.alerts.AlertScheduler).
Oups !
La copie dans le presse papier a échouée. Ouvrez le code et copier-le manuellement.
Les mêmes clés que pour le rappel programmé peuvent être utilisées.
Nouvelles clés pour les contenus orphelins (pas de page) ou hors site (contenus ODF)
Comme pour les notifications par mail sur les états de workflow, les clés i18n définies dans le plugin defaul-workflow, sont suffixées de "_ORPHAN" pour les contenus orphelins, "_NOSITE" pour les contenus hors site. Autrement dit, pour chaque alerte, vous devez avoir 6 clés (3 pour le sujet, 3 pour le corps du message), par exemple : CONTENT_ALERTS_MAIL_REMINDER_BODY CONTENT_ALERTS_MAIL_REMINDER_BODY_ORPHAN CONTENT_ALERTS_MAIL_REMINDER_BODY_NOSITE
Si vous n'avez pas surchargé les clés proposées par défaut par le noyau vous n'avez rien à faire. Sinon pensez à redéfinir les clés *_ORPHAN et *_NOSITE.
Modification du paramètre de site pour l'acceptation des cookies (18/03/16)
Le paramètre de site concernant la politique d'acceptation des cookies, a été remplacé par une liste déroulante, pour offrir plus de possibilité.
Vous pouvez exécuter le script suivant pour migrer automatiquement tous vos sites.
Oups !
La copie dans le presse papier a échouée. Ouvrez le code et copier-le manuellement.
var qm = session.getWorkspace().getQueryManager();
var migrated = 0;
var query = qm.createQuery("//element(*, ametys:site)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
var count = 0;
while (nodes.hasNext())
{
var node = nodes.next();
if (node.hasProperty("ametys:force-accept-cookies"))
{
var value = node.getProperty("ametys:force-accept-cookies").getString();
if (value == 'true')
{
node.setProperty("ametys:force-accept-cookies", "always");
count++;
}
else if (value == 'false')
{
node.setProperty("ametys:force-accept-cookies", "ask_refuse");
count++;
}
}
}
print(count + " site(s) have been migrated");
session.save();
var qm = session.getWorkspace().getQueryManager();
var migrated = 0;
var query = qm.createQuery("//element(*, ametys:site)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
var count = 0;
while (nodes.hasNext())
{
var node = nodes.next();
if (node.hasProperty("ametys:force-accept-cookies"))
{
var value = node.getProperty("ametys:force-accept-cookies").getString();
if (value == 'true')
{
node.setProperty("ametys:force-accept-cookies", "always");
count++;
}
else if (value == 'false')
{
node.setProperty("ametys:force-accept-cookies", "ask_refuse");
count++;
}
}
}
print(count + " site(s) have been migrated");
session.save();
var qm = session.getWorkspace().getQueryManager();
var migrated = 0;
var query = qm.createQuery("//element(*, ametys:site)", javax.jcr.query.Query.XPATH);
var nodes = query.execute().getNodes();
var count = 0;
while (nodes.hasNext())
{
var node = nodes.next();
if (node.hasProperty("ametys:force-accept-cookies"))
{
var value = node.getProperty("ametys:force-accept-cookies").getString();
if (value == 'true')
{
node.setProperty("ametys:force-accept-cookies", "always");
count++;
}
else if (value == 'false')
{
node.setProperty("ametys:force-accept-cookies", "ask_refuse");
count++;
}
}
}
print(count + " site(s) have been migrated");
session.save();
Page visible / invisible (30/03/16)
Ametys inclut désormais la notion de page visible/invisible. Une page invisible n'apparaitra pas pas dans la navigation du site (plan du site, menus, ...).
Dans vos fichier cms/WEB-INF/param/cms-ribbon-*.xml, il vous faut rajouter le bouton permettant de modifier la visibilité d'une page (org.ametys.web.page.Visibility) dans l'onglet Page
Oups !
La copie dans le presse papier a échouée. Ouvrez le code et copier-le manuellement.
Le bouton est soumis au droit "Visibilité de la page" dans la catégorie "Droits sur le plan du site". Pensez à l'ajouter aux utilisateurs concernés.
Workflow sur les entrées des formulaires (16/04/16)
Suite à l'ajout de workflow sur les entrées des formulaires (stocké en base de données), dans votre fichier WEB-INF/param/runtime.xml, vous devez remplacer l'exclusion de la feature workflow/workflow-store par workflow/workflow-store-jcr
Oups !
La copie dans le presse papier a échouée. Ouvrez le code et copier-le manuellement.