Carnet Wiki

NouveauCritere ( bases vieillottes )

Version 14 — Octobre 2015 JLuc

2015 : Page remise à jour, à finir de relire et valider.
Todo : illustrer avec critere_logo_dist()

Voir aussi : Créer un critère avec pipeline pre_boucle et accéder à l’environnement

Attention Page Périmée

SVP : trier et actualiser cette page

| NouveauCompilo | NouvelleBoucle | NouvelleBalise | InterfaceEtUsages | CreerUnCritere avec pipeline pre_boucle CreerUnCritere


Des nouveaux critères

Principe

Le NouveauCompilo permet maintenant d’ajouter ses propres paramètres aux boucles. Le compilateur permet Cela va dans le sens de l’ajout de définir ses propres critères pour toutes les nouvelles boucles , sur les tables SPIP ou sur de nouvelles tables, dans SPIP .Mais bien sûr, on peut aussi les utiliser pour écrire ses propres extensions des tables actuelles.

Pour des critères de base Dans SPIP , une boucle dans le squelette est traduite en requête SQL vers la base de données sont stockées les tables articles , brèves et autres . Un Du coup , un critère de boucle se traduit comme une nouvelle contrainte dans la requête. D’autres critères peuvent requérir l’exécution de code php.

Implémenter un nouveau critère demandera donc une connaissance des requêtes SQL.

Par exemple, quand on ajoute le critère {exclus} à une boucle d’articles, SPIP va ajouter une contrainte disant que l’on ne veut pas récupérer l’article en cours de la table, mais juste les autres :

WHERE _  <code >
		 WHERE  ... AND spip_articles.id_articles != XX</code XX 
</ code >


Le compilateur SPIP analyse le source et crée la structure de donnée représentative du squelette, de ses boucles et donc des critères qu’on veut analyser.


Les critères ’maison’ doivent donc respecter la syntaxe SPIP.


Pour les définir, on peut 
- définir une fonction critère_nomducritere : c'est ce qu'on voit ici.
- ou  [glisser un code de traitement dans le pipeline pre_boucle->1770]


{{{Implémentation}}} {{{implémentation}}} 


Les critères du noyau de SPIP sont tous déclarés dans <code>ecrire/public/criteres strike>{inc-criteres .php</code >. php3}</strike >  {criteres . php}, y jeter un coup d’œil est une bonne idée.


Pour déclarer un nouveau critère, il faut déclarer une fonction < code>critere_quelquechose</code >  {{critere_quelquechose}}   dans un  < code>mes_options {ecrire/mes_options .php

. php3 (ou dans un fichier indépendant si on veut utiliser le SystemeDePlugin).

quelquechose</code >  {{quelquechose}}   étant le nom du critère qui apparaîtra dans la boucle.  ( ainsi ,  on  ne  peut  pas  déclarer  de  critère  purement  numérique ). 


Les fonctions critere_ reçoivent à la fois les données sur la boucle globalement et les données sur le critère lui-même.


Par exemple, la fonction pour le critère <code>{exclus}

est déclarée comme cela :
<code class=’php ’>
>
function critere_exclus_dist($idb, &$boucles, $param, $not)
$boucle = &$boucles[$idb] ;

if ($param != ’exclus’ OR $not)
erreur_squelette(_T(’info_erreur_squelette’), $param) ;

$boucle->where[] = $boucle->id_table . ’.’ . $boucle->primary.« !=’ »."
. calculer_argument_precedent($idb,$boucle->primary, $boucles) .
« . »’" ;


Cette fonction a un < code>_dist</code > _ dist à la fin, parce que c’est une fonction du noyau, on peut la surcharger ainsi écraser cette fonction en déclarant sa propre fonction < code>critere_exclus</code >. critere_exclus .

La fonction prend quatre paramètres :
1- $idb qui est l’identifiant de la boucle (le nom après BOUCLE dans le squelette),
2- &$boucles qui est un tableau de toutes les boucles de ce squelette, indexé par leur identifiant,
3- $param qui est le critère qui a fait appeler cette fonction, ainsi, si on veut passer des paramètres, on peut les récupérer ici,
4- $not qui indique si le critère est inversé.

Elle commence par deux morceaux de code assez commun :

$boucle &lt;code >
	 $boucle  = &$boucles[$idb];&lt;/code ;
 &lt;/code >
_ qui permet de récupérer la boucle actuelle.
_ <code>if &lt;code >
	 if  ($param != 'exclus' OR $not)
		erreur_squelette(_T('info_erreur_squelette'), $param);


qui vérifie que le critère passé n’est pas accompagné d’autres paramètres et qu’il n’est pas nié (ce qui n’aurait pas de sens pour ce critère)

La dernière partie du code ajoute la nouvelle contrainte à la requête :

$boucle->where &lt;code >
	 $boucle->where [] = $boucle->id_table . '.' . $boucle->primary."!='"."
	. calculer_argument_precedent($idb,$boucle->primary, $boucles) .
	 "."'";&lt;/code "'";
 &lt;/code >


On peut modifier un certain nombre de champs de la requête d'une boucle:
- {$select} quels champs seront sélectionnés et rendus accessible pour l'affichage (c'est un tableau de nom de champ),
- {$from} sur quelles tables faire la requête, (ici aussi, un tableau de nom de table), mais attention à la notive de ESJ  :  «   {Il  faut  remarquer  qu’un  critère  n’a  a  priori  pas  à  affecter  le  champ  from  de  la  requête  SQL  à  construire Déesse  A . Les exceptions dans le code de Spip sont des scories à évacuer.:
_ <quote>
_  Il faut d’ailleurs remarquer qu’un critère n’a a priori pas à affecter le champ from de la requête SQL à construire (il y a des exceptions dans le code de Spip, je sais, mais ça fait partie des scories que je cherche à évacuer).
}  » _  &lt;/quote >
 
