SPIP - Contrib

SPIP - Contrib

[ar] [en] [es] [fr] [it]

86 visiteurs en ce moment

fontsizeup fontsizedown
[119 commentaires]

Lancer un script PHP dans un article

vendredi 23 avril 2004, par GoUaRfIg !

1 vote

Pouvoir lancer un script personnel dans un article spécifique et créer ainsi des articles à contenu « dynamique ».

Introduction :

La philosophie de SPIP est de pouvoir publier des articles. Donc on ne peut pas faire un <?php include( "script.php"); ?> dans un article, ca n’est pas fait pour ca.

Pourtant dans certains cas précis, vous pouvez avoir besoin d’afficher dans un article des informations que vous avez calculé et surtout qui peuvent évoluer.

Exemple

Je dois gérer sur mon site une liste des membres d’un club.

Cette liste est modifiée régulièrement, et je l’ai donc mise dans une table de ma base de données.

J’aurai pu créer une page spécifique pour afficher cette liste, et pourtant j’aurai aimé qu’elle s’intègre parfaitement dans l’environnement SPIP, déjà niveau design, mais aussi qu’on puisse faire une recherche SPIP sur la partie fixe de l’article (autour de la liste), qu’elle apparaisse dans les rubriques, etc.

J’aurai également pu utiliser la fonction de redirection d’article, mais elle ne me plait pas non plus parce que j’ai envie d’utiliser une fonctionnalité importante de SPIP qui est le cache des pages !

Je vais donc vous montrer comment j’ai fait !

Avantages :

Par rapport au développement d’un partie spéciale d’un site, cette solution permet :
- de garder une arborescence homogène avec les rubriques de SPIP, et compatible avec le moteur de recherche.
- de pouvoir habiller un script dans un article et donc de le modifier facilement.
- de bénéficier du moteur de cache de SPIP.

Sécurité :

Pour une question de sécurité, chaque script proposé dans les articles DOIT être inscrit dans une liste de scripts autorisés, pour ne pas que chaque rédacteur puisse faire n’importe quoi avec n’importe quel script !

Concrètement :

Ce que nous allons pouvoir faire c’est inclure à n’importe quel endroit de l’article la commande suivante :

#INCLURE (mon_script.php3)

Ceci plusieurs fois, et avec plusieurs scripts différents.

Le filtre qui va bien

J’ai créé un filtre appelé "autoriser_php" à appliquer sur le champs voulu (en particulier #TEXTE)

Voici ce filtre, à ajouter au fichier « mes_fonctions.php3 »

  1. /*****************************************************************************/
  2. /**  Cette fonction permet de lancer un script PHP dans un article
  3. /**
  4. /**  La syntaxe est la suivante :
  5. /**    #INCLURE ( nom_fichier )
  6. /**
  7. /**  Auteur  : F. Quointeau
  8. /**  Version : 0.0.2
  9. /**  Date    : 16 Mai 2004
  10. /*****************************************************************************/
  11. function autoriser_php( $texte) {
  12.     // Dossier où sont stockés les scripts
  13.     $dossier_inclus = './';
  14.    
  15.     // Liste des scripts autorisés
  16.     $scripts_autorises = Array(
  17.         'mon_premier_script.php3',
  18.         'mon_second_script.php3'
  19.     );
  20.    
  21.     // Les fichiers inclus autorises sont : *.php, *.php3, *.php4, *.phtml, *.htm, *.html, *.inc
  22.     $chaine_recherche = '/#INCLU[R|D]E( *)\(( *)([^\)]*\.(php|php3|php4|phtml|htm|html|inc))( *)\)/i';
  23.    
  24.     // Recherche la chaine #INCLUDE(script)
  25.     while( preg_match( $chaine_recherche, $texte, $resultats)) {
  26.         // Verifie le droit d'inclure ce fichier script !
  27.         $autorise = false;
  28.         reset( $scripts_autorises);
  29.         while( $script = each( $scripts_autorises)) {
  30.             if( strcasecmp( $script[value], $resultats[3]) == 0) $autorise = true;
  31.         }
  32.         if( $autorise == true) {
  33.             // Verifie que le fichier existe
  34.             if( file_exists ( $dossier_inclus . $resultats[3])) {
  35.                 // Vide le buffer de sortie
  36.                 $affichage_php = '';
  37.                 // Et lance le fichier inclu !!!
  38.                 include( $dossier_inclus . $resultats[3]);
  39.             } else {
  40.                 $affichage_php = "<b>#INCLURE: Le fichier de script n'existe pas !</b>";
  41.             }
  42.         } else {
  43.             $affichage_php = "<b>#INCLURE: Script NON autoris&eacute; !</b>";
  44.         }
  45.         // Attention, n'effectue qu'un seul remplacement à la fois !
  46.         $texte = preg_replace( $chaine_recherche, $affichage_php, $texte, 1);
  47.     }
  48.    
  49.     return( $texte);
  50. }

Attention : Au début de la fonction, il y a un tableau php qui décrit la liste des scripts qui ont le droit d’être lancé à partir d’un article. Pensez à le mettre à jour avec vos scripts.

Dossier des scripts

Si vous souhaitez mettre vos scripts dans un dossier spécial, mettez également le chemin des scripts dans la variable $dossier_inclus au début de la fonction filtre. Par exemple :

   $dossier_inclus = 'mes_scripts/';

Notez le ’/’ obligatoire à la fin du dossier.

Mais vous pouvez aussi « cacher » vos scripts (non disponibles par une requête HTTP dessus) en les placant en amont du dossier racine du site web :

   $dossier_inclus = '../mes_scripts_caches/';

Attention, en fonction de votre hébergeur, vous n’aurez pas forcément la possibilité de le faire !

Le script des familles :

Voici le script que vous voulez promouvoir :

  1. <?php
  2.     echo( "Hello World !");
  3. ?>

Puissant, mais vous allez devoir l’écrire sous cette forme :

  1. <?php
  2.     $affichage_php = "Hello World !";
  3. ?>

Vous suivez ?

Vous ne pouvez pas vous permettre d’afficher sauvagement vos informations directement par un echo( ), celles-ci ne seraient pas prises en compte dans le cache de SPIP, et souvenez-vous que votre script travaille à l’intérieur d’un filtre, et qu’il y a peut être d’autres filtres qui attendent derrière :-)

Et maintenant, comment relier le tout ?

Créez un article comme celui-ci par exemple :

Bonjour,
voici le résultat de ma fonction :
#INCLURE (mon_premier_script.php3)

Hop

Créez ensuite un fichier mon_premier_script.php3 qui contient le script énoncé plus haut ; mettez le dans le dossier de SPIP si vous n’avez pas spécifié de dossier dans la variable $dossier_inclus (par défaut elle contient le dossier courant).

Dans votre squelette, vous devez avoir quelque chose du genre :

<BOUCLE_1 (ARTICLES) {id_article}>
 [(#TEXTE|autoriser_php)]
</BOUCLE_1>

J’ai appliqué le filtre "autoriser_php" à l’affichage de #TEXTE.

Et votre article affiche désormais :

Bonjour,
voici le résultat de ma fonction :
Hello World !

Hop

Pour aller un peu plus loin...

Imaginons que vous ayez besoin de récupérer une variable de l’url dans votre script. Les variables globales de SPIP sont accessibles depuis votre script, puisqu’il fonctionne à l’intérieur d’un filtre SPIP.

Regardez le script suivant

  1. <?php
  2.   // Ma variable
  3.   $id_machin = $GLOBALS['id_machin'];
  4.   $affichage_php = "Hello machin n°$id_machin";
  5. ?>

Je récupère la variable globale $id_machin et je l’affiche dans mon script. Cette variable globale est tout simplement une des variables passées en paramètres.

Si j’essaye l’url :
article.php3?id_article=x{{&id_machin=11}}

J’aurai alors l’affichage :

Bonjour,
voici le résultat de ma fonction :
Hello machin n°11

Hop

C’est d’autant plus pratique que SPIP va générer un cache pour TOUTES les url différentes.

Fort heureusement, sinon l’affichage de
article.php3 ?id_article=x&id_machin=1
serait le même que l’affichage de
article.php3 ?id_article=x&id_machin=2

puisque la page article.php3 ?id_article=x est à priori déjà dans le cache.

Attention toutefois à ne pas remplir votre cache de millions de fichiers si votre script peut comporter des millions de combinaisons de paramètres dans l’url !

Récupérer des variables globales de SPIP

En plus de pouvoir récupérer des variables de l’url, vous pouvez récupérer des variables de l’environnement SPIP, comme celle-ci :

$GLOBALS['spip_lang']

qui vous permet de récupérer la langue courante (si vous utilisez SPIP multilingue). Ca peut en effet être très pratique si vous avez besoin de générer un affichage « localisé » avec votre script. [1]

Mise en garde avec MySQL

SPIP utilise par défaut la connexion courante à la base de données MySQL. Autrement dit, si dans votre script, vous ouvrez une base MySQL autre que celle utilisée par SPIP, celui-ci n’aura plus accès à sa base une fois le filtre exécuté.

Pour remédier à ca, il y a deux solutions :

- Utiliser la base de SPIP. Pour avoir la base toujours ouverte au début de votre script, utilisez
include_ecrire( "inc_connect.php3") ;
En effet ce sript ouvre la base seulement si elle n’est pas déjà ouverte, et l’avantage c’est que vous n’avez pas besoin de gérer vous même les paramètres d’ouverture.

- Demander à SPIP de faire des accès complets à la base (avec sélection de la base à chaque requête). Pour ca, renseignez la variable
$mysql_rappel_connexion = true ;
dans mes_options.php3 [2].

Exemple d’utilisation :

  1. <?php
  2. include_ecrire( "inc_connect.php3");
  3.    
  4. $ma_requete = mysql_query( "SELECT id, nom, prenom, DATE_FORMAT(naissance, '%d/%m/%Y') as naissance, FROM utilisateur ORDER BY nom,prenom");
  5. if( $ma_requete) {
  6.     if( mysql_num_rows($ma_requete) > 0) {
  7.         $affichage_php .= "<table cellpadding=\"2\" align=\"center\" border=\"0\" class=\"spip\">\n";
  8.         $affichage_php .= "<tr align=\"center\" class=\"row_first\"> <td><b>Nom</b></td> <td><b>Date de naissance</b></td> </tr>\n";
  9.         while ($mon_resultat = mysql_fetch_array($ma_requete)) {
  10.             $affichage_php .= "<tr class=\"row_" . ($ncr_numero_ligne++ % 2 ? 'odd' : 'even') . "\">";
  11.             $affichage_php .= "<td>" . $mon_resultat["nom"] . " " . $mon_resultat["prenom"] . "</a></td> <td align=\"right\">" . $mon_resultat["naissance"] . "</td>";
  12.             $affichage_php .= "</tr>\n";
  13.         }
  14.         $affichage_php .= "</table>\n";
  15.     }
  16. }
  17. ?>

Conclusion

Attention, ceci ne fonctionne que dans la partie publique évidemment !

J’utilise actuellement ce script sur mon site, et ca fonctionne plutôt bien ! Et ce qui est génial, c’est que le cache est géré correctement par SPIP.

Notez : la page est regénérée quand elle a expirée, et pas quand le résultat de votre script a changé !

Notes

[1] Merci à Paolo pour l’info

[2] Je l’indique pour information puisque je ne l’ai pas testé

Retour en haut de la page

119 Messages de forum

Voir toute la discussion

Pages 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |...

  • Répondre à ce message

    10 avril 17:36 , par Murphy

    Merci pour l’article, je viens de tester et ça fonctionne bien avec SPIP 2.

  • Répondre à ce message

    14 février 21:40 , par Guillaume Clarys

    Bonsoir,

    Pour utiliser #INCLURE (mon_script.php) dans un article spip 2, on peut placer le code du filtre dans ecrire/inc/filtre.php à la place de mes_fonctions.php. et ne pas oublier d’éditer #TEXTE|autoriser_php dans votre squelette d’article.

  • Répondre à ce message

    1er février 22:59 , par H2Fooko

    Bonsoir à tous,

    Le post de tracolin m’a un peu refroidi pour passer en V2, en attendant j’ai résumé les différentes méthodes récupérées ici ou là pour exécuter du PHP dans nos articles. J’y ai même contribué en mettant en oeuvre le passage des paramètres pour 2 d’entre-elles grâce à l’idée de Jim Wanderscheid.

    Par contre je pense que la méthode des modèles évoquée par Cédric Morin devrait fonctionner avec la V2 à défaut de celles utilisant les filtres.

    J’avoue que j’aimerais savoir ;-) Je ne suis qu’en 1.9.2d.

    En pièce jointe ou sur mon site le résultat de mes comparaisons.

    Enjoy

  • Répondre à ce message

    23 décembre 2008 23:11 , par tracolin

    Bonjour,

    Je viens d’installer Spip V2 et il me semble que la fonctionnalité d’appel de script php ne marche plus...

    Avez vous des informations ? , Le paramétrage reste il le même ?

    Merci de votre réponse.

  • Répondre à ce message

    21 août 2008 01:21

    Bonjour à tous,

    version de Spip + Sarkaspip : SPIP 1.9.2d [11132] | Sarka-SPIP 2.0.2 [18368]

    Modification du fichier article.html : [(#TEXTE|autoriser_php|typo_couleur|image_reduire{#CONFIG{taille_preview}})]

    Filtre placé dans le fichier sarkaspip_filtres.php et chemin des fichiers autorisés : $dossier_inclus = './inc/';

    /*************************************************************/
    /**  Cette fonction permet de lancer un script PHP dans un article
    /**
    /**  La syntaxe est la suivante :
    /**    #INCLURE ( nom_fichier )
    /**
    /**  Auteur  : F. Quointeau
    /**  Version : 0.0.2
    /**  Date    : 16 Mai 2004
    /*****************************************************************/

    /*****************************************************************
         Aménagements : Michel MAILLARD - 20 Août 2007

       * recherche automatisée des fichiers dans le dossier de stockage
        * ajout des fonctions ob_....()
              (pour assurer l'affichage à l'emplacement désiré et non en haut de page)
       * variable $f pour le fichier inclus
              (pour compatibilité avec certains serveurs)

          Ne pas  oublier de placer cette fonction dans les squelettes ad-hoc,
          en particulier article.html
           [......(#TEXTE|autoriser_php)........]

    /************************************************************/

       function autoriser_php( $texte) {

       // Dossier où sont stockés les scripts
       //(à partir du fichier spip.php et non à partir du répertoire squelettes)
       $dossier_inclus = './inc/';

       // Les fichiers inclus autorises sont :
       // *.php, *.php3, *.php4, *.phtml, *.htm, *.html, *.inc
       $fichiers_autorises="(php|php3|php4|phtml|htm|html|inc)";

       // Recherche des fichiers inclus autorisés dans le dossier de stockage
       $dir=opendir("$dossier_inclus");
       while ($fichier=readdir ($dir))
           {
                if(( preg_match( $fichiers_autorises, $fichier)))
                      {
                      $scripts_autorises[]= $fichier;
                      }
           }
       closedir($dir);



       // Recherche la chaine #INCLURE(script)
       $chaine_recherche = "/#INCLURE( *)\(( *)([^\)]*\.".$fichiers_autorises.")( *)\)/i";

       while( preg_match( $chaine_recherche, $texte, $resultats)) {
           // Verifie le droit d'inclure ce fichier script !
           $autorise = false;
           reset( $scripts_autorises);
           while( $script = each( $scripts_autorises)) {
               if( strcasecmp( $script[value], $resultats[3]) == 0) $autorise = true;
           }
           if( $autorise == true) {
               // Verifie que le fichier existe
               $f=$dossier_inclus . $resultats[3];
               if( file_exists ($f )) {
                   // Vide le buffer de sortie
                   $affichage_php = '';
                   // Et lance le fichier inclu !!!
                   ob_start();
                   include ($f);
               } else {
                   $affichage_php = "<b>#INCLURE: Le fichier de script $f n'existe pas !</b>";
               }
           } else {
               $affichage_php = "<b>#INCLURE: Script NON autoris&eacute; !</b>";
           }
           // Attention, n'effectue qu'un seul remplacement à la fois !
           $affichage_php = ob_get_contents();
           ob_end_clean();
           $texte = preg_replace( $chaine_recherche, $affichage_php, $texte, 1);
       }

       return( $texte);
    }
  • Répondre à ce message

    6 juin 2008 00:17 , par Michel

    Je ne suis qu’un utilisateur lambda.. et je n’ai pas la compétence....

    Mais SPIP est une grande communauté, nul doute que quelqu’un saura le faire

  • Répondre à ce message

    5 juin 2008 08:52 , par Louis

    Bonjour,

    Merci pour votre éclairage...
    Je suggère que soit étudiée, puis intégrée, pour une prochaine version de spip, la possibilité de pouvoir entrer directement la valeur d’une variable, dans un article.
    Cela aurait pour effet d’augmenter de manière très intéressante, le champ d’action des rédacteurs.
    Aujourd’hui pour eux, donner une valeur à une variable est impossible et c’est bien dommage. Seul, actuellement, l’administrateur peut insérer des données dans les fichiers, et les mettre en place par FTP.

    Vous avez certainement le pouvoir de communiquer cette proposition et suggestion, auprès des différents responsables du développement de SPIP..

  • Répondre à ce message

    5 juin 2008 01:24 , par Michel

    Bonjour

    Ce script reste parfaitement d’actualité avec la dernière version de SPIP (1.9.2d à ce jour)

    Il est ajouté au contenu du fichier "mes_options.php" (à créer avec ce contenu s’il n’existe pas)

    Ce fichier soit être placé de préférence dans le dossier "squelette" (à crér si nécessaire)

    Il permet d’exécuter un script en php contenu dans un dossier spécifié (voir les remarques dans le script) ce qui provoque directement un affichage lors de la génération de la page web.


    Voir ce lien : L’affichage des photos est déclenché par l’instruction

    #INCLURE(AG_Saint-Malo.php)

    qui fait appel à un module extérieur (simpleviewer) après une lecture dynamique du contenu du répertoire de photos (celles ci ont été mises en ligne par FTP indépendamment de SPIP)

    On pourrait plus simplement afficher sous forme de tableau le contenu d’un répertoire qui aurait été lu (et filtré) en utilisant les fonctionnalités de php


    Pour le reste, (récupération de la valeur d’une variable) je ne garantis rien... car je crains que les variables déclarées dans le script ne restent que locales.

    Il conviendrait donc de lire
    - la rubrique "pour aller plus loin" dans l’article initial
    - le contenu de cet article

  • Répondre à ce message

    4 juin 2008 22:15 , par Louis

    Bonsoir,

    Vous serait-il possible de préciser pour un non expert, les points suivants :
    1)Avec SPIP 1.9.2d ce script reste t-il d’actualité ?
    2)Quel nom de fichier donné à celui qui contient le script ?
    3)Où mettre ce fichier ?

    Je cherche simplement à entrer $a=9 dans un article. Puis à récupérer la valeur de $a dans un squelette.

    Merci pour vos précisions.

  • Répondre à ce message

    3 juin 2008 10:56 , par hermine

    Bravo Michel et merci, ton script fonctionne parfaitement

Pages 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |...

Répondre à cet article

Retour en haut de la page

Ça discute par ici