Flex : son role et sa fonction dans SPIP

Certain·es d’entre vous ont vu passé des PR / commits concernant l’utilisation de Flex. Comme c’est une petite nouveauté dans SPIP, et qu’il reste des questions en suspens, ce long fil pour expliquer le pourquoi du comment, et les questions qui se posent.

Le besoin

Historique

Historiquement, la configuration de SPIP est gérée à l’aide de constantes PHP, (certaines étant surchargeables), de variables PHP globales, de données stockées en base de données ou sous forme de fichiers, plus ou moins temporaires.

Le contenu du dossier config/ de SPIP n’est « pas versionné ». Il est propre à chaque installation, à chaque site, qu’il soit unique ou dans le cadre d’une mutualisation. Il peut contenir une base sqlite, un fichier servant à la connexion à un serveur SQL, de la « personnalisation » via mes_options.php, mais aussi des « clés », la déclaration de la constante _SPIP_CHMOD etc. Autant de techniques différentes pour chaque cas d’usage.

Situation depuis le 30 septembre 2024 : des tableaux de configuration PHP

Pour remplacer certaines constantes PHP, des fichiers ont été ajoutés dans le dossier config/spip du dépôt git de spip/spip (voir « mode détaché versus synchronisé » du document create-project)

https://git.spip.net/spip/spip/-/tree/master/config/spip?ref_type=heads

ils sont pris en compte par un site SPIP à chaque requête HTTP (ou une commande CLI), comme tous les autres fichiers historiques de configuration ou d’options de plugins. Les valeurs lues sont intégrés dans un container de service (spip-league/kernel)

ces fichiers sont de la forme

return [
    'key' => value,
];

leur chemin est de la forme

config/vendor/file.php

dans le container de service, le paramètre prend le nom

vendor.file.key

l’appel à la fonction

param('vendor.file.key')

renvoie value de type mixed. Mais par convention, value est de type scalaire (une valeur numérique, une chaîne de caractère, un booléen) et ne devrait être ni un tableau, ni un objet. Pour les objets, les « services » sont prévus à cet effet. Pour les tableaux, créer autant de clés (key) que nécessaire dans un fichier.

Un fois SPIP installé et configuré, historiquement, d’autres fichiers peuvent y être placés manuellement, ou modifiés, pour mettre en œuvre des astuces de personnalisation.

Mise en lien avec composer

Rappel sur l’intérêt de composer

On ne reviendra pas ici sur l’intérêt de composer. Rappelons simplement qu’il s’agit

  1. De pouvoir adopter des librairies externes plus facilement
  2. De mieux diviser le code de SPIP en modules autonomes, plus facilement maintenables et testables, car non dépendant d’une installation complète de SPIP
  3. Potentiellement, de proposer ces modules au delà de la communauté SPIP, et/ou d’attirer de nouveaux/nouvelles dev
  4. Faciliter le processus de release

Spécificités SPIPienne dans l’emploi de composer

SPIP bénéficie d’un plugin composer original : spip-league / composer-installer · GitLab

