Carnet Wiki

PortageV2 : Migrer un plugin vers SPIP2

Version 43 — Décembre 2011 — 193.252.xx.xx

Voir aussi : migrer un plugin vers spip3

Attention !


Ces indications utiles sont pertinentes pour porter à moindre frais du code déjà existant. Les méthodes et fonctions indiquées ne correspondent plus forcément aux bonnes pratiques pour un chantier neuf, en particulier en ce qui concerne l’interface de l’espace privé

Dans l’état de l’Art en Juin 2009, les plugins à utiliser comme modèle technique pour le développement d’interfaces privées sont :
-  Forum du core
-  Sites du core
-  urls_etendues du core
-  gestion_documents du core

De manière générale, toutes les correspondances avec les anciennes fonctions sont définies dans le fichier inc/vieilles_defs.php !!

Trucs utiles pour le portage d’un plugin vers SPIP version 2.0


définir une fonction qui teste la version

On peut faire appel à la fonction version_compare pour implémenter les fonctionnalités critiques de 2 manières différentes selon la version du core de SPIP. On peut ainsi garder le plugin compatible avec plusieurs versions de SPIP, mais cela allourdit le code.

if (version_compare($GLOBALS['spip_version_code'],'1.9300','<')) { // SPIP <= 1.9.2x 
   ...}
elseif (version_compare($GLOBALS['spip_version_code'],'1.9300','>=')) {        
... // spip V2
};

Ou bien :

if (version_compare($GLOBALS['spip_version_branche'],'2.1.0 dev','<')) 
 {...

Voir aussi la fonction spiplistes_spip_est_inferieur_193() du plugin spipliste.


debut_page

pour thelia il a fallu remplacer :

debut_page(_T("spip_thelia:catalogue_thelia"), "Catalogue T&eacute;lia", "Catalogue T&eacute;lia");

par

$commencer_page = charger_fonction('commencer_page', 'inc');
echo $commencer_page(_T("spip_thelia:catalogue_thelia"),_T("spip_thelia:catalogue_thelia"),_T("spip_thelia:catalogue_thelia"));

Pour spip2spip

debut_page(_T('spiptospip:copy_spip2spip'), "administration", "configuration","contenu");
echo "<br / ><br />";

a été remplacé par

$commencer_page = charger_fonction('commencer_page', 'inc');
echo $commencer_page(_T("spiptospip:copy_spip2spip"),_T("spiptospip:copy_spip2spip"),_T("spiptospip:copy_spip2spip"));

debut_gauche, debut_droite, fin_gauche, fin_droite

debut_gauche();
est remplacé par
echo debut_gauche('', true);

il en est de même pour les « fins » qui deviennent par exemple :

echo fin_gauche();
echo fin_page();

attention : fin_droite n’existe pas
pour finir une page correctement le code est
echo fin_gauche().fin_page();


debut_boite_info, fin_boite_info, debut_cadre_relief, fin_cadre_relief

debut_boite_info();
est remplacé par
echo debut_boite_info(true);

fin_boite_info();
est remplacé par
echo fin_boite_info(true);

fin_cadre_relief(true);
est remplacé par
echo fin_cadre_relief(true);

Autre exemple d’emploi de debut_cadre_relief :
echo debut_cadre_relief($icone,true,'',$titre);


gros_titre

gros_titre(_T('peuplementldap:titre_page'),'',false);
est remplacé par
echo gros_titre(_T('peuplementldap:titre_page'),'',false);


bouton_block_invisible

bouton_block_depliable et fin_block


debut_raccourcis,fin_raccourcis

 debut_raccourcis();
        echo "<p>";
        icone_horizontale (_L('Administrer les tables'), generer_url_ecrire("csvimport_admin"), "../"._DIR_PLUGIN_CSVIMPORT."img_pack/csvimport-24.png");
        echo "</p>";
        fin_raccourcis();


est remplacé par

$icone_horizontale = icone_horizontale (_L('Administrer les tables'), generer_url_ecrire("csvimport_admin"), "../"._DIR_PLUGIN_CSVIMPORT."img_pack/csvimport-24.png");
 echo bloc_des_raccourcis($icone_horizontale);

generer_url_xxxx

generer_url_XXX() est systématiquement remplacé de manière plus générale par generer_url_entite(’XXX’)

Remplacer les generer_url_xxxx(’...’) par generer_url_entite($id, ’xxxx’), idem dans les squelettes :
|generer_url_site{...} => |generer_url_entite{site, ...}

Pour un code portable, on teste la version, ce qui fait que pour un portage compatible :
$url = generer_url_article($row['id_article']);
devient :

$url = ( spiplistes_spip_est_inferieur_193()) ? 
                  generer_url_article($row['id_article']) : generer_url_entite($row['id_article'], 'article');

_q (sql_quote)

-  _q est remplacé par sql_quote pour échapper les champs non numeriques dans les syntaxes de requêtes SQL
-  intval est utilisé pour les champs numeriques

-  _q est deprecié et ne doit plus être utilisé
-  les echappements en php peuvent etre faits avec les fonctions php usuelles selon les besoins (addslashes, ...) mais mieux faut utiliser sql_quote pour éviter les problèmes de charset

note@marcimat le 21/01/09 : je ne savais pas que _q est déprécié ? c’est écrit où ça ?
note@erational 21/01/09 : je ne sais mais on dirait que c’est vrai, le core n’utilise quasiment plus _q


spip_query, spip_fetch_array,...

Ces fonctions sont encore définies mais sont depreciée et disparaitront rapidement car elle ne permettent pas la portabilité pour postgresql ou sqlite

Il faut préférer les fonctions en sql_ (cf http://doc.spip.org/spip.php?page=r...)

Exemples :

« spip_num_rows » devient « sql_count »

« spip_query » devient « sql_query »

« spip_fetch_array » devient « sql_fetch »

(idem spip_abstract.., calcule_mysql_in, ...)

Exemples :

selection


-  1) selection : 1 résultat seulement (doc sql_fetsel) :
il existe plusieurs fonctions de sélections (sql_fetsel, sql_select, ...) qui retournent des objets differents. bien choisir celle dont vous avez besoin

        $result = spip_query("SELECT * FROM spip_forms WHERE id_form="._q($id_form));
        if (!$row = spip_fetch_array($result)) return false;

est remplacé par :

        if (!$row = sql_fetsel("multiple","spip_forms","id_form=".intval($id_form)))
                return false;

-  2) selection : compter les résultats :

        $row = spip_fetch_array(spip_query("SELECT COUNT(*) AS tot FROM spip_forms_donnees WHERE id_form=".intval($id_form)." AND confirmation='valide' AND statut<>'poubelle'"));
        if ($row)        $nb_reponses = $row['tot'];