- {$ where} {$where}  quelles sont les contraintes sur la requête, toutes les contraintes seront associées avec un AND, si on veut faire un OR entre deux contraintes, il faut le mettre comme une seule contrainte (encore un tableau de contraintes),
- {$limit} limiter le nombre de résultat (format SQL de LIMIT : <code>{$debut, $nombre}

, l’indexation commence à 0 bien entendu. C’est le critère {a, b} des boucles.)
-  $group quelle colonne groupée (un nom de champ),
-  $order par quelle colonne trier (une chaîne entre guillemets, ainsi il faudra toujours retourner quelque chose du genre : "'colonne'"),
-  sous_requete ????
-  compte_requete ????

Un certain nombre de sucres d’attributs (?Un certain nombre de sucres syntaxiques (éléments facilitants ) sont présents pour nous aider à garder des critères génériques génériques qui puissent marcher avec le plus de boucles possible :
-   $ boucle->id_table $boucle->id_table est le nom de la table sur laquelle la boucle s’applique,
-  $boucle->primary est la clef « primaire » de la table,
-  on peut récupérer un argument passé dans la boucle (soit par le contexte, soit par assignation) grâce à la méthode calculer_argument_precedent qui prend trois paramètres :

  • l’identifiant de la boucle actuelle,
  • le nom du champ à récupérer,
  • le tableau des boucles.

Pour chaque boucle, dans le fichier inc-boucles.php, une requête de base est déjà spécifiée, il faut donc faire attention à ajouter des nouvelles contraintes compatibles avec cela. En général, cela implique de mettre une contrainte sur la clef « primaire » de la table :$boucle->id_table . '.' . $boucle->primary

Pour accéder aux champs nouveaux demandés dans la requête, il y a deux méthodes :
-  si c’est un champ déclaré dans le fichier de configuration, on y a accès directement par la balise #NOM_CHAMP,
-  sinon (c’est une balise calculée), il faut déclarer une fonction balise_CHAMP qui explique à Spip comment récupérer ce nouveau champ (voir la page sur le NouveauCompilo).

Exemple

-  Nouveau Critére : trouver les articles (ou autres) similaires
-  critère LIKE MySQL : {like titre %machin-chose%}

function critere_like($idb, &$boucles, $crit) {


$boucle = $boucles[$idb]; //la boucle actuelle
        $not = $crit->not; //est-ce que le critère est inversé: !like
	$id = $boucle->primary; //l'id de la table actuelle


if (count($params) < 2) //vérifie le nombre de paramètres
	      erreur_squelette(_T('zbug_info_erreur_squelette'),
			       "{like ?} BOUCLE$idb");


$champ = array_shift($crit->param);
	$champ = $champ[0]->texte; //on prend le premier paramètre comme  un champ fixe


$variable = array_shift($crit->param);
	$variable = calculer_liste($variable, array(), $boucles, $boucle->id_parent); //on calcule la valeur du 2e~paramètre. Ainsi, on peut utiliser une balise SPIP dedans.


$boucle->where[] = "$id.$champ ".($not?'NOT ':'')."LIKE $variable"; //on ajoute une nouvelle condition WHERE
}

| NouveauCompilo | NouvelleBoucle | NouvelleBalise | InterfaceEtUsages | CreerUnCritere avec pipeline pre_boucle

--------------

Question sous SPIP 1.8

J’ai un champ #NOM_SITE qui contient une liste d’id_article
séparés par des points virgules. Ex : 66 ;58
Je fais :

<BOUCLE_a(ARTICLES){id_rubrique=38}>
<BOUCLE_b(ARTICLES){id_article IN #NOM_SITE*}>

La boucle b ne renvoie que le premier n° (66). Le séparateur peut être ; ou , ou | ou ... c’est pareil.
La requête MySQL est ainsi faite :

SELECT articles.id_article,
FIND_IN_SET(articles.id_article, "'66;58'") AS rang, articles.lang
FROM spip_articles AS articles
WHERE articles.id_article IN ('66;58')
    AND articles.statut='publie'
    AND articles.date < NOW()
ORDER BY rang

(Que je mette #NOM_SITE ou #NOM_SITE*, les guillemets
simples sont tjrs là, et le résultat est le même)
Une idée ?

Réponse
Ce que cherche à faire Philippe, il me semble, c’est à définir un nouveau critère basé sur le PS de l’article. Il faut donc qu’il ecrive un nouvelle fonction critere_montruc()
à utiliser sous la forme {montruc}

A ce moment il n’y aura pas à faire appel à une construction complexe
x IN #TRUC qui en effet n’est pas prévue pour ça.

FranckSG : une astuce serait d’utiliser d’autres séparateurs que le point virgule. Avec | il est possible d’utiliser un critere=regex( | ), les expressions régulières sont parfaites dans ce cas !

| NouveauCompilo | NouvelleBoucle | NouvelleBalise | InterfaceEtUsages | CreerUnCritere