Il traite les spécificités d’installation de SPIP, telles qu’elles sont historiquement et qui ne sont pas prises en compte dans le cadre d’un projet PHP plus conventionnel. Il définit et installe les packages « spip/* » au bons endroits, à savoir, ecrire/, prive/, squelettes-dist/ et plugins-dist/.

Le cœur du sujet : l’intérêt de Flex

flex est un plugin composer issu de la communauté Symfony. Il prend en charge l’installation et la mise à jour de fichiers, entre autres (voir les configurators : GitHub - symfony/recipes: Symfony Recipes Repository), qui n’ont pas vocation à être versionnés dans un dépôt git. Le plus évident étant la configuration des applications web. Voir : Upgrading Existing Applications to Symfony Flex (Symfony Docs)

Pour cela, un « manifest » est exposé sur le web. C’est un ensemble de fichiers json, les recipes qui sont associés à un package composer.

À propos des plugins composer : Setting up and using plugins - Composer et Setting up and using custom installers - Composer

Comme flex est un plugin composer, il s’utilise via composer et comme composer est un outil pour les « dev », les clés de compréhension ci-dessous sont destinées aux « dev ».

Dépôt de recette partagée dans la communauté PHP

Un peu comme composer avec packagist.org, un dépôt central existe pour les composants du framework symfony, ainsi qu’un dépôt de contributions (pour tout ce qui n’est pas symfony). Les recipes sont à proposer sur github ici GitHub - symfony/recipes-contrib: Symfony Contrib Recipes Repositories.

Généralisation de flex

L’emploi de flex dans SPIP permettrait d’homogénéiser les techniques, faciliter la mise en place de la configuration par défaut d’un composant, en respectant les versions sémantiques de celui-ci et quelque soit sa nature (package composer, plugin spip composerisé), de même pour la personnalisation des composants.

La solution proposée pour l’instant est de faire créer par flex, au moins un fichier config/vendor/name.php lors de l’installation (avec composer install ou composer create-project) ou lors de la mise à jour (avec composer update*****)

Comme vu plus haut, ce type de fichiers devrait retourner un tableau PHP qui, analysé par spip-league/kernel, permettra le comportement suivant :

param('vendor.name.key') # renvoie value, un scalaire

Il est à considérer que ces paramètres de configuration sont immutables (readonly, lecture seule), comme n’importe quelle configuration, ou constante, devrait l’être : constant pendant le runtime.

Notes

  • ***** si un SPIP est personnalisé, le comportement de flex n’est pas d’écraser la personnalisation. Une action est attendue. Faire les bons choix et les valider appartient à la personne qui fait la mise à jour. L’aide à la prise de ce genre de décision peut toutefois être prise en compte avec la mise en place d’une recipe.

Voir GitHub - symfony/recipes: Symfony Recipes Repository

Dépôt flex pour SPIP

Comme pour composer (cf le dépôt composer pour SPIP ici spip/composer) il existe un dépôt flex pour SPIP ici https://get.spip.net/flex/recipes/index.json

Expérimental pour l’instant, ce dépôt répond aux spécifications du document How To Configure and Use Flex Private Recipe Repositories (Symfony Docs)

À lire pour une intégration de recipes alternative : GitHub - symfony-tools/recipes-checker

spip_loader.php

spip_loader.php récupère le zip d’une release choisie via un formulaire et le déploie (décompresse) dans un espace web qui est soit vide si c’est une première installation, soit contient un SPIP pour mettre à jour les fichiers.

La mise à jour procède aussi à la suppression de fichiers obsolètes lors d’un saut de version.

À l’issue de cette opération, il redirige vers SPIP, qui lance des scripts issus du zip (donc, du « noyau » de SPIP) pour « finir la mise à jour ou l’installation ».

Ce qui est important à retenir, c’est que spip_loader ne fait QUE mettre à jour des fichiers. C’est SPIP lui-même qui exécute les procédures suivantes. Elles sont graphiques et se déroulent dans l’espace privé (le CMS, en gros) que ce soit avec la fonctionnalité « minipres » ou un ou des « exec ».

Que se passe-t-il avec les fichiers du dossier config/ ?

Les zip de release SPIP n’embarquent historiquement que les fichiers suivants, en fonction des versions :

Comportement actuel

4.3 et antérieures

  • ecran_secrurite.php
  • remove.txt

À partir de 4.4 et postérieures, depuis le 30 septembre 2024, il embarquera (sauf changement de stratégie)

  • spip/dirs.php (versionné)
  • spip/routes.php (versionné)
  • ecran_secrurite.php (via composer-installer)

La finalisation par SPIP lui-même ajoute

  • .ok
  • .htaccess
  • les fichiers décrit « dans le monde de SPIP »

La personnalisation (manuelle) d’un site peut ajouter

  • mes_options.php
  • et ça dépend … tout devient un cas particulier à partir de là …

Risques à maîtriser et remédiation si flex est utilisé

Le projet de « généralisation de flex » propose comme convention, lors de la génération de fichiers de configuration, la forme config/vendor/file.php (ou file peut être égal au name du vendor/name du package).

Sauf erreur, la seule dérogation à devoir gérer pourrait être le dossier config/bases/ en cas d’installation sqlite. Toutefois, les fichiers créés dans ce cas sont de la forme config/bases/.sqlite et donc, a priori, pas de fichiers PHP dans ce dossier. De même, un vendor valant « bases » semble exclu (on s’attend à des noms du type spip ou spip-contrib, voire seenthis, giseh, … bref, un nom correspondant à une organisation de personne sur un serveur git…).

Le composant spip-league/kernel devrait donc être capable de traiter n’importe quel dossier « vendor » pour que flex puisse déposer des fichiers PHP de configuration respectant ce modèle.

Si un zip de release SPIP contient des fichiers dans le dossiers config/ (parce que généré avec composer create-project et flex), le fonctionnement actuel de spip_loader écrasera tout les fichiers installés avec un zip similaire… ce que ne ferait pas une installation en ligne de commande avec composer …

Plusieurs pistes sont à envisager :

1/ gestion d’un fichier config/custom.php
2/ dans spip_loader, prendre en compte l’existence de config/spip

3/ déplacement de config/bases/spip.sqlite : c’est une base de de données, pas de la configuration. C’est à cet endroit parce que c’était le plus facile à faire lors de l’intégration de sqlite dans un SPIP qui se protège avec des .htaccess dans un dossier config/ présent dans l’espace web d’un serveur apache.
mettre spip.sqlite dans le dossier racine du projet et mettre une règle dans htaccess.txt seraient rigoureusement équivalent.
autre exemple : mettre ce fichier dans /var/lib/sqlite (comme on a une base mysql dans /var/lib/mysql) serait encore plus « logique » d’un point de vue système (mais perdrait l’avantage d’avoir un sqlite accessible facilement pour les gens qui n’ont accès qu’à une partir du serveur).
Seul le chemin vers le fichier .sqlite accessible en écriture est nécessaire pour l’application web, rien n’oblige à ce qu’il (le .sqlite) soit dans l’espace web

(valable aussi pour formidable qui écrit dans config)

4/ ou en imaginer d’autres

5/ ou abandonner flex

4 « J'aime »

#documentation_ici

Merci pour les explications, ça a l’air très détaillé.
Je vais prendre le temps de lire et comprendre tout ça.

Qu’est ce que vous appelez un composant : un package composer ? un plugin SPIP ?

A la lecture, je m’interrogeais sur :

Versionnés dans /ecrire j’imagine ? dans un /spip/* en tout cas.
Et du coup, comment les personnaliser / surcharger ?

Je lis plus bas les alternatives. notamment la prise en charge d’un fichier config/custom.php, mais @JamesRezo semble dire que ce n’est qu’un pis aller, mais pour quelle raison ?

Question subsidiaire : quid des plugins, est ce que la table spip_metas serait concernée à terme par un déplacement dans /config/vendor/truc.php ?
Ces configs ne sont pas immuables donc je ne crois pas (?)

Un composant composer c’est un code php autonome associé à un composer.json qui peut être marqué comme dependant dans un composer.json (d’apèrs ce que je comprend)

Aujourd’hui dans le monde spip on a comme composant composer

  • les plugins-dist
  • ecrire
  • prive
  • des elements sous jacent dev dans spip-league : gestion des paths, du cache etc.

Les plugins classiques ne sont actuellement pas des composants, sauf certains encore.

Ici spip/composer la liste des composants disponibles propres à la commu SPIP, il y a aussi ceux de la commu PHP

Et du coup, comment les personnaliser / surcharger ?

actuellement c’est une modification du fichier. Et c’est pour cela que la question de « comment on gère la personnalisation » se pose, notamment lié à la problématique spip_loader

nicod_I’m only in it for the money.

37 min

Qu’est ce que vous appelez un composant : un package composer ? un plugin SPIP ?

A la lecture, je m’interrogeais sur :

Versionnés dans /ecrire j’imagine ? dans un /spip/* en tout cas.
Et du coup, comment les personnaliser / surcharger ?

Je lis plus bas les alternatives. notamment la prise en charge d’un fichier config/custom.php, mais @JamesRezo semble dire que ce n’est qu’un pis aller , mais pour quelle raison ?

Question subsidiaire : quid des plugins, est ce que la table spip_metas serait concernée à terme par un déplacement dans /config/vendor/truc.php ?
Ces configs ne sont pas immuables donc je ne crois pas (?)

A mon sens ce n’est pas de la config système, mais de la config éditoriale, donc ca ne devrait pas bouger. Enfin, il pourrait y avoir des exceptions, par ex sur la gestion des assets qui se trouve en cfg (dans le cas de saisies), mais même cela ce n’est pas certains. Config/truc/xxx concerne uniquement de la config système / technique, pas édito.

Ok, donc peut être préciser dans cette doc : « faciliter la mise en place de la configuration par défaut d’un composant (i.e. package composer) »

Le terme « composant » est trop générique (comme on vient de le voir ailleurs pas plus tard qu’il y a 5 minutes, dans un autre contexte).

Ok, donc peut être préciser dans cette doc : « faciliter la mise en place de la configuration par défaut d’un composant (i.e. package composer) »

oui, cela me semblerait pas mal. Mais j’aimerais bien qu’une tiere personne qui a rédigé la doc me confirme que c’est pas une betise.