Carnet Wiki

Créer un nouveau critère

Version 22 — Janvier 2020 — 78.242.xx.xx

Voir aussi
-  Créer un critère avec pipeline pre_boucle
-  Accéder à l’environnement
-  Le code du critère {logo}"
-  Nouveau Critére : trouver les articles (ou autre) similaires


Le compilateur permet de définir ses propres critères pour toutes les boucles sur les tables SPIP ou sur de nouvelles tables.

Pour des critères de base, une boucle dans le squelette est traduite en requête SQL vers la base de données. 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.

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 ... AND spip_articles.id_articles != XX

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

Implémentation

Les critères du noyau de SPIP sont tous déclarés dans ecrire/public/criteres.php.

Pour déclarer un nouveau critère truc, il faut déclarer une fonction critere_truc dans le mes_options.php de votre site ou plugin ou dans un fichier public/criteres.php de votre plugin, inclu dans le fichier d’option.

Les fonctions critere_ reçoivent à la fois
-  l’identifiant $idb de la boucle courante
-  les données $boucles de structure de toutes les boucles du squelette,
-  les données sur le critère lui-même.
Elles peuvent récupèrer la boucle courante, où notre critère est présent :
$boucle = &$boucles[$idb];
Elles peuvent alors modifier la boucle et ses attributs. Par exemple : ->where[] est un tableau des bouts de requete SQL qu’on veut voir dans la partie WHERE de la requête SQL.

Par exemple, la fonction pour le critère {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) ;

function critere_exclus_dist($idb, &$boucles, $crit) {
  $not = $crit->not;
  $boucle = &$boucles[$idb]$boucle->where[] ;
   $id  =  $ boucle->primary ;
   if  ($ not  or  ! $boucle->primary . $id) {
    return (array('zbug_critere_inconnu', array('critere' => $not . "!='"."
	. $crit->op )));
   } 
  $ arg  =   kwote(calculer_argument_precedent($idb calculer_argument_precedent($idb,$boucle->primary , $id ,  $boucles));
   $boucle->where []  )  .
	  =  array ("'! '  .  ='",  "'$boucle->id_table =  $boucle->id_table .  "  .  '. "$id'", $arg);
}

« . »’" ;


Cette fonction a un _dist à la fin, parce que c’est une fonction du noyau, on peut la surcharger en déclarant sa propre fonction 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- $crit $param qui est le critère qui décrit a fait appeler cette fonction , ainsi , si on veut passer des paramètres , on peut les arguments du récupérer ici ,
_ 4 - $not qui indique si le critère dans cette boucle est inversé . En particulier $crit->not indique s’il y a une négation de ce critère, et $crit->cond indique si le critère est utilisé de manière conditionnelle.

Elle commence par deux morceaux de code assez commun :
$boucle = &$boucles[$idb];
qui permet de récupérer la boucle actuelle.

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[] =  array ("'! '  .  ='",  "'$boucle->id_table =  $boucle->id_table .  "  .  '. $boucle->primary."!='"."
	. calculer_argument_precedent($idb,$boucle->primary, $boucles) .
	 "."$id '",  $arg);&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. Les exceptions dans le code de Spip sont des scories à évacuer.} »
-* rq : on peut spécifier le type de jointure avec sur une table avec {from_type}. Exemple  <code>$boucle->from_type['auteurs_liens'] = 'LEFT';

(cf dans le source de l’organiseur en ligne 22 ou 108 ou dans GIS sur les boucles avec le critère  !gis.

-  $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 : {$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 ????

A savoir

-  $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 récupére un argument du le contexte de la boucle grâce à la méthode calculer_argument_precedent : voir Accéder à l’environnement

-  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).

-  Pour que le critère force le squelette à être sessionné, parceque le critère utilise des données de session, on fait $boucles[$idb]->descr['session'] = true; ( par exemple dans le critère langues_preferees de tradlang ).
Sauf qu’en fait il semble que ça ne marche pas, ou pas toujours. Il faut donc Et si ça ne marche pas ( car il semble que parfois ça ne marche pas ), on peut utiliser le hack suivant en complément :

$boucle->hierarchie = "invalideur_session(\$Cache);";&lt;/code>,  qui  marche  bien . > 


</cadre>


{{{Exemple 2}}}


Dans un critère, tester si une rubrique est positive ou = -1
<code>	$boucle->where[] = array("'>'", "'articles.id_rubrique'", "'\"0\"'");
	$boucle->where[] = array("'='", "'articles.id_rubrique'", "'\"-1\"'");	

Exemple 3

Recréer un 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
}

CreerUnCritere avec pipeline pre_boucle | Accéder à l’environnement