Migration d’un squelette de SPIP 2 vers SPIP 3

Ainsi que sa numérotation l’indique, la version SPIP 3 est une version majeure de SPIP, qui apporte de nombreuses et importantes fonctionnalités. Dans l’ensemble, l’équipe de SPIP s’est assuré que les sites fonctionnant avec SPIP 2 fonctionnent également avec SPIP 3.

-  Base de données : la mise à jour se fera sans encombre mais aussi, comme toujours, sans possibilité de revenir à SPIP 2. Comme pour toute migration, il est donc recommandé de faire une sauvegarde de la base de donnée dans sa version SPIP 2 avant de faire une migration de vos sites vers SPIP 3, afin de vous ménager la possibilité de revenir à SPIP 2.

-  Plugins : l’API ayant été modifiée, une modification du code des plugins est souvent requise pour SPIP 3, soit pour simplement fonctionner, soit pour bénéficier des nouveaux apports de SPIP 3. De nombreux plugins distribués par la zone sont d’emblée compatibles avec SPIP 3 ou bénéficient d’une version adaptée pour SPIP 3.
Si jamais vous avez réalisé vous même un plugin et que vous devez le porter en SPIP 3, un bloc note a collecté un ensemble de points destinés à faciliter sa migration. Voyez l’article "Migration de Plugins de SPIP2 à SPIP3" du Carnet SPIP. Au besoin, vous pouvez aussi demander de l’aide sur les listes ou IRC.

-  Squelettes : Les éléments du langage SPIP 2 sont tous valables en SPIP 3. Bien que très rarement rencontrées, il existe toutefois de petites incompatibilités dans certaines configurations de squelettes, qui nécessiteront donc une adaptation, et ce d’autant plus que vous utiliserez des fonctionnalités profondes.

C’est sur ce dernier point : les rares incompatibilités du langage de squelette, que porte cet article.

Chaînes de langues déportées dans des plugins

Un grand nombre de fonctionnalités du noyau de SPIP sont désormais déportées dans des plugins, et avec elles les chaînes de langues qu’elles utilisent. En conséquence, pour y faire appel dans les squelettes, il faut les préfixer par le préfixe du plugin correspondant si vous les utilisez dans vos squelettes.

Par exemple,

<:forum_texte:>

doit pour SPIP3 être remplacé par

<:forum:forum_texte:>

A propos des chaines de langues, voyez la doc sur les nouveautés des chaînes de langues avec SPIP 3.

Formulaire inscription

La balise #FORMULAIRE_INSCRIPTION n’est jamais totalement vide en SPIP3 , même quand les inscriptions ne sont pas autorisées sur le site. En conséquence, elle ne pourra pas servir pour conditionner un affichage (par exemple [(#FORMULAIRE_INSCRIPTION) lien vers la page d'inscription] affichera toujours le lien).

A la place, il faut tester directement la configuration du site SPIP. Il existe deux entrées pour cela :
-  accepter_visiteurs
-  accepter_inscriptions

Exemple :