est remplacé par

        $nb_reponses = sql_countsel("spip_forms_donnees","id_form=".intval($id_form)." AND confirmation='valide' AND statut<>'poubelle'");

-  3) selection complexe :
De même,

        $result = spip_query("SELECT r.id_donnee, r.date,r.url, c.champ, c.valeur ".
                "FROM spip_forms_donnees AS r LEFT JOIN spip_forms_donnees_champs AS c USING (id_donnee) ".
                "WHERE id_form=".intval($id_form)." AND confirmation='valide' AND statut<>'poubelle' AND c.id_donnee IS NOT NULL ".
                "ORDER BY date, r.id_donnee");
        while ($row = spip_fetch_array($result)) 
        {...


est remplacé par

     $rows = sql_allfetsel(
                "r.id_donnee, r.date,r.url, c.champ, c.valeur ",
                "spip_forms_donnees AS r LEFT JOIN spip_forms_donnees_champs AS c ON r.id_donnee=c.id_donnee",
                "id_form=".intval($id_form)." AND confirmation='valide' AND statut<>'poubelle' AND c.id_donnee IS NOT NULL ",
                "date, r.id_donnee");
        foreach($rows as $row) 
        {...

-  4 ) selection classique (doc sql_select) :

$result_copie = spip_query("SELECT * FROM ".$table_prefix."_spip2spip ORDER BY site_titre");
while($row_copie  = spip_fetch_array($result_copie)) {  
   ...

est remplacé par

$result = sql_select("*","spip_spip2spip", "", "", "site_titre"); 
 while ($row = sql_fetch($result)) {  

Note sur le code précedent :
préfixe des tables il n’est plus nécessaire d’indiquer les préfixes de tables (cas particulier où l’on possède plusieurs SPIPs sur une même base de données), l’API sql_* se débrouille tout seule
instruction ORDER BY :
$result = sql_select(« * »,« spip_spip2spip ORDER BY site_titre ») ;
n’était pas correct, remplacé par :
$result = sql_select(« * »,« spip_spip2spip », «  », «  », « site_titre ») ; sinon PG ou SQLite ne vont pas du tout aimer (note@marcimat 21/01/09)

-  5) delete :

spip_query("DELETE FROM spip_forms_champs_choix WHERE id_form=3");
est remplacé par
sql_delete("spip_forms_champs_choix","id_form=3");

-  6) Insertions : ( sql_insertq)

        $lsDate = date('Y-m-d H:i:s');
        spip_query("INSERT INTO spip_articles (titre, id_rubrique, texte, date, statut) VALUES ('$titre', '$id_rubrique', '$texte', '$lsDate', 'publie')");
        $id_article = spip_insert_id();


est remplacé par :

        $lsDate = date('Y-m-d H:i:s');
        $id_article = sql_insertq( 'spip_articles', array(
                                 'titre'=>$titre, 'id_rubrique'=>$id_rubrique, 
                                 'texte'=>$texte, 'statut'=>'publie', 'id_secteur'=>$id_secteur, 
                                'date'=> $lsDate, 'accepter_forum'=>'non', 'lang'=>$lang));

-  7) insertions multiples : on pourra également remplacer de multiples appels à spip_query ("INSERT...")
par un unique appel à sql_insertq_multi après avoir préparé les données.

