L’installeur Composer pour SPIP

, par James

Retour sur l’arborescence d’une application basée sur SPIP

Le nom des choses nous rappelle l’organisation en répertoire d’un site SPIP "standalone" (a.k.a. non-mutualisé) :

|-spip.php         racine d'une application basée sur SPIP
\-ecrire/          tout le code de SPIP...
\-prive/           squelettes de l'espace privé
\-squelettes-dist/ squelettes par défaut d'une distribution
\-plugins-dist/    plugins à activer et à vérouiller pour une distribution
\-plugins/         plugins supplémentaires de l'application

On trouve bien sûr d’autres fichiers à la racine, et d’autres répertoires tels que config/, IMG/, tmp/, local/ et optionnellement squelettes/. Chacun ayant son rôle dans le fonctionnement de l’application.

Le fait d’avoir un répertoire racine destiné à être l’espace web d’une application « standalone » pose quelques problèmes de securité, reglés applicativement à ce jour pour certains, auxquels s’ajoute le risque d’exposition non souhaitée de fichiers critiques. Le fonctionnement de base de composer ajoute de nouveaux fichiers (a.k.a. ./vendor/**/* et ./composer.*) qu’il est recommandé d’exclure de l’espace web [1]. Ces problèmes sont mieux gérés en mode mutualisé. Il serait d’ailleurs interessant qu’une version future des projets basés sur SPIP se repose sur un mode « mutu » avec un site par defaut plutôt que de maintenir un mécanisme qui fait l’inverse.

Le comportement par défaut de Composer est le suivant :

  • Exécuté à la racine du projet, il s’appuie sur les fichiers ./composer.lock, ou ./composer.json afin de générer un nouveau fichier lock, pour télécharger les dépendances du projet dans le répertoire ./vendor.
  • Chaque « library » sera installée ou mise à jour dans un sous-répertoire <vendor>/<name>.
  • Ce sous-répertoire ./vendor/<vendor>/<name> est créé s’il n’existe pas et effacé à chaque installation/mise à jour,
  • le code de chaque « library », déterminé par la résolution de version est téléchargé depuis le cache local de composer, lui-même mis à jour le cas échéant, à partir d’une archive zip ou du code source (git, svn, hg)

Besoins d’un SPIP standalone

SPIP, pour des raisons historiques, a besoin d’un répertoire ./ecrire qui contient toute la mécanique du CMS et d’un répertoire ./prive qui contient les gabarits de l’interface d’administration. Le répertoire ./ecrire est à la fois le point d’entrée de l’interface d’admin et le réceptacle de toute la mécanique de base. En gros, l’application « site web » contient une autre application « espace privé » dont l’habillage est dans un autre sous-répertoire.

De plus, l’écran de sécurité, développé en dehors du code source de SPIP doit être installé dans le répertoire ./config, répertoire protégé par une directive apache, et les plugins et l’interface graphique du « site web » doivent être déposés, quant à eux dans les répertoires ./squelettes-dist/, ./plugins/ ou ./plugins-dist.

Types de composants, répertoires et attribut "extra" dans spip/spip

Chaque composant ne peut être installé que dans un seul répertoire. Le couple de répertoires ./ecrire et ./prive ne peut donc être géré comme un seul composant. De plus, un composant, lorsqu’il s’installe efface son répertoire cible. Il est donc risqué de désigner le répertoire racine de l’application comme cible d’un composant, car tout sera effacé pour être remplacé.