[(#CONFIG{accepter_visiteurs}|=={oui}|oui)
 <a href='#URL_PAGE{inscription_visiteurs}'>]

Critère {id_parent}

Avec SPIP 3, cette boucle ne fonctionne pas de la même manière qu’avec SPIP 2

<BOUCLE_sousrubrique(RUBRIQUES){id_parent}>
#ID_RUBRIQUE
</BOUCLE_sousrubrique>

En effet :
-  si il y a une boucle RUBRIQUES englobante, {id_parent} prend le #ID_RUBRIQUE de la boucle englobante
-  s’il n’y en pas, id_parent prend le #ENV{id_parent},

En SPIP 2 {id_parent} prend #ENV{id_rubrique}.

En conséquence, avec SPIP 3, il est désormais possible d’écrire {id_parent ?}{id_rubrique ?}.

Pour migrer une telle boucle, il faut :
-  appeler l’url avec un paramètre id_parent supplémentaire ;
-  ou adapter la boucle en mettant un critère supplémentaire {id_parent ?}{id_rubrique ?}.

Dans certains cas, le critère suivant a son utilité pour remplacer {id_parent} en assurant la compatibilité d’un squelette entre versions SPIP 2 et SPIP 3 : {id_parent=#ENV{id_parent,#ENV{id_rubrique}}}.

Boucles FORUMS et ARTICLES imbriquées

Avec SPIP 2, la table forums comporte plusieurs champs id_article, id_breve et id_rubrique qui permettent certaines boucles.

Ces boucles doivent être adaptées pour fonctionner avec SPIP 3 puisque ces champs ont été remplacés par deux champs objet etid_objet.

Ces deux champs permettent de mettre des forums sur n’importe quel objet éditorial, que ce soit des mots, des documents ou tout autre objet créé par un plugin.

Par exemple, les emboitements suivants ne marchent plus :

<BOUCLE_racine_forums_parents(FORUMS) {id_thread}>
  <BOUCLE_forum_suivant_article(ARTICLES) {id_article}>
  ...

ou :

<BOUCLE_forums(FORUMS){0,1}>
   <BOUCLE_articles(ARTICLES){id_article}>    
       #ID_ARTICLE
   </BOUCLE_articles>
</BOUCLE_forums>

En SPIP 3 on corrige en :

<BOUCLE_forums(FORUMS){0,1}{objet=article}>
  <BOUCLE_articles(ARTICLES){id_article=#ID_OBJET}>
      #ID_ARTICLE
  </BOUCLE_articles>
</BOUCLE_forums>

ou bien avec :

<BOUCLE_forum_suivant_article(ARTICLES){id_article=#ID_OBJET}{si (#OBJET|=={article})}> 
etc... 

Titres et rangs

#TITRE bénéficie désormais d’un traitement qui enlève automatiquement le n° qui préfixe éventuellement le contenu.

La plupart du temps, c’est bien ce comportement qu’on recherche, et il est donc inutile d’appeler le filtre supprimer_numero comme il le fallait avant. Si toutefois vous voulez afficher le titre avec son numéro, il faut enlever ce traitement, c’est à dire employer #TITRE*.

Cette différence de comportement par défaut peut avoir des conséquences sur des squelettes qui feraient des comparaisons dans un critère, car le traitement n’est par contre toujours pas appliqué sur le champ ’titre’ lorsqu’il figure en partie gauche d’un critère.

Par exemple :

<BOUCLE_A(ARTICLES){id_article}>
   <BOUCLE_tri(ARTICLES){titre>#TITRE|recuperer_numero} >
etc...

Cette boucle pour afficher les articles de rangs supérieurs au rang de l’article courant ne marchera plus puisque #TITRE ne renvoie plus de numéro. À la place, il faut employer la balise avec étoile #TITRE*.

<BOUCLE_A(ARTICLES){id_article}>
   <BOUCLE_tri(ARTICLES){titre>#TITRE*|recuperer_numero} >
etc...

Modèles

Les modèles reçoivent maintenant l’environnement. Tous les paramètres de contextes, présents dans l’environnement d’appel ou explicitement passés en paramètre de l’appel, avec une priorité à ces derniers, sont à la fois accessibles par #VARIABLE et en #ENV{variable}. Des adaptations sont donc nécessaires dans certains modèles.

À titre d’exemple, un modèle inclus dans le corps de l’article 18 et donc noté : <mon_modele|> transmet 2 informations supplémentaires :

    #ENV{article18} =>
    #ENV{id_article} => 18

Dans le cas où l’appel du modèle inclue id_article comme paramètre (<mon_modele|id_article=2>) c’est bien cet id_article là (2) qui sera transmis, quel que soit l’id de l’article dans lequel ce modèle est appelé (comportement : comme avant).

En revanche, lorsqu’on ne passe pas de paramètre explicite, le comportement sera différent, si le modèle fait appel :
-  au critère conditionnel {id_article?} dans une boucle
-  à un test sur [(#ID_ARTICLE) affichage si id_article]
puisque dans tous les cas #ID_ARTICLE ou #ENV{id_article} existera.

Pour corriger lorsque ce sera nécessaire, il est possible :
-  de changer de nom de paramètre pour enlever l’ambiguité
-  d’utiliser le fait que seuls les paramètres passés explicitement lors de l’appel du modèle sont accessibles en plus par #ENV{arg/variable}, à la différence des paramètres non explicites passés automatiquement au contexte.

Ainsi on pourra remplacer un critère conditionnel {article ?} par la combinaison de deux critères :

{id_article >= #ENV{args/id_article, 0}} 
{id_article <= #ENV{args/id_article, 99999999}}

Balise #FOREACH

La balise #FOREACH disparaît. A la place il faut utiliser une boucle itérateur DATA.

<BOUCLE_for(DATA){source tableau,#LE_TABLEAU}>
#CLE / #VALEUR
</BOUCLE_for>

Si c’est juste pour afficher le contenu des tableaux#ENV ou #CONFIG, il est aussi possible d’utiliser :

[<pre>(#ENV**|unserialize|print_r{1})</pre>]
[<pre>(#CONFIG**|unserialize|print_r{1})</pre>]

Avec le plugin developpement on pourra plus simplement écrire :
[(#ENV|bel_env)] ou [(#CONFIG|bel_env)]

Boucles avec jointures

Certaines jointures qui devaient être explicitées dans SPIP 2 se font désormais automatiquement.

Exemple : jointure de spip_rubriques avec spip_mots.

Le commit 90091 remplace la boucle SPIP 2

    <BOUCLE_Exclure(RUBRIQUES mots){type_mot=_FondPage}{fusion mots.id_mot}>

par la boucle SPIP 3

    <BOUCLE_Exclure(RUBRIQUES){type_mot=_FondPage}{fusion id_mot}>

Table de liens

Les tables de liaisons sur les mots ou sur les auteurs, qu’il y avait pour chaque objet spip spip_mots_articles, spip_auteurs_articles, spip_mot_breves, spip_mot_rubriques... ont toutes été fusionnées en spip_mots_liens et spip_auteurs_liens.

Au lieu d’une seule colonne id_article ou id_breve ou id_rubrique comme l’avaient chacune des tables disparues, les nouvelles tables génériques de lien ont deux colonnes génériques : objet etid_objet. Elles peuvent ainsi décrire les liens avec mots et auteurs de tous les objets : ceux livrés avec SPIP, et ceux créés par les plugins.

Cela ne change rien pour les boucles simples qui ne mentionnent pas ces tables de liaison même si SPIP les utilise grâce à l’ingéniosité de son compilateur de boucles.

En revanche, il faut évidemment modifier les boucles plus complexes qui référencent explicitement ces tables, si jamais il y en a dans vos squelettes.

Exemple : dans c90093, la boucle avec double jointure explicite, dont une sur mots_rubrique

    <BOUCLE_MemoGoodiesRubrique(ARTICLES rubriques mots_rubriques){titre_mot=Goodies}{doublons goodies}{age>=(#CONFIG{soyezcreateurs/age_goodies,30})} /> 

est remplacée par les deux boucles imbriquées :

    <BOUCLE_MemoGoodiesRubrique(RUBRIQUES){titre_mot=Goodies}>
        <BOUCLE_Articles_Exclus(ARTICLES){id_rubrique}{doublons goodies}{age>=(#CONFIG{soyezcreateurs/age_goodies,30})}{lang} />
    </BOUCLE_MemoGoodiesRubrique> 

Jointures sans critère identifiant

Dans une boucle avec jointure implicite, si vous ne spécifiez pas l’identifiant sur laquelle la jointure se fait en critère de boucle, SPIP ne pourra plus deviner sur quel type d’objet vous bouclez, et il n’y aura que #ID_OBJET à disposition.

Par exemple si vous avez en SPIP 2 une boucle :

<BOUCLE_a(FORUMS){par date}{0,4}>#ID_ARTICLE </BOUCLE_a>

il faudra la remplacer par :

<BOUCLE_a(FORUMS)>#ID_OBJET</BOUCLE_a>

Fort heureusement, ce besoin est assez rare, car le problème ne se pose pas dés qu’il y a un critère portant sur {id_article} dans la boucle. En effet, le compilateur de SPIP détecte ce critère et s’en sert pour comprendre d’où vient l’#ID_ARTICLE demandé dans le corps de la boucle.

Personnalisation des urls publiques

Si vous définissez des modèles d’urls publiques personnalisées, vous devrez renommer les fonctions qui les définissent.

Par exemple, pour la balise #URL_ARTICLE , renommez la fonction generer_url_article en urls_generer_url_article_dist. Et pour les adresses <emb> des documents insérés par les modèles dans un article, renommez la fonction generer_url_document en urls_generer_url_document_dist

Auteur JLuc, Maïeul Publié le : Mis à jour : 18/04/23