-  8) Mise à jour (update) : ( sql_update)

$sql = "UPDATE spip_spip2spip SET last_syndic = NOW() WHERE id=$current_id LIMIT 1";
spip_query($sql);

remplacé par

sql_update("spip_spip2spip", array('last_syndic' => 'NOW()'), "id=$current_id");

spip_abstract_insert

spip_abstract_insert("spip_forms_donnees","(id_donnee,id_form,date,ip,id_auteur,url,confirmation,statut,maj)","(".intval($id_donnee).",".intval($id_form).", NOW(),"._q($ip).","._q($id_auteur).","._q($url).", 'valide', 'publie', NOW() )");


est remplacé par

$id_donnee = sql_insertq("spip_forms_donnees",
                                                          array(
                                                          "id_donnee"=>$id_donnee,
                                                          "id_form"=>$id_form,
                                                          "date"=>"NOW()",
                                                          "ip"=>$ip,
                                                          "id_auteur"=>$id_auteur,
                                                          "url"=>$url,
                                                          "confirmation"=>"valide",
                                                          "statut"=>'publie',
                                                          "maj"=>"NOW()"));

spip_abstract_fetch

$row = @spip_abstract_fetch($result,"")
est remplacé par
$row = @sql_fetch($result,"")


spip_abstract_count

spip_abstract_count($result, $verif->sql_serveur)
est remplacé par
sql_count($result,$verif->sql_serveur)


include_ecrire

inclure_ecrire($file)
est remplacé par
inclure_spip($file)


gestion du cron

il faut utiliser le pipeline taches_generales_cron et créer un sous-répertoire genie dans lequel on place les fonctions appelés par le cron. voir en plugin exemple agenda2

Déclarer une tache en CRON

Il y a aussi un nouveau plugin dédié au cron, à chercher sur la zone. Il s’appelle « job_queue ».


La base de données SPIP

  • la table spip_documents_articles est remplacée par spip_documents_liens

sur les autres tables, beaucoup de champs ont évolué, être prudent donc.


$auteur_session[’nom’] ne fonctionne plus depuis un bout de temps
On remplace par $GLOBALS[« visiteur_session »][’nom’]


Comment ajouter son plugin version 2 à la liste automatique ?

  1. documenter le plugin en écrire un article sur http://www.spip-contrib.net
  2. ajouter le zip du plugin (éventuellement en document distant depuis la zone)
  3. ajouter à cette article le mot-clé Plugins pour SPIP 2.0

à creuser, du côté des motclés

-  create_groupe a peut être changé de signature.
-  voir ce qu’il en est de create_rubrique_mot ou create_mot_rubrique


Quelques liens utiles

-  Réaliser un premier plugin
-  Compatibilite-des-plugins
-  Les points d’entrée (pipelines)
-  API sql_*
-  L’interface de SPIP avec SQL sur doc.spip.org
-  L’interface de SPIP avec SQL sur spip.net

-  Romy : porter ses sites en SPIP V2
-  DenisB : Mise à jour d’un site spip 1.9.2 vers spip 2.0.3