Carnet Wiki

Gestion des dossiers /plugins

Version 3 — Avril 2010 cy_altern

Dans le cas d’une mutualisation pour différents domaines, la bidouille suivante permet de disposer à la fois d’un répertoire de plugin « centralisé » (comme c’est le cas général dans la mutualisation) mais également d’un répertoire /plugins pour certaines des instance de mutualisation (i.e. les sites mutualisés pour lesquels on estime pouvoir faire confiance au webmestre...).

Testé pour le plugin Mutualisation installé pour avoir des sites avec domaines différents avec la configuration suivante :

  • le SPIP « maître » est installé dans /var/www/toto
  • dossier /mutualisation à la racine du SPIP « maître » /var/www/toto/mutualisation
  • les sites mutualisés ont chacun leur nom de domaine et un vhost apache qui pointe sur /var/www/toto
  • chaque site correspond à un sous-dossier de /sites portant le nom de domaine du site : /var/www/toto/sites/mon-site.tld [1]
  • un dossier /plugins (= « central » pour la suite) également à la racine de ce SPIP : celui-ci est utilisé par tous les sites mutualisés (i.e. les plugins dedans sont visibles dans tous les sites) /var/www/toto/plugins
  • la config du apache et des vhost authorise le suivi des liens symboliques (Options FollowSymLinks)
    _
    _

En SPIP 2 . NB : cet article est désormais obsolète puisque la version SPIP SVN intègre la possibilité de déclarer un dossier de plugins personnalisé pour chaque site et que cette possibilité est portée en version 2..x par le plugin Multiplug. * : il faut ajouter le plugin Multiplug