Il devient nécessaire que composer sache installer chaque composant au bon endroit. Pour cela, nous avons développé un plugin composer [2] et spécifié des types. Le projet « spip/spip » requiert ce plugin et ses autres dépendances seront donc installées là où le code de SPIP les attend. Le code historique de SPIP a aussi été découpé pour répondre à cette double contrainte :

  • À titre expérimental, un type « spip-classic » a été mis au point, mais ne devrait pas être pérennisé dans le temps. Il n’est pas totalement fonctionnel mais a été imaginé comme étape de développement du plugin Composer.
  • Le contenu du répertoire ./ecrire se trouve donc dans un dépôt qui lui est propre, son propre versioning peut être indépendant ou non, le type de ce composant est « spip-ecrire ». Ce sera le seul composant de ce type.
  • Idem pour le contenu du répertoire ./prive de type « spip-prive ».
  • un composant de type « metapackage » permet de gèrer les 2 composants ci-dessus comme un seul. Voir https://getcomposer.org/doc/04-sche... pour plus de renseignements.
  • Enfin le type « spip-plugin » d’un composant permet au plugin Composer d’installer un plugin spip dans un sous-répertoire de ./plugins. L’attribut « extra » du projet spip/spip spécifie d’autres répertoires si le plugin spip doit être le squelette par défaut, le « template » (./squelettes-dist) ou une des « extensions » (./plugins-dist) de la distribution.

Reconstituer l’arbo de base

Un composant, de type « project » nommé spip/spip reconstitue le répertoire de base d’un site SPIP. On y trouve les fichiers de la racine et les répertoires principaux, un fichier composer.json ainsi qu’un fichier .gitignore.

Les autres plugins

Tout composant de type « spip-plugin », développé dans le respect du standard layout et de semver sera éligible à intégrer un dépôt Composer pour être associé à une application web basée sur le modèle SPIP et automatiquement reconnu par le plugin Composer.

Faire d’autres distributions

Pour faire une distribution basée sur SPIP mais avec un autre squelette par défaut et/ou d’autres plugins que ceux de la distribution « Classic », il suffira de cloner le projet « spip/spip », de le renommer (par exemple « seenthis/seenthis ») et de changer les plugins requis ainsi que l’attribut « extra ». Un exemple opérationnel sera fourni ultérieurement.

Futur immédiat

Dans le cadre des versions 3.x, le plugin Composer devrait proposer une pratique similaire pour gérer les fichiers de langue et éventuellement des thèmes de squelettes.

Dans un avenir plus proche, une étape importante sera de faire faire évoluer le script spip_loader.php afin qu’il télécharge une sorte de gros paquet "classic". Pour cela, il devrait être capable d’intérroger un dépôt Composer, plutôt que de requêter l’interface redmine du dépôt subversion, et avec une restriction sur ces gros paquets. On pourrait aussi envisager le découpage de ce script en composants (http, archiviste, minipres, i18n) et produire un fichier phar.

De manière équivalente, le plugin SVP devrait être adapté pour interroger le dépôt Composer avec une restriction sur le type « spip-plugin ». Cela remettrait peut-être en cause la mécanique de sécurisation du répertoire ./plugins/auto.

Avertissement sur la sécurité : Historiquement, l’accès en écriture d’un certain nombre de sous-répertoires (IMG/, tmp/ et local/ entre autres), voire de tout l’espace web (comprendre la racine du site) est requis. C’est considéré, à juste titre, comme une faille de sécurité par certains hébergeurs. Composer a besoin d’écrire dans son répertoire ./vendor, voir de modifier les fichiers ./composer.*, ce qui n’est pas une bonne pratique via le web. C’est la raison pour laquelle il n’existe pas de GUI "officielle" de Composer. SVP, en devenant l’interface graphique de Composer pour un site SPIP, devra être assumée par une équipe de maintenance qui saura trouver les bons compromis et garantir la sécurité des sites pour ses usagers.

SPIP 4.0

Il pourra être envisagé dans le cadre des versions 4.x de SPIP de ne gérer que des composants de type library exclusivement. Le plugin Composer deviendrait alors obsolète. Ce genre de refonte serait à envisager autour d’une réorganisation de l’arborescence historique d’un « site sous SPIP ». Aujourd’hui, une application basée sur SPIP ne peut être autre chose qu’un « site web ». Le répertoire ./ecrire impacte beaucoup l’application : à titre d’exemple, seenthis porte un espace d’administration parfaitement inutile. La partie Base de données ne peut être appliquée que par l’accès à l’admin... etc. On pourrait aussi souhaiter des composants issus de SPIP mais utilisables ailleurs et les types de composants imaginés pour cette transition n’aurait plus d’utilité.

Notes

[1où de sécuriser, temporairement, via une directive dans un fichier .htaccess

[2Code source ici.