Editeur de script (outil)

Les fonctionnalités décrites dans cette page ne sont disponible qu'à partir d'Ametys v4.2 

 

L'éditeur de scripts permet d'écrire et d'exécuter des scripts depuis l'outil back-office.
Cet outil dispose d'une grille permettant d'afficher les contenus retournés par le script, en plus de l'affichage texte des messages et résultats. Il dispose d'une fonction permettant de mettre en forme les contenus retournés, et de spécifier les colonnes à afficher dans la grille.
Par ailleurs, il peut prendre en compte les contenus actuellement sélectionnés (depuis un outil de recherche par exemple) au moment de l'exécution du script, par le biais d'une variable "selection" mise à disposition.

  1. Scripts
    1. Présentation de l'outil
    2. Language des scripts
  2. Variables et fonctions Ametys
    1. Variables
    2. Fonctions
  3. Exemples de scripts
    1.  Afficher les programmes ayant la même composante que le programme sélectionné
    2. Générer un rapport sur les programmes et éléments pédagogiques

 

Scripts

Présentation de l'outil

Pour pouvoir accéder à l'outil, il faut posséder le droit "Outil Script" de la catégorie "Autres outils". L'outil est alors disponible dans l'onglet Accueil.

Cet outil est découpé en 3 zones :

- En haut, la partie script, où le script pourra être écrit à l'intérieur d'une fonction "main". En dessous de la zone de script, il y a un bouton "Exécuter" permettant d'exécuter le script.

- En bas à gauche, prenant toute la largeur par défaut, se trouve une grille vide permettant d'afficher les contenus retournés par l'exécution du script.

- En bas à droite, réduit par défaut, se trouve la "Console", c'est à dire le résultat au format texte de l'exécution du script.

Après exécution d'un script avec succès, la partie script est rétracté pour afficher la grille et la console avec les résultats du script.

Language des scripts

L'éditeur de scripts utilise le moteur de JavaScript de Java 8, appelé "Nashorn". La syntaxe attendue est donc la syntaxe de Nashorn. Ce moteur étant exécuté en Java, il permet en plus du JavaScript d'accéder et manipuler les méthodes et class de Java. Par exemple:

var ArrayList = Java.type('java.util.ArrayList');     
var list = new ArrayList();     

Une autre fonctionnalité couramment utilisée est la méthode "print()" permettant d'afficher du texte dans la sortie console.

print("Sélection actuelle : " + selection)     

Référez-vous à la syntaxe Nashorn pour pouvoir écrire vos propres scripts.

 

Variables et fonctions Ametys

Ametys met à disposition un certain nombre de variables et fonctions pour pouvoir utiliser les fonctionnalités d'Ametys au sein des scripts Nashorn. Pour voir à tout moment la liste des variables et fonctions disponibles dans l'outil, il suffit de passer la souris sur le "?" en haut à droite de l'outil scripts :

Pour aller plus loin
Il est possible d'ajouter ses propres fonctions dans le fichier "WEB-INF/param/scripts.xml". Il est également possible, au sein d'un plugin, d'utiliser le point d'extension "org.ametys.plugins.core.ui.script.ScriptBindingExtensionPoint" pour apporter d'autres variables et fonctions.

 

Les fonctions et variables disponibles dépendent du contexte courant.
Par exemple, la fonction contents et la variable selection ne sont disponibles que dans le CMS, vous n'aurez pas accès à cette fonction dans l'outil Script de l'interface d'administration.

Variables

- "sourceResolver" est un raccourci pour le composant "org.apache.excalibur.source.SourceResolver", permettant de résoudre des URI d'Ametys. Par exemple :

var newsletterTemplateSource = sourceResolver.resolveURI("context://skins/" + skinId + "/newsletter/" + id + "/stylesheets/template.xsl")     

- "selection" est la liste des contenus actuellement sélectionnés, ou une liste vide si aucun contenu n'est sélectionné.

for each (var content in selection) {     
 print(content.getId())     
}     

- "session" donner accès en lecture et écriture au repository. Par exemple :

var rootNode = session.getRootNode().getNode("ametys:root");     

- "ConsoleHelper" est un raccourci vers la class "org.ametys.workspaces.repository.ConsoleHelper", un helper qui fournit des méthodes comme "setProperty" ou "convertSingleToMultipleProperty" pour aider lors des opérations sur le repository

- "avalonContext" correspond au contexte avalon de la requête. Il possède des informations comme le site courant.

var site = avalonContext.get(org.apache.cocoon.components.ContextHelper.CONTEXT_REQUEST_OBJECT).getAttribute("siteName");     

- "ametysResolver" permet de résoudre les objets Ametys à partir de leur identifiant ou leur "path"

var creator = ametysResolver.resolveById("courseContent://471545a1-2c75-4f75-b774-dda2bf0fa960").getCreator();   
var site = ametysResolver.resolveByPath("ametys:sites/www");     

- "repository" représente le repository, et permet par exemple de changer le workspace de la session :

var credentials = new javax.jcr.SimpleCredentials('ametys', []);     
session = repository.login(credentials, 'archives');     

- "serviceManager" permet de récupérer les components avalon que possède Ametys : 

var contentTypesHelper = serviceManager.lookup(org.ametys.cms.contenttype.ContentTypesHelper.ROLE)     

 

Fonctions

- "jcrXPathQuery" exécute une requête XPath JCR pour récupérer une liste de noeuds

for each (var content in jcrXPathQuery("//element(*, ametys:content)[jcr:like(@ametys-internal:contentType, 'odf-enumeration.%')]")) {    
 print(content.getId())    
}    

