Carnet Wiki

Astuces courtes pour SPIP

Version 223 — Novembre 2016 — Stéphane

<blockquote class="spip">

Ici vont uniquement les astuces courtes

Une astuce courte est faite de 1 à 3 lignes maximum.
Au-delà, merci de déplacer votre astuce dans les astuces longues car sinon la page sera impossible à maintenir !
Merci de vous rendre dans la partie privé pour lire les règles de publication dans le forum attaché à cet article.

</blockquote>

Contenu :

Voir aussi :


UTF-8


-  Convertir sa base en UTF-8 :
Convertir un site SPIP 3 en utf-8 avec le plugin Grenier.
Pour les problèmes d’interclassement sur une recherche un tri, utiliser le critère {collecte...} doc

Retour..


SPIP3 Debug

Pour voir les spip_log, il faut dans mes_options.php (voir inc/utils)
define ("_LOG_FILTRE_GRAVITE",8);


BOUTONS

Créer un bouton de déconnexion

Utiliser la balise #BOUTON_ACTION cf doc SPIP :
-  avec en premier paramètre le texte du bouton
-  et en second l’url de l’action, soit #URL_LOGOUT
La balise #URL_LOGOUT accepte uniquement en paramètre l’url de redirection après déconnexion
(voir à ce propos http://core.spip.org/issues/2471)
[(#BOUTON_ACTION{<:proposer_logout:>, #URL_LOGOUT{#URL_PAGE{mon_compte}}, 'logout', <:confirmer_logout:>})]
générera un bouton « se déconnecter » qui renverra vers ?page=mon_compte


ESPACE PRIVE

- Tester si l’espace est public ou privé

[(#REM|test_espace_prive|oui) on est dans le privé ]
En php

if(test_espace_prive()){
 echo "On est dans le privé";
}

- Supprimer l’événement onmouseover sur les Intertitres h3
(suppression de l’ouverture des dépliants au survol sur les H3)

$(document).ready(function(){
	$("h3.titrem").each(function() { 
		$(this).attr("onmouseover","").unbind("onmouseover");
	});
});

- Images/icones de l’espace privé

Cherche une image dans le theme de l’espace privé et retourne son chemin complet
Doc : CHEMIN_IMAGE

[(#CHEMIN_IMAGE{supprimer-12.png})]

a combiner avec balise_img{} Doc : balise_img

[(#CHEMIN_IMAGE{supprimer-16.png}|balise_img{'texte Alt', class_css})]


FAVICON

Les squelettes de Spip acceptent automatiquement une icône (un fichier .bmp 16 ou 256 couleurs, en format 16x16 ou 32x32 pixels) nommée favicon.ico pour le site public ; depuis 2015, vous pourrez aussi générer la favicon depuis votre logo, avec le plugin homonyme favicon .
Et pour remplacer l’icône Spip grise dans les onglets de l’interface privée (pratique quand on intervient simultanément sur plusieurs sites sous SPIP), il suffit de la poser en fichier « spip.ico » dans votre dossier de squelettes.
Pour memoire, voici les liens-type attendus (images à la racine du site) :

<link rel='shortcut icon' type='image/x-icon' href="/favicon.ico" /> <!-- Internet Explorer -->
<link rel='icon' type='image/png' href="/favicon.png" /> <!--navigateurs W3C -->
<link rel='apple-touch-icon' href='/apple-touch-icon.png'/> <!-- Apple iPhone -->

Ne pas oublier de recopier les favicon à la racine du site.

Retour..


PLUGINS

-  Quelques dépôts pour les plugins SPIP, cf http://plugins.spip.net/spip.php?page=depots
http://files.spip.org/spip-zone/archives.xml
http://files.spip.org/contribs/archives_autres.xml
http://files.spip.org/core/archives_core.xml
http://files.spip.org/externals/archives_externals.xml

-  Charger une fonction en php

 $ma_fonction = charger_fonction('ma_fonction','repertoire');
    $ma_fonction();

-  Modifier le bouton submit ’Enregistrer’ d’un formulaire CVT créé avec le plugin saisies
dans la fonction charger, ajouter
$contexte[’saisies_texte_submit’]=« Continuer » ;

-  Relancer SVP en SPIP3
var_mode=vider_paquets_locaux voir http://lapsuske.brubel.net/Debloquer-SVP

-  Tester si un plugin est actif :

Depuis SPIP 2 : voir la doc SPIP à ce propos

En php :

test_plugin_actif('prefixe_du_plugin'); retourne true ou false.
voir la doc sur code.spip.net

-  Récupérer le chemin d’un plugin dans un squelette :

#SET{cheminmonplugin, #EVAL{_DIR_PLUGIN_MONPLUGIN}}
#GET{cheminmonplugin}

Voir aussi #PLUGIN sur spip.net

-  Adopter plutôt une numérotation x.y.z comme numéro de version

z est incrémenté sur une correction
y sur une évolution fonctionnelle
x sur une incompatibilité avec les version précédentes.

exemple : version plugin 1.3.8

-  forcer la priorité d’un plugin par rapport un autre plugin (ou un plugin-dist) pour une surcharge ou un pipeline
Il faut définir un <utilise...>
rédaction du paquet

-  Supprimer des boutons du bandeau de l’espace privé avec le pipeline ajouter_menus

function prefixduplugin_ajouter_menus($flux){
    unset($flux['menu_edition']->sousmenu['pays']);
    unset($flux['menu_edition']->sousmenu['coordonnees']);
return $flux;   
}

Retour..


CSS

-  Pipeline automatique de CSS dans un plugin :

Pour l’espace privé : prive/style_prive_plugin_xxx.html

-  Faire un CSS qui soit un squelette (cela permet de récupérer des variables) :

[(#REM) dans la page monstyle.html et en première ligne ]
#HTTP_HEADER{'Content-Type: text/css'}
.couleurdefond {
  background-color:green;
  [(#ENV{id_article}|={33}|?{background-color:pink;})]
}

Appeler la CSS dans une page SPIP

[(#REM) dans la page article.html par exemple cela retournera /?page=styles&id_article=33]
<link rel="stylesheet" type="text/css" href="[(#URL_PAGE{monstyle}|parametre_url{id_article,[(#ENV{id_article})] )]" />
...
<div class="couleurdefond">
change ici la couleur de fond en rose si article=33
</div>

-  Utiliser modulo pour des lignes de 3 éléments en float, chaque ligne démarrera avec clear:both
class="floatleft [ (#COMPTEUR_BOUCLE|modulo{3}|=={1}|oui) clearboth]"
Retour..


BALISES

-  #EDIT partout
#EDIT{meta-demo/truc} ou #EDIT_CONFIG{demo/truc} voir http://blog.spip.net/Gazette-d-octobre-rend-le-vigneron.html

Quand on crée une balise, on peut vouloir récupérer des variables du contexte (il y a un article déjà sur contrib qui explique cela) ; mais quand on veut trouver le « type » de boucle du contexte, il faut aller le chercher dans la pile $p :

$p->boucles[$p->id_boucle]->id_table

Compter le nombre de liens signalés dans un article
Meme pas nécessaire de batir une regex, juste
[Liens cités: (#PS|extraire_balises{a}|count)    ....]

Intégrer une balise à une expression
Pour afficher une chaine contenant une expression avec une balise

#SET{ma_variable,#VAL{'chaine avant le titre '}|concat{#TITRE}|concat{'
a la fin'}}

Afficher l’environnement #ENV (dans un squelette) :
[<pre>(#ENV**|unserialize|print_r{1})</pre>]
ou [(#ENV**|unserialize|foreach)]

Retour..


FILTRES

-  Passer & en simple & : |filtrer_entites

-  N’afficher que le texte d’un champ, sans les images (ou autres documents)
Définir dans mes_fonctions le filtre sans_doc :

function sans_doc ($texte) {
return propre(preg_replace('#'._RACCOURCI_MODELE.'#', ' ', $texte));
}

Usage : [(#TEXTE*|sans_doc)]

-  Utiliser |textebrut pour compter la chaîne correctement, sinon l’apostrophe compte 5 :

[(#TITRE|textebrut|strlen|>{30}
|et{[(#TITRE|textebrut|strlen|<{60})]}|oui)
[(#INTRODUCTION|PtoBR|couper{85})] 
]

-  |unique dans un modèle. :

Un modèle inséré dans un texte ne peut pas simplement appeler le filtre |unique car il arrive que SPIP calcule plusieurs fois le #TEXTE (par exemple pour les besoins de #INTRODUCTION) et l’environnement de |unique n’est pas réinitialisé à chaque fois...
Pour ces besoins, on utilisera un « unique nommé », avec un nom généré dynamiquement de manière ... unique à chaque fois : #SET{ident, #REM|uniquid} ; puis utiliser |unique{#GET{ident}}.

-  Utiliser |replace pour créer l’équivalent d’un sprintf dans la définition d’un #SET utilisé dans une boucle itérateurs (_fil_ et BoOz sur irc) :

#SET{req, #VAL{"
  SELECT a.truc_1,
         s.truc_2,
         s.truc_x
    FROM spip_matable s,
         spip_auteurs a
   WHERE a.id_auteur = s.id_auteur
     AND date_format(s.truc_x, '%Y %m %d') = '%s'
ORDER BY s.truc_x desc
   LIMIT , 100
"}|replace{'%s', #ENV{ladate}}}


<BOUCLE_rech(DATA) {source sql, #GET{req}}>
  ...

-  N’afficher que les images d’un texte :

<BOUCLE_f(ARTICLES) {id_article}>
  #SET{tab_img, #TEXTE|extraire_balises{img}}
  [(#GET{tab_img}|implode{'<br />'}|image_reduire{150})]
</BOUCLE_f>

-  Laisser SPIP créer la balise avec son width et height :
|balise_img{alt,class} s’applique au chemin d’un fichier image.

-  Compter des objets éditoriaux sans passer par une boucle :
Compter le nombre total d’articles :
[(#VAL{article}|table_objet_sql|sql_countsel)]
Nombre de commandes ayant le statut « payé » :
[(#VAL{commande}|table_objet_sql|sql_countsel{statut='paye'})]

-  (SPIP 3) compter le nombre de liens entre objets éditoriaux sans passer par une boucle :
Nombre d’albums liés à l’article 25 (par rapport à la table de liens spip_albums_liens) :
[(#VAL{albums}|lister_objets_lies{article,25,''}|count)]

-  

Tester si une balise est égale à deux valeurs et à ces deux valeurs uniquement par exemple 19 et 32 (mais pas 119,320, ..)

éviter le filtre |match :

  • [(#ID_RUBRIQUE|match{19|32}|oui) ...] est faux.
  • [(#ID_RUBRIQUE|match{^19$|^32$}|oui) ...] est correct mais verbeux

Utiliser simplement [(#LISTE{19,32}|find{#ID_RUBRIQUE}|oui) ... ]

Retour..


VIGNETTES

-  Comment surcharger les vignettes des fichiers proposés par défaut dans SPIP ?
Il faut surcharger les fichiers du plugin medias, en déposant vos fichiers dans votre propre prive/vignettes/
Dans le cas d’un plugin, il faut aussi ajouter dans le paquet.xml <utilise nom="medias" compatibilite="[2..;]" />


CRITÈRES

-  Afficher un objet entre deux dates

Envoyer dans l'url date_debut=2014-07-11&date_fin=2014-07-14
et mettre en critères {date>=#ENV{date_debut,1970-01-01}}{date<=#ENV{date_fin,3000-01-01}}

-  Utilisation de variables dans un critère IN : voir Astuces #ARRAY, #LISTE et boucles DATA

-  critères sur un titre numéroté

MYSQL ne comprend pas les raccourcis \s et \d dans une regexp, on ne peut donc pas les utiliser.

{titre==^[[:digit:]]+[.)][[:space:]]+[[:alnum:]]}

ou

{titre==^([0-9]+\. +)?[Aa]}

-  Critère conditionnel, sans parenthèses ni crochets, seulement des bisoux, euh, des accolades... :

<BOUCLE_seulement_pour_la_rubrique_dix(RUBRIQUES) {id_rubrique=#ID_RUBRIQUE|=={10}|?{10}}>

-  Afficher les articles ayant le mot clef « truc » :

<BOUCLE_g(ARTICLES) {titre_mot=truc}>

{titre_mot} étant obsolète on écrit désormais :

<BOUCLE_g(ARTICLES) {mots.titre}>

-  Le critère {par multi titre} permet de trier les titres alphabétiquement quand ils utilisent la balise multi pour le multilinguisme.

-  Le critère {fusion} pour faire un index  :

on veut faire un index des titres d’articles, donc récupérer leur première lettre :

<BOUCLE_index(ARTICLES) {fusion SUBSTR(titre, 1, 1)} {" - "}>
[(#TITRE|mb_substr{0, 1})]
</BOUCLE_index>

-  Le critère {fusion} permet de faire un « GROUPBY » :

exemple sur un fil RSS, pour éviter des articles de même nom, on peut faire :

<BOUCLE_syndic(SYNDIC_ARTICLES) {fusion titre} {0, 10}>

On peut également faire une fusion pour avoir les articles tous issus de sites différents :

<BOUCLE_syndic(SYNDIC_ARTICLES) {fusion syndic_articles.id_syndic}>

-  Un simple {statut?} dans une boucle annule la restriction de statut sur la boucle document (comme sur une boucle article), on peut aussi demander {statut=prepa}

-  Utiliser un critère optionnel, et demander le critère via l’url :

<BOUCLE_articles(ARTICLES) {branche ?} {id_mot ?} {id_auteur ?}>

-  Limiter l’affichage des mots-clés liés seulement aux rubriques (ou articles) :

<BOUCLE_grmots(GROUPES_MOTS){id_groupe?}{tables_liees=rubriques}>
    <h3>#ID_GROUPE. <i>Groupe:</i> <a href="#URL_PAGE{groupmot,id_groupe=#ID_GROUPE}">#TITRE</a>. </h3> 
    <B_mot><ul>
    <BOUCLE_mot(MOTS){id_groupe}{par num titre, titre}{" -   "}>
        #SET{total,0} 
        <BOUCLE_desmotscles(RUBRIQUES){id_mot}>
            #TITRE
        </BOUCLE_desmotscles>
        #SET{total,#GRAND_TOTAL}
        </B_desmotscles>
        <a href="#URL_MOT">#TITRE </a> 
        [(#GET{total}|choixsiegal{0, "", [ ((#GET{total}))]})]
        </BOUCLE_mot>
        </ul></B_mot>
</BOUCLE_grmots>
<//B_grmots>


Mais attention, le champ #TABLES_LIEES etant eventuellement multi-valué (!), cette astuce ne vous affichera pas les groupes de mots-clés liés aux articles et à autre chose (Spip 2) !

-  N’afficher que les articles dont le « num titre » est pair :

on considère que tous les titres des articles sont préfixés avec un nombre suivi d’un point suivi d’un espace (« 123. Le titre ») :

<BOUCLE_art_pair(ARTICLES) {par num titre} {titre==^[[:digit:]]*[02468][.][[:space:]]} {"<br />"}>
#TITRE
</BOUCLE_art_pair>
<hr>
<BOUCLE_art_impair(ARTICLES) {par num titre} {titre==^[[:digit:]]*[13579][.][[:space:]]} {"<br />"}>
#TITRE
</BOUCLE_art_impair>


-  un formulaire simple (pas cvt) qui boucle sur la page et y renseigne un critère de boucle :

par exemple un select de mots-clefs (name="avec_mot") dont chaque value est un « id_mot » mais avec une option « tous les mots »

la boucle ARTICLES correspondante (au retour du formulaire) utilisera donc le critère {id_mot ...}.
mais comment ? puisque la boucle doit retourner les articles liés soit à un id_mot unique soit à n’importe quel id_mot

pour la boucle on utilisera les REGEXP de mysql avec comme critère :
   {id_mot == ^#ENV{avec_mot}$}

dans le select, on passera comme value pour l’option ’tous les mots’
 :
pour un formulaire en method get :
 <option value=".%2B">tous les mots</option>
pour un formulaire en method post :
 <option value=".+">tous les mots</option>


-  Afficher les articles « sauf » ceux qui ont un flash dans le corps de leur texte :

On travaille en 2 boucles. La première va extraire les id_article depuis la table spip_documents_liens des articles (objet) liés à un document (id_document) inséré dans le corps du texte (vu) et d’extension .flv :

#SET{noflash, #ARRAY}
<BOUCLE_noflash(spip_documents_liens) {objet = article} {vu = oui} {spip_documents.extension = flv}>
#SET{noflash, #GET{noflash}|push{#ID_OBJET}}
</BOUCLE_noflash>

la seconde boucle exclue ces articles (!IN) de sa recherche :

<BOUCLE_a(ARTICLES) {id_article !IN #GET{noflash}} {"<br />"}>
#TITRE
</BOUCLE_a>


-  N’afficher que les articles dont le surtitre contient la lettre « x » à une certaine position, position fournie dans une variable d’environnement (par exemple, passée en url).

SPIP ne permettant pas d’utiliser la fonction « SUBSTRING » de mysql comme critère de boucle, on utilise les expressions régulières (REGEXP) de mysql.

tout d’abord, construire la regexp :

#SET{reg, #VAL{.}|str_repeat{#ENV{position}|moins{1}}}

deux cas de figure :

  • si la position où rechercher la lettre « x » est 1 (c’est à dire au début du surtitre) ; la regexp sera vide «   »
  • si la position n’est pas 1, par exemple si #ENV{position} est égale à 4, on aura « ... »

il ne reste plus qu’à écrire le critère de boucle en ajoutant ^  commence par ») et le x final :

<BOUCLE_p(ARTICLES) {surtitre == ^#GET{reg}x}>
  #SURTITRE  -- (x en #ENV{position}e position)
  ...

-  Affichage conditionnel d’un tableau d’objets avec (CONDITION)  :

<BOUCLE_testRub(CONDITION){si #GET{inRub}|find{#ID_RUBRIQUE}}>

-  champ, tri et critère multicolonne

Exemple : champ pour la somme de 2 colonnes (ou toute autre expression sql en fait !).

Pour mettre la somme de plusieurs colonnes mysql dans un même champ spip,
il faut simplement déclarer un alias :
$exceptions_des_tables['table']['colonne_somme'] = 'colonne1+colonne2+colonne3';

#COLONNE_SOMME renvoie alors la valeur de colonne1+colonne2+colonne3

et on peut aussi faire {par colonne_somme}

ou {colonne_somme >100}


-  Seléctionner les articles qui commencent par 00.

{titre == ^00\.}

- le critère |picker_selected(article)
http://code.spip.net/autodoc/tree/ecrire/inc/filtres_selecteur_generique.php.html#function_picker_selected permet facilement de boucler sur un champ extra (3) de type « Sélection d’articles » : si on le nomme « refs » on peut écrire <BOUCLE_articles(ARTICLES){id_article IN #REFS|picker_selected(article)}>...</BOUCLE_articles>

- ----
[where<-]Utiliser

Utiliser un filtre où les 2 termes du test sont des champs de la table : critère {where ...}


Exemple : on veut trouver les articles ayant même id_rubrique et id_secteur

<BOUCLE_t(ARTICLES){id_rubrique = id_secteur}>

ne retourne rien, alors que

<BOUCLE_t2(ARTICLES){where id_rubrique = id_secteur}>

----


Retour..

AUTORISATIONS


-  savoir si l’on est connecté à une rubrique
en Administrateur Restreint :
      [Admin Restreint à (#SESSION{restreint}|table_valeur{#ID_RUBRIQUE}) #TITRE <br>]
NB : suite à une « feature » de SPIP, cela gère aussi les Admins.Restreints devenus Rédacteurs....

-  rediriger les visiteurs déjà identifiés vers une autre page
Par exemple, sur une page inscription, les renvoyer directement sur leur page perso.

[(#SESSION{login}|non|sinon_interdire_acces{#URL_AUTEUR{#SESSION{id_auteur}}})]

Retour..

MES_OPTIONS

Quelques constantes sont répertoriées ici

Les codes sont à mettre dans config/mes_options.php

-  Ajouter une fonction à appliquer au traitement du texte.

$table_des_traitements['TEXTE'][] = 'mafonction(%s)';	
function mafonction($texte){
	 return $texte." ajout final";
}

-  Trier les articles par titre dans /ecrire

define('_TRI_ARTICLES_RUBRIQUE', 'titre'); 

-  Éviter de voir les numéros ou les balises multis des titres dans l’espace privé (par exemple sur médiathèque) :

$table_des_traitements['TITRE'][] = test_espace_prive() ? 'typo(%s)' : 'typo(supprimer_numero(%s))';

-  Changer la qualité par défaut de compression jpg :

define('_IMG_GD_QUALITE', 95);

Limiter les opérations graphiques sur des images trop grosses :

if (!defined('_LOGO_MAX_SIZE')) define('_LOGO_MAX_SIZE',xxGD2); // Poids max des logos
if (!defined('_IMG_MAX_SIZE')) define('_IMG_MAX_SIZE',xxGD2); // Poids max des images 

Toutefois l’appel de SPIP à GD2 détecte la taille maximum qu’il pourra gérer, et ne lancera normalement pas une opération graphique qui pourrait échouer (une marge de 10% est rajoutée pour SPIP3)

-  En local, interdire le compactage des js et css dans le privé, et tout envoi de mails par facteur

if ($_SERVER["HTTP_HOST"] == "127...1" OR $_SERVER["HTTP_HOST"] == "localhost") {
	define('_INTERDIRE_COMPACTE_HEAD', true);
	define('_TEST_EMAIL_DEST', 'monmail@exemple.org'); // si mail vide = Facteur n'envoie rien 
}

Avoir le même cache pour tous les connectés, et un autre cache pour les non connectés

Par défaut avec la balise #SESSION SPIP crée un cache différent pour chaque internaute connecté. On peut souhaiter avec le même cache pour tous les connectés et un autre pour tous les non connectés.

$GLOBALS['marqueur'].=(isset($GLOBALS['visiteur_session']['login'])?':on':':off');

Afficher uniquement le titre des documents dans la médiabox lorsqu’on utilise le plugin albums
il faut mettre dans mes_options.php
define('_ALBUMS_TITRE_COURT','non');


Retour..

SQUELETTES


-  SPIP ne calcule pas les boucles dans les balises, il y a deux solutions :

  • soit mettre le résultat de la boucle dans un #SET, (mais ça oblige à calculer la boucle avant),
  • soit faire un inclure du fichier :
    [(#LOGO_ARTICLE|sinon{
        [(#INCLURE{'chemin/du/fichier_de_la_boucle'})]
    })]

-  URL de la page courante : #SELF
-  Nom de la page courante : #ENV{type-page} (retourne sommaire, article … nécessite le plugin Z-CORE ou SPIP_R)
-  Couple possible php/html pour les fonctions d’un squelette, exemple allocine_fonctions.php/allocine.html
-  #LOGO_XXX{url} génère un logo qui pointe vers l’url
-  Retrouver la profondeur d’une rubrique sous SPIP 2 ( sous Spip 3, voir #PROFONDEUR ).

<BOUCLE_profondeur(HIERARCHIE){id_rubrique}{tout}></BOUCLE_profondeur>#SET{profondeur,#TOTAL_BOUCLE}<//B_profondeur>
#GET{profondeur}


-  N’afficher que les articles ayant un document

<BOUCLE_articles(ARTICLES spip_documents_liens){spip_documents_liens.id_objet!=""}> ... 


-  Récupérer le nom du fichier sans extension (blabla.pdf blabla.zip deviendront blabla)
avec [(#FICHIER|basename{.#EXTENSION})] dans une boucle document.
-  Sans dépendance à une boucle, afficher le titre d’un objet SPIP ...avec le plugin bonux (?)

#INFO_TITRE{#OBJET,#ID_OBJET} exemple #INFO_TITRE{article,122}
ou
#INFO_<QUOI>{type_objet, id_objet}

-  Utiliser le filtre |ou :

[(#ENV{id_article}
	|ou{#ENV{id_rubrique}}
	|ou{#ENV{id_article}}
	|ou{#ENV{id_breve}}
) alors afficher ce texte ]

-  Remplaçer « lire la suite » par « autre chose » :

[(#TEXTE|couper{110, <a href="#URL_RUBRIQUE"><em>autre chose ...</em></a>})]

-  Une syntaxe (à partir de SPIP 2) pour tester l’existence d’un élément :

[(#PLUGIN{ABONNEMENT}|oui)
    #INCLURE{fond=inc/menu_abonnement}]
[(#PLUGIN{ABONNEMENT}|non)
    #INCLURE{fond=prive/menu_inscription2}]

-  Le critère {ajax} permet de recharger uniquement le morceau de noisette appelé :

utilisé en SPIP 2 avec pagination :

<INCLURE{fond=inc-manoisette, ajax}>

Mais comment faire fonctionner le callback ? et hop :

$(document).ready(function() {
  var fonction_a_rappeler=function() {
    ...
  }
  if (typeof onAjaxLoad == 'function') onAjaxLoad(fonction_a_rappeler);
  if (window.jQuery) jQuery(document).ready(function() {
    fonction_a_rappeler.apply(document);
  });
});

-  changer le caractère séparateur de pagination

d’abord modifier un peu le modèle de pagination choisi :

#SET{separateur,#ENV{separateur,'|'}}

devient :

#SET{separateur,#ENV{separateur}|sinon{'|'}}

et passer ensuite le paramètre de pagination dans la boucle elle-même :

[<p class="pagination">(#PAGINATION{page}{separateur=' '})</p>]

(il faut bien renseigner le modèle choisi si on renseigne la valeur du séparateur)

-  mettre un séparateur dans une liste (un menu par exemple) de manière propre :
dans une liste, les boucles permettent {' | '} pour insérer un séparateur, sauf que le html en pâtit car le séparateur se retrouve entre les balises <li>...</li> | <li>...</li> ce qui n’est pas très correct.
Il est aussi possible de faire {'<li> | </li>'} mais ça fait un item de liste qui n’en est pas vraiment un....

On peut utiliser avantageusement ce test dans la boucle, donc dans la balise li :

<li>#TITRE
[(#COMPTEUR_BOUCLE|=={[(#TOTAL_BOUCLE)]}|non) <span class="sep">|</span> ]
</li>

pour obtenir un séparateur seulement entre les item (visuellement) mais bien situé dans la structure html...

-  Empêcher l’apparition des boutons pour recalculer sur une page en particulier :

placer sur la première ligne du squelette :[(#HTTP_HEADER{Content-type: text/html[; charset=(#CHARSET)]})] Voir http://www.spip.net/fr_article4631.....

-  Se servir de #VAL :

par exemple pour |image_typo cela donnerait une image (avec la police victor.ttf) du mot « Actuellement » :

[(#VAL{Actuellement}|image_typo{police=Victor.ttf, taille=14, largeur=150})]

-  Tester les autorisations d’écriture ou de modification d’un auteur (à partir de SPIP 2) :

[(#AUTORISER{modifier, article, #ENV{id_article}}) vous pouvez modifier l'article ] 

Voir la doc

-  Savoir si l’on se trouve dans une « branche » particulière :

Comment savoir si l’article (ou la rubrique) en cours est un descendant direct ou non d’une rubrique donnée (dans la même « branche » donc) ?

[(#ID_RUBRIQUE|in_array{#VAL{12}|calcul_branche|explode{','}}|oui) je suis bien dans la descendance de la rubrique 12 ; dans la même branche donc.]

(On pourra, bien sûr, utiliser #SET et #GET pour remplacer le #VAL)

-  Afficher le dernier article publié de chaque auteur :

C’est impossible en une seule boucle ? Qu’à cela ne tienne : nous en ferons donc deux.

<BOUCLE_aut(AUTEURS)>
<p>
<BOUCLE_art(ARTICLES) {id_auteur} {!par date} {0,1}>
auteur n° #_aut:ID_AUTEUR : #_aut:NOM<br />
dernier article publié le #DATE (n° #ID_ARTICLE : "#TITRE")
</BOUCLE_art>
</p>
</BOUCLE_aut>

La première boucle récupère toutes les informations sur les auteurs qui ont au moins un article publié mais elle n’affiche rien.

La seconde, imbriquée, va récupérer toutes les informations du plus récent article publié par l’auteur sélectionné à chaque passage de la première boucle. Et c’est elle qui affichera les informations sur cet auteur en utilisant l’écriture #_NomDeBoucle:BALISE.

-  Faire un menu de mots à sélection multiple

  • proposer les mots des groupes 1, 2 et 3 seulement
  • afficher comme déjà sélectionnés les mots situés dans l’environnement (issu d’un précédent POST du formulaire ou bien présents dans l’url)
<BOUCLE_groupes (GROUPES_MOTS){par num titre}{id_groupe IN 1,2,3}>
	<select name="mots[#ID_GROUPE]" class="select" style="width: 135px;">
	<option value="">- indifférent -</option>
	<BOUCLE_mots(MOTS){id_groupe}{par num titre}>	
	        <option value='#ID_MOT'  [(#ENV{mots}|table_valeur{#ID_GROUPE}|=={#ID_MOT}|?{selected,})] >
                            [(#TITRE|supprimer_numero)]-#ID_MOT
		</option>
        </BOUCLE_mots>
        </select>
</BOUCLE_groupes>

Retour..


MODELES

Rappel
<emb> va faire appel aux modèles <video> ou <audio> ou <application> ou autres en fonction du type de document

Comment passer une variable à un modèle ?
Un modèle SPIP, inclus dans le texte d’un article, ne permet pas de récupérer la variable #ENV (qui passe par une transmission d’un include à l’autre). Si l’on veut par exemple récupérer le contenu de « toto » que l’on a dans l’url (?toto=truc) on ne peut le faire avec #ENV{toto} comme on pourrait le faire si on était dans un squelette et pas dans un modèle.

L’astuce est ici d’utiliser #SELF (qui lui, passe vers le modèle) et d’en extraire la chaine qui nous intéresse, ici « truc », qui se trouve juste après « toto= », grâce au filtre « match » :

[(#SELF|match{'toto='(\w+)$, 1})]

Raccourci
-  Sera <charte|typo> si le fichier se nomme modeles/charte_typo.html

-  Avec #MODELE, définir plusieurs paramètres dans un array (voir le plugin nuage) :

[(#MODELE{nuage} {notid=5|6|7})]

définira les groupes à exclure dans la boucle du modèle

{id_groupe !== ^((#ENV{notid, -1}))$}

Pour mémoire, les modèles ne reçoivent pas d’environnement, que vous pourrez utiliser par :
[<pre>(#ENV**|unserialize|print_r{1})</pre>]
ou [(#ENV**|unserialize|foreach)]

-  Un modele pour insérer un FORMULAIRE_ECRIRE_AUTEUR dans un article
On ne peut appeler directement le formulaire dans le texte d’un article car il manque le contexte pour ce formulaire. Il faut créer un modèle qui appelle ce formulaire :

<BOUCLE_auteur(AUTEURS){id_auteur}>
  #FORMULAIRE_ECRIRE_AUTEUR
</BOUCLE_auteur>
  <BOUCLE_auteur_id(AUTEURS){id_auteur=#ENV{id}}>
  #FORMULAIRE_ECRIRE_AUTEUR
  </BOUCLE_auteur_id>
<//B_auteur>

Avec ce code il est aussi bien possible d’écrire <ecrire_auteur79> que <ecrire_auteur|id_auteur=79>.

Retour..


DATA

-  Afficher les années entre deux dates

<BOUCLE_annee_data(DATA){enum 2001,2010}{' '}>
            [<a href="[(#SELF|parametre_url{annee,#VALEUR})]">(#VALEUR)</a>]
</BOUCLE_annee_data>    

LANG

<blockquote class="spip">

Voir sur le carnet spip la FAQ Multilangue

</blockquote>


-  Modifier une chaine, voire en ajouter garder le même nom de fichier et la même structure

// monplugin/lang/spip.fr 
'form_forum_voici1'=>'Voici vos identifiants pour vous amuser sur "@nom_site_spip@" @adresse_site@spip.php?page=amuse_toi',

-  Variable dans une chaîne de langue en squelettes :

<:ma_chaine{nom=Charles Martin, age=37}:>

permet de passer deux paramètres 'ma_chaine'=>"Bonjour, je suis @nom@ et j'ai @age@ ans".

-  Variable dans une chaîne de langue en php (utilisé par le plugin medias) :

"._T("medias:erreurs_voir", array('nb'=>count($erreurs)))"

-  Des chaînes de langue dynamiques :

Dans le fichier de langue :

'chaine_a' => 'traduction un',
'chaine_b' => 'traduction deux',
'chaine_c' => 'traduction trois',

[(#TOTAL_BOUCLE|singulier_ou_pluriel{local:nombre_truc_un, local:nombre_truc_plus})]

-  Variable et chaine au pluriel en php, avec dans le fichier de lang

'texte_un' => 'Il y a @nb@ truc',
'texte_plus' => 'Il y a @nb@ trucs',


$texte=singulier_ou_pluriel($nbtruc,_T('pluginx:texte_un', array('nb'=>$nb_truc)),_T('pluginx:texte_plus', array('nb'=>$nb_truc)));

dans le squelette, <:prefixe:chaine_#VARIABLE:> ne fonctionnera pas. Il faut utiliser :[(#VAL{prefixe:chaine_#VARIABLE}|_T)] qui affichera la bonne traduction en fonction de la valeur de #VARIABLE.

du coup il est également possible de faire
[(#TOTAL_BOUCLE|singulier_ou_pluriel{#VAL{local:texte_un#BALISE}, #VAL{local:texte_plus#BALISE}})]

-  Ne pas avoir de retour en cas de chaîne de langue inexistante :

Dans le cas où on fait appel à une chaîne de langue dynamique qui n’existe pas, on peut souhaiter ne rien afficher. Or par défaut, la fonction _T force un retour même si la chaîne de langue n’existe pas.
Dans ce cas il faut passer l’option force à false :
[(#VAL{prefixe:chaine_#VARIABLE}|_T{'',#ARRAY{'force',''}})]

-  Avoir des urls commencant par la langue : http://tld/en/, http://tld/de/, ...

  1. adopter la configuration : 1 langue par secteur
  2. adopter le type url : urls arbos

on obtient alors des urls du type http://tld/1/
pour corriger et placer son prefixe de langue

  1. aller via phpmyadmin
  2. editer la table spip_urls, inserter un enregistrement dans le futur lointain pour forcer votre prefixe (’url’,’type’,’id_objet’,’date’)->(’en’,’rubrique’,’1’,’3000-06-11 05:02:03’)

CONFIG

-  Accéder aux données contenues dans les metas du site (nécessite le plugin CFG : voir doc) :

#CONFIG{meta::descriptif_site}

Retour..


ARRAY

-  Déclarer un ARRAY puis le remplir dans une boucle incrémentée par le compteur :

#SET{articles, #ARRAY}
<BOUCLE_articles_rub(ARTICLES) {id_rubrique}>
#SET{articles, #GET{articles}|array_merge{#ARRAY{#COMPTEUR_BOUCLE, #ID_ARTICLE}}}
</BOUCLE_articles_rub>

Encore plus court :

#SET{arraymot, #ARRAY}
 <BOUCLE_mot(MOTS) {id_groupe}>
#SET{arraymot, #GET{arraymot}|push{#ID_MOT}}
 </BOUCLE_mot>

MYSQL

-  Faire le ménage en base de données :

Aller directement dans la base pour modifier ou supprimer ; par exemple lorsque vous avez 2000 sites qui encombrent, un gros coup de balai peut être nécessaire ! La méthode rapide est donc de lancer une commande directement depuis MYSQL (par exemple via l’interface phpmyadmin)

  • sélectionner les sites en proposition :
    SELECT * FROM <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+c3BpcF9zeW5kaWM8L2NvZGU+"></span> WHERE <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+c3RhdHV0PC9jb2RlPg=="></span> =  'prop'
  • Supprimer les sites en proposition :
    DELETE FROM <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+c3BpcF9zeW5kaWM8L2NvZGU+"></span> WHERE <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+c3RhdHV0PC9jb2RlPg=="></span> =  'prop'

-  Supprimer les syndications trop anciennes

Vous avez beaucoup de sites syndiqués et ils ne possèdent pas tous l’option effacer au bout de 2 mois
Voici la requête pour effacer toutes les vieux articles syndiqués (modifier la date selon vos besoins) :

DELETE FROM <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+c3BpcF9zeW5kaWNfYXJ0aWNsZXM8L2NvZGU+"></span> WHERE date <  '2007-12-31 10:00:00'

-  Déplacer tous les articles de la rubrique 39 à la rubrique 12 :

UPDATE spip_articles SET id_rubrique = 12 WHERE id_rubrique = 39;


attention : si les deux rubriques ne sont pas dans le même secteur, il faut aussi mettre à jour id_secteur

-  Transférer les données crées avec EXTRA2 (mettre en réserve vos spip_metas, iextras et les champs créés) :
En ligne :

  • créer les champs supplémentaires dans phpmyadmin, du style
    ALTER TABLE <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+c3BpcF9hdXRldXJzPC9jb2RlPg=="></span> ADD  <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+bm9tX2NoYW1wX25vdXZlYXU8L2NvZGU+"></span> text NOT NULL;
  • Le plus important : supprimer tmp/meta_cache.php
  • MODIFIER spip_metas, iextras dans la base en collant le contenu précédemment sauvegardé
  • vider le cache, voila

-  Copier descriptif vers adresse (table événements)
UPDATE spip_evenements SET adresse=descriptif, descriptif='' WHERE adresse=''

-  Déplacer les articles dans les rubriques ayant le même titre que l’article et uniquement dans ce cas là :
UPDATE spip_articles SET id_rubrique = (SELECT spip_rubriques.id_rubrique FROM spip_rubriques WHERE spip_rubriques.titre=spip_articles.titre) WHERE spip_articles.id_rubrique = XX AND titre = (SELECT spip_rubriques.titre FROM spip_rubriques WHERE spip_rubriques.titre = spip_articles.titre)

XX est le numéro de la rubrique contenant les articles à déplacer.

-  Afficher les auteurs en doublons

SELECT a.id_auteur, a.nom
FROM spip_auteurs a
INNER JOIN spip_auteurs b ON a.nom = b.nom
WHERE a.id_auteur <> b.id_auteur
ORDER BY  <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+YTwvY29kZT4="></span>.<span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+bm9tPC9jb2RlPg=="></span> ASC 
LIMIT  , 30

Retour..


URLS et LIENS

-  Fabriquer une url publique avec #OBJET et #ID_OBJET
[(#ID_OBJET|generer_url_entite{#OBJET})]

-  Passer un tableau de variables en url :

[(#SELF|parametre_url{'id_mot[]', #ID_MOT})]

ne fonctionne pas ; il faut écrire : [(#SELF)]&id_mot[]=#ID_MOT
et pour vider l’url on écrira : [(#SELF|parametre_url{id_mot, ''})]

-  Créer un lien vers la page site avec la variable id_syndic=xx
à mettre dans une boucle de syndication
corrige également l’erreur produite par generer_url_site (maj SPIP) :

[(#URL_PAGE{site}|parametre_url{id_syndic,#ID_SYNDIC})]

-  Créer un lien vers l’article 54 en se passant de boucle :

<a href="#URL_ARTICLE{54}">lien</a>

-  Créer un lien vers une page de l’espace prive de style /ecrire/?exec=unepageprive :
#URL_ECRIRE{unepageprive}

-  URL propres arborescentes

cf http://comments.gmane.org/gmane.com...

$type_urls = 'arbo';
define('_SET_HTML_BASE', 1); // ajoute aux pages html une directive  
<base..> et traite les ancres des pages produites

En cas de problèmes, penser à placer à la main la balise
<base href="..." />

-  Y’a-t-il moyen d’avoir des URL plus longues ?

Oui, en mettant dans mes_options.php :

@define('_URLS_PROPRES_MAX', 100); 

Ou plus que 100, si on veut avoir des urls de plus de 100 caractères.

-  Afficher les requêtes SQL (SPIP 2) :

http://adresse_spip/?var_profile

permet d’afficher les requêtes SQL que fait SPIP pour créer la page ainsi que les temps de calcul pour chaque boucle et inclusion.

-  Afficher les noisettes d’un squelette (SPIP 2) :
http://adresse_spip/?var_mode=inclure

<blockquote class="spip">

voir Les aides au débuggage de squelettes

</blockquote>

-  Obtenir une URL raccourci à la bit.ly, yourls, ....
C’est natif dans SPIP, il suffit de prendre le numéro de l’article
Par ex. http://www.spip-contrib.net/Soyez-s... est raccourci par http://www.spip-contrib.net/3125

-  Créer un objet éditorial sans URL de page publique
Dans le fichier de création de plugin monobjet_base.php
'page' => false,


DATE

Afficher une date complète avec un mois abrégé (septembre -> sept.)

[(#DATE_DEBUT|jour) ][(#DATE_DEBUT|affdate_base{'nom_mois', #ARRAY{'param','abbr'}})][ (#DATE_DEBUT|annee)]

…affichera 2 sept. 2016


SITES D’ASTUCES

-  http://www.weblog.eliaz.fr/rubrique...

Retour..


RACCOURCIS TYPOS

Pour faire un lien dans un texte, on utilise le raccourci [->artXX] ou [->rubXX] ou [->motXX], etc.
Mais comment fait-on si on veut pointer vers une page en lui transmettant des paramètres ? Un nom d’onglet par exemple : l’onglet des sites sur une page de mots-clés...
C’est simple il suffit d’écrire [->motXX?parametre=valeur] (dans notre ex. ce pourrait être [->mot33?onglet=sites]) Spip transforme alors le raccourci en URL cliquable du type spip.php?motxx&parametre=valeur
Remarquez comment Spip jongle automatiquement avec les & et les ?.


INCLURE dans un squelette

On utilisera la constante des squelettes pour indiquer à SPIP de rechercher automatiquement un fond dans les dossiers de son choix.
Pour utiliser une constante dans un squelette #EVAL{_MA_CONSTANTE}

-  Définir une variable calculée par une noisette
sans variable on utilise <INCLURE{fond=monsquelette}> ou [(#INCLURE{fond=monsquelette})]
pour définir la variable calculée :#SET{mavariable, #INCLURE{fond=monsquelette}{monparam=#ENV{monparam}}}

INCLURE dans le php d’un formulaire

$date_recolte = recuperer_fond('formulaires/inc-date_recolte', $flux['args']['contexte']);
$code = recuperer_fond("inclure/inc-liste-articles", array( 'id_rubrique' => $id_rubrique));

Voir http://programmer.spip.org/recupere...


BOUCLES

Ecrire un appel silencieux sur une table même si elle n’existe pas, SPIP2 & SPIP3 (CONTACTS?)

Optimisation

Une boucle avec jointure est parfois fois bien plus efficace que 2 boucles imbriquées et d’autant plus qu’il y a un grand nombre de combinaisons .

Plutôt que

<BOUCLE_GpAdmin(GROUPES_MOTS){titre==^_}>
	<BOUCLE_MotsExclus(MOTS){id_groupe}{doublons 1}> </BOUCLE_MotsExclus>
</BOUCLE_GpAdmin>

il sera bien plus efficace d’utiliser (la jointure est implicite) :

<BOUCLE_MotsExclus1(MOTS){type==^_}{doublons 1}> </BOUCLE_MotsExclus1>

Mais trop de jointures tue parfois la jointure :

<BOUCLE_Citations(RUBRIQUES){titre_mot=Citations}{0,1}> 
<BOUCLE_Citation(ARTICLES) {id_rubrique} {par hasard}{0,1} {lang}> 

est plus efficace que :
<BOUCLE_Citation(ARTICLES rubriques mots_rubriques) {mots.titre=Citations} {par hasard}{0,1} {lang}>

Boucler directement à partir d’une requête sql (SPIP 3 ou plugin iterateur pour SPIP 2)

il peut s’avérer utile, parfois, de pouvoir boucler à partir d’une requête sql. Surtout lorsque les boucles standard de spip atteignent leur limites.
la requete ci-dessous n’est donnée qu’a titre d’exemple, car bien sur, dans ce cas, il serait bien plus judicieux d’utiliser la boucle AUTEURS

<BOUCLE_ma_requete(DATA){source sql, SELECT * FROM spip_auteurs}></BOUCLE_ma_requete>

Contrôler l’affichage du niveau hiérarchique d’une rubrique

Exemple : Collège -> Discipline -> Arts plastiques -> 6es -> Un article.
Il est plus parlant d’afficher que l’article est présent dans la rubrique « Arts plastiques » plutôt que dans la sous rubrique « 6e ».

La boucle HIERARCHIE permet de spécifier l’interval :

<BOUCLE_hi(HIERARCHIE) {id_article} {2,1}>On est dans la rubrique #TITRE</BOUCLE_hi>

Placée dans la boucle (ARTICLES), cette boucle (HIERARCHIE) avec l’interval 2,1 retournera 1 niveau de résultat a partir du niveau 2. Dans notre exemple : Arts plastiques.

----

Retour..

Retour à la version courante

Toutes les versions