Ce plugin ( disponible uniquement via SVN  : [->http://zone xml de Multiplug->http://zone .spip.org/trac/spip-zone/browser/_plugins_/multiplug] org/trac/spip-zone/browser/_plugins_/multiplug/plugin . ), permet de déclarer dans le Pour plus d’infos voir  : [le fichier mes_options plugin .php du SPIP central un ensemble de sites autorisés à utiliser leur propre dossier /plugins en plus du dossier /plugins « central » du SPIP central.xml]

La syntaxe est la suivante :

// les sites autorisés à avoir un dossier /plugins supplémentaire (nom du dossier du site)
   $GLOBALS['multiplug_autorise'] = array(
        'mon-site1.tld',
        'ze-site2.tld'
   );

En SPIP 2.1 : utilisation de la constante _DIR_PLUGINS_SUPPL

A partir de cette version, chaque SPIP peut déclarer un ensemble de dossiers supplémentaires dans lesquels peuvent êtres placés des plugins.

Pour cela il faut définir _DIR_PLUGINS_SUPPL dans le mes_options.php du site : par exemple pour utiliser le dossier /plugins dans le site mon-site.tld cela donnerait :

define('_DIR_PLUGINS_SUPPL','../sites/mon-site.tld/plugins/');

(NB : ne pas oublier le ../ en début des chemins...)

Il est possible d’utiliser plusieurs dossiers avec «  : » comme séparateur : Par exemple si on veut utiliser le dossier /plugins du site mon-site.tld et le dossier /le_depot situé à la racine de la mutu cela donnerait :

define('_DIR_PLUGINS_SUPPL','../sites/mon-site.tld/plugins/:../le_depot/');

NB  : la suite est obsolète mais conservée à titre d’historique


Pour chaque instance de site mutualisé pour laquelle on veut laisser au webmestre la possibilité d’installer des plugins supplémentaires, on crée un sous-dossier /plugins (= « spécifique » pour la suite) dans le sous-dossier de site correspondant : /var/www/toto/sites/mon-site.tld/plugins. On va alors créer un lien symbolique dans le dossier plugins central qui pointe vers ce sous-dossier, ce lien sera nommé avec le nom de domaine du site :
/var/www/toto/plugins/mon-site.tld(=symlink)—>/var/www/toto/sites/mon-site.tld/plugins
Tel quel on se retrouve donc avec tous les plugins de tous les répertoire « spécifiques » mélangés avec ceux du répertoire « central » donc visibles et disponibles pour tous les sites mutualisés, ce qui n’est pas exactement le but recherché...

Il reste donc à « filtrer » les liens symboliques qui seront suivis en fonction du site : le lien portant le nom de domaine du site, on à donc un moyen simple de « faire le tri ». Ce tri sera fait au niveau de la fonction de SPIP qui scanne le répertoire des plugins : liste_plugin_files() dans le fichier /inc/plugin.php

La seule difficulté pour réaliser cette opération est que cette fonction du core n’est pas surchargeable puisqu’elle n’est pas de la forme nom_de_la_fonction_dist()... Du coup on doit procéder via la surcharge de l’ensemble du fichier /inc/plugin.php ce qui revient à « forker » celui-ci (c’est très mal !).

Pour minimiser la chose et essayer de gérer au mieux les éventuels changements du fichier lors des prochaines versions de SPIP, on peut procéder en faisant une bidouille à base de copie « à la volée » du fichier /inc/plugin.php de la dist et ne modifiant que le strict nécéssaire dans la fonction liste_plugin_files(). Ce qui peut être obtenu de la façon suivante :

  • déclarer /mutualisation dans les répertoires scannés par find_in_path() en l’ajoutant dans les dossiers de squelettes du fichier mes_options.php (après demarrer_site()) :
    $GLOBALS['dossier_squelettes'] .= ':mutualisation';
  • créer un sous-dossier /inc dans /mutualisation
  • créer un fichier plugin.php dans ce dossier et mettre dedans le code suivant :
    <?php
    // mutualisation: pour pouvoir utiliser à la fois le rep /plugins central
    // et le rep /plugins du site via un lien symbolique dans /plugins central, 
    // on filtre la liste des ss-reps de plugins retournée par liste_plugin_files() de /inc/plugin.php
    // ce qui nécessite une mauvaise bidouille pour hacker la fonction  
    // et pour ne pas trop galérer avec les mises à jour du core de SPIP 
    // on recrée le fichier à partir de celui de la dist en ne modifiant que le strict minimum
        $inc_plugin_mutu = _DIR_TMP.'inc_plugin_mutu_'.$GLOBALS['spip_version_code'].'.php';
        if (is_file($inc_plugin_mutu)) include($inc_plugin_mutu);
        else {
          // faire le remplacement dans le code de la fonction pour avoir le filtrage
            $a_remplacer = '$plugin_files[]=substr(dirname($plugin), strlen(_DIR_PLUGINS));';
            $code_sup_mutu = '// filtrage des liens symboliques vers les autres sites de mutu'."\r\n";
            $code_sup_mutu .= '$rep_plugin = explode("/",substr(dirname($plugin), strlen(_DIR_PLUGINS)));'."\r\n";
            $code_sup_mutu .= '$rep_plugin = $rep_plugin[0];'."\r\n";
            $code_sup_mutu .= '$site = str_replace("www.", "", $_SERVER["HTTP_HOST"]);'."\r\n";
            $code_sup_mutu .= 'if (is_link(_DIR_PLUGINS.$rep_plugin) AND $rep_plugin != $site) continue;'."\r\n";
            $code_sup_mutu .= $a_remplacer."\r\n";
            $contenu = file_get_contents(_DIR_RESTREINT.'inc/plugin.php');
            $contenu = str_replace($a_remplacer, $code_sup_mutu, $contenu);
            
          // finalement enregistrer le contenu dans /tmp/inc_plugin_mutu_XXX.php puis l'inclure
            if (function_exists('file_put_contents')) {
                if (!file_put_contents($inc_plugin_mutu, $contenu)) include _DIR_RESTREINT.'inc/plugin.php';
                else include $inc_plugin_mutu;
            }
            else {  // php4
                $fic = fopen($inc_plugin_mutu, 'wb');
                if (!fwrite($fic, $contenu)) include _DIR_RESTREINT.'inc/plugin.php';
                else { 
                    fclose($fic);
                    include $inc_plugin_mutu;
                }
            }
        }
    ?>

    Comme on peut le voir en lisant le code, le principe est de créer un fichier inc_plugin_mutu_XXX.php dans le répertoire /tmp du site mutualisé dans lequel on recopie le fichier /inc/plugin.php de la dist en ajoutant le système de filtrage par remplacement d’une ligne de la fonction liste_plugin_files(). Ce fichier est intégré par un include() dans le fichier en cours (i.e. le fichier qui forke l’original). Une fois ce fichier créé il sera réutilisé tel quel les fois suivantes : chaque site mutualisé dispose donc de son fichier « personnalisé » mis en « cache ».

Le XXX correspond à la version du code de SPIP de façon à ce qu’à chaque modification de la version de SPIP le fichier soit régénéré pour être à jour d’une éventuelle modification du fichier original.