- "printSqlQuery" exécute la fonction "sqlQuery" (voir plus bas), et affiche directement le résultat dans la console, mis en forme

printSqlQuery("SELECT * FROM users", "SQL-j2c1c5hc")    

- "migrateContent" est une fonction helper permettant d'exécuter une liste de fonctions de migration, tout en marquant ou non les versions précédentes comme incompatibles, en ajoutant ou non un tag ("live" par exemple) sur les nouvelles version.

function _titleMigration(content) { /* migrate title ... */ }    
 migrateContent(content, [_titleMigration], true /*old versions incompatible*/, null /*no tag*/, false /*not verbose*/);    

- "sqlQuery" exécute une requête sql sur la dataSource passée en 2e paramètre. Le paramètre dataSource peut aussi être l'identifiant d'une dataSource, par simplicité.

var dataSource = serviceManager.lookup("org.ametys.core.datasource.SQLDataSourceManager").getSQLDataSource("SQL-j2c1c5hc");    
var result = sqlQuery("SELECT * FROM users", dataSource)    

- "contents" est une fonction helper utilisée pour mettre en forme des contenus, pour les afficher dans la grille de résultats. Le premier paramètre est un tableau avec les différentes colonnes à afficher. Si la valeur est un tableau vide, tous les champs du contenu seront affichés dans la grille. Le deuxième paramètre est une liste de contenus.

return contents([], selection); // affiche la sélection courante dans la grille    

- "sqlUpdate" permet d'effectuer une requête SQL modifiant des données existantes (mise à jour, suppression, ...)

sqlUpdate("UPDATE users SET FIRSTNAME='Firstname' WHERE FIRSTNAME='admin'", "SQL-j2c1c5hc");    

 

Exemples de scripts

Les exemples donnés ci-après son des exemples pouvant être exécutés dans une application Ametys ODF.

 Afficher les programmes ayant la même composante que le programme sélectionné

var showContentsIds = [];    
selection.forEach(function (content) {    
  var orgUnits = content.getOrgUnits();   
    
  orgUnits.forEach(function (orgUnit) {    
    // Nashorn supporte la syntaxe "for each(var ... in ...)" ci dessous, mais on peut également utiliser le "list.forEach(callback)" de java, ligne au dessus  
    for each (var contentWithOrgUnit in jcrXPathQuery("//element(*, ametys:programContent)[@ametys:orgUnit = '" + orgUnit + "']")) // jcrXPathQuery permet d’exécuter un XPATH sur le repository  
    {    
      if (showContentsIds.indexOf(contentWithOrgUnit.getId()) == -1)    
      {    
        showContentsIds.push(contentWithOrgUnit.getId());    
      }    
    }    
  });    
});    

var returnContents = [];    
showContentsIds.forEach(function (contentId) {    
  returnContents.push(ametysResolver.resolveById(contentId));  // utilisation du ametysResolver pour transformer les ids en contents  
})    

return contents([], returnContents); // retourner "contents()" permet d'afficher des contenus dans la grille de résultats    

Si le script renvoie un objet avec une propriété "results" qui contient une liste de contenus, ils seront affichés dans la grille. Si le script renvoie un objet avec une propriété "columns", la grille sera configurée pour afficher ces columns. Si columns est un tableau vide, alors les champs du ou des contenu(s) seront utilisés pour définir les colonnes de la grille. La méthode "contents(columns, contents)" permet de renvoyer facilement un objet avec les bonnes propriétés pour remplir la grille.

 

Générer un rapport sur les programmes et éléments pédagogiques

var StringUtils = Java.type("org.apache.commons.lang3.StringUtils");   

function doProgram(program) {   
  var out = program.getTitle();   
  out += ";";   
     
  out += program.getLanguage();   
  out += ";";   

  program.getOrgUnits().forEach(function (orgUnit) {   
    var org = ametysResolver.resolveById(orgUnit);   
    if (org != null) {   
      out += org.getTitle() + ",";   
    }   
  });   
  out += ";";   

  out += "ects (" + (StringUtils.isEmpty(program.getEcts()) ? "EMPTY" : "OK") + ")";   
  out += ";";   

  out += ";"; // parcours - Titre (vide)   

  print(out);   

  traverseProgramPart(program, {program: program});   
}   

function traverseProgramPart(part, data) {   
  traversePattern(part, "getProgramPartChildren", traverseProgramPart, data);   
  traversePattern(part, "getCourses", doCourse, data);   
}   

function doCourse(course, data) {   
  var out = data.program.getTitle();   
  out += ";;;;"; // ;lang;Composante;Champs texte; (vide)   
  out += course.getTitle();   

  print(out);   

  traversePattern(course, "getCourseLists", traverseProgramPart, data);   
}   

// Méthode helper pour traverser les noeuds de l'arbre des program/subprogram/container/courseList/course  
function traversePattern(traversable, getChildrenFctName, traverseChildFct, data) {   
  if (typeof traversable[getChildrenFctName] == "function")   
  {   
    traversable[getChildrenFctName]().forEach(function (child) {   
      traverseChildFct(child, data);   
    });   
  }   
}   

var contents = [];   
print("Formation;lang;Composante;Champs texte;Parcours - Titre"); // entête du fichier csv   
jcrXPathQuery("//element(*, ametys:programContent)").forEach(doProgram);   

 Ce script affiche dans la console, au format csv, la liste de toutes les formations disponibles, avec le nom de la composante parente, la langue, si le champ texte "ects" est vide ou pas, et le titre des éléments pédagogiques sous la formation.