Ce qui a été corrigé
- •Erreurs du programme de mise à jour : échec d’écriture des fichiers et de
version.json, correctifs et aperçu des modifications non pris en charge, dépôt inaccessible et connexion réussie.
- •Page de mise à jour : erreur de réponse du serveur, « N fichiers modifiés · N commits », terminé, application en cours, tâche enregistrée, délai dépassé et restauration terminée.
- •Notices d’enregistrement de tâche : le message indiquant qu’une tâche de mise à jour, de correctif ou de restauration a été mise en file d’attente.
- •Le worker à privilèges (cron) laisse désormais ses messages de progression ainsi que ses notifications de réussite et d’échec dans la bonne langue.
Page d’historique des modifications (`/changelog`)
- •Les durées relatives comme « 5 months ago » n’existaient qu’en coréen et en anglais ; elles sont maintenant disponibles en 13 langues.
Le message de liste vide, l’indication « Traduction IA », la note « pas de traduction — affiché en KO » et « seules les N plus récentes sont affichées » sont aussi traduits.
- •La langue de la page est désormais la langue réellement utilisée par le site, et non plus seulement la valeur de session (
?lang=, session, cookie, langue par défaut).
Auparavant, une première visite retombait sur le coréen, si bien que des libellés coréens se glissaient dans les sites japonais et anglais.
- •Les identifiants et chemins longs (texte sans espaces) ne débordent plus de la carte et ne passent plus sous le bouton d’installation à droite.
Bon à savoir
- •Le worker à privilèges n’a pas d’utilisateur connecté et donc pas de langue. Il écrit ses messages dans la langue par défaut du site.
(Auparavant, il ne démarrait pas le système de traduction ; des clés comme updater.write_failed pouvaient donc s’afficher telles quelles. Le worker le démarre maintenant.)
- •Les journaux du serveur (
error_log) et les journaux de débogage destinés aux développeurs sont lus par les exploitants ; ils sont restés tels quels.
- •Sur un site déjà installé, c’est l’ancien programme de mise à jour déjà installé qui exécute la mise à jour ; ces améliorations n’apparaissent donc qu’à la mise à jour suivant le passage à la 2.8.2.
v2.8.1
2026-10-12 · il y a 7 jours
Multilinguisme renforcé (nom de l’appli, données de recherche, `?lang=`) · les mises à jour protègent les modifications du cœur propres à un site
Multilinguisme
- •Le nom et la description de l’appli dans « Ajouter à l’écran d’accueil » et dans l’invite d’installation apparaissent maintenant dans la langue du visiteur. Auparavant, la valeur enregistrée (par exemple en japonais) s’affichait telle quelle.
Les traductions se placent sous des clés comme pwa.front.name dans rzx_translations. manifest.php se contente désormais de passer la main à la sortie officielle.
- •Données structurées (JSON-LD) : les traductions des valeurs des paramètres sont consultées en premier. Nous avons corrigé le deuxième élément du fil d’Ariane qui contenait aussi le nom du site, et « Home » qui apparaissait en anglais dans toutes les langues.
- •Widget de statistiques : le nombre et l’unité (
suffix) acceptent maintenant des valeurs par langue, comme le libellé. Une valeur unique fonctionne exactement comme avant.
- •L’écran hors ligne et le dernier message du service worker existent désormais en coréen, en japonais et en anglais.
La version du cache du service worker passe de v5 à v6, afin que les appareils déjà installés reçoivent le nouvel écran.
- •« Aucun résultat » dans la recherche de messages était écrit en dur en coréen ; il existe maintenant en 13 langues.
Moteurs de recherche et IA
- •Nous produisons
<meta property="og:locale"> et les langues alternatives (og:locale:alternate). Lors d’un partage sur les réseaux sociaux, cela indique la langue de la page.
- •Les pages système publiques dessinées par le code figurent maintenant dans
sitemap.xml (elles manquaient).
- •La première ligne de
llms.txt (la description du site) apparaît dans la langue du visiteur.
- •Le paramètre robots par page (l’écran d’administration avait le champ, mais rien ne le lisait) est maintenant réellement appliqué.
Problèmes corrigés
- •La valeur de
?lang= n’est acceptée qu’après vérification avec la liste des langues prises en charge. Auparavant, une valeur non prise en charge restait un an dans le cookie,
et l’ouverture ultérieure de cette langue pouvait faire basculer un visiteur vers cet écran contre son gré. Le sélecteur de langue suit la même règle.
- •Constructeur de widgets : les traductions des langues sans champ de saisie à l’écran étaient effacées à chaque enregistrement.
- •Recherche de messages de la communauté : les noms sont stockés chiffrés, si bien qu’aucun nom ne donnait de résultat. La recherche déchiffre maintenant avant de comparer.
Les mises à jour protègent les modifications du cœur propres à un site
- •Si vous indiquez des chemins dans
storage/custom/update-preserve.txt, un par ligne (# pour un commentaire, les dossiers sont acceptés), la mise à jour n’écrase pas ces fichiers.
Servez-vous-en pour protéger ce que vous avez placé directement dans des fichiers du cœur, comme une règle de connexion propre au site. Les chemins absolus et .. ne sont pas acceptés,
et si le fichier est illisible, la mise à jour ne s’arrête pas : elle continue avec la liste de protection par défaut.
- •Bon à savoir : la partie qui exécute la mise à jour doit déjà disposer de cette fonction pour en profiter. Elle s’applique à partir de la mise à jour suivant le passage à la 2.8.1.
Ce qui change
Le module de paiement avait déjà un fichier par prestataire, mais « quels prestataires existent » était écrit en dur à plusieurs endroits du code.
Pour ajouter un prestataire, il fallait modifier le gestionnaire de paiement, l’écran des paramètres et le webhook.
- •Déposez un dossier (
gateway.json plus le fichier d’implémentation) dans rzxlib/Modules/Payment/Gateways/ et le cœur le reconnaît tout seul.
Le choix du prestataire, les champs de clés et l’adresse du webhook dans l’écran des paramètres d’administration sont générés à partir de cette spécification.
- •Un site choisit toujours un seul prestataire dans l’écran des paramètres (comme avant). Ce n’est pas une fonction pour utiliser plusieurs prestataires en même temps.
- •La manière d’ajouter un prestataire est décrite dans
docs/PAYMENT_GATEWAYS.md.
Square
- •Sont pris en charge : paiements par carte, remboursements et consultations, cartes enregistrées (pour les prélèvements récurrents) et webhooks (avec vérification de signature).
- •Le formulaire de saisie de carte passe par l’authentification du porteur (SCA) et affiche la raison à l’écran en cas d’échec. 13 langues.
- •L’écran des paramètres d’administration a un nouveau bouton « Test de connexion ». En mode test, il exécute un petit paiement, une consultation et un remboursement
pour vérifier que vos clés sont correctes. Aucun argent réel n’est transféré, et le test ne s’exécute pas en mode réel (live).
- •Tant que vous ne choisissez pas Square, rien ne change pour aucun site.
Les prestataires existants (PAY.JP et Stripe) restent tels quels
- •Les fichiers d’implémentation des deux prestataires n’ont pas été touchés. Les anciens paramètres (clé unique, v2, v3) sont lus comme avant.
- •Même si les fichiers de spécification ne peuvent pas être lus pour une raison quelconque, un filet de sécurité fait créer PAY.JP et Stripe à l’ancienne.
- •Avec les paramètres réels de sites en production et de nombreux paramètres synthétiques, nous avons comparé l’ancien et le nouveau code et confirmé qu’ils choisissent le même prestataire, le même mode et les mêmes clés
(scripts/test-payment-parity.php).
Lecture des paramètres de paiement par site
Lorsqu’une base de données contient un paramètre de paiement distinct pour chaque site, le module de paiement lit désormais le paramètre de son propre site.
Auparavant, on ne savait pas quel paramètre de site serait retenu. Si un site n’a pas de paramètre propre, il se comporte comme avant.
Bon à savoir
- •Une adresse de webhook commune a été ajoutée (
/api/webhook-payment.php?gateway=…). Les adresses de webhook existantes de PAY.JP et de Stripe ne changent pas.
- •La liste des prestataires dans l’écran des paramètres garde son ancien ordre ; les prestataires ajoutés via une spécification viennent ensuite.
Quel était le problème
Le plan du site (sitemap.xml) et le guide pour l’IA (llms.txt) ne contenaient que ce que le cœur connaît.
Pour qu’une extension ajoute ses propres pages, il fallait modifier directement des fichiers du cœur, et cette modification
disparaissait à chaque mise à jour. De plus, le cœur devinait comment lire la table des extensions, si bien que certains endroits dérivaient sans bruit.
- •Les annonces immobilières n’étaient publiées qu’à une adresse distincte (
/properties-sitemap.xml) ; si rien ne pointait vers cette adresse,
les moteurs de recherche ne la trouvaient pas.
- •Les articles du marché n’avaient jamais figuré dans le plan du site, à cause d’une requête qui cherchait une colonne inexistante.
L’erreur était avalée, si bien que personne ne le savait.
- •Certains sites publiaient les adresses des boutiques sous une forme erronée, ce qui faisait indexer des adresses menant à des pages inexistantes.
Les extensions publient désormais leurs propres pages
- •Si une extension indique
seo dans son plugin.json, le cœur le lit et l’intègre au plan du site et au guide pour l’IA.
Cela fonctionne comme pour les widgets, les mises en page et les modules d’intranet, et en cas d’adresse identique, c’est le cœur qui l’emporte.
- •Les adresses pour plusieurs langues et les marqueurs de langue sont ajoutés par le cœur. Une extension n’a qu’à fournir ses adresses.
- •Une extension défectueuse ne fait plus tomber tout le plan du site. Seule la part de cette extension est omise.
- •Les adresses des extensions désactivées disparaissent automatiquement ; les pages d’une extension désactivée ne s’ouvrent de toute façon pas.
Les adresses alternatives chinoises étaient ignorées
Le plan du site écrivait le marqueur de langue zh_CN, alors que la norme est zh-CN, si bien que Google ignorait cette ligne entièrement.
Les pages elles-mêmes étaient écrites correctement ; un même site disait donc deux choses différentes à deux endroits.
Les adresses alternatives en chinois simplifié et traditionnel sont désormais correctement reconnues.
Guide pour l’IA par langue
- •
llms.txt n’existait que dans la langue par défaut. Il produit maintenant des éditions par langue comme ?lang=en.
Les noms et descriptions sortent dans cette langue, et l’en-tête du guide indique de quelle édition il s’agit.
- •Sur les sites multilingues, les moteurs de réponse d’IA peuvent désormais présenter ce site aux utilisateurs de chaque zone linguistique.
Les employés peuvent voir leur propre fiche RH (intranet)
- •La fiche RH que seuls les responsables RH pouvaient voir peut maintenant être consultée aussi par l’employé. On y accède depuis le menu du profil en haut.
- •Elle est en lecture seule. Un parcours où l’on demande une correction et où le responsable RH l’approuve est en préparation.
- •Les évaluations ne sont pas visibles pour l’employé. Il en va de même pour les récompenses et les sanctions. Pour les documents joints, seule la liste est affichée.
- •On ne peut pas ouvrir la fiche d’un autre en modifiant la barre d’adresse ; à qui appartient la fiche est déterminé uniquement par les informations de connexion.
- •L’employé peut aussi vérifier qui a consulté ses informations RH.
Utiliser les écrans du forum dans une autre enveloppe
Tous les liens d’un écran de forum sont construits à partir d’une seule valeur ($boardUrl), mais le cœur l’écrasait toujours.
Ceux qui utilisent un forum à l’intérieur d’un écran d’administration, comme l’intranet, devaient donc remplacer caractère par caractère la page déjà entièrement générée.
Si le cœur changeait si peu que ce soit la forme d’un lien, tout dérivait sans bruit.
- •Si l’appelant fixe l’adresse de base à l’avance, cette valeur est utilisée. Sinon, rien ne change par rapport à avant.
- •Le lien de la roue dentée (paramètres du forum) est lui aussi défini en un seul endroit. Auparavant, la liste, la FAQ, les Q&R et le thème de liens avaient chacun le leur.
Les mises en page peuvent se trouver dans une extension
- •Les mises en page sont cherchées d’abord dans
skins/layouts/ du cœur, et à défaut dans plugins/{id}/skins/layouts/ de l’extension.
C’est la même règle que pour les widgets et les modules d’intranet, et en cas de nom identique, c’est le cœur qui l’emporte.
- •Les mises en page d’extension apparaissent aussi dans le sélecteur de mise en page de l’administration.
- •Jusqu’ici, une mise en page propre à une extension devait être placée dans le dossier du cœur. Une mise à jour ne la supprime pas,
mais si le cœur propose plus tard une mise en page du même nom, elle est écrasée, et pour déplacer l’extension vers un autre site il fallait emporter le dossier à la main.
Les extensions déclarent elles
La liste des écrans d’intranet (menu de gauche et chemins d’entrée) n’existait que dans un seul fichier de paramètres du cœur.
Pour qu’une extension ajoute son propre module, il fallait modifier un fichier du cœur, et cette modification disparaissait à la mise à jour.
- •Si une extension indique
intranet_module dans son plugin.json, le cœur le lit et l’intègre. Cela fonctionne comme pour les menus et les pages système.
- •La valeur peut être un tableau écrit directement, ou un chemin de fichier comme
"data/intranet-module.php".
- •En cas de nom identique, c’est le cœur qui l’emporte. Une extension ne peut pas détourner un module du cœur pour changer son comportement par défaut.
- •Les cinq endroits du cœur qui lisaient cette liste utilisent maintenant la nouvelle méthode. Même si une mise à jour écrase le fichier de paramètres, les modules d’extension restent.
Ères japonaises (和暦) dans la saisie des dates
- •Dans les écrans en japonais, si l’on choisit une ère (令和, 平成, 昭和, 大正, 明治) et saisit le numéro d’année dans le champ de date, l’année grégorienne se remplit automatiquement.
On n’a plus à convertir à chaque fois une valeur retenue par ère, comme une date de naissance.
- •Le champ d’affichage du jour de la semaine reste inchangé.
Le paramètre de mise en page du forum n’était pas pris en compte à l’écran
- •Même en choisissant une mise en page par forum dans l’administration, l’écran affichait la mise en page par défaut du site.
L’endroit où l’on enregistrait et celui où l’on lisait étaient différents.
- •Correction : lors de l’enregistrement d’un forum, on écrit aussi le paramètre que l’écran lit.
Les forums existants gardent leur aspect actuel jusqu’à leur prochain enregistrement (l’apparence ne change pas soudainement).
Les messages n’étaient pas enregistrés à la rédaction
- •L’enregistrement d’un message laissait de côté la colonne du titre, si bien que sur les sites où cette colonne existe encore, l’enregistrement échouait.
L’écran n’affichait que « Unexpected end of JSON input ».
- •Correction : si la colonne existe, elle est aussi renseignée. Les sites qui l’ont supprimée fonctionnent comme avant.
Recherche du forum
- •La recherche consultait l’ancienne colonne, si bien que sur les sites qui l’ont supprimée, toute la liste ne s’ouvrait plus dès qu’on saisissait un terme.
- •Les sites qui ont conservé la colonne avaient aussi un problème. Modifier un message ne mettait pas la colonne à jour, si bien que la recherche ne trouvait que le texte d’avant la modification.
- •Correction : la recherche passe désormais par la table de traduction. Elle trouve maintenant la langue affichée et aussi le contenu traduit.
Messages invisibles dans les listes, les widgets et « Mon espace »
- •Le widget à onglets des domaines d’activité et le widget en grille du forum affichaient toujours une liste vide (l’erreur était avalée en interne).
- •Dans « Mes commentaires » de « Mon espace », les commentaires du forum manquaient totalement.
- •Le thème du forum de liens avait toujours un titre vide.
- •Correction : tous lisent maintenant le titre et le texte dans la table de traduction. Les miniatures sont aussi retrouvées à partir du texte.
Traduction par IA et nouvelle installation
- •Nous avons corrigé la traduction des messages par IA, qui échouait à la lecture du texte d’origine et faisait échouer toutes les tâches de traduction.
- •Nous avons corrigé le cas où, lors d’une nouvelle installation, le titre et le texte en langue d’origine des messages d’exemple n’entraient pas dans la table de traduction, si bien que le titre semblait vide.
Divers
- •Nous avons corrigé le cas où la liste ne s’ouvrait pas quand le tri du forum était réglé sur « par recommandations » (il renvoyait à une colonne inexistante).
Le texte d'autrui arrivait tel quel dans la fenêtre d'information
La fenêtre d'information commune de l'administration (modale de résultat) collait dans la page les titres de menu, les noms de thème et les messages du serveur tels quels.
Il suffisait de mettre <script> dans un nom pour que cela puisse s'exécuter à l'ouverture de l'écran par un autre administrateur (XSS stocké).
- •Corrigé : tous les textes de la fenêtre (titre, contenu, bouton, ligne de confirmation) sont désormais convertis pour s'afficher comme de simples caractères avant insertion.
- •Le message affiché en cas d'échec de connexion à la base de données utilise maintenant un texte traduit et passe par la même conversion.
Les boutons s'affichaient en coréen quelle que soit la langue
- •« Confirmer » et « Annuler » étaient écrits en coréen dans le JavaScript. Ils s'affichent maintenant dans la langue consultée.
Le serveur fournit les libellés de la langue en cours et le script lit ces valeurs.
Libellés d'administration en 13 langues
Les textes coréens codés en dur dans les écrans de design (thème), de menus et de paramètres de page ont été remplacés par des clés de traduction, renseignées en 13 langues.
- •Thèmes : résultats du renommage, de la duplication et de la suppression ; confirmation « les fichiers et réglages du thème seront définitivement supprimés » ; résultat de l'envoi d'images
- •Menus : information indiquant qu'une page système est seulement retirée du menu ; confirmation « la page liée (forum) sera également supprimée »
- •Paramètres de page : messages sur le type de fichier, l'échec d'enregistrement et l'URL en doublon
Les articles privés fuitaient dans les listes
Un article marqué privé affichait toujours son titre, son image et son résumé dans la liste. Seul le corps était masqué.
- •Corrigé : dans les listes aussi, seuls l'auteur, les administrateurs ou les personnes ayant saisi le mot de passe voient le titre et l'aperçu.
- •La lecture du contenu via l'URL de la pièce jointe est également bloquée : les pièces jointes appliquent désormais le même contrôle.
- •Les titres de l'article précédent et suivant sur la page de lecture sont eux aussi masqués.
- •Les widgets qui reprennent des listes (cartes de forum, grilles, onglets) excluent les articles privés dès la requête.
Le premier affichage était trop lent
Sur mobile, les premiers caractères mettaient longtemps à apparaître. La cause : les polices.
- •Le CSS des polices (Google Fonts 152 Ko + Pretendard 29 Ko) bloquait le rendu.
La page s'affiche maintenant d'abord avec les polices système, puis les polices web prennent le relais dès leur arrivée.
- •Pretendard n'est chargée que sur les écrans en coréen. En japonais, une police japonaise passe d'abord : seuls des fragments étaient téléchargés puis jetés.
- •Deux petites feuilles de style (taille du texte, corps du forum) sont intégrées à la page au lieu d'être demandées en fichier.
- •À la première visite, le cache d'écran (service worker) faisait lire le document deux fois ; c'est supprimé.
- •Le calcul de largeur du menu à défilement horizontal est reporté après le chargement de la page (il figeait 0,5 s).
Pour que les robots de recherche et les IA suivent les pages par langue
- •Les liens de langue pointent désormais vers de vraies adresses (
?lang=…). C'étaient auparavant des liens JavaScript, que les robots ne pouvaient pas suivre.
Administration
- •Dans la liste des pages, une même page apparaissait autant de fois qu'il y a de langues ; ces lignes sont maintenant regroupées en une seule.
- •Modifier uniquement le titre d'un menu effaçait les traductions des autres langues. Elles ne sont désormais nettoyées que si la page liée change.
- •Une publication programmée du blog avec une heure passée était enregistrée telle quelle ; un message s'affiche et le statut reste inchangé (13 langues).
Notifications et libellés
- •L'objet des notifications de messages de la communauté était figé en coréen. Il part maintenant dans la langue du destinataire.
- •Le texte du lien du bandeau cookies, trop sombre, a été éclairci.
Rangement interne
- •Suppression des dossiers de vues d'administration dupliqués par erreur (
admin/site/site, admin/components/components).
Ce sont les dossiers d'origine qui servent réellement. La construction de la distribution les exclut également.
Des forums privés figuraient dans le plan du site
Même les adresses de forums visibles uniquement par les administrateurs (comme les boîtes de réception des demandes) étaient incluses dans le plan du site.
Les robots d'exploration ne recevaient qu'une erreur 403 (accès interdit) à ces adresses, et l'existence de forums privés était révélée.
- •Correction : seuls les forums consultables par les non-membres sont inclus. Le critère : les forums dont les droits d'affichage de la liste et de lecture des messages sont réglés sur « Tous ».
- •Les messages secrets et les forums exclus de la recherche (noindex) dans leurs paramètres sont également écartés.
- •Une page portant le même nom qu'un forum est évaluée selon le forum, car c'est le forum qui prend l'adresse en premier.
- •Les pages multilingues sont également incluses dans le plan du site.
- •Les pages à ne pas inclure sur un site donné s'indiquent dans le paramètre
sitemap_exclude. llms.txt suit le même paramètre.
Les e — mails envoyés arrivaient en spam ou étaient renvoyés
- •Il manquait l'heure d'envoi (Date) et l'identifiant unique du message (Message-ID), si bien que les serveurs destinataires les classaient facilement comme spam.
Les deux sont désormais ajoutés et le corps est envoyé en base64. Cela évite aussi que les longues lignes soient coupées ou que le corps s'interrompe à cause d'un « . » en début de ligne.
- •Lorsque l'adresse du destinataire appartenait au même domaine que l'expéditeur (par exemple une copie envoyée à l'adresse de l'entreprise), la messagerie de ce domaine la rejetait comme usurpation.
Dans ce cas uniquement, l'envoi se fait désormais depuis l'adresse du compte SMTP, et les réponses arrivent toujours à l'adresse d'origine.
Paramètres SEO et recherche IA renforcés
- •Des champs Informations sur l'exploitant (données structurées Organization) ont été ajoutés aux paramètres SEO de l'administration. Les champs vides ne sont pas publiés.
- •Les paramètres SEO propres à chaque page sont désormais réellement utilisés, et une adresse de référence (canonical) est définie lorsque le même contenu est accessible à plusieurs adresses.
- •Un champ pour le code de vérification de site Bing a été ajouté. La recherche de ChatGPT utilise l'index de Bing.
- •Les descriptions sont coupées selon la largeur d'affichage des résultats de recherche, en fin de phrase plutôt qu'au milieu.
Nettoyage de l'affichage des langues
- •La page 404 s'affichait toujours en coréen. Elle apparaît désormais dans la langue consultée (japonais, coréen ou anglais ; les autres langues passent à l'anglais).
- •Correction du « à l'instant » de la cloche de notifications, qui était codé en dur en coréen.
- •Les écrans en japonais utilisent d'abord des polices japonaises. L'assistant de polices par langue est toujours chargé, si bien que les écrans qui ne passent pas par la mise en page (comme les pages de partage) ne s'arrêtent plus à cause des polices.
- •La liste « Langue préférée » de Mon espace n'affiche plus les langues sans textes.
- •À l'inscription, la langue de l'écran consulté est enregistrée comme langue préférée (elle restait vide jusqu'ici). Les e-mails de réinitialisation du mot de passe sont également envoyés dans cette langue.
Saisie et connexion
- •Les dates comme la date de naissance se saisissent désormais dans trois champs : année, mois et jour. Auparavant, l'affichage variait selon la langue du navigateur.
- •Correction de la vérification reCAPTCHA qui manquait, selon le thème, lors de la connexion et de la récupération du mot de passe.
Paiement
- •Pour chaque prestataire de paiement, les clés de test et les clés de production sont conservées séparément. Il suffit de sélectionner le mode test, et les clés ne se perdent plus lors des changements.
Widgets
- •Le bouton du widget hero peut désormais s'ouvrir dans une nouvelle fenêtre.
- •Les éléments répétés du constructeur de widgets peuvent aussi être rédigés par langue (bouton globe).
Build
- •Les fichiers de configuration (.env) et leurs sauvegardes ne sont jamais inclus dans la distribution, quel que soit leur nom.
- •Les fichiers de sauvegarde laissés lors de l'édition (
.bak, y compris ceux dont le nom est suivi d'une date) ne sont pas inclus non plus.
- •Les scripts utilisés uniquement pour l'exploitation du siège (synchronisation de sites, hébergement, serveur de messagerie, mise à jour des conditions, etc.) et les tâches cron utilisées seulement par des plugins absents de la distribution ont été retirés de la distribution. Les scripts dont les sites clients ont besoin, comme les workers de mise à jour, d'installation et de traduction, restent inclus.
- •Après la création du zip, une nouvelle vérification a lieu ; si des fichiers de configuration ou de sauvegarde s'y trouvent, la publication est interrompue.
- •Les scripts de test n'écrivent plus les mots de passe dans le fichier ; ils les lisent dans la configuration.
Après la mise à jour, le nom et la date de sortie de la version ne changeaient pas
Seul le numéro augmentait, et le titre de la version précédente restait tel quel.
L’écran d’administration affichait par exemple « 2.7.9 · Polices japonaises · avis de renouvellement de contrat… », le numéro et le nom ne correspondant pas.
À l’écran seul, on ne pouvait pas savoir ce qu’on avait reçu.
- •Cause :
version.json est un fichier qui n’est volontairement pas écrasé, afin de protéger les réglages propres à chaque client.
Le programme de mise à jour le remplit donc lui-même, mais il ne remplaçait que le numéro et l’heure et laissait le titre et la date de sortie.
- •Correctif : le titre et la date de sortie de la nouvelle version sont maintenant lus dans le paquet reçu et appliqués aussi.
Pour les mises à jour partielles sans paquet, ils sont lus dans la liste de distribution (manifest.json).
Les réglages propres à chaque client (github, etc.) sont conservés tels quels.
Attention — même après être passé à cette version, l’écran peut encore afficher l’ancien nom. C’est en effet
le programme de mise à jour de la version actuellement installée qui exécute la mise à jour.
L’affichage sera correct à partir de la version suivant celle qui aura reçu la 2.7.10.
Contrôle de build
La panne du constructeur dans la 2.7.8 (corrigée dans la 2.7.9) a passé les tests de régression sans encombre.
C’est que les contrôles existants ne regardaient que « le fichier existe-t-il · la chaîne s’y trouve-t-elle ».
- •Désormais, le script qui entre dans le constructeur est réellement généré puis soumis à un contrôle de syntaxe (
node --check).
- •Si du code insère tel quel un fichier de plusieurs lignes dans une chaîne JS, le build est bloqué en indiquant le numéro de ligne.
- •Nous l’avons essayé avec un fichier reproduisant la 2.7.8 et avons confirmé que le contrôle l’attrape bel et bien.
Symptômes
- •Aucun widget n’apparaît dans la palette
- •Les widgets déjà placés ne sont pas dessinés sur le canevas — les vidéos, images et autres semblent avoir disparu
- •L’enregistrement ne fonctionne pas
Cause
Dans 2.7.8, nous avons réuni les déclarations de police en un seul endroit, partials/fonts.php. Or l’endroit où l’on construit l’aperçu du constructeur se trouvait
à l’intérieur d’une seule ligne d’une chaîne JS, et la déclaration de police de 33 lignes y a été insérée telle quelle.
Dès que la ligne s’est brisée, la chaîne a été coupée et tout le script du constructeur est mort avant même d’être lu.
Comme c’est le genre de panne qui tue le fichier entier, cela ne ressemble pas à « certaines fonctions sont étranges » mais à un constructeur qui ne fait rien du tout.
Les versions 2.7.5 et antérieures n’ont pas ce problème.
Comment nous l’avons corrigé
Nous avons gardé les définitions de police à cet unique endroit, fonts.php, et ce n’est qu’au moment de les insérer dans le constructeur que la sortie est repliée sur une seule ligne et que les guillemets sont traités.
Il n’y a toujours qu’un seul endroit où modifier les polices.
Police par défaut désormais basée sur le japonais
Jusqu’ici la police par défaut était basée sur le coréen. Nos principaux utilisateurs sont au Japon, pourtant les écrans paraissaient étranges,
et changer de langue ne changeait pas la police, si bien que des phrases japonaises s’affichaient dans une police coréenne.
- •Les valeurs par défaut sont maintenant Mincho pour les titres et Pretendard JP pour le texte.
- •Sur l’écran des réglages de langue, on peut définir une police séparément pour chaque langue. Sans réglage, la langue reçoit une valeur par défaut adaptée.
- •La même règle s’applique à tous les écrans d’administration, de membre et de la partie publique, ainsi qu’à tous les thèmes (default, modern, minimal, shop).
Avis de renouvellement de contrat et de fin de gratuité
Il arrivait que l’on ne s’aperçoive de l’expiration d’un contrat qu’une fois celle-ci passée. Désormais, on est prévenu à l’avance quand la date de renouvellement approche.
- •Les renouvellements à venir et la fin de la période gratuite s’affichent en notification avant que la date n’arrive.
- •Cela fonctionne avec une seule ligne de cron (
cron.d-voscms-contract-notice), et le guide d’installation explique comment l’enregistrer.
Paiement par carte
Les paiements ayant franchi l’authentification des émetteurs de cartes japonais (3-D Secure) réussissaient l’authentification mais voyaient le débit refusé.
- •PAY.jp bloque l’utilisation d’un jeton créé pour l’authentification s’il est laissé tel quel. Une fois l’authentification passée, le serveur doit faire un appel de finalisation,
c’est seulement alors qu’il peut servir à un débit, et cette étape manquait.
- •Nous avons aussi ouvert un moyen de vérifier au préalable que les informations du client existent toujours chez le prestataire de paiement — cela évite les échecs dus à des tentatives de débit sur un client supprimé.
Cloche de notification et règlement de remboursement dans toutes les langues
- •Dans la cloche de notification de l’en-tête, des textes comme « Aucune notification » et « il y a quelques minutes » qui étaient figés en coréen changent désormais selon la langue.
- •Nous avons nettoyé les formulations fixes qui subsistaient dans le texte du règlement de remboursement.
Comptabilité
Des transactions en wons se mêlaient aux livres de la société japonaise, et les totaux ne tombaient pas juste.
- •Les pièces dans une autre devise que la devise des livres (le yen) ne génèrent pas d’écritures. L’enregistrement est conservé mais n’entre pas dans les livres.
Nettoyage de la distribution
- •Des fichiers de sauvegarde créés pendant l’édition partaient avec la distribution (noms du type
nom.php.bak.nombre).
La règle d’exclusion ne filtrait que .bak et laissait passer les noms suivis d’un nombre. Nous bloquons maintenant aussi .bak., .orig et *~.
- •Les documents commerciaux du service THEVOS AI (grille tarifaire, calcul des forfaits, cron de rapprochement des paiements) ont été retirés de la distribution.
Tout ce qui les lit avait déjà été retiré, ce qui en faisait des fichiers que personne n’utilisait dans la distribution.
« Migration de la base de données requise »
039_ai_knowledge_base crée les tables de l’IA de consultation des boutiques NaitoWork X,
et pourtant elle partait telle quelle dans la distribution. De plus, la dernière ligne de ce fichier était
ALTER TABLE rzx_shop_inquiries ADD COLUMN IF NOT EXISTS ai_meta ...
rzx_shop_inquiries est une table créée par le plugin vos-store.
La distribution ne contient pas vos-store — le noyau cherchait à modifier la table d’un plugin qui n’existe pas.
Ainsi, à chaque nouvelle installation : 4 tables sont créées puis cela échoue sur la dernière ligne → comme on n’allait pas jusqu’au bout,
ce n’est pas enregistré comme « appliqué » → la bannière reste affichée en permanence, et un clic échoue de nouveau au même endroit.
Nous avons retiré entièrement la consultation IA (RAG) de la distribution :
039 · rzxlib/Core/AI/{Knowledge,Embedding,Generate} ·
scripts/{ai-kb-ingest,ai-rag-test,cron-ai-consult,hanesbot-ingest}.php
La traduction IA (rzxlib/Core/AI/Translation) est conservée. C’est le moteur du plugin payant vos-ai
et il suit la même règle que la comptabilité et l’hébergement : « le moteur reste dans le noyau, et le plugin ouvre la fonctionnalité ».
« 1 plugin n’est pas authentifié (vos
Le noyau détient une liste des « plugins fournis qui fonctionnent sans licence », et cette liste était périmée.
Ce que le code connaissait comme fourni | vos-autoinstall · vos-marketplace |
Ce qui est réellement fourni | vos-autoinstall · vos-community |
vos-marketplace est sorti de la distribution et vos-community a pris sa place,
mais seule cette liste n’a pas été corrigée. Nous l’avions fourni, puis affiché un avertissement parce que nous ne savions pas qu’il était fourni.
Pour que cela ne se reproduise pas
La cause est que la liste des plugins fournis est écrite à deux endroits —
la liste d’exclusion du script de build et LicenseStatus::BUNDLE_PLUGINS.
Nous avons ajouté au build une étape de recoupement. Si les deux divergent, aucun zip n’est créé et le build s’arrête.
Ce n’est pas quelque chose que les gens doivent retenir.
Le bouton d’écriture n’apparaissait pas dans les forums
Dans Q&A et FAQ, même les personnes autorisées à écrire n’avaient pas de bouton. Il y avait deux causes.
- •Les administrateurs étaient bloqués — pour vérifier le droit d’écriture, on demandait d’abord s’il s’agissait d’un membre et on ne regardait les administrateurs qu’ensuite.
Les administrateurs ne figurent pas dans users et se faisaient donc arrêter au premier barrage. Nous avons inversé l’ordre pour laisser passer les administrateurs en premier.
- •Sans aucun message, le bouton disparaissait aussi — le bouton se trouvait à l’intérieur de la liste,
et en passant à l’affichage « aucun message », il disparaissait avec elle. La première personne qui voulait écrire ne le pouvait pas.
Nous avons sorti le bouton de la liste.
- •FAQ regardait même directement
admin_id — en ignorant le droit d’écriture des réglages du forum.
Les titres et sous
Un écran en coréen où seul le sous-titre apparaissait en japonais.
- •Les traductions n’étaient pas du tout lues. Le titre et le sous-titre sont enregistrés dans les réglages du thème sous forme d’une seule chaîne,
alors que les traductions se trouvent à part dans rzx_translations. L’écran affichait simplement la chaîne enregistrée.
- •Il n’y avait aucune distinction entre forums. La clé de traduction était
skin_config.subtitle_text, si bien que Q&A et FAQ
partageaient le même emplacement. Modifier l’un changeait l’autre.
Nous l’avons séparée en board.{numéro du forum}.{élément}.
- •Le corps était dessiné avant que la langue soit fixée. Le noyau produit d’abord le corps et ajoute l’en-tête ensuite,
mais la langue était déterminée dans l’en-tête. Nous avons déplacé cette décision du côté du corps pour qu’elle ait lieu en premier.
Les migrations du noyau manquaient à l’installation
install-core.php ne regardait pas du tout database/migrations.
Sur un site fraîchement installé, quelques tables manquaient dès le départ, et cela plantait plus tard, lorsque la fonctionnalité était activée.
Migrations ignorées en silence (suite de 2.7.4)
La version 2.7.4 avait traité les commentaires sur une ligne (--), mais les commentaires sur plusieurs lignes (/ /) subsistaient.
Le point-virgule situé dans un tel bloc réunissait le fichier en un seul morceau, de sorte que pas une seule ligne n’était exécutée
tout en étant enregistré comme « appliqué ». Nous avons constaté des dégâts réels — une installation avait perdu 9 tables en entier.
Un -- ou un /* à l’intérieur d’une chaîne n’est pas un commentaire. Nous supprimons les commentaires en comptant les guillemets.
Autres
- •En-tête de la boutique — nous avons ajouté « Toutes les catégories » tout en haut du menu déroulant des catégories.
Ceux qui voulaient entrer pour parcourir n’avaient nulle part où aller.
- •Constructeur de widgets — l’édition des éléments répétés (
repeater) a été séparée dans un fichier à part.
- •Barre latérale de l’intranet — le libellé de comptabilité est maintenant recherché dans les trois variantes (salon, boutique en ligne, entreprise générale).
En n’en regardant qu’une, le menu affichait la clé brute dès qu’une autre comptabilité était utilisée.
- •Ma page — nettoyage du tableau de bord.
- •Rapport des plugins payants — la vérification de licence envoie aussi les plugins payants activés.
Ceux qui sont seulement installés sans être activés ne sont pas envoyés — l’argent ne s’attache qu’à ceux qui sont activés.
Des pages réservées au siège partaient dans la version distribuée
config/system-pages.php était entré tel quel dans la version distribuée, si bien que les « Pages système » de l’administration de l’installation d’un client
comptaient six menus sur lesquels on peut cliquer mais derrière lesquels il n’y a rien.
📥 downloads | Téléchargements de la version distribuée — seul le siège les distribue |
📋 changelog | C’est l’historique du produit du siège |
📧 contact | Les clients le construisent eux-mêmes avec un widget (ce n’est pas une page système) |
💼 recruit · 💃 casts | Uniquement pour le portail des métiers de la nuit (NaitoWork X) |
🎟 coupons | Le plugin de la place de marché le fournit |
- •L’étape de build
[4e/8] a été ajoutée (strip-system-pages.php). Après la suppression, la syntaxe est vérifiée avec php -l —
si ce fichier est cassé, tout l’écran d’administration tombe.
- •Les pages système qui restent dans la version distribuée sont au nombre de huit : home · terms · privacy · data-policy ·
refund-policy · hosting-terms · tokushoho · funds-settlement
Pages système des plugins
- •Le texte
site.pages.blog a été ajouté dans 13 langues.
Même si un plugin enregistre une page système, si le cœur n’a pas de texte pour elle, site.pages.blog s’affiche tel quel à l’écran.
- •(La correction du
plugin.json propre à vos-blog passe par la place de marché — c’est un plugin qui ne fait pas partie de la version distribuée)
Sites déjà installés
Si les « Pages système » de l’administration montrent un élément que vous n’utilisez pas, supprimez le bloc correspondant de config/system-pages.php.
Le contenu des pages (rzx_page_contents) n’est pas supprimé — il disparaît seulement de la liste.
① Les migrations commençant par un commentaire étaient ignorées entièrement
- •Un commentaire de
DatabaseMigrator::splitSql() disait « découper après suppression des commentaires », mais
en réalité il ne découpait que sur les points-virgules.
- •Si la première ligne d’un fichier SQL est
-- description, le fichier entier devient un seul fragment,
qui est arrêté par str_starts_with($stmt, '--') dans la partie d’exécution, et aucune instruction n’est exécutée.
- •Quand 0 instruction est exécutée, il y a aussi 0 erreur ; c’est donc traité comme
success et enregistré comme appliqué.
Une fois enregistré, il ne s’exécute plus jamais, si bien que la table reste absente pour de bon.
- •Les dégâts concernaient tous les fichiers commençant par
--. Mesuré : sur 9 fichiers, 6 n’ont exécuté aucune instruction et 2 une partie seulement.
- •Il supprime maintenant les commentaires de ligne
-- et # ainsi que les blocs / / avant de découper.
Un -- à l’intérieur d’une chaîne n’est pas touché (si une valeur comme 'a -- b' était coupée, les données seraient corrompues).
② Une nouvelle installation n’exécutait pas du tout les migrations incrémentales
- •Le script d’installation n’exécutait que
migrations/core et migrations/migrations
et oubliait le niveau supérieur database/migrations/*.sql. Le programme de mise à jour, lui, ne suit que le niveau supérieur.
- •Résultat : à l’installation neuve, 034 à 042 étaient absentes dès le départ et restaient vides jusqu’à la version suivante.
- •À l’installation, il exécute désormais aussi le niveau supérieur et l’enregistre comme appliqué (pour que la première mise à jour n’exécute pas les mêmes une seconde fois).
Sites déjà installés
Veuillez cliquer une fois sur Exécuter les migrations dans Admin → Paramètres → Mise à jour.
Les entrées enregistrées à tort ne s’exécuteront pas de nouveau ; si une table est vide, vous pouvez le vérifier ainsi.
SELECT migration FROM rzx_migrations; -- enregistré
SHOW TABLES LIKE 'rzx_home_notices'; -- réel
Ce qui a été retiré de la version distribuée
- •
vos-cp (panneau de contrôle des services) et vos-shopping (boutique en ligne) voyageaient dans la version distribuée.
Ce sont deux plugins récemment créés qui ne figuraient simplement pas sur la liste d’exclusion.
- •
vos-cp est un panneau pour les services propres de THEVOS. Il n’a aucune raison d’être dans l’installation d’un client
- •
vos-shopping est encore en développement (v0.1.0), et la règle veut que les plugins s’achètent sur la place de marché
- •
vos-review a lui aussi été retiré — pour la même raison (instruction du propriétaire).
- •Seuls deux plugins entrent dans la version distribuée :
vos-community et vos-autoinstall.
Tout le reste s’obtient sur la place de marché.
Ce qui a été ajouté au cœur
- •Un en-tête de boutique à deux niveaux (
skins/layouts/shop) — un menu déroulant de toutes les catégories, la recherche, un aperçu du panier et
un menu d’avatar après la connexion. Tout en haut du menu déroulant des catégories, nous avons placé « Toutes les catégories » pour offrir un chemin de retour
- •Points acquis, avoir et niveau de membre affichés dans « Mon espace ». Les noms reprennent les valeurs que vous avez définies
- •Prise en charge des widgets de plugin — si un plugin dispose d’un dossier
widgets/, le constructeur du cœur le reconnaît automatiquement
- •Un composant partagé de recherche d’adresse par code postal — le formulaire de commande et les informations du membre utilisent le même
- •Une cloche de notification dans la barre supérieure de l’administration
- •Remise en ordre des groupes de menus de la console d’administration (
config/intranet-modules.php)
- •Prise en charge des champs répétables (repeater) du constructeur de widgets
Ce qui a été corrigé
- •Le problème où les champs de saisie multilingues écrasaient les données d’origine
- •Un bug dans l’enregistrement du registre des avoirs
- •Le problème où la mise à jour de la version distribuée transformait des pages d’hébergement en 404
Ce qu’il faut vérifier sur les installations existantes
Sur les sites installés avec une ancienne version distribuée et qui n’ont reçu que des mises à jour, les dossiers des plugins inutilisés subsistent
(une mise à jour ne supprime pas les dossiers de plugins). Tout ce qui apparaît comme non installé sous Admin → Plugins
peut être supprimé de plugins/ avec son dossier.
Changed
- •Routage unifié des URL de demande de service —
/service/hosting, /service/mail et /service/domain → vers /service/order en 302 (en attendant que des pages de demande dédiées soient prêtes, les visiteurs sont orientés vers la page de demande intégrée, et elles pourront être remplacées plus tard par des pages dédiées).
Notes
- •Les corrections du cœur de la 2.7.1 (hreflang multilingue, prévention des échecs silencieux du programme de mise à jour, fusion des tarifs
/pricing dans /service/order) étaient déjà correctement incluses dans le paquet de la 2.7.1. La 2.7.2 est une reconstruction qui y ajoute la remise en ordre du routage des demandes de service.
- •La version distribuée n’inclut en principe que le cœur pur (plugins payants et verticaux exclus). Les sites du siège (voscms.com et thevos.jp) ne sont pas concernés par l’auto-mise à jour de la version distribuée ; ils sont déployés depuis les sources/git.
SEO
- •hreflang multilingue — un canonical auto-référent par page + hreflang automatique pour les langues prises en charge, indexation par langue avec
?lang=xx, normalisation en 301 du ?lang de la langue par défaut vers l’URL simple et sitemap étendu.
Fixed
- •Échecs silencieux du programme de mise à jour corrigés — les échecs d’écriture des fichiers du cœur ou de version.json sont maintenant traités comme des exceptions. Quand l’application échoue pour cause de permissions insuffisantes ou autre, on obtient désormais une erreur explicite et un retour arrière automatique au lieu d’un faux « SUCCESS ».
- •Protection contre le plantage en 500 de la page des tarifs où un champ multilingue était transmis à htmlspecialchars sous forme de tableau.
Changed
- •Extension de l’interrupteur reCAPTCHA v3 par formulaire (blog_comment et autres).
- •L’onglet « Notifications de la console du propriétaire » des paramètres n’apparaît que lorsque vos-store est actif.
- •La page des tarifs
/pricing a été fusionnée dans /service/order (301), et l’offre « Système illimité » est réservée aux administrateurs.
Contenu de la version distribuée
- •La version distribuée est réduite à un cœur pur — seuls 3 plugins du cœur (
vos-autoinstall, vos-community, vos-review) sont inclus. Les plugins verticaux (métiers de la nuit / salon / POS), les widgets et le thème (story) sont tous exclus. Les fonctions générales comme la vérification de l’âge et la bannière de cookies font partie du cœur (rzxlib) et sont donc incluses.
Added/Changed (widgets du cœur)
- •location-map — prend en charge l’intégration sans clé (
map_embed), supprimant la dépendance à une clé d’API, et relie la langue de la carte à la locale
- •practice-tabs (onglets des domaines d’activité) — un nouveau widget inclus
- •Réglage global de la largeur des pages (
widget_page_width) — uniformise la largeur des pages de widgets/documents
Les widgets propres à un site qui ne sont pas inclus (bundled:false) (hero-slideshow, overlap-cards, office-intro, page-hero, content-head, consult-cta, board-grid, clients-logos, le thème de profil du forum) ne figurent pas dans la version distribuée du cœur.
Removed
- •Les widgets prépayés (
prepaid-charge, prepaid-pass, prepaid-purchase) — exclus de la distribution car vos-prepaid n’est pas inclus
Added (paramètres et cœur)
- •Le portail de vérification de l’âge a été promu en paramètre général du cœur
- •Réglage de l’opacité de l’arrière-plan de la bannière de consentement aux cookies
- •Images de logo par langue
- •Des coordonnées bancaires dans les informations de l’entreprise + un avis sur le virement bancaire
- •Un avis sur les « Cartes acceptées » sur l’écran de paiement (icônes des marques) + paramètre de l’admin
Fixed
- •Localisation des titres et sous-titres de pages dans la langue du visiteur (page-scoped db_trans), et correction de content_width qui n’était pas appliqué
- •De nombreuses corrections de bugs dans les widgets/l’administration/les pages et des ajouts dans 13 langues
Added
- •Nettoyage automatique des fichiers obsolètes — une mise à jour qui écrase avec le zip du paquet complet ne peut pas supprimer les fichiers retirés de la source, si bien que des restes (orphelins) subsistaient dans les versions installées (par exemple, le
settings.php monolithique, scindé et supprimé lors d’une refonte, restait dans les anciennes installations). Nous avons ajouté un mécanisme à liste explicite pour les nettoyer.
- •
config/obsolete-files.php — une liste cumulative des chemins à supprimer (les installations qui ont sauté plusieurs versions sont nettoyées en une seule fois).
- •Juste après
applyUpdate() du programme de mise à jour, cleanupObsoleteFiles() exécute un unlink sûr des fichiers de la liste. Il ne touche jamais aux cibles protégées (.env, storage, etc.), aux échappements de chemin ni aux répertoires.
- •Premier enregistrement :
resources/views/admin/settings.php.
Fixed
- •Le lien « Paramètres système » du tableau de bord — le lien des actions rapides pointait vers l’ancien chemin
/settings, séparé puis supprimé, et menait donc à une mauvaise page (de repli). Corrigé vers le point d’entrée des paramètres /settings/general. (Oubli après le build de 2.6.22.)
Fixed
- •La bannière « Migration de la base de données requise » du tableau de bord — CSRF token invalid — le bouton de nouvelle tentative n’envoyait pas de jeton CSRF à
/update-api.php (run_migrations) et était donc rejeté avec un 419. Il garantit maintenant $_SESSION['csrf_token'] et l’envoie à la fois dans l’en-tête et dans le corps.
- •La bannière ne disparaissait pas même après l’exécution des migrations —
DatabaseMigrator::recordMigration supposait une colonne batch et le préfixe patch_, si bien que sur le schéma de type installé (migration/version/executed_at) l’INSERT d’enregistrement échouait et que le préfixe faussait aussi la correspondance des noms de fichiers. Corrigé pour enregistrer le nom de fichier tel quel, en accord avec les colonnes réelles. (C’était la cause du fait que, lors de la mise à jour vers 2.6.20, les migrations ne laissaient qu’un journal « OK » sans être appliquées.)
Fixed
- •Clés brutes dans la barre latérale des pages du cœur comme la gestion des permissions de l’admin — comme la mise en page de l’intranet était activée à partir des seuls route_prefixes de
config/intranet-modules.php, la page du cœur /staff/admins d’un site sans le plugin correspondant (par exemple sans vos-salon installé) s’affichait avec la barre latérale de l’intranet salon, et les clés salon.intranet. et salon.section. apparaissaient en texte brut. Corrigé.
- •Ajout d’une fonction d’aide partagée
resolve_intranet_module() — l’intranet n’est activé que si les ressources lang du module (le plugin) sont réellement installées ; sinon, repli sur la barre latérale admin-sidebar du cœur.
- •La logique de détection dupliquée dans
_head.php / admin-sidebar.php a été unifiée dans la fonction d’aide. Le comportement reste inchangé sur les sites où le plugin est installé (salon, store, etc.).
Fixed
- •Erreur d’enregistrement des niveaux de points — correction de l’échec avec l’erreur
Unknown column 'group_id' lors de l’enregistrement d’un niveau dans le module de points de l’admin. La cause était un conflit de schéma de point_levels/member_points entre core/004 et migrations/019(v190) (le CREATE TABLE IF NOT EXISTS de 019 ne pouvait pas ajouter les nouvelles colonnes à une table existante).
- •migration
034_point_system_schema_reconcile (niveau supérieur, appliquée automatiquement à la mise à jour) :
- •
point_levels — ajout de group_id, valeur par défaut pour name et index unique sur level (pour que l’upsert fonctionne).
- •
member_points — ajout de point/balance/total_accumulated/level.
- •Tout est additif (aucune perte de données), sans effet sur les colonnes existantes ni sur les consommateurs (comme vos-prepaid).
Added
- •3 widgets d’achat — un intégré (
prepaid-purchase, affichage au choix : tout / recharge seulement / cartes multi-usages seulement) + un réservé aux recharges (prepaid-charge) + un réservé aux cartes multi-usages (prepaid-pass). Un seul composant partagé purchase-widget.php fait fonctionner les 3 widgets (zéro duplication), avec une bifurcation par le filtre $ppOnly.
- •Image d’arrière-plan des produits — envoi par glisser-déposer (ou par clic) dans la fenêtre d’ajout/modification de produit de l’admin, avec l’arrière-plan appliqué à « Mon espace » et aux cartes des widgets. Migration 003
image_url.
- •Saisie multilingue du nom de produit + traduction par IA — réutilise le
multilang-modal partagé (bouton globe), enregistré sur la base de rzx_translations et affiché dans la langue du visiteur avec prepaid_name(). La traduction par IA réutilise le point d’accès du cœur /api/translations.
- •Un champ de saisie du nom du titulaire de la carte a été ajouté au formulaire de paiement (transmis à
createToken de PAY.jp).
- •Sélection du client pour une recharge manuelle — passage de la saisie directe d’un user_id à une recherche avec saisie semi-automatique par nom/téléphone/e-mail (action
customer_search). La liste de la situation des clients affiche aussi le nom + l’e-mail du client au lieu d’un hachage de user_id.
- •Bascule d’activation — la case « produit actif » a été remplacée par un interrupteur.
Changed
- •Boîte d’achat sur 4 colonnes — la grille des cartes de produits est adaptative 2→3→4 (
lg:grid-cols-4), et la largeur fixe max-w-3xl du widget a été supprimée → elle s’adapte à la largeur du conteneur de placement.
Fixed
- •Hauteur de la palette et du méga-menu du constructeur de widgets — la hauteur des lignes du constructeur est fixée à
calc(100vh - 88px), de sorte que les catégories de gauche et le menu déroulant occupent automatiquement toute la hauteur de l’écran et que le chevauchement des éléments du méga-menu est résolu.
Added
- •Validation de link dans
api/broadcast.php — si le schéma est absent, https:// est ajouté automatiquement au début (example.com → https://example.com) ; si la valeur ne passe pas filter_var FILTER_VALIDATE_URL, une réponse 400 avec l’erreur field: 'link' est renvoyée ; au-delà de 500 caractères, elle est refusée.
- •Validation en temps réel côté client —
type="url", inputmode="url", et dès la saisie :
- •Schéma absent → contour emerald + ✓ + indication « Ajouté automatiquement à l’envoi : … »
- •Pas de point (.) dans l’hôte ou format incorrect → contour red + ⚠ + « Ce n’est pas un format d’URL valide »
- •Valide → contour emerald + ✓ + « Il s’agit d’une URL valide »
- •Le client complète aussi avant l’envoi → l’aperçu et le corps réellement envoyé sont garantis identiques.
Added
- •En-têtes de section : ✉ Rédiger le message / 📡 Canaux d’envoi — regroupement visuel + texte explicatif.
- •Compteurs de caractères (titre
0/255, corps 0/2000) — couleurs automatiques : amber à partir de 70 %, red à partir de 90 %.
- •Encadré d’aperçu du message (bordure pointillée) — affiche en temps réel l’aspect du titre, du corps et du lien combinés dans LINE + un compteur du total de caractères
n/5000 (red au-delà de 4500).
- •Texte d’aide pour chaque champ :
- •Titre : « S’affiche à la fois dans la boîte de messages du membre et dans la notification LINE »
- •Corps : « Si vous écrivez une URL dans le corps, elle est raccourcie et le suivi des clics est activé automatiquement »
- •Lien : « Ajouté automatiquement à la fin du corps après une ligne vide. Si vous l’écrivez aussi dans le corps, il apparaîtra deux fois, attention »
- •Icône d’état à droite du champ du lien (
absolute) — ✓ / ⚠ s’affichent immédiatement.
Added
🔗 Règles de validation des URL (nouvelle 5e section) :
- •Doit commencer par
http:// / https:// → converti en jeton de suivi des clics
- •Un schéma absent est complété automatiquement
- •Les hôtes sans point ou au format incorrect sont refusés
- •Limite de 500 caractères
- •Encadré d’exemple :
✓ https://voscms.com/event / ✓ example.com/page → complété automatiquement / ✗ asdfasdf (pas de point dans l’hôte)
Notes
- •La production (
voscms-com) et salon sont synchronisés. L’API, l’interface et l’i18n prennent effet immédiatement.
- •i18n en 13 langues :
community.broadcast.guide_url_, section_message, section_channels*, subject_hint, body_hint, link_hint, link_{invalid,autofixed,valid}, preview_{title,empty}.
Added
- •Changement de mise en page de
/theadmin/community/broadcast — l’ancienne carte unique est divisée en lg:grid-cols-3. Le formulaire d’envoi principal occupe les 2 colonnes de gauche (lg:col-span-2), et un nouvel encadré d’aide occupe la colonne de droite (<aside>, sticky top-4).
- •Contenu de l’aide en 6 sections :
1. 📅 Qu’est-ce que l’envoi programmé ? — envoi automatique à une heure future, utilisable la nuit, le week-end et pour des événements
2. 🛠 Comment l’utiliser — 4 étapes (choisir la cible → cocher LINE → cocher la programmation → envoyer), interface avec pastilles numérotées
3. ⏱ Précision de l’envoi — explication de l’intervalle de 5 minutes du cron + un encadré d’exemple (10:00 → 10:00 à 10:05)
4. 🆚 Immédiat ou programmé — la différence de comportement entre les deux modes sous forme de cartes
5. 📋 Vérifier la file d’attente — un bouton raccourci vers /history?status=queued
6. ⚠ Précautions — au moins 30 secondes dans le futur, la programmation n’est pas possible dans l’appli/push, ne fonctionne pas sur un hébergement sans cron, l’annulation depuis l’interface n’est pas prise en charge
- •Fond en dégradé indigo (
from-indigo-50 to-blue-50) — l’encadré d’aide se distingue visuellement de la carte principale tout en s’y fondant en douceur.
- •i18n en 13 langues — environ 20 clés
community.broadcast.guide_* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
Added
- •Ajout d’une carte « Langue préférée » dans
/mypage/settings — un select de 14 options (automatique / 13 langues). À l’enregistrement, il met à jour (UPDATE) rzx_users.locale et applique immédiatement $_SESSION['locale'].
- •Hook de Auth::loginUser — à la connexion, si
$user['locale'] existe et que la locale de session est vide, il la renseigne automatiquement. Si l’utilisateur l’a modifiée manuellement pendant la session, cette valeur est conservée en priorité.
- •i18n en 13 langues —
auth.settings.language.{title,description,label,auto,hint,save,success,error_invalid,error_save} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
- •Après le changement, l’interface s’affiche dans la langue du membre dès la page suivante, et si un administrateur a défini
messages_by_locale sur une règle d’envoi automatique, le corps correspondant est envoyé à ce membre par LINE.
Added
3 nouvelles cartes en haut de /theadmin/community/broadcast/history (après les 4 cartes existantes) :
1. Taux de clic global (CTR) — SUM(rzx_broadcast_clicks.click_count) / SUM(rzx_line_broadcasts.recipient_count WHERE status='sent') × 100. Grand texte en emerald.
2. Test A/B (30 derniers jours) — pour les envois avec variant IS NOT NULL, destinataires, clics et CTR par variant. Le variant au CTR le plus élevé est mis en évidence en emerald.
3. Répartition par locale (30 derniers jours) — uniquement pour les envois avec source='auto_rule' AND messages_by_locale IS NOT NULL, la locale est mise en correspondance en comparant les clés du JSON messages_by_locale de la règle avec les 30 premiers caractères du corps du broadcast → destinataires/clics/CTR par locale. Trié avec ksort.
- •i18n en 13 langues :
community.broadcast.stat_{ctr_title,ctr_breakdown,variant_title,variant_hint,locale_title,locale_hint,empty}.
Notes
- •Les arborescences
voscms-com et salon sont synchronisées. Il n’y a aucune nouvelle colonne en base (elles étaient déjà toutes incluses dans les migrations 008/009/010 de l’étape 4).
- •La logique de correspondance de locale compare les 30 premiers caractères du corps — si le corps correspond après la substitution des variables, il est compté dans le même groupe de locale. Si le corps est trop court ou entièrement rempli par la substitution des variables, le taux de correspondance peut baisser (on pourrait à l’avenir ajouter directement une colonne locale à la ligne du broadcast).
Added
- •migration 010 —
rzx_auto_broadcast_rules.messages_by_locale JSON NULL + rzx_users.locale VARCHAR(10) NULL + un index idx_locale.
- •AutoBroadcaster::lineUserIdsWithLocale — recherche des paires userId LINE et locale du membre. Les environnements sans la colonne
users.locale se replient sur lineUserIds.
- •AutoBroadcaster::pickLocaleMessage — priorité : la user.locale du membre → la locale par défaut du site (rzx_settings.locale) → la première clé du JSON (si tout échoue, null → repli sur le corps A).
- •AutoBroadcaster::fire — si
messages_by_locale existe, il utilise le corps correspondant à la locale de chaque membre ; sinon le variant A/B ; et à défaut, le A unique. Quand la locale, le variant et le défaut donnent le même corps, ils sont envoyés comme un seul groupe par multicast (efficacité).
- •Fenêtre modale des règles de l’admin — « Routage multilingue activé » et une saisie directe du JSON, dépliables via
<details>. Affiché en pretty-print. Validation invalid_locale_json.
- •i18n en 13 langues —
community.automation.locale_{toggle,placeholder,hint} + fields.messages_by_locale + error.invalid_locale_json (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
Notes
- •Les étapes 1 à 4 de l’infrastructure d’envoi LINE sont terminées (2.6.9 à 2.6.15) :
1. Step 1 — CTA · utility stack · envoi manuel · audience par niveau · sélection multiple (7872c4b, 7c94a55, c4a3325)
2. Step 2 — Classement automatique des groupes de membres (b24979c)
3. Step 3 — Règles d’envoi automatique basées sur les événements (60d47cd) + cron d’envoi programmé (8cf02ad)
4. Step 4 — Suivi des clics (79c99a84) + test A/B (86e19b0b) + routage multilingue (celui-ci)
- •La migration 010 a été appliquée en production (
voscms.com). users.locale est une nouvelle colonne — tous les membres existants sont NULL (la locale par défaut du site est utilisée → même comportement qu’avant).
- •Une interface « Mon espace » où les membres définissent eux-mêmes leur locale préférée est le prochain jalon.
- •Enregistrements cron recommandés :
/5 /usr/bin/php8.3 /var/www/voscms-com/scripts/process-scheduled-broadcasts.php, 0 3 /usr/bin/php8.3 /var/www/voscms-com/scripts/recalculate-member-grades.php.
v2.6.14
2026-05-30 · il y a 5 mois
Test A/B (Step 4-B)
Added
- •migration 009 —
rzx_auto_broadcast_rules.message_template_b TEXT NULL, rzx_line_broadcasts.variant CHAR(1) NULL, rzx_broadcast_clicks.variant CHAR(1) NULL + un index (source_rule_id, variant).
- •AutoBroadcaster::fire — si
message_template_b n’est pas vide, les userIds LINE sont répartis 50:50 en A/B par crc32 mod 2. Pour chaque variant, l’historique d’envoi est inséré au préalable (INSERT, logQueued) → wrap du jeton → multicast → finalize. Le même utilisateur reçoit toujours le même variant lors d’envois répétés (cohérence du hachage).
- •Fenêtre modale des règles de l’admin — l’option « Test A/B activé » et la saisie du variant B, dépliables via
<details>. L’envoi unique simple est le choix par défaut, et l’A/B est un opt-in explicite.
- •ClickTracker — propage les métadonnées du variant. Si la colonne broadcast_clicks.variant existe, elle est renseignée à l’INSERT. Sinon, un repli s’applique (compatible avec les environnements où la migration 009 n’a pas été appliquée).
- •Repli de logQueued — fonctionne aussi dans les environnements sans la colonne variant (lorsque la migration 009 n’a pas été appliquée).
- •i18n en 13 langues —
community.automation.ab_{toggle,placeholder,hint} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
Notes
- •Les 3 instructions ALTER de la migration 009 ont été exécutées séparément en production (
voscms.com). Les règles existantes ont message_template_b=NULL (le comportement d’envoi unique est conservé).
- •Modifier une règle → saisir le variant B dans la zone dépliable « Test A/B activé » → il suffit d’enregistrer, et dès la prochaine occurrence la répartition A/B se fait automatiquement.
Added
- •migration 008 (
rzx_broadcast_clicks) — token (8 caractères base62, UNIQUE), broadcast_id, source_rule_id, original_url (2048), click_count, last_clicked_at, last_user_agent. La même combinaison (broadcast_id, original_url) réutilise le jeton.
- •Classe
ClickTracker — wrap($pdo, $siteId, $body, $meta) extrait les URL http/https du corps par expression régulière → INSERT ou réutilisation → les remplace par /t/{token}. consume($pdo, $token, $ua) transforme un jeton en URL d’origine et incrémente click_count.
- •Route
/t/{token} (index.php:330) — entrée dans le routeur à expressions régulières. ClickTracker::consume → redirection 302 vers l’URL d’origine, ou 404 s’il n’y en a pas. Validation du jeton d’URL ([A-Za-z0-9]{4,16}).
- •Intégration aux règles d’envoi automatique —
AutoBroadcaster::fire() fonctionne, juste avant l’envoi, dans l’ordre logQueued → obtention de broadcast_id → ClickTracker::wrap → multicast → finalizeBroadcast. Le lien entre le jeton et broadcast_id est garanti.
- •Intégration à l’envoi manuel — dans
api/broadcast.php, wrap juste après l’assemblage du texte de l’envoi immédiat. Dans scripts/process-scheduled-broadcasts.php, wrap juste avant l’envoi depuis la file (le broadcast_id est connu).
- •Réglage du domaine de suivi —
rzx_settings.click_track_domain est prioritaire, sinon APP_URL. Un domaine court (par exemple s.voscms.com) est possible.
Notes
- •La migration 008 a été appliquée en production (
voscms.com).
- •Test d’intégration de wrap/consume : 2 URL dans le corps → 2 jetons de 8 caractères insérés (INSERT) → à l’appel de consume, l’URL d’origine est renvoyée et click_count augmente correctement.
Added
- •migration 007 (
rzx_line_broadcasts) : les colonnes scheduled_at DATETIME NULL et processed_at DATETIME NULL plus un index (status, scheduled_at). scheduled_at NULL = envoi immédiat (comme avant), une heure future = mise en file.
- •
scripts/process-scheduled-broadcasts.php — le point d’entrée du cron. Il récupère 50 éléments avec status='queued' AND scheduled_at <= NOW() AND processed_at IS NULL → les verrouille aussitôt avec processed_at = NOW() (transaction) → résout l’audience (all / grade_N, comme broadcast.php) → multicast LineMessenger par lots de 500 → met à jour le statut avec le résultat. Fréquence cron recommandée : /5 *.
- •Interface de broadcast.php : une case
[Programmer l’envoi] + une saisie datetime-local. Une fois cochée, la valeur par défaut est l’heure actuelle + 1 heure (heure locale de l’utilisateur). Si elle n’est pas cochée ou est vide, l’envoi est immédiat comme avant. Seul le canal LINE peut être programmé (dans l’appli et push restent immédiats).
- •api/broadcast.php : traite le paramètre POST
scheduled_at. Pour une heure future (> NOW + 30s) avec send_line, il se contente d’insérer (INSERT) rzx_line_broadcasts (status='queued', scheduled_at) sans appeler l’API LINE, et renvoie scheduled: true, scheduled_at dans la réponse.
- •i18n en 13 langues :
community.broadcast.schedule_{label,enable,hint,success} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
Fixed
- •Les colonnes de l’INSERT ont été corrigées pour correspondre au schéma réel de
rzx_line_broadcasts (title, body, audience varchar(20), recipient_count, status enum(queued|sent|failed)). Auparavant, l’INSERT utilisait des noms de colonnes qui n’existent pas (message_text, recipients_count, sent_count, failed_count, audience_value, partial), et même le repli échouait, si bien que l’historique de l’envoi automatique manquait.
Notes
- •La migration 007 a été appliquée en production (
voscms.com). Un dry-run a confirmé que pickup valait 0 élément.
- •Les arborescences de la production (
voscms-com) et de salon sont synchronisées. .env exclu.
- •L’enregistrement du cron relève de l’exploitation de l’hébergement (si besoin,
/5 * /usr/bin/php8.3 /var/www/voscms-com/scripts/process-scheduled-broadcasts.php).
Added
- •Table des règles d’envoi automatique (
rzx_auto_broadcast_rules) — migration 005_auto_broadcast_rules.sql. Règles isolées par site_id, avec les colonnes trigger_type / trigger_filter (JSON) / audience (all|grade_X|custom) / message_template / is_enabled / fired_count / last_fired_at.
- •Répartiteur AutoBroadcaster (
rzxlib/Core/Notification/AutoBroadcaster.php) — point d’entrée statique AutoBroadcaster::fire($triggerType, $ctx). Correspondance avec les règles actives → substitution des variables du modèle ({{title}}, {{url}}, {{author}}, {{board_name}}, {{site_name}}) → résolution de l’audience (même logique que broadcast.php ; pour le niveau is_default, les membres NULL sont inclus automatiquement) → recherche des userIds LINE via rzx_user_social_accounts → multicast par lots de 500 → enregistrement de l’historique dans rzx_line_broadcasts → mise à jour des statistiques de la règle.
- •Hook d’envoi automatique pour les nouveaux messages du forum (api-posts.php:184) — juste après l’INSERT d’un message (hors messages privés), il appelle
AutoBroadcaster::fire('board_post', [post_id, board_id, title, url, author, board_name]). Même si l’envoi échoue, la réponse au message n’est pas affectée.
- •Page d’administration de gestion des règles (
/theadmin/community/automation) — interface en grille de cartes. CRUD des règles + bascule activé/désactivé + badge de couleur par déclencheur (board_post=blue, review_created=amber, reservation_created=green). Le déclencheur / le filtre (JSON) / le niveau cible / le modèle de message sont modifiés dans une fenêtre modale.
- •Colonnes de suivi de l’origine pour rzx_line_broadcasts — migration
006_line_broadcasts_add_source.sql. source ('manual' | 'auto_rule') + source_rule_id (INT) + un index. L’historique de l’envoi automatique se distingue de l’envoi manuel dans la même table.
- •Routes et migrations enregistrées dans plugin.json — la route
community/automation, et les migrations 004/005/006 indiquées après 003.
- •i18n en 13 langues — toutes les clés
community.automation.* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW). Libellés des déclencheurs, champs, indications, messages de réussite/d’erreur et modèles par défaut.
Notes
- •Les migrations 005/006 ont été appliquées en production (
voscms.com). Aucune règle n’est encore enregistrée.
- •Les arborescences de la production (
voscms-com) et de salon sont synchronisées. .env exclu.
- •Le Step 3-B (envoi programmé
scheduled_at + cron) est le prochain jalon.
Added
- •Attribution automatique du niveau par défaut à l’inscription (
rzxlib/Core/Auth/Auth.php::register()) — juste après l’inscription, le niveau avec is_default=1 est recherché dans rzx_member_grades et le grade_id du nouveau membre est renseigné immédiatement. Sur les sites sans table member_grades (anciens ou non configurés), il est ignoré silencieusement par try-catch. Les membres NULL existants sont renseignés par un script de recalcul ou un bouton distinct.
- •Script CLI de recalcul des niveaux (
scripts/recalculate-member-grades.php) — à partir de la somme des paiements de rzx_payments et du nombre de réservations de rzx_reservations (seulement si la table existe), il parcourt les niveaux dans l’ordre sort_order DESC et attribue le niveau le plus élevé que le membre peut satisfaire. Les niveaux sans règle définie (min_spent=0 AND min_reservations=0) sont ignorés automatiquement — seuls les niveaux ayant des règles explicites sont candidats à une promotion. Les membres qui ne remplissent pas les conditions retombent au niveau par défaut.
- •Options :
--dry-run (simulation sans UPDATE réel), --user-id=UUID (un membre précis seulement).
- •Exemple de cron :
0 3 * /usr/bin/php8.3 /var/www/voscms/scripts/recalculate-member-grades.php
- •Bouton admin « Recalculer maintenant » (
/theadmin/members/groups) — ajout d’un bouton de ton émeraude dans la barre d’actions. Au clic : fenêtre de confirmation → AJAX action=recalculate_grades → notification du résultat (cible/promu/rétrogradé/nouveau) → rechargement automatique. La même logique que le script étant incluse en ligne, cela fonctionne même dans les environnements sans permission PHP CLI.
- •i18n en 13 langues — nouvelles clés
members.groups.recalculate* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW) : recalculate, recalculate_hint, confirm_recalculate, recalculate_stat.{total,upgraded,downgraded,fallback}, success.recalculated, error.{no_grades,no_default_grade}.
Notes
- •En production (
voscms.com), vérification de --dry-run → exécution réelle → ré-exécution après ajout de règles. Les 5 membres avec grade_id NULL ont tous été correctement affectés à Normal (par défaut). VIP/Gold/Silver n’ont pas de règle et restent à 0 membre tant que des règles ne sont pas ajoutées (voulu).
- •Les arborescences de la production (
voscms-com) et de salon sont synchronisées. .env exclu.
Added
- •Composant CTA d’ajout d’ami LINE pour les membres (
resources/views/components/line-friend-cta.php) — 5 variants (card / button / bar / side-tab / bubble) × 6 positions (bottom-right/bottom-left/bottom-center/top-right/middle-right/middle-left) × 3 tailles, couleurs personnalisées, délai d’affichage et « se souvenir de la fermeture » pendant 24 heures (localStorage).
- •Interface de réglages modifiable — nouvelle section « CTA d’ajout d’ami LINE » en bas de la carte du canal LINE dans
/theadmin/settings/message-api. Basic ID, bouton d’activation, radio de variant, sélecteur de position, taille, sélecteur de couleur et saisie du delay.
- •Affichage automatique dans 5 mises en page — inclus automatiquement depuis
skins/layouts/{default,modern,minimal,modern-copy-260413}/footer.php. Il est ignoré automatiquement sur les pages de paiement, de demande de service et de parcours d’installation.
Added
- •Nouveau composant
resources/views/components/utility-floating-stack.php — le modèle de conception cameron_plugin de thevos.jp (un stack carré de 80×80 sur le bord droit + 1 px d’espacement + une couleur d’accent par icône). La position, la taille et la couleur sont réglables par l’exploitant.
- •Les deux modes coexistent —
utility_stack_mode = separate (par défaut, chaque CTA seul) / unified (PWA + LINE affichés ensemble en un stack). En mode intégré, l’affichage automatique des 5 variants du CTA LINE est désactivé, ainsi que les déclencheurs automatiques de la fenêtre d’installation PWA (bannière via setTimeout/DOMContentLoaded) ; la fenêtre ne s’ouvre que par un clic sur l’icône PWA du stack.
- •Extension naturelle à l’avenir — avec un modèle d’enregistrement d’éléments (canal Kakao, WhatsApp, abonnement à la newsletter, bascule du mode sombre, etc.), d’autres éléments peuvent rejoindre le stack simplement en ajoutant des clés de réglage.
- •Retour à la ligne automatique garanti — le CSS en ligne
word-break: break-all; overflow-wrap: anywhere; max-width: 72px contourne la limite de largeur des enfants flex de Tailwind. Les libellés CJK passent aussi naturellement à la ligne dans la boîte.
- •i18n en 13 langues — le groupe
line_cta. (22 clés) et le groupe utility_stack. (12 clés) dans resources/lang/{13 locale}/messaging.php. En japonais et en chinois, des espaces aux frontières de sens (par exemple « アプリとして インストール ») garantissent des points de retour à la ligne naturels.
Added
- •
LineMessenger::broadcast(messages) + broadcastText(text) — envoie en une fois à tous les amis (jusqu’à 5 objets de message ; le quota d’envoi de LINE est décompté du nombre de destinataires × le nombre de messages).
- •
LineMessenger::multicast(userIds[], messages) — envoie à un maximum de 500 userIds indiqués (infrastructure d’envoi par groupe).
- •Amélioration de l’interface
/theadmin/community/broadcast — ajout d’une case « Envoyer aussi aux amis LINE » (bannière verte). Indépendamment de l’envoi push, elle envoie automatiquement aux amis LINE par multicast/broadcast.
- •Envoi par niveau de membre —
rzx_member_grades est chargé dynamiquement et des options radio par niveau s’affichent automatiquement (pastille de couleur + slug + décompte en direct). Le format d’audience est grade_<id>.
- •Les membres avec
grade_id IS NULL sont automatiquement inclus dans le niveau is_default=1 — même sur les sites où aucun niveau n’est attribué automatiquement à l’inscription, les membres NULL sont naturellement inclus dans le décompte et l’envoi du niveau par défaut.
- •Table d’historique d’envoi
rzx_line_broadcasts — isolation par site_id, method (broadcast/multicast), audience, title/body, recipient_count, line_request_id, api_status/error, status. Une ligne est insérée automatiquement (INSERT) à l’envoi.
- •Pour
audience=all, broadcast ; sinon multicast, choisi automatiquement — collecte les userIds LINE des utilisateurs ciblés ayant user_social_accounts.line_friend=1 et envoie par lots de 500.
- •Largeur unifiée — dans broadcast.php,
max-w-3xl → max-w-7xl (comme les autres pages d’administration).
- •i18n en 13 langues — ajout des clés
send_line_label/desc et audience_grade_group.
Changed
- •
resources/views/admin/dashboard.php — le commentaire d’en-tête, le repli de pageTitle et la bannière d’avis de mise à jour RezlyX v... ont tous été corrigés en « VosCMS ».
- •
resources/views/admin/partials/admin-topbar.php — commentaire d’en-tête corrigé.
Fixed
- •
storage/.update_cache conservait un ancien cache current: "2.6.4", si bien que même après la mise à jour vers v2.6.8, le tableau de bord affichait encore la bannière « Nouvelle mise à jour disponible » — une fois le cache supprimé, il est recalculé automatiquement à la requête suivante.
- •Les changements accumulés de dev → production n’étaient pas synchronisés — en dehors de cette session, de nombreux fichiers comme install-core.php (correctifs des défauts n° 1 à n° 7) et version.json n’avaient jamais été synchronisés avec la production. dev a été synchronisé avec la production d’un seul coup par rsync (342 fichiers modifiés + 196 nouveaux, 6,3 Mo, hors données utilisateur,
.env, storage/, uploads/, vendor/ et .git/).
Documentation
- •
docs/LINE_FRIEND_CTA_DESIGN_GUIDE.md — ajout de la Part 3 (mise en œuvre réelle du Utility Floating Stack intégré), de la Part 4 (mise en œuvre réelle de l’exploitation de l’envoi de la Phase 1), de la Part 5 (scénarios d’utilisateurs externes — analyse de la valeur de l’envoi à sélection multiple) et de la Part 6 (feuille de route des Phases 2 à 4). D’environ 631 à 920 lignes.
Regression Test
- •Vérifie l’existence de
utility-floating-stack.php et des 5 fichiers partial de variants de line-friend-cta.
- •Vérifie l’existence des méthodes
LineMessenger::broadcast/multicast.
- •Vérifie l’existence du fichier de migration
plugins/vos-community/migrations/004_line_broadcasts.sql.
- •Vérifie l’existence des clés
messaging.utility_stack. + community.broadcast.send_line_ dans 13 langues.
- •Vérifie automatiquement l’absence de reste de RezlyX dans dashboard.php / admin-topbar.php.
Fixed
- •Consolidation de la table des licences vos-market — 6 fichiers API interrogeaient la mauvaise table
{$pfx}vos_licenses, causant "Server error" 500 à chaque paiement. Toute la vérification des licences est désormais acheminée vers le maître unique vcs_licenses (géré par vos-license-server).
- •Suppression du trou de sécurité d'enregistrement maître non vérifié dans
sync.php — Le code précédent UPSERT-ait dans vos_licenses sans vérifier vos_key, permettant à quiconque d'enregistrer automatiquement des clés de licence arbitraires dans le maître via un simple POST. Le suivi est désormais géré par rzx_mkt_sync_reports existant (par élément).
- •
migrations/007 obsolète — La migration mal conçue est désormais un no-op (SELECT 1), raison et historique des modifications dans les commentaires.
Added
- •4 cartes de statistiques — Sites suivis / Sites à vérifier / Licences multi-domaines / Inactifs 30+ jours.
- •Onglet violations (affichage au niveau de l'article) — Voyez en un coup d'œil quel widget payant est installé sans licence sur quel domaine. Prix, version, vos_key et dernière vue sont affichés.
- •Onglet multi-domaines — Cas où une seule clé de licence est signalée depuis plusieurs domaines.
- •Onglet inactifs — Sites sans signal de synchronisation depuis 30+ jours.
- •Définition affinée des violations —
unknown_product et articles gratuits sont exclus. Seuls les articles payants du marketplace en état non licencié comptent comme violations.
- •Liste blanche des domaines propriétaires — Les domaines de l'opérateur stockés comme tableau JSON dans
settings.mkt_owner_domains sont automatiquement exclus des comptes.
- •i18n en 13 langues — Barre latérale, cartes, onglets et textes d'aide sont tous correctement traduits.
Changed
- •
settings/system/updates — Cartes de version installée et dernière version corrigées en "VosCMS vX.Y.Z".
- •
updates/ajax.php — Fallback du nom de la DB et User-Agent corrigés.
Regression Test
- •Vérifie automatiquement qu'il n'y a pas de résidu SQL
vos_licenses dans 6 fichiers vos-market
- •Détecte la régression du trou de sécurité INSERT dans
sync.php
- •Vérifie que l'état no-op de
migrations/007 est maintenu
- •Vérifie automatiquement qu'il n'y a pas de résidu RezlyX dans 3 fichiers de l'écran des mises à jour
Fixed
- •Initialisation automatique de
site_url — L’assistant d’installation écrivait le siteUrl saisi par l’utilisateur uniquement dans APP_URL du .env et pas dans rzx_settings.site_url de la base, si bien que toutes les fonctions d’un site nouvellement installé dépendant de site_url (installation automatique, SEO, liens des e-mails, etc.) étaient cassées. Corrigé en ajoutant site_url au tableau $settings de install-core.php.
- •Enregistrement automatique dans
rzx_site_domains — L’assistant d’installation n’ajoutait pas automatiquement le domaine d’installation actuel à la table site_domains, si bien que SiteRouter ne reconnaissait pas le domaine. Le domaine installé est désormais INSÉRÉ automatiquement comme primary de site_id=1.
- •Écriture automatique de
MARKET_API_URL dans .env — À l’installation neuve, le .env ne contenait pas l’adresse de l’API de la place de marché, et InstallerService ne trouvait pas la cible de l’appel. Elle est désormais écrite automatiquement avec la valeur par défaut https://market.voscms.com/api/market (exploitation avec un seul maître de licences).
- •Faute de frappe dans le nom de table de l’API d’installation de la place de marché —
vos-market/views/api/item/install.php interrogeait la table inexistante rzx_vos_licenses lors de la vérification de licence, si bien que toutes les installations automatiques répondaient « Server error » (HTTP 500). Corrigé vers la vraie table vcs_licenses (le maître des licences, fixe et sans préfixe).
- •Configuration automatique des permissions des dossiers widgets/plugins/themes — Après l’installation, l’utilisateur PHP-FPM ne pouvait pas écrire dans ces dossiers, et l’installation automatique échouait silencieusement. L’assistant d’installation accorde désormais automatiquement setgid et l’écriture pour le groupe (le groupe d’exécution de PHP est détecté automatiquement pour s’adapter à la diversité des environnements externes).
- •Replis multiples dans
install-handler.php — En environnement multisite, la recherche de site_url utilisait LIMIT 1 sans filtre site_id et était instable. Un repli en trois étapes SiteRouter → repli sur site_id=1 → $_SERVER['HTTP_HOST'] garantit la reconnaissance du domaine dans tous les environnements.
Added
- •
InstallerService::installTheme() — Lit le theme.json d’un produit type=theme et installe récursivement les plugin/widget/skin présents dans requires. Garantit une vérification sur 13 langues et l’idempotence (les éléments déjà installés sont ignorés).
- •
runPostInstall — Juste après l’installation d’un thème, exécute automatiquement les graines post_install/settings.json / boards.json / pages.json : pages, placement des widgets et réglages par défaut sont configurés automatiquement d’un seul coup.
- •13 langues obligatoires (
REQUIRED_LOCALES) — Les objets multilingues (name, description, title de la page, config.title des widgets, etc.) ne passent officiellement que s’ils contiennent les 13 clés. Un avertissement est émis pour les locales manquantes.
- •Maître
vcs_licenses unique — Toute émission et vérification de licence est gérée via la place de marché de production (market.voscms.com). Les environnements dev et test utilisent le même maître.
Added
- •Vérification automatique de ces six défauts — 13 points au total, dont la logique d’initialisation de l’assistant d’installation, les permissions des dossiers, l’API de la place de marché, l’accessibilité du serveur de licences, la branche theme d’InstallerService et les replis multiples d’install-handler.
- •Crochet automatique dans build-voscms.sh — Appelé automatiquement à la fin du build. Dès qu’un seul FAIL se produit, le code de sortie est différent de 0 et la distribution est bloquée. Si le même défaut réapparaît lors d’un build ultérieur, il est détecté immédiatement.
Documentation
- •
docs/theme-package/THEME_PACKAGE_SPEC.md — Définit le standard des paquets de thème VosCMS (theme.json). Il indique l’exemple du thème intégré Salon, le schéma détaillé de post_install et la règle des 13 langues.
Fixed
- •Sauvegardes de mise à jour : une seule par version conservée —
Backup::createFull() supprime désormais la sauvegarde existante de la même version avant d’en créer une nouvelle. Cela résout le problème où des mises à jour ou des restaurations répétées sur la même version accumulaient des doublons de cette version dans la liste des sauvegardes (seul le dernier état juste avant la mise à jour est conservé).
v2.6.5
2026-05-27 · il y a 5 mois
Remise en ordre du système de mise à jour (canal unique, session/permissions, réparation de la version distribuée)
Fixed
- •Restauration du
update-api.php manquant dans la version distribuée — Le script de build classait par erreur update-api.php, le backend de mise à jour, comme « fichier dev » et le supprimait de la version distribuée. Résultat : l’onglet de mise à jour de toutes les installations distribuées était inutilisable et affichait « File not found ». Il n’est plus exclu du build et est maintenant correctement inclus dans la version distribuée.
- •Correction de la session de connexion non reconnue (Unauthorized) —
update-api.php regardait le chemin de session par défaut (/var/lib/php/sessions) ; il utilise désormais le même storage/sessions que index.php. Cela résout l’erreur Unauthorized qui apparaissait même une fois connecté en administrateur.
Changed
- •Les mises à jour du Core n’utilisent que le manifeste de distribution propre comme canal unique — Suppression des restes de tags GitHub, de jeton et de diagnostic dans
update-api.php (le chemin par lequel check écrasait le résultat du manifeste par un tag GitHub est bloqué). La place de marché n’a pas de Core (extensions uniquement).
- •Sécurité renforcée — Ajout à
update-api.php d’une vérification CSRF et d’un contrôle de permission maître (propriétaire).
- •Mise en ordre de la liste de conservation des mises à jour —
skins et config ont été retirés de la liste de conservation. Comme applyUpdate ne fait que copier, les thèmes du cœur et la config du zip distribué sont mis à jour, tandis que les fichiers personnalisés des clients absents du zip sont conservés.
Changed
- •Suppression du bouton « Rechercher des mises à jour » en double — la dernière version est vérifiée automatiquement à l’ouverture de la page.
- •Correction de la liste des sauvegardes qui disparaissait lors d’une erreur passagère → la section est conservée et affichée vide.
- •En cas d’erreur, l’avis « Vous utilisez actuellement la dernière version » s’affiche à la place de messages bruts comme
Unauthorized.
Added
- •Section
um en 13 langues ajoutée — toutes les locales de vos-community/lang/{locale}.php (ko·en·ja·de·es·fr·id·mn·ru·tr·vi·zh_CN·zh_TW) : follow·following·message·block·unblock·report·report_about·report_reason/detail/placeholder·reason_spam/harassment/inappropriate/other·report_submit/sent/failed·msg_title/placeholder/send/sent/failed·block/unblock_confirm·block/unblock_done·cancel·failed·network_error
- •i18n complète de
user-mention-menu.php — tout le coréen codé en dur dans le HTML PHP remplacé par __('community.um.*') ; les chaînes d'exécution JS sont émises comme objet PHP via UM_LANG = <?= json_encode(...) ?>, l'assistant umT(key, name) substituant l'espace réservé :name
- •Menu de mention autorisé aux invités — structure de garde de
community-overlays.php repensée : les chemins admin/API sont entièrement bloqués, tandis que user-mention-menu est inclus même pour les invités (suivre/signaler invitent à se connecter) ; les gardes d'action de page et de username restent réservées aux utilisateurs connectés
Changed
- •
boardPreloadUsers(array $rows) ajoutée (board/_init.php) — charge en masse la liste des user_id en une seule requête IN, partagée via le cache $GLOBALS['_boardUserCache']
- •
boardAuthorMention() étendue — ajout des attributs data-user-username·data-user-avatar (relie précisément l'URL de la story /story/{username}, affiche l'image d'avatar). Privilégie un HIT du cache de préchargement, se rabat sur une requête unique paresseuse en cas d'échec
- •
board/list.php·board/read.php·skins/board/qna/_list-full.php — appellent boardPreloadUsers() avant le rendu pour éviter les requêtes N+1
Fixed
- •Analyseur d'affichage étendu (
resources/views/system/changelog/index.php) — ajout du rendu des blocs de code (``), tableaux (|...|), liens markdown (text), sous-titres #### et lignes horizontales (---`). Corrige l'affichage en markdown brut des versions antérieures (2.4.1·2.3.8·2.3.7, etc.) utilisant cette syntaxe
- •Repli de locale par version — passage de la récupération de toute la liste dans une seule langue à une base par version (
locale actuelle → en → ko). Chaque version apparaît désormais dans n'importe quelle langue, et les versions non encore traduites affichent un badge de langue de repli
- •Alignement des limites de bloc (
rzxlib/Core/Changelog/ChangelogParser.php) — empêche un en-tête ## [Unreleased] sans date d'être absorbé par la version précédente (p. ex. 1.5.0), en séparant les blocs à chaque ## [
Added
- •Migration 056 table
dist_downloads (site_id·version·ip·user_agent·referrer·utm_*·is_bot·created_at)
- •Point de terminaison de téléchargement
api/dist-download.php — au lieu d'un lien direct statique /download/*.zip, les requêtes passent par lui pour enregistrer des statistiques par version / jour / provenance (referrer·UTM) puis effectuent une redirection 302. Les UA de bots sont comptés séparément ; liste blanche de versions (protège du path-traversal)
- •Page de statistiques d'administration
resources/views/admin/dist-downloads.php (maître uniquement, 13 langues) — cartes de synthèse (total/aujourd'hui/7j/30j), barres par version, tendance quotidienne (30j), Top-10 des sources, UTM. Graphiques SVG/CSS maison (sans bibliothèque externe)
- •Lien de téléchargement du widget
download-hero redirigé vers le point de terminaison de comptage
- •Ajout du menu d'administration « Statistiques de téléchargement » (config/admin-menu.php, maître uniquement)
Added
- •
hero-cta-text — zone de texte supérieure (saisie). Les valeurs par défaut correspondent au contenu en production de hero-cta2 (13 langues) ; les réglages utilisateur priment
- •
hero-cta-button — bouton de téléchargement (détecte automatiquement la dernière version + compte les téléchargements, sans configuration) plus un bouton marketplace optionnel (un seul bouton si laissé vide)
- •Libellés et valeurs par défaut du formulaire de réglages en 13 langues (prise en charge des objets
getLabel du constructeur)
- •Couleur/fond du bouton de téléchargement unifiés avec hero-cta2 (#2563eb)
Added
- •Glissez une carte de la palette sur le canevas pour ajouter un widget (groupe
pull:'clone' de SortableJS + remplacement par un vrai bloc dans le onAdd du canevas). Fonctionne avec l'ajout par clic et le réordonnancement ↑↓/poignée existants
- •Le flyout reste ouvert pendant le glissement + mise en évidence de la zone de dépôt (
wb-drop-active)
Changed
- •Suppression de l'espace du wrapper de page entre les widgets (
type-widget.php py-2 → 0)
- •Traduction IA synchrone des commentaires stabilisée — nginx
fastcgi_read_timeout 150s (vhost du forum) · PHP-FPM request_terminate_timeout 150 · set_time_limit 150, OllamaProvider keep_alive 30 min (le modèle reste résident, éliminant les démarrages à froid)
- •Ajout de boutons de copie pour l'URL Webhook et la Redirect URI dans les onglets Message API et Connexion sociale (13 langues, avec repli pour contexte non sécurisé)
Added
- •Migration 036 — colonnes
withholding_tax · consumption_tax · tax_basis dans partner_earnings / payouts
- •Migration 037 — colonnes
fx_rate · fx_amount · fx_currency dans payouts (enregistrement des virements convertis en USD)
- •Migration 038 — colonne
vcs_developers.paypal_email
- •Helper
rzxlib/Core/Helpers/MarketTax::calculate() — modèle de déduction standard japonais
· Le prix de vente est TTC (税込) ; la marketplace règle directement la TVA à la NTA
· freelance → retenue à la source de 10,21% / invoice_eligible → crédit de taxe sur les achats / no_invoice → TVA non versée
· Sans catégorie ou sans donnée → freelance forcé (conservateur : un sous-paiement peut être remboursé, un trop-perçu est irrécupérable)
- •Script de remplissage
scripts/market-tax-backfill.php — recalcul des earnings/payouts existants (protège status='paid', supporte --dry-run)
- •Affichage du règlement en 5 parties : revenus → commission → déduction TVA → retenue (freelance) → paiement net
- •Nouvelles clés dans
rzx_mkt_settings : min_payout_amount · consumption_tax_rate · default_commission_rate (settings prioritaire partout ; suppression du fallback codé en dur)
Added
- •Modal de règlement dans
/theadmin/market/partners/payouts — prompt() × 2 + alert() → modal unique
· JOIN avec vcs_developers pour préremplissage automatique banque/agence/titulaire/numéro de compte/type d'entreprise/numéro T (prefill ; PII enc : déchiffrement automatique)
· Calcul automatique des 5 parties + puces de base légale japonaise (freelance_withholding, etc.) + citation des articles (§204, système de factures)
· Notification toast dans la page ; fermeture du modal et rechargement automatique
- •Conversion automatique en USD pour les comptes hors pays d'exploitation (Migration 037)
· Taux de change automatique Frankfurter API (cache storage TTL 24 h) + substitution manuelle administrateur (TTS bancaire)
· Sélection automatique de method=paypal
· Pour les étrangers : carte de compte bancaire masquée, carte d'adresse e-mail PayPal affichée (bank_country == site_country)
- •Saisie du montant de règlement par le développeur (
/mypage/developer/earnings)
· Solde total → saisie du montant + bouton montant total + validation du montant minimum
· Colonnes en 5 parties pour l'historique des ventes, encadré informatif de règlement (loi fiscale applicable selon le type d'entreprise)
- •Conversion en USD et taux de change en information auxiliaire dans l'historique des paiements (côté administrateur et développeur)
- •Remplacement du graphique de tendance des ventes par un graphique à barres SVG (corrige le problème de visibilité des barres div)
Added
- •Politique de verrouillage basée sur
tax_review_status (profil développeur)
· not_submitted / rejected → modifiable
· pending / approved → verrouillage de modification (cadenas + avertissement)
· rejected → modifiable + hint "à l'enregistrement, entre dans la file de révision"
· Défense côté serveur : HTTP 423 Locked (bloque le contournement de l'interface)
- •
update.php mise à jour partielle sécurisée — UPDATE dynamique des seuls champs transmis (avant : écrasement total avec risque de NULL sur les champs non transmis)
- •Lien vers le site de vérification officiel (écran de vérification administrateur + profil développeur)
· 🇯🇵 Site de publication du numéro de personne morale de la NTA (https://www.houjin-bangou.nta.go.jp/)
· 🇯🇵 Site de publication des émetteurs de factures qualifiées de la NTA (https://www.invoice-kohyo.nta.go.jp/regno-search/)
· 🇰🇷 Consultation du statut d'immatriculation d'entreprise sur Hometax Corée
· Bouton de copie en un clic à côté du numéro d'entreprise/numéro T
Added
- •Nouveau compte (
/mypage/developer) — sélection de nationalité déplacée en haut du formulaire, avec guide comparatif avec le pays d'exploitation
· country == site_country → 🏠 formulaire domestique (type d'entreprise / compte bancaire)
· country != site_country → 🌐 formulaire étranger (freelance automatique + e-mail PayPal obligatoire)
· Getter isDomestic Alpine.js, constante globale OPERATING_COUNTRY
- •Modification du profil (
/mypage/developer/profile) — même structure (règle [feedback_admin_user_parity])
· Étranger : section entreprise masquée ; informations de règlement = e-mail PayPal uniquement
· Verrouillage de la nationalité (contacter l'administrateur pour modifier), puce de mode en haut
- •Validation côté serveur de l'API d'inscription — e-mail PayPal obligatoire pour les étrangers, freelance forcé, valeurs entreprise/compte ignorées
Added
- •Substitution automatique de tokens dans
page.php — appliquée globalement à toutes les pages système
· {{COMPANY_NAME}} {{COMPANY_ADDRESS}} {{COMPANY_PHONE}} {{COMPANY_EMAIL}} {{COMPANY_REG_NUMBER}} {{COMPANY_REPRESENTATIVE}}
· {{SITE_NAME}} {{SITE_URL}} {{DOMAIN}}
· Mappage automatique depuis les settings business_ ou site_ de l'administration
· page_title / page_subtitle personnalisés passent également par la substitution de tokens
- •Priorité de
{{DOMAIN}} — official_domain (domaine officiel pour les CGU et politiques) → hôte de site_url
· Même sur le serveur de développement vos.21ces.com, le corps des CGU affiche voscms.com
Added
- •Remplacement complet de
terms / privacy dans rzx_page_contents (13 lignes chacun) — CGU de la plateforme de réservation RezlyX → CGU du logiciel libre VosCMS
- •CGU avec 18 articles : objet · définitions · publication et révision · règles complémentaires · formation du contrat · vie privée · notifications · obligations de la société · obligations de l'utilisateur · fourniture du service · modifications · restrictions d'utilisation · licence (utilisation gratuite) · propriété et conservation des données · droits d'auteur des publications · exonération de responsabilité (AS-IS) · indemnisation · règlement des litiges
- •Politique de confidentialité avec 10 articles : finalité du traitement · catégories · durées de conservation · transfert et sous-traitance à des tiers · droits de la personne concernée · mesures de sécurité · cookies · responsable de la protection · recours en cas de violation (PPC) · modifications
- •Droit japonais + compétence exclusive du tribunal de district de Fukuoka, citant APPI §33·§34·§35
- •Les informations d'entreprise utilisent des tokens → une seule modification dans l'administration synchronise automatiquement CGU et politique
- •La version japonaise fait foi ; traductions officielles en langue native pour 13 langues
- •Carte d'informations d'entreprise — 3 éléments uniquement : raison sociale, siège et téléphone (représentant légal/nom supprimé pour éviter les révisions des CGU lors de changements d'immatriculation)
- •Scripts de conservation :
scripts/voscms-terms-update.php · scripts/voscms-privacy-update.php
Fixed
- •
menus-api.php de /theadmin/site/menus avait 99 lignes de retard sur vos, provoquant l'omission de validation et de traduction lors de l'enregistrement/modification des menus
- •Synchronisation de menus-api.php de vos → market :
· mn_link_target_exists() — les menus de raccourci (lien) ne sont enregistrés qu'après vérification de l'existence de la page cible (page système · rzx_page_contents)
· Défense contre la réutilisation des ID de menu — nettoyage automatique des rzx_translations.menu_item.{id}.* obsolètes pour les nouveaux IDs
· Méthode INSERT pour les traductions : INSERT IGNORE → INSERT … ON DUPLICATE KEY UPDATE (permet l'écrasement)
· Lors d'un changement de title·url : nettoyage complet des anciennes traductions + réenregistrement automatique des traductions lors de la correspondance avec une page système (config/system-pages.php)
- •Ajout de 4 fichiers
admin/site/menus*.php aux INCLUDES de sync-to-market.sh
Fixed
- •Table
rzx_contact_messages manquante → migration 041_create_contact_messages.sql ajoutée (IF NOT EXISTS, sans effet sur vos existant)
- •Double layout dans
contact-messages.php — _head.php émettait déjà sidebar+topbar mais la vue les incluait à nouveau directement, résultant en <body> dupliqué et main imbriqué. Réorganisé selon le modèle vos (en-tête = _head 1 fois, pied = _foot 1 fois)
Added
- •Migration 040
040_create_developer_platform.sql — création groupée de 7 tables : vcs_developers + vcs_developer_earnings/payouts/activity/notes + vcs_review_queue + rzx_mp_items (IF NOT EXISTS, schéma final après application des ALTER 030~038)
· vcs_developers sur vos.21ces.com n'existait que dans le dump sans migration CREATE TABLE — corrige l'échec de l'ALTER 030 sur les sites créés après
- •Synchronisation de
mypage/profile-sidebar.php — requête rzx_mkt_partners (ancienne) → requête vcs_developers (nouvelle) (intégration de l'activité développeur dans la page personnelle)
- •Correctif des routes
index.php de market (manuel, évitant le sync complet) :
· /developer/ → /mypage/developer/ redirection 301 (mapping login/dashboard/my-items/submit/earnings/profile/logout)
· Routes mypage/developer/{register|items|items/new|earnings|profile} + mypage/developer/items/{N} + mypage/developer/items/{N}/edit
- •Ajout de la migration 040 + profile-sidebar.php aux INCLUDES de
sync-to-market.sh
- •Sauvegarde automatique de la BD market (
storage/backups/market-YYYYMMDD-HHMMSS/market_vos.sql) avant application de la migration 040
Added
- •Les CGU de market.21ces.com suivent le modèle de marketplace opérée par des tiers, distincts des CGU du logiciel libre VosCMS
- •CGU avec 18 articles (incluant les règles d'exploitation de la marketplace) :
· Art. 8 : le contrat de vente est établi entre acheteur et développeur ; la société assure l'intermédiaire pour le paiement et la livraison
· Art. 9 : quatre exceptions de remboursement pour les produits numériques (avant téléchargement · discordance de description 7 jours · confirmation de malware · erreur système) — satisfait aux exigences de divulgation de l'art. 15-2 de la Loi japonaise sur les transactions commerciales spéciales
· Art. 10 : sans taux de commission explicite (renvoi aux "taux publiés séparément" ; permet des ajustements sans révision des CGU)
· Art. 10 : retenue à la source japonaise de 10,21% selon art. 204 de la Loi sur l'impôt sur le revenu ; pour les titulaires du numéro T, la TVA est versée directement à la NTA par la marketplace ; comptes hors pays d'exploitation → virement PayPal en USD
· Art. 14 : les CGU individuelles du développeur ont la priorité — sauf pour les opérations de la plateforme (paiement, règlement, procédure de remboursement)
· Art. 17 : plafond d'indemnisation : total des commissions/règlements des 6 mois précédents
· Art. 18 : droit japonais + compétence exclusive du tribunal de district de Fukuoka
- •Politique de confidentialité avec 12 articles (perspective marketplace tierce partie) :
· Catégories de données — communes / acheteurs / développeurs (communes) / résidents au Japon / résidents à l'étranger / livraison : 6 catégories
· Durées de conservation — membres 1 an · transactions 7 ans · règlements/retenues 7 ans · vérification d'identité 5 ans · logs 6 mois · demandes 3 ans
· Sous-traitants — Stripe · KOMOJU · PayPal · Frankfurter · SendGrid · NTA explicités
· Transferts internationaux — États-Unis (PayPal/Stripe/SendGrid) · UE (taux de change) · autres pays (passerelle/banque locale) explicités
- •Scripts :
scripts/market-terms-update.php · scripts/market-privacy-update.php (UPSERT — UPDATE d'abord ; INSERT si aucune ligne existante)
- •BD market mise à jour (terms/privacy, 13 lignes chacun dans rzx_page_contents), titres et sous-titres multilingues page-i18n également appliqués
Added
- •Correction du mappage manquant des paramètres de skin (
page_title · page_subtitle) — les valeurs saisies dans l'écran de configuration n'apparaissaient pas sur la page
- •Création du partiel
_page-title-bg.php manquant (corrige l'avertissement d'include dans nginx error log)
- •Option couleur ajoutée à
title_bg_type + champ title_bg_color — fallback automatique vers couleur lorsque image/vidéo sont vides
- •Suppression du fallback de boîte blanche lorsque
content_bg=transparent (corrige l'aspect étroit du contenu max-w-5xl à l'intérieur de la carte)
- •Variable CSS
--page-content-width générée automatiquement — les composants inclus externement comme la barre d'actions "À propos de cette page" (vos-community) s'alignent sur la même largeur que le content_width de la page
Fixed
- •PDOException sur la page de règlements — suppression de la référence à la colonne
p.currency inexistante dans rzx_mkt_partners
- •Graphique de tendance des ventes invisible — les barres div avec hauteur en % apparaissaient presque à 0px selon l'environnement → remplacé par un graphique basé sur SVG viewBox (visibilité minimale de 4px garantie)
Added
- •Écran de détail d'article sur la page développeur (
/mypage/developer/items/{id}) — statistiques, historique des versions, tendances de téléchargement
- •Écran de modification d'article développeur (
/mypage/developer/items/{id}/edit) — même interface 3 onglets qu'items-new, valeurs existantes pré-remplies, nouvel upload ZIP suit un flux séparé
- •Nouvelle API :
/api/developer/item-update — met à jour name(JSON), short/desc(JSON), tags(JSON), price, license, repo/demo URL, dépendances, version minimale, icon, screenshots
- •Nouvelle API :
/api/developer/request-payout — demande de virement
- •Nouvelle API :
/api/developer/update-bank — mettre à jour son propre compte de règlement
- •Nouvelle API :
/api/developer/issue-reply — publier une réponse Q&A (canal de réponse propre au développeur)
- •Écran de détail développeur admin (
/theadmin/developers/show) — carte entreprise/compte/documents + mode révision de documents (approbation/rejet)
- •Vérification d'e-mail pour l'inscription et la connexion (
/verify-email) renforcée + champ company sauvegardé dans Auth::register
- •Clés de traduction officielle en 13 langues ajoutées (
show_edit_btn, items_edit_*, items_back_detail, api_updated, etc.)
Added
- •Formulaires de soumission d'avis, d'issues et de Q&A directement exposés dans les widgets (sans navigation vers une page séparée)
- •Seuls les acheteurs peuvent soumettre — les non-acheteurs voient le formulaire mais reçoivent un message d'information lors de la soumission
- •Les réponses Q&A supportent les fils (réponses à des réponses) — migration BD 035 (
parent_reply_id)
- •Nouvelles APIs :
/plugins/vos-market/views/api/item/post-issue.php, post-reply.php, post-review.php
- •Core
rzxlib/Core/Helpers/Notifications.php — helper de notifications (associé à la migration BD 034)
Added
- •Support complet en 13 langues appliqué à tous les écrans :
/theadmin/market/licenses, sync, orders, settings, submissions, partners/payouts, items
- •Écran de paramètres du marketplace — libellé "Partenaire" unifié en "Développeur" (texte d'affichage uniquement ; noms de variables conservés pour la compatibilité)
- •La saisie du nom d'article du marketplace utilise le modal de saisie multilingue partagé —
name_json édité simultanément en 13 langues
- •
plugins/vos-market/lang/* — nouveau pool de langues au niveau du plugin
- •
resources/lang/*/marketplace.php — les 13 langues traduites dans leur langue native (conforme à la règle de traduction complète i18n)
Added
- •
033_developer_notes_activity.sql — notes et journal d'activité par développeur
- •
034_notifications.sql — table rzx_notifications (notifications utilisateur)
- •
035_issue_reply_thread.sql — colonne rzx_mkt_issue_replies.parent_reply_id ajoutée (réponses en fil)
Fixed
- •
/Market?item={slug} slug manquant — corrigé dans items-show par une requête sur colonne unique dédiée
- •Nom de colonne
icon_url dans l'API de mise à jour d'article corrigé en nom de colonne réel icon
- •Page de paramètres du marketplace vide — migration 005 manquante pour
rzx_mkt_settings appliquée
Added
- •VARCHAR(12)
users.username + UsernameValidator (6 caractères minimum, restriction des caractères spéciaux)
- •Modal de portail à la première visite après connexion (AJAX
/api/username-set)
- •Traductions complètes en 13 langues (fallback anglais supprimé)
Added
- •
/profile/{uuid} → /story/{username} redirection 301
- •Libellé du menu contextuel : « Voir le profil » → « Voir la story »
Added
- •Plugin vos-story extrait du noyau — dédié à
/story/{username}
- •En-tête style Facebook + 5 onglets fixes (Tout / Info / Photos / Abonnés / Abonnements)
- •CRUD de publications + flux SNS (
vos_story_posts, body_format = text/html)
- •Bascule TEXT/EDIT + intégration Summernote
- •Pièces jointes images (multiples) + grille de l'onglet Photos
- •Système de likes + commentaires
- •Système de skin Story (
skins/story/default) + jeton par utilisateur (/mypage/story)
- •Page de politique d'administration (
/admin/vos-story/policy)
- •Barre d'actions de page : i18n + position (fin du contenu principal) + jeton de largeur de contenu
- •Grille 2:1 (zone de contenu uniquement) — côté droit : publicités + amis (onglets Abonnés/Abonnements)
- •Boutons d'action dans l'en-tête — icônes uniquement ([Paramètres de ma Story] / [Modifier le profil] / [Suivre])
Added
- •D-1 : Barre latérale à 4 menus (Tableau de bord / Story / Compte / Messages)
- •D-2-A : Nouveau tableau de bord — 8 cartes de statut + navigation à 8 onglets + onglet infos du compte
- •D-2-B : Onglets Favoris / Messages / Amis (chacun avec lien « Tout voir »)
- •D-2-C : Onglets Enregistrés / Mes publications / Mes commentaires (tableau + Story + page unifiés)
- •D-2-D : Gestion de la connexion automatique (remember tokens)
Added
- •Assistant commun
rzx_mirror_external_images() — cURL + protection SSRF + redimensionnement GD
- •E-1 : Capture de snapshot de favori + absorption d'images externes
- •E-2 : Absorption lors de la création d'un post Story (colonne source de story_attachments)
- •E-3 : Absorption lors de la création d'une publication de tableau
- •E-4 : Absorption lors de la création d'un contenu de page
- •Marquage des images :
data-source-original, data-source-mirrored
Added
- •Barre latérale de gestion hébergement — dernier élément [Paramètres] menant aux 4 onglets de la page de demande de service (general/domain/hosting/addons)
- •Politique de remboursement → Paramètres système → Général → carte séparée (isolée des paramètres fiscaux)
- •Stockage en clé unique
rzx_settings.refund_policy
- •Clés
settings.refund.* pour 13 langues
Added
- •Migration 009 : colonnes
page_contents.created_by / updated_by
- •Enregistrement automatique sur tous les écrans d'édition de page (admin/customer/system)
Added
- •Comptage des publications — reconnaît la structure séparée de
rzx_translations pour les publications de tableau (board_post.{id}.title)
Added
- •Paramètres admin pour quota de stockage par hébergement / seuil d'avertissement / politique (block/notify/none)
- •Graphique en anneau d'utilisation dans Mon Espace
- •Moniteur d'arrière-plan
scripts/db-quota-monitor.php
Added
- •Bouton de réinstallation VosCMS — onglet hébergement admin
- •Action de changement de [Statut] d'hébergement + journal
- •Formulaire d'édition « Paramètres de connexion serveur » supprimé (évite une exposition inutile)
Fixed
- •Erreur réseau scrap
add_scrap — conflit de require du fichier API vos-story
- •Carte de scrap — contour + icônes supprimer/modifier (corbeille)
- •Incohérence entre le nombre de publications et la liste (filtre de statut manquant)
- •Correspondance nick_name supprimée (évite l'identification erronée des données de seed avec user_id NULL)
- •Position du menu Story dans Mon Espace — top → main (reconnaissance automatique du plugin)
- •Icône du menu Story au format noyau (balise
<path> complète)
- •Colonne key manquante dans settings SELECT de l'onglet modules complémentaires (deux sections masquées)
- •Action hosting_status 500 — emplacement de définition de la fonction auxiliaire
- •Barre d'actions de page — jeton de largeur de contenu appliqué
- •Bug où les publications existantes disparaissent lors de la publication d'un nouveau post (actualisation immédiate du flux)
Added
- •Détail de l'hébergement → Onglet domaine → Bouton
+ Ajouter un domaine → modal
- •Options : sous-domaine gratuit / nouvelle inscription / connexion de domaine existant
- •Recherche WHOIS (
/api/domain-check.php réutilisé) + affichage du prix par TLD
- •Paiement : carte enregistrée (client PAY.JP de l'hébergement réutilisé) ou nouvelle carte (PAY.JP Elements)
- •Séparation automatique de la TVA à 10 % (sous-total / taxe / total)
- •À la fin du paiement, ajout dans
metadata.added_domains[] du sub d'hébergement (pas de sub séparé créé)
- •Filet de sécurité de remboursement automatique — en cas d'échec de traitement BD, le débit PAY.JP est automatiquement remboursé
Added
- •Date de début~expiration + bouton de vérification (DNS A/CNAME → correspondance avec notre zone ou plage IP Cloudflare)
- •Bascule de renouvellement automatique + bouton de demande de renouvellement (par domaine)
- •registrar_pending / manual_attach_pending : bouton de vérification → badge « En attente »
- •Badge violet « Domaine ajouté »
Added
- •Barre latérale de gestion de l'hébergement : 2e élément ajouté nouveau
- •Liste unifiée : sub type='domain' + hosting sub.added_domains[] tous affichés dans l'ordre chronologique
- •Cartes de statistiques (total/en attente/terminé) + filtres (statut/option/recherche)
- •Actions : [Marquer comme enregistré] / [Traiter l'annulation] (à l'annulation : remboursement PAY.JP + INSERT de ligne de remboursement)
- •Déchiffrement automatique du nom d'utilisateur
Added
- •Barre latérale de gestion de l'hébergement : 3e élément ajouté nouveau
- •Journal de transactions basé sur
rzx_payments — cartes de statistiques revenus/remboursement/revenus nets/taxe
- •Calcul automatique du montant hors taxe pour la déclaration de TVA japonaise (prix TTC → base = total × 100/110, taxe = total × 10/110)
- •Tableau des tendances des 12 derniers mois + tableau du journal de transactions + filtres/pagination
Added
- •Onglet add-ons de mon espace : section « Disponible à la demande » (messagerie professionnelle automatiquement exclue)
- •Actions par prix :
- •Gratuit (support d'installation) : notification admin + order_logs
- •Devis (personnalisation) : « Demander un devis »
- •Prix fixe récurrent (support technique 1 an) : modal de paiement par carte (
_addon-pay-modal.php)
- •À la fin du paiement, sub d'addon créé automatiquement + écriture dans payments
- •Correspondance avec l'étiquette d'un sub déjà actif : bouton de demande automatiquement désactivé
- •Ligne install_info : boutons [Aller à l'admin / Aller au site] à droite
Added
- •Schéma BD : UNIQUE
uk_payment_order supprimé → UNIQUE uk_payment_key (charge_id) remplacé
- •Plusieurs lignes de paiement par commande autorisées (hébergement + domaine + add-on cumulés)
- •En cas de remboursement : ligne payée inchangée, INSERT d'une ligne de remboursement séparée (status='refund', intégrité comptable)
- •Obligation de conservation de 7 ans du Japon + standard de réponse aux litiges marchands PAY.JP respecté
Added
- •composer require minishlink/web-push
- •Aide à l'envoi de push VAPID pour admin/superviseur
- •Nettoyage automatique des endpoints expirés + journalisation automatique dans rzx_push_messages
- •Points d'appel : pay_domain (paiement de domaine terminé), service-order (demande d'enregistrement de domaine), request_addon
Added
- •Correspondance automatique de sous-domaine de notre zone (CNAME générique reconnu)
- •Correspondance de 15 plages CIDR IPv4 Cloudflare (sur réponse proxy)
- •Réponse « already_refunded » traitée comme succès (quand PAY.JP a déjà remboursé)
Added
- •Sous-requête totalisant
rzx_payments (paid − refunded)
- •Affichage cumulé du paiement de base d'hébergement + ajout de domaine + paiement d'add-on
Added
- •
admin_cancel_addon — status sub='cancelled' + remboursement PG + INSERT de ligne de remboursement
- •Routage PG : basé sur la colonne
gateway de la ligne de paiement (sûr même après changement de PG)
Removed
- •Conformément à l'obligation de conservation de 7 ans du Japon + politique de réponse aux litiges PAY.JP, tous les boutons « supprimer » de l'UI admin ont été retirés
- •Icône de corbeille + adminDeleteAddon JS + admin_delete_addon API + 4 étiquettes en 13 langues toutes retirées
- •Seulement « Annuler » — les lignes de données ne sont jamais supprimées (DELETE)
Fixed
- •Conflit de préfixe deux-points dans les espaces réservés Translator —
[':count' => N] → ['count' => N] corrigé en masse
- •
metadata[refund_reason] de PayjpGateway::refund() rejeté par PAY.JP → changé en refund_reason
- •Vérification des permissions admin dans service-manage.php —
role === 'admin' → role IN ('admin','supervisor') corrigé pour 5 actions
- •Onglet domaine de la commande de service : après remboursement, la carte comptable affiche un négatif → logique SQL corrigée (somme séparée status='paid' / 'refund')
Added
- •ssh.21ces.com Cloudflare Tunnel enregistré (Public Hostname : SSH → localhost:22)
- •PC externe :
cloudflared access ssh --hostname ssh.21ces.com ou ProxyCommand dans ~/.ssh/config
- •Côté serveur : PermitRootLogin no, clé thevos enregistrée
Added
HostingProvisioner.php installVoscms() appelle désormais install-core.php en séquence step 3 → step 4 après un déploiement zip (auparavant seulement step 2) :
- •Nouvelle méthode
runInstallCoreSteps() — contournement de session via le fallback POST _db + vérification du marqueur .installed
- •Nouvelle méthode
callInstallCore() — bouclage HTTP (port 80, utilise le SSL edge Cloudflare ; gère l'absence de certificat origin en cas de rate limit)
- •Nouvelle méthode
appendHostingEnv() — réinjecte les variables HOSTING_* après que install-core.php ait écrasé le .env
- •Suppression automatique de welcome.html à la fin de l'installation (pour que VosCMS index.php soit prioritaire)
- •Flux de paiement service-order.php:567-576 — en cas de succès, enregistrement automatique de
install_completed_at et install_admin_url dans les métadonnées addon (déclencheur d'affichage dans l'onglet espace client)
Added
admin/service-orders/detail.php:175-260 + partials/addon.php :
- •Dans l'addon « Support d'installation » de l'onglet services supplémentaires, deux boutons :
- •Installer VosCMS (violet) — affiché si
install_info est présent et install_completed_at absent
- •Page d'administration (vert) — ouvre l'URL admin dans un nouvel onglet après installation
- •Action API
admin_run_voscms_install — appel direct de HostingProvisioner.installVoscms(), avec fallback DB depuis metadata.server.db ou le .env client
- •En cas de succès : écriture des métadonnées addon + entrée
voscms_installed dans order_log
Added
customer/mypage/service-partials/hosting.php :
- •🟢 Bouton Sauvegarde du site —
service-manage.php?action=request_backup (nouveau)
- •mysqldump → dump DB + packaging zip (public_html, .env, sql)
- •URL de téléchargement signée (HMAC, expiration 10 min) — api/backup-download.php nouveau
- •Nettoyage automatique des sauvegardes de plus de 7 jours
- •🟣 Bouton Ouvrir phpMyAdmin —
https://pma.voscms.com/?lang=<user_locale> dans un nouvel onglet
- •vhost nginx : pma.voscms.com.conf nouveau (routage automatique via le wildcard Cloudflare Tunnel
*.voscms.com)
- •Connexion avec les identifiants DB propres à l'utilisateur
- •Affichage des informations de connexion DB (hôte / nom DB / utilisateur / mot de passe avec toggle)
- •i18n 13 langues :
btn_site_backup, btn_open_phpmyadmin, confirm_site_backup, backup_in_progress, backup_ready, f_password, password_notice, f_protocol
Added
customer/mypage/service-partials/_setup-monitor.php :
- •Séparation des étapes : provisionnement hébergement → installation automatique VosCMS
- •Les commandes
system_imported (hébergements enregistrés par l'administrateur, ex. vos.21ces.com) sont activées immédiatement — la boîte de monitoring n'est pas affichée
- •Nouveau i18n 13 langues :
setup_step_voscms_install
Changed
Ajouts aux exclusions rsync :
- •5 plugins internes (ne doivent pas être déployés chez les clients hébergés) :
- •
vos-developer, vos-hosting, vos-license-server, vos-market, vos-salon
- •7 migrations SQL reservation (non installées chez les clients hébergés) :
- •
001_create_reservation_tables.sql, 011_seed_service_translations.sql, 012_seed_service_translations_p2.sql, 013_add_source_to_reservations.sql, 014_add_payment_status_to_reservations.sql, 015_create_reservation_core.sql (nouveau), 016_alter_reservation_services.sql, 024_reservations_bundle_columns.sql
Ajouts aux fichiers dev à supprimer :
- •Répertoire
admin/ (résidu de offline.html) — répertoire vide provoquant un 403 avec l'indexation nginx, seul root /offline.html est référencé par sw.js
- •Encodage de base →
obfuscate.php (l'ancien ionCube EVAL causait un hang à l'exécution ; ionCube uniquement si USE_IONCUBE=1)
Changed
Séparation de la structure où 001_create_base_tables.sql créait à la fois les tables de base et les tables de réservation :
- •Modifié :
001_create_base_tables.sql — uniquement les 5 tables essentielles (rzx_admins, rzx_users, rzx_member_grades, rzx_settings, rzx_migrations) + seeds essentiels (member_grades par défaut, settings par défaut)
- •Nouveau :
015_create_reservation_core.sql — 9 tables de réservation (rzx_categories, rzx_services, rzx_service_options, rzx_reservations, rzx_payments, rzx_point_transactions, rzx_business_hours, rzx_holidays, rzx_staff_positions, rzx_staff) + seeds réservation (business_hours, point_*)
En build de distribution hébergement, 015 est exclu → rzx_reservations non créée → $hasReservations = false dans admin/dashboard.php:25-27 → le calendrier n'est pas affiché automatiquement.
Les sites utilisant le système de réservation (voscms.com, RezlyX, etc.) appliquent les deux fichiers SQL → aucun changement.
Changed
config/templates/nginx-vhost.conf.tpl + HostingProvisioner addHttpsToVhost() :
- •Avant : port 80 (redirection HTTPS) + port 443 (contenu réel) → boucle infinie avec Cloudflare Tunnel + redirection 80→443
- •Après : un seul bloc server unifié 80/443, même contenu servi, aucune redirection
- •
fastcgi_read_timeout 60s → 300s (évite le timeout nginx lors de gros INSERT)
Changed
- •
provision-hosting.php (outil CLI de remplissage) : mise à jour automatique des métadonnées d'abonnement hébergement (hosting_provisioned, server.{ftp,db,env}) — auparavant seul _autoProvisionHosting de service-order.php était exécuté
- •Suppression automatique des 5 plugins internes + du répertoire admin/
Added
Nouveau scripts/install-cli.php :
- •Remplissage de l'appel automatique à install-core.php après le provisionnement hébergement
- •Identifiants DB : priorité aux métadonnées d'abonnement, fallback vers le
.env du docroot client
- •Usage :
sudo -u www-data php scripts/install-cli.php --order=<ORDER>
- •En cas de succès : écriture automatique de
install_completed_at dans les métadonnées addon + action voscms_installed dans order_logs
Fixed
- •Appel manquant à
_autoProvisionHosting() dans la branche paiement par carte — ajouté
- •
install_info.admin_pw dans les métadonnées de paiement était affiché en clair → unification du pattern toggle (👁) côté espace client et côté administration
Migration Notes
- •Clients hébergés externes : aucune action requise. Le build
voscms-2.4.3.zip utilise un zip propre pour l'installation automatique.
- •Site principal (voscms.com) : aucun changement (les deux fichiers SQL sont appliqués).
- •Clients hébergés existants (dwhahn, etc.) : déprovisionner + reprovisionner pour une réinstallation propre (recommandé après la séparation avec le nouveau zip).
- •Nettoyage manuel :
/etc/nginx/sites-available/pma.voscms.com.conf ajouté — à déployer directement sur le système principal (hors rsync).
Added
Appelé immédiatement après la finalisation du paiement dans service-order.php :
- •Nouvelle fonction
_autoProvisionHosting($pdo, $prefix, $orderId, $orderNumber) — s'exécute en dehors de la transaction de paiement (intégrité BD isolée ; la commande elle-même n'est pas affectée en cas d'échec)
- •Seul
domain_option = 'free' est configuré immédiatement (sous-domaine Cloudflare — l'enregistrement DNS automatique est déjà effectué)
- •
new (en attente de changement NS après achat du domaine) / existing (en attente de changement NS du domaine existant) sont en deferred — l'administrateur déclenche séparément au moment de l'activation du domaine
- •Si l'addon 'install' a
install_info, les fichiers voscms sont déployés + .env est généré automatiquement (l'automatisation du flux de session pas à pas d'install-core.php (étapes 2–5) nécessite une refonte complète du pipeline d'installation voscms — reporté en Phase 5 ; l'utilisateur accède à https://<domaine>/install.php après paiement → procède avec l'assistant, infos BD pré-injectées dans .env)
- •Les infos ftp/db/env sont automatiquement enregistrées dans
metadata.server de l'abonnement hébergement → affichage automatique dans l'onglet hébergement de Mon Espace (aucune modification d'UI nécessaire)
- •Actions order_logs :
hosting_provisioned / hosting_provision_skipped / hosting_provision_deferred / hosting_provision_failed
Ordre d'appel : commit paiement → _autoProvisionHosting() → _autoProvisionMailDomain()
Added
$actionLabels sur la page de détail de commande de service administrateur (detail.php:498-528) étendu de 8 à 31 entrées. Corrige l'affichage brut des codes d'action (ex. mail_account_added) dans le journal d'activité.
Actions nouvellement mappées :
- •Mail :
mail_account_added/deleted, mail_address_changed, mail_provisioned/_skipped/_failed, mail_domain_migrated/activated, bizmail_upgrade_request
- •Hébergement :
hosting_provisioned, hosting_provision_skipped/deferred/failed, hosting_deprovisioned
- •Modules complémentaires :
admin_add_storage_addon, admin_delete_addon, storage_addon_paid/requested
- •Système :
customer_notified, setup_email_sent, server_info_updated, bulk_extended, manual_capacity_period_fix
Sémantique des couleurs par action : green (terminé/positif), amber (en attente/avertissement), red (échoué/supprimé), blue (info/notification), violet (admin/spécial), zinc (neutre).
23 clés i18n — services.admin_orders.act_* — ajoutées en ko/ja/en (page opérateur). Les 10 autres langues utilisent l'anglais comme fallback.
Changed
Lors du provisionnement automatique de l'hébergement, l'installation automatique de VosCMS se limite au déploiement des fichiers + génération automatique du .env. L'automatisation du flux de session pas à pas d'install-core.php (étapes 2–5) nécessite une refonte complète du pipeline d'installation voscms — reporté en Phase 5. Après le paiement, l'utilisateur accède à https://<domaine>/install.php → procède avec l'assistant (infos BD pré-injectées dans .env).
Valeur de retour de installVoscms() modifiée — retourne désormais install_url + message note.
Added
HostingProvisioner.php — Classe principale pour la configuration automatique lors d'une commande d'hébergement. Transaction en 9 étapes (annulation dans l'ordre inverse en cas d'échec) :
- •Création d'utilisateur Linux (
vos_<order_number>, dans la limite de 32 caractères, en préservant la casse)
- •Structure de répertoires :
/var/www/customers/<order>/{public_html,logs,tmp} (chmod 750/2775/750/1770)
- •Quota disque (
setquota -u <user> <soft> <hard>, hard = soft × 1.1)
- •Vérification de conflit de répertoire : refus si conflit avec un vhost nginx existant /
reserved_subdomains
- •Montage SSD 1,9 To
/var/www (ext4 + noatime + usrquota,grpquota)
- •Sudoers central (
/etc/sudoers.d/voscms-hosting-provisioner) — www-data exécute les commandes root (useradd/setquota/nginx, etc.) en NOPASSWD
- •Restriction de motif d'argument par commande (
vos_, /var/www/customers/, *.conf) — passe la validation visudo
Outil CLI scripts/provision-hosting.php :
php provision-hosting.php SVC260428AE7476 hotel.com 1GB
php provision-hosting.php --order SVC260428AE7476 # consultation BD automatique
php provision-hosting.php --deprovision SVC260428AE7476 hotel.com
php provision-hosting.php --install-voscms <order> <domain> <capacity>
Modèles config/templates/ :
- •
nginx-vhost.conf.tpl — HTTP + emplacement défi ACME + socket FPM par utilisateur
- •
welcome.html.tpl — page d'accueil d'activation
Added
Chaque hébergement exécute PHP sous son propre utilisateur (évite les compromissions inter-sites) + SSL émis automatiquement même derrière le proxy Cloudflare.
config/templates/php-fpm-pool.conf.tpl :
- •
user = vos_<order> / group = www-data — isolation UID
- •
listen = /var/run/php/<order>.sock — socket par utilisateur
- •
pm = ondemand — efficace en mémoire pour les hébergements à faible trafic
- •
php_admin_value[open_basedir] — accès limité au répertoire du site + /tmp + /usr/share/php
- •
disable_functions — exec, passthru, shell_exec, system, proc_open, popen, pcntl_exec
- •
session.save_path / upload_tmp_dir — isolés dans le répertoire utilisateur
- •env : HOSTING_ORDER / HOSTING_USER / HOSTING_DOMAIN
SSL Let's Encrypt — défi Cloudflare DNS-01 :
- •Plugin
python3-certbot-dns-cloudflare
- •
/etc/letsencrypt/cloudflare/credentials.ini (root 0600, CLOUDFLARE_API_TOKEN depuis .env)
- •Émis indépendamment du proxy Cloudflare / de l'accessibilité externe
- •Bloc serveur HTTPS ajouté automatiquement (TLS 1.2/1.3, chiffrement fort, HSTS, X-Frame-Options, X-Content-Type-Options)
- •Redirection automatique HTTP → HTTPS 301
- •
certbot.timer renouvelle automatiquement deux fois par jour (déjà actif)
Added
Isolation BD + utilisateur par commande d'hébergement.
- •Compte MySQL
hosting_admin (créé une fois, ALL PRIVILEGES + GRANT OPTION) — pour la gestion BD uniquement
- •Nom BD/utilisateur =
vos_<order> (identique au nom d'utilisateur Linux)
- •Mot de passe : 32 hex aléatoire (
bin2hex(random_bytes(16)))
- •
GRANT ALL PRIVILEGES ON vos_<order>.* TO vos_<order>@localhost — accès à sa propre BD uniquement
- •Vérification d'isolation : accès à une autre BD d'hébergement / voscms_prod retourne Access denied 1044
Installation automatique de VosCMS (installVoscms() — déclenché par --install-voscms ou lorsque l'addon a install_info) :
- •Extrait le dernier
voscms-dist/voscms-X.Y.Z.zip → public_html
- •Génère automatiquement
.env : APP_KEY=base64:<32octets> / infos BD / HOSTING_ORDER injecté
- •Permissions : vos_:www-data, .env chmod 640
- •Appel headless de
install-core.php (problème de redirection 301 actuellement, à résoudre en Phase 4)
Verified
provision DEMO260429FULL demo07.21ces.com 1GB --install-voscms :
- •✅ Utilisateur
vos_DEMO260429FULL (isolation UID, groupe www-data)
- •✅ Quota disque 1 Go soft / 1,05 Go hard
- •✅ Pool PHP-FPM avec socket propre
- •✅ vhost nginx (HTTP + HTTPS, HSTS)
- •✅ SSL Let's Encrypt (
/etc/letsencrypt/live/demo07.21ces.com/)
- •✅ BD MySQL
vos_DEMO260429FULL + utilisateur (isolation vérifiée)
- •✅ Fichiers VosCMS 2.3.9 + .env déployés
deprovision : Toutes les ressources proprement supprimées (utilisateur/home/BD/pool FPM/nginx/SSL).
Added
Au lieu du système de facturation anniversaire standard du secteur (date d'inscription jusqu'à la même date un an plus tard), la facturation passe au mode fin de mois calendaire (du 1er du mois suivant jusqu'au dernier jour du mois d'expiration). Les utilisateurs s'inscrivant le même mois partagent la même date d'expiration, ce qui simplifie le traitement par lots cron et la clôture comptable. Suit le standard japonais d'hébergement (月末締め翌月1日請求).
- •BD : colonne
rzx_subscriptions.billing_start DATETIME NULL ajoutée (date de début de facturation normale)
- •Helpers :
_proratedFirstAmount (unité mensuelle ÷ 30 × jours restants), _calendarBillingStart (1er du mois suivant), _calendarExpires (dernier jour 23:59:59)
- •Formulaire de commande :
hosting_prorated ajouté automatiquement aux éléments de paiement hébergement (ex. : inscription le 2/4, 12 mois à ¥1 000/mois → premier mois ¥967 + 12 mois normaux ¥12 000 = ¥12 967)
- •Les domaines conservent la facturation anniversaire (cycle d'enregistrement d'1 an) ; hébergement, mail, maintenance et add-ons utilisent la facturation calendaire
- •Le traitement
-1 second → -1 day dans service-order.php également unifié
- •Les services complémentaires (espace web supplémentaire) utilisent aussi le même prorata + somme des N mois normaux, synchronisés automatiquement avec la date d'expiration de l'hébergement
Added
Installation de Postfix + Dovecot + Rspamd + Roundcube + OpenDKIM + Let's Encrypt sur ConoHa VPS (133.117.72.149). mail-tester 10/10, FCRDNS vérifié. Configuration automatique du domaine à la commande.
- •Enregistrement DNS automatique (
CloudflareDns.php) — A / MX / SPF / DKIM / DMARC 5 enregistrements en un seul lot
- •Génération de clé DKIM — mx1 SSH
rspamadm dkim_keygen (clé ed25519 dédiée storage/keys/mailsync_ed25519, propriétaire www-data, 0700)
- •Provisionnement en 3 modes (
MailDomainProvisioner.php) : free (sous-domaine instantané) / new (domaine acheté, activation admin) / existing (instructions de changement NS). Machine à états : existing_pending / new_pending / active
- •Mot de passe : SHA512-CRYPT (
{SHA512-CRYPT}$6$...) — hash unidirectionnel compatible Dovecot. Script de migration pour les anciens mots de passe enc: (fonction encrypt) : scripts/migrate-mail-passwords.php
- •Cron de synchronisation mx1 (
scripts/mail-sync-to-mx1.php) — voscms_prod → mx1 mail_lookup virtual_users toutes les 5 minutes. Déclencheur immédiat (triggerMailSyncToMx1()) pour synchronisation en arrière-plan juste après les actions mail
- •Enregistrement automatique du cron :
/etc/cron.d/voscms-mail-sync
- •Notifications : modèles de mail HTML pour admin (provisionnement requis) / client (mail disponible) (
MailNotifier.php)
Added
Mail de base / mail professionnel géré conjointement avec l'hébergement. Correction du problème d'affichage en double où la même adresse était stockée dans la souscription mail ET dans les métadonnées d'hébergement (source unique de vérité : souscription mail).
- •Bouton webmail — paramètre GET
?_user=adresse de Roundcube pour préremplir le nom d'utilisateur, target="_blank". Priorité URL : metadata.mail_server.webmail_url → env WEBMAIL_URL → défaut https://mail.voscms.com/
- •Bouton de changement d'adresse mail — pour corriger les fautes de frappe. Le domaine est fixe ; seule la partie locale change. Toutes les métadonnées mail + hébergement de la même commande sont synchronisées
- •Logique de déduplication (
mail.php) — _seenAddresses affiche chaque adresse une seule fois, la souscription mail est prioritaire
- •La conversion virtuelle hébergement → mail dans service-detail.php ne s'exécute que lorsqu'il n'existe pas de vraie souscription mail (compatibilité ascendante)
- •service-order.php ne sauvegarde plus hosting metadata.mail_accounts pour les nouveaux abonnements (la souscription mail est la source unique)
Added
Achat de stockage complémentaire avec paiement dans l'onglet services complémentaires de Mon espace. Enregistrement client PAY.JP + chargeCustomer.
- •Modal : sélection de capacité (1 Go / 3 Go / 5 Go) + saisie des informations de carte (payjp.js v2 Elements)
- •Enregistrer la carte / payer avec une autre carte / revenir à la carte enregistrée — bascule
- •Détection automatique des cartes expirées/refusées (
expired_card, card_declined, invalid_* etc., codes d'erreur PAY.JP) → formulaire de carte ouvert automatiquement + bannière d'orientation
- •Champ de nom du titulaire de carte ajouté (
addon-card-holder) — stocké comme métadonnées client, non transmis au token (PAY.JP v2 Elements ne prend pas en charge l'option name)
- •Modèle Portal :
document.body.appendChild() pour sortir des conteneurs avec transform et couvrir tout le viewport (z-[9999])
- •Si le débit échoue après la création d'un nouveau client : remboursement automatique + suppression du client (prévention des orphelins)
- •hosting metadata.extra_storage[] cumulé ; la jauge de stockage de l'onglet hébergement affiche le total combiné
Added
Structuration de 14 articles (définitions, demande, tarifs, renouvellement automatique, résiliation, service, sauvegarde, utilisations interdites, suspension, maintenance, vie privée, responsabilité, modifications, juridiction) en référence aux conditions générales standard des hébergeurs japonais comme StarServer. Facturation calendaire + prorata premier mois + remboursement des mois non utilisés en cas de résiliation spécifiés.
- •Enregistrement page système :
config/system-pages.php slug hosting-terms, 🖥️ indigo
- •Mapping éditeur de pages :
pages-document.php — pageMetaMap['hosting-terms']
- •Seed BD : ja (principal) / ko / en — 3 langues (rzx_page_contents)
- •i18n :
site.pages.hosting_terms + hosting_terms_edit (editor_title/desc)
Added
- •4 onglets toujours visibles (detail.php) — hébergement/domaine/mail/addon. Message d'état vide (empty_*) affiché quand aucune donnée
- •Onglet services complémentaires — bouton
+ Ajouter du stockage (modal d'attribution gratuite admin ; la sélection de capacité crée immédiatement une addon subscription active, billing_amount=0, expires=date d'expiration hébergement) + bouton corbeille/suppression par élément (suppression logique status=cancelled, supprimé de hosting metadata.extra_storage[])
- •Liste — amélioration de l'affichage du demandeur (index.php) — les commandes des administrateurs système avec rôle
supervisor/admin s'affichent sous la forme user.name + sous-titre violet Super-administrateur : [email protected] (contourne l'échec de déchiffrement de l'ancien applicant_name chiffré comme FKzGx9SE7xG/2)
- •Bouton de création de commande (
+ New Order) — interface uniquement, fonctionnalité à venir
- •i18n 13 langues :
role_supervisor, role_admin, btn_create_order, empty_, btn_add_storage_addon, btn_delete_addon, modal_add_storage_, confirm_, alert_ et plus de 20 clés supplémentaires
Added
- •
subdomain-check.php — priorité BD (reserved_subdomains) + fallback API Cloudflare. JS checkSubdomain() appelle le serveur et reflète le résultat
- •Revalidation côté serveur dans service-order.php juste avant le paiement — empêche le contournement côté client
- •Import automatique de
reserved_subdomains — 11 enregistrements existants de la zone Cloudflare (vos/bestatech/bt/dev/ec430/ec431/salon/ssh/test/thevos/ai.21ces.com)
- •Correction du bug INSERT IGNORE du menu (menus-api.php) :
- •
add_menu_item : nettoyer les traductions périmées immédiatement après INSERT + écraser avec INSERT ... ON DUPLICATE KEY UPDATE
- •
update_menu_item : détecter les changements title/url, supprimer les 13 anciennes traductions + ré-enregistrer si page système
- •
rename_menu_item : nettoyer les anciennes traductions lors du changement de titre
- •Correction de la régression où l'ancien menu (id=38, « Introduction à VosCMS ») pointait vers le nouveau menu des CGU d'hébergement
Added
Flux construit : commande de service → paiement effectué → provisionnement automatique du domaine mail → notification client.
- •Appel à
_autoProvisionMailDomain() ajouté dans service-order.php — s'exécute en dehors de la transaction de paiement (isolation de l'intégrité BD)
- •BD :
rzx_reserved_subdomains (zone, subdomain, record_type, reserved_by, reason) — cache de disponibilité
- •Clé DKIM générée automatiquement, stockée dans metadata.mail_provision sous forme mode/origin/domain/zone/subdomain/provisioned_at
- •Branchement UI par mode de provisionnement (service-detail.php) :
pending / new_pending / existing_pending — onglets masqués, seul le monitoring affiché (_setup-monitor.php) ; onglets visibles uniquement à l'état active
Fixed
Le $arr['key'] ?? [] de PHP retourne une valeur temporaire, donc &$ref n'affecte pas le tableau d'origine. change_mail_password / change_mail_address renvoyaient des réponses de succès mais l'UPDATE des métadonnées était sans effet — les changements de mot de passe et d'adresse échouaient silencieusement.
- •Passage au modèle de mise à jour directe par index :
foreach ($arr as $i => $item) { $arr[$i]['k'] = ... }
- •Le stockage du nouveau mot de passe mail dans service-order.php également changé de
encrypt() (bidirectionnel) vers mail_password_hash() (SHA512-CRYPT)
Fixed
- •Résumé de paiement vert fluo vif → couleur plus propre :
text-green-400 → text-green-600 dark:text-green-400 (7 emplacements)
- •Clé i18n manquante dans le message de réponse de disponibilité de sous-domaine (mapping PHP→JS i18n dans
order.php + espace réservé :fqdn unifié)
- •Calcul de la date d'expiration corrigé :
+N months -1 second (même jour) → +N months -1 day (exactement 1 jour avant) → finalement unifié à la méthode calendaire
Database
- •
rzx_subscriptions.billing_start DATETIME NULL ajouté (dev + prod)
- •Table
rzx_reserved_subdomains (cache de collision de zone Cloudflare)
- •
rzx_page_contents initialisé avec hosting-terms (ja/ko/en)
Added
Tous les textes des 6 zones (domaine, hébergement, options, demandeur, paiement, récapitulatif) et de la page de paiement complété ont été traduits en 13 langues. Les textes d'alerte/modal côté client sont injectés depuis PHP via le modèle var I18N = {...} + t(key, replace).
- •Emplacement : plugins/vos-hosting/lang/{13 locales}/services.php —
services.order.* plus de 200 clés
- •Détail du service sur Mon espace :
services.detail.* plus de 70 clés, service-detail.php
- •Gestion des commandes admin :
services.admin_orders.* plus de 115 clés, admin/service-orders/
- •Les libellés coréens stockés en BD (plans d'hébergement, maintenance, options) sont mappés par ID de paramétrage via le closure
_localizeLabel($sub) et db_trans() est appliqué → traitement cohérent sur Mon espace et l'admin
Added
Au clic sur le bouton de paiement, les détails de la commande (domaine/plan/options/demandeur/conditions) sont validés et un modal récapitulatif est affiché → l'utilisateur confirme → le paiement est traité. Empêche des erreurs comme l'enregistrement d'un sous-domaine vide.
- •order.js —
showOrderConfirmModal(), closeOrderConfirmModal(), confirmAndPay()
- •Suppression renforcée des couches de modal résiduelles après paiement (suppression DOM + réinitialisation du overflow body/documentElement)
Added
Lorsque "Support d'installation" (_id='install') est coché dans les options, un formulaire apparaît pour l'ID administrateur/e-mail/mot de passe/nom du site. Le mot de passe est masqué + bascule icône œil + notice "changer après installation". Les valeurs sont stockées comme install_info dans les métadonnées d'abonnement et affichées sur Mon espace et l'admin.
- •Saisie : _addons.php
- •Affichage : Mon espace/admin partials/addon.php (boîte à fond bleu + bascule mot de passe)
Added
Le mémo lié à l'onglet options a été déplacé au niveau de la commande (rzx_orders.admin_notes). Il s'affiche toujours sous forme de zone de texte de 7 lignes au-dessus du journal d'activité à droite, qu'il y ait des options ou non. Action AJAX update_order_memo ajoutée.
Added
Un champ section (top/main/bottom, par défaut main) a été introduit pour séparer visuellement les menus du cœur des menus de plugins. Un séparateur est inséré automatiquement entre les zones ; si une zone n'a aucun menu affichable, toute la zone incluant le séparateur est ignorée.
Barre latérale admin :
- •top : Tableau de bord / Gestion des membres / Gestion du site / Installation automatique (
vos-autoinstall)
- •main : Licence VosCMS (
vos-license-manager) / Gestion de l'hébergement (vos-hosting)
- •bottom : Plugins / Paramètres
- •Modifications : config/admin-menu.php, admin-sidebar.php
Barre latérale Mon espace :
- •top : Tableau de bord / Profil / Messages
- •main : Services (
vos-hosting ajouté automatiquement) — s'accumule automatiquement lorsque d'autres plugins ajoutent des entrées
- •bottom : Paramètres / Mot de passe / Suppression du compte / Déconnexion
- •Modifications : config/mypage-menu.php, mypage-sidebar.php
Enregistrement du menu plugin : les champs section + position dans les entrées menus.admin / menus.mypage de plugin.json spécifient la zone. Le menu services a été déplacé de core mypage-menu.php → vos-hosting/plugin.json (enregistrement automatique).
Added
L'API de validation de licence et l'API du portail développeur étant dans le cœur, elles seraient exposées sur tous les sites voscms déployés. Les deux APIs ont été séparées dans un nouveau plugin réservé au siège.
- •
vos-license-server (scope: hq_only) : 7 endpoints de licence déplacés (check, register, verify, stats, updates, register-plugin, _init)
- •
vos-developer (scope: hq_only) : 7 endpoints du portail développeur déplacés (register, login, submit, my-items, earnings, update-version, _init)
- •
api/_plugin_dispatch.php — le wrapper du cœur vérifie rzx_plugins.is_active avant de dispatcher ; retourne 404 si inactif
- •Le cœur
/api/license/.php et /api/developer/.php ne conservent que le wrapper (compatibilité externe maintenue)
- •
/api/notices.php avec liste blanche d'env HQ_HOSTS ajoutée (répond uniquement depuis le domaine HQ voscms.com)
- •Le script de build (
build-voscms.sh) exclut déjà api/license, api/developer, api/notices.php et vos-license-manager
Fixed
- •Bug de +1 jour sur la date d'expiration du contrat d'hébergement (
+12 months → +12 months -1 second) — appliqué à 4 endroits : subscription/free/paid/bank
- •E-mail professionnel : impossible d'en ajouter 2 ou plus (le sélecteur capturait le bouton X)
- •Récapitulatif de commande : stockage supplémentaire non agrégé (attribut
name manquant sur le select de stockage)
- •Libellé du plan d'hébergement non localisé — résolu en faisant correspondre
service_hosting_plans._id avec db_trans()
Added
_init.php interroge désormais directement rzx_translations pour board.{id}.{title|description|header_content|footer_content|seo_keywords|seo_description} (locale actuelle → en → source). Sur toutes les pages — list/read/write/settings — $board[$field] est automatiquement rempli avec la valeur traduite. Le bouton "← Retour" sur la page de paramètres du forum est également traduit automatiquement via le même mécanisme.
Seed en 13 langues pour title + header_content du forum des incidents (id=6) — structure HTML préservée, seul le texte est traduit, les badges d'étape de traitement également dans chaque langue. Scripts de seed : scripts/seed_issue_i18n.php + scripts/seed_issue_i18n_data.php.
Added
Traduction des définitions (étiquette/description/options/valeur par défaut) de rzx_board_extra_vars en 13 langues. 4 champs × 13 = 52 lignes.
- •
ExtraVarRenderer::renderAll($vars, $values, $mode, $boardId) — argument boardId ajouté, applyDefTranslations() charge toutes les traductions des vars en une seule requête.
- •
ExtraVarRenderer::getOptionLabel($boardId, $varName, $value) — consultation de l'étiquette traduite d'une seule option pour les vues de liste (cache statique).
- •
renderStatusBadge($value, $size, $displayLabel = null) — la couleur utilise le mappage source (ko), seul le texte est traduit → couleur cohérente dans toutes les langues (reçu = rose, résolu = émeraude).
- •select/radio/checkbox : modèle
value=source / label=traduit. La valeur source est toujours enregistrée lors de la publication, garantissant la compatibilité des données.
- •Mises à jour des appelants :
read.php, write.php, _list-row.php, _list-card/_list-webzine/_list-gallery du skin par défaut.
Seed en 13 langues pour la variable extra status du forum des incidents : scripts/seed_ev_status_i18n.php.
Added
L'API extra_var_get retourne les valeurs traduites pour la locale actuelle sous forme d'objet localized via db_trans(). Le modal JS affiche localized.title || ev.title en priorité → en mode japonais, l'ouverture du modal affiche automatiquement "処理ステージ".
extra_var_update se branche selon la locale :
- •Locale source (ko) → mise à jour de la ligne source entière (comportement existant)
- •Locale non source (ja/en/…) → seules les métadonnées (
var_type/permissions/3 cases) sont sauvegardées dans la source ; les 4 champs de traduction (title/description/options/default_value) sont sauvegardés dans rzx_translations sous la locale actuelle → intégrité de la source garantie
Les noms d'affichage dans la liste des variables extra utilisent également db_trans('board_ev.{boardId}.{varName}.title').
Added
La section "Permission d'édition" (étiquette/options du menu déroulant/texte d'aide) du modal d'édition des variables extra séparée dans des fichiers lang de 13 langues. Nouvelles clés : site.boards.ev_permission, ev_perm_all, ev_perm_member, ev_perm_admin, ev_permission_help.
Added
Normalisation bidirectionnelle du champ "Options" dans le modal d'édition des variables extra :
- •Chargement du modal : convertit le tableau JSON de la DB (
["a","b","c"]) en format saut de ligne pour l'affichage dans la textarea (correspondant aux instructions)
- •API de sauvegarde : le helper
ev_normalize_options() accepte une entrée en saut de ligne ou JSON et sauvegarde systématiquement en tableau JSON. Correction d'un bug où les entrées en saut de ligne étaient sauvegardées comme NULL.
Added
Deux nouveaux skins pour les modèles de contenu au-delà des incidents/annonces.
FAQ (skins/board/faq/) — publication = question, corps = réponse. Inclut barre de recherche, filtre de catégorie et pagination. Bascule d'affichage de la zone de titre, titre/sous-titre multilingue, support de fond (image/vidéo/aucun), réglage de l'opacité du calque. v1.0.1.
Q&A (skins/board/qna/) — publication = question (titre+corps), commentaire = réponse. Badge "sans réponse", premier élément auto-développé, affichage des commentaires triés en arbre (parent_id/depth). Les réponses aux réponses sont indentées + étiquetées "↳ Réponse" (niveau supérieur = "A."). Formulaire inline d'édition/réponse (auteur/admin uniquement pour l'édition, permission perm_comment pour les réponses). v1.0.0.
Les deux skins partagent : icône d'engrenage des paramètres admin placée en bas à droite de la barre de recherche (séparée de la zone de titre). boardSkinFile() fonctionne avec la priorité _list-full.php.
Added
Action update ajoutée à api-comments.php. Seuls comment.user_id == utilisateur actuel ou admin peuvent modifier. Après validation du nombre de caractères, met à jour content + updated_at.
Added
Le jeton {year} dans le champ copyright des paramètres de mise en page est automatiquement remplacé par l'année en cours lors du rendu. La DB conserve l'original (avec {year}) de sorte qu'il ne nécessite jamais de mise à jour manuelle. Appliqué à : default/minimal/modern/base-footer.php. La description du copyright dans 4 fichiers layout.json étendue à 13 langues, avec les instructions d'utilisation de {year} affichées dans chaque langue native.
Également corrigé un bug où $_lc['copyright'] était ignoré dans les pieds de page default/minimal — la valeur des paramètres de mise en page est maintenant effectivement rendue.
Added
Seed en 13 langues pour menu_item.38.title (Présentation de VosCMS / About VosCMS / VosCMSについて / Über VosCMS / Acerca de VosCMS / À propos de VosCMS / Tentang VosCMS / VosCMS-ийн тухай / О VosCMS / VosCMS Hakkında / Giới thiệu VosCMS / 关于 VosCMS / 關於 VosCMS).
Added
Un exemple par étape de traitement + 1 existant résolu = 4 au total. Traduction du titre/contenu de chaque publication en 13 langues (104 lignes).
| Étape | Titre (ko) | Statut |
|---|
| Reçu | [Bug] Le bouton X du menu hamburger mobile ne fonctionne pas | Nouveau |
| En cours d'examen | [Demande de fonctionnalité] Notification par e-mail à l'auteur lors d'un commentaire | Nouveau |
| En cours | [Performance] Améliorer la vitesse de chargement initial de la page de détail du marketplace | Nouveau |
| Résolu | Image jointe dans une publication du forum insérée dans le corps... | Existant |
Publication 34 existante supprimée (publication de test avec styles inline Tailwind accumulés).
Fixed
customer/board/list.php faisait un require du helper rzx_admin_icons à la ligne 167, mais l'include du fichier skin à la ligne 161 sortait avec return — provoquant une erreur 500 lors de l'appel de rzx_admin_icons() dans les skins FAQ/Q&A. Le require_once a été déplacé avant l'include du skin.
Changed
Suppression des références résiduelles à l'ancien nom /marketplace. Correction d'un bug où le formulaire de recherche soumettait en GET vers /marketplace, provoquant une redirection vers le tableau de bord (navigation hors page lors des changements de recherche/tri/filtre). Unification de tous les fichiers browse.php, item-detail.php, item-submit.php, purchases.php et assets/js/marketplace.js vers /autoinstall.
Added
À l'étape 4 de install.php, ajout d'une astuce jaune sous le champ de saisie du chemin administrateur, d'un aperçu d'URL en temps réel et d'un guide dépliable « Pourquoi devrais-je le changer ? ». Trois raisons présentées dans un langage accessible à tous : tentatives de piratage automatisé (force brute), analyse de vulnérabilités et limites des mots de passe forts. Appliqué aux 13 langues.
Added
À l'étape de finalisation de l'installation de install.php, le plugin vos-autoinstall est automatiquement enregistré et activé (en appelant directement PluginManager::install()). Les utilisateurs peuvent accéder au marketplace dès l'entrée dans le panneau d'administration sans étape d'installation supplémentaire.
Added
Ajout du paramètre ?locale=xx à market.21ces.com/api/market/catalog et /item. Le JSON multilingue de name, description, short_description, cat_name est renvoyé comme une seule chaîne par le serveur (repli : locale demandé → en → première valeur). Suppression de toute la logique en double json_decode + locale fallback côté VosCMS (browse.php, item-detail.php, _components/item-card.php).
Added
Gestion intégrée du TTL du cache de réponse API du marketplace (basé sur des fichiers) dans les paramètres de PluginManager. 30 minutes codées en dur → 5 minutes par défaut, options 1/5/10/30/60 minutes. La section cache marketplace de https://vos.21ces.com/theadmin/settings/general et /theadmin/autoinstall/settings lisent et écrivent le même paramètre, avec synchronisation automatique. Bouton d'actualisation immédiate du cache ajouté sur la page AutoInstall et la page de paramètres généraux. Le cache existant est automatiquement invalidé lors d'un changement de TTL.
Added
Affichage du même tableau que l'admin du marketplace (type de données / courte description / slug / Product Key / versions VosCMS et PHP minimales / partenaire / prix / licence) immédiatement après l'en-tête. Ratio de contenu gauche:droite modifié de 2:1 à 3:1 pour agrandir la zone de contenu.
Added
Bouton « Écrire un avis » en haut à droite de l'onglet avis de la page de détail. Modal de saisie note par étoiles / pseudo / corps → API VosCMS → relayé vers le marketplace POST /api/market/item/review. Clé de licence VosCMS + domaine attachés automatiquement, limite d'une soumission par domaine, les acheteurs reçoivent automatiquement is_verified=1. Les avis sont stockés dans la BD du marketplace (rzx_mkt_reviews) avec status='pending' et publiés après approbation de l'opérateur. Nouvel endpoint GET /api/market/item/reviews?slug=... retourne uniquement les avis approuvés. Le domaine est partiellement masqué (mys***.com).
Added
L'ancienne case à cocher Gratuits uniquement → étendue à un toggle 3 états Tous / Gratuits / Payants. Paramètre paid=1 ajouté à l'API catalog du marché (i.price>0). Sorti de la barre de recherche et déplacé devant la zone de toggle de vue, intégré avec le sélecteur de tri dans une barre d'outils d'en-tête.
Changed
Bordure de l'input de recherche border-2 border-emerald-300, boîte de fond vert sur l'icône de recherche gauche, bouton de recherche bg-emerald-500. Barre de recherche simplifiée en ne conservant que la saisie de mots-clés ; tri et filtres déplacés vers l'en-tête du corps.
Changed
| Statut | Affichage |
|---|
| Gratuit | Installer + Télécharger |
| Payant (non acheté) | Acheter (modal de paiement PAY.JP du marketplace) |
| Payant (acheté) | Installer + Télécharger |
| Déjà installé | « Installé » |
Même branchement appliqué aux 4 vues de liste (liste/webzine/carte/grille). L'ensemble des slugs achetés est interrogé une fois à l'entrée de la page et réutilisé. Le paiement est géré par le marketplace POST /api/market/item/purchase, qui effectue la facturation PAY.JP + émission de licence.
Changed
- •Toggle de style de vue : étiquettes texte supprimées → icônes uniquement +
title / aria-label (accessibilité maintenue)
- •Badge de type : fond clair
bg-<color>-100 → translucide sombre bg-zinc-900/85 backdrop-blur-sm + texte coloré (meilleure lisibilité sur les images)
- •Section captures d'écran : déplacée de juste après l'en-tête → sous le contenu des onglets, comptage affiché comme
(n) comme dans le marketplace
- •
dark:prose-invert sur la page de détail ne fonctionnait pas → plugin typography ajouté au CDN Tailwind
- •Zone de description de la page de détail : même approche que l'admin du marketplace — rend le balisage HTML tel quel, en supprimant uniquement les éléments dangereux comme
<script>/<iframe>/<style>/onXX
Fixed
- •Formulaire de carte PAY.JP n'accepte pas les saisies : monté en avance à l'état caché, causant le rendu de l'iframe à 0px. Résolu avec initialisation paresseuse + montage
requestAnimationFrame
- •Miniature de widget manquante : 28 widgets enregistrés dans la BD du marketplace mais seulement 12 widgets gratuits copiés dans
/var/www/market/widgets/. Synchronisation des 14 manquants. Conversion d'URL absolue pour screenshots + filtrage automatique des fichiers inexistants ajoutés à l'API catalog/item
- •Avertissement d'autorisation de plugin bundle :
vos-autoinstall était capturé comme unauthorizedPlugins. Constante BUNDLE_PLUGINS = ['vos-autoinstall', 'vos-marketplace'] ajoutée à LicenseStatus.php, filtrage appliqué dans active()/fromCache()/canUsePlugin(). Même traitement appliqué au serveur de licences verify.php
- •Possibilité d'ajout en double de widgets : le seeding de
install.php n'utilisait que INSERT IGNORE, mais rzx_page_widgets n'a pas de contrainte UNIQUE, donc les doublons étaient possibles. Changé en DELETE FROM page_widgets WHERE page_slug='home' avant INSERT (la contrainte UNIQUE DB n'est pas ajoutée car des doublons intentionnels existent pour des cas comme les widgets de forum)
Migration Notes
- •Le menu/routes/migrations du plugin
vos-autoinstall sont auto-activés sur les nouvelles installations (les installations existantes doivent l'activer une fois depuis le panneau d'administration)
- •TTL par défaut du cache de l'API marketplace : 30 minutes → 5 minutes (pour une réflexion plus rapide des changements de prix/contenu)
- •Le paramètre de plugin
vos-autoinstall.cache_ttl est nouveau
Changed
- •
browse.php : passage de la requête BD locale à un appel API en direct vers market.21ces.com/api/market/catalog
- •
item-detail.php : passage de la BD locale aux appels API /api/market/item et /api/market/item/versions
- •
CatalogClient.php : URL de base de l'API modifiée de /api/v1 → /api/market, champ de réponse items[] → data[] aligné
Fixed
Problème : Le bloc d'application de la mise en page dans market.21ces.com/index.php ne gérait pas le cas $__noLayout = true, ce qui faisait retourner HTTP 200 + réponse vide à toutes les routes API du plugin (api/market/*).
Correction : Ajout de elseif ($__pageFile && $__noLayout) { include $__pageFile; } en fin de index.php. api/market/catalog, api/market/item, api/market/updates/check, etc., fonctionnent désormais correctement.
Added
Paramètres sort, free et featured ajoutés à plugins/vos-market/views/api/catalog.php, avec des champs de réponse étendus (sale_price, rating_avg, is_featured, etc.).
Added
Helper mpApiFetch() : minimise les requêtes vers le serveur marketplace grâce à un cache fichier TTL de 30 minutes. Affiche une bannière d'erreur en cas d'échec de la réponse API.
Fixed
Problème : Dans AdminRouter, après la création d'une instance $licenseClient = new LicenseClient() et la tentative d'enregistrement automatique, la mise à jour de $_ENV['LICENSE_KEY'] n'était pas reflétée dans le $this->licenseKey interne de l'instance — de sorte qu'un appel à check() dans la même requête renvoyait toujours unregistered.
Changed
- •À l'entrée de
check(), si $this->licenseKey est vide, appeler immédiatement /api/license/register
- •En cas de succès : mettre à jour
$this->licenseKey + mettre à jour $_ENV['LICENSE_KEY'] + sauvegarder le fichier .env, puis passer à l'étape de vérification
- •Renvoyer
unregistered uniquement en cas d'échec (pas de réponse du serveur)
- •Nouvelle méthode
saveKeyToEnv() : remplace une ligne LICENSE_KEY= vide (cas d'échec d'install.php) par la clé réelle ; ignorée si une clé valide existe déjà
Effet
- •Utilisateurs ayant installé manuellement sans install.php → licence enregistrée automatiquement au premier accès à l'administration
- •Utilisateurs ayant mis à jour depuis une ancienne version (sans LICENSE_KEY) → enregistrement automatique au premier accès à l'administration après la mise à jour
- •Le message du tableau de bord « Licence non enregistrée » n'apparaît désormais que lorsque le serveur de licences lui-même est inaccessible
Fixed
Le fichier seed database/seeds/legal_pages.php contenait des variables CSS Tailwind (--tw-scale-x, --tw-pan-x, etc., 400+) intégrées en ligne dans l'attribut style="" de chaque balise <h1>/<h2>/<p>. Chaque installation propageait cette contamination dans la BD, alourdissant les pages terms et privacy (notamment privacy/ko atteignait 128KB ; la normale est 2KB).
- •
database/seeds/legal_pages.php : 442KB → 131KB (réduction de 70%, syntaxe valide)
- •Nettoyage de 26 lignes déjà contaminées dans la BD de développement : 1,04MB → 56KB (988KB supprimés, −95%)
- •Nouveau
scripts/clean-inline-styles.php — outil de nettoyage en masse pour style="... --tw-* ..." (réutilisable en cas de récurrence)
Changed
Le CSS de .board-content contenait des règles forçant la conversion de chaque page de document en traitant « h2 comme en-tête de carte et h2+p comme corps de carte ». Cela brisait la structure hero des pages conçues directement avec Tailwind (ex. Brand).
- •Suppression de 103 lignes de règles de blocs en cartes (149 → 45 lignes)
- •Règles restantes : typographie de base (p/h·/blockquote/code/ul/ol/table), carte de lien OG, surcharge du texte en mode sombre
- •Résultat : design original de la page
Brand restauré (h2 avec barre bleue gauche, hero centré, etc.)
- •Les documents juridiques (terms/privacy, etc.) sont suffisamment servis par la typographie standard
<h1><h2><p> — le style en cartes était une décoration excessive
Changed
Contexte : En 2.3.1, le contenu des pages a été séparé entre rzx_page_contents pour l'original coréen et rzx_translations pour les autres langues, puis en 2.3.2 un chemin de sauvegarde distinct a été ajouté dans l'éditeur. Cependant, après révision de la conception, il est apparu que les deux tables ont une structure essentiellement identique (slug/key + locale + content) tout en engendrant les coûts suivants :
- •Le texte original coréen est stocké en double dans les deux tables (pour le miroir de la chaîne de fallback db_trans)
- •La logique de sauvegarde de l'éditeur nécessite une branche ko vs. non-ko
- •L'affichage de l'état de la locale dans l'interface de gestion des pages requiert un JOIN sur deux tables
- •La justification initiale (« file d'attente du pipeline de traduction IA intégrée ») a peu de valeur en pratique, car le corps long des pages HTML (10 Ko) et les courtes chaînes d'interface (20 octets) nécessitent des workflows différents (découpage en fragments, préservation des balises, etc.)
Structure restaurée : table unique rzx_page_contents, une ligne par locale (conception d'origine)
Migration
- •
rzx_translations.page.{slug}.title/content × 7 slugs × 12 locales non-ko (168 lignes) → restauré dans rzx_page_contents
- •Toutes les clés
page.* supprimées de rzx_translations (234 lignes)
- •Cibles : Brand, terms, privacy, refund-policy, tokushoho, funds-settlement, data-policy
- •Appliqué aux bases de données de développement et de production
Changed
- •
resources/views/admin/site/pages-edit-content.php — branche ko/non-ko supprimée, UPSERT simplifié
- •
resources/views/admin/site/pages-document.php — idem
- •
resources/views/customer/page.php — db_trans('page.*.title/content') supprimé, lecture directe depuis page_contents (chaîne de fallback locale → en → ko maintenue)
- •
resources/views/admin/site/pages.php — les titres de la liste des pages lisent également directement depuis page_contents.title
Kept
rzx_translations est maintenu — continue d'être utilisé pour :
- •Forums (
board_post.{id}.title/content)
- •Chaînes d'interface (
menu.*, libellés de paramètres)
- •Méta SEO de page (
page.{slug}.browser_title|meta_keywords|meta_description) — courtes chaînes, appropriées ici
Principe : courtes chaînes d'interface/méta → rzx_translations ; long contenu de corps de page → rzx_page_contents, stockage séparé selon les caractéristiques de chaque type de données.
Changed
Après la migration en 2.3.1 de la structure de sauvegarde du contenu des pages vers ko original (rzx_page_contents) + DB de traduction (rzx_translations), l'éditeur administrateur continuait à INSERT/UPDATE toutes les locales uniquement dans rzx_page_contents — créant un décalage avec le format de migration et des échecs de requête de db_trans() côté rendu. Cette version corrige ce problème.
Règles de branchement (locale source = $_ENV['DEFAULT_LOCALE'] ?? 'ko'):
| locale | destination de sauvegarde |
|---|
ko (source) | rzx_page_contents + miroir dans rzx_translations (repli pour db_trans()) |
en/ja/zh_CN/... | rzx_translations uniquement (page.{slug}.title, page.{slug}.content) |
Lors de la sauvegarde d'une locale non source, si la ligne source n'existe pas dans rzx_page_contents, une ligne stub est créée automatiquement (pour préserver les connexions menu/paramètres). is_active est appliqué uniformément à la ligne source.
Changed
Lors de l'ouverture d'une page d'édition de locale non source :
1. Rechercher d'abord page.{slug}.title/content + locale dans rzx_translations
2. Se replier sur la ligne héritée de rzx_page_contents si non trouvée (compatibilité avec les pages manquées lors de la migration)
Pour la locale source, seul rzx_page_contents est utilisé comme avant.
Changed
- •Suppression de page : aussi supprimer
rzx_translations WHERE lang_key LIKE 'page.{slug}.%'
- •Changement de slug : UPDATE en masse de
page.{old_slug}. → page.{new_slug}. dans rzx_translations.lang_key
Changed
L'ancienne méthode consistant à stocker une ligne de contenu complet par locale dans rzx_page_contents a été unifiée en méthode ko original + BD de traduction (rzx_translations). Assure la cohérence structurelle avec le format de stockage du forum (board_post.*).
7 pages cibles : Brand, terms, privacy, refund-policy, tokushoho, funds-settlement, data-policy
Before:
rzx_page_contents
├── Brand / ko (contenu complet)
├── Brand / en (contenu complet)
├── ... (13 lignes de locale)
After:
rzx_page_contents
└── Brand / ko (1 ligne originale)
rzx_translations
├── page.Brand.title × 13 locale (ko inclus)
└── page.Brand.content × 13 locale
Résultats de la migration :
- •
rzx_page_contents : 7 slugs × 12 lignes non-ko = 84 lignes supprimées
- •
rzx_translations : 7 slugs × 13 locales × (title + content) = 182 lignes migrées
- •Appliqué aux BD de développement et de production, validation du rendu réussie (affichage correct par locale pour ko/en, etc.)
Changed
- •Bouton « Nouvelle page » de l'en-tête supprimé — c'était un espace réservé non fonctionnel. Les pages sont créées depuis la gestion des menus comme unique source de vérité.
- •Icône corbeille 🗑 + handler AJAX + JS
deleteUserPage() supprimés — les pages sont nettoyées lors de la suppression du menu, donc un chemin de suppression de page autonome est inutile. Évite les menus corrompus par des suppressions involontaires.
- •Conservés : icônes paramètres ⚙ · modifier ✏ · aperçu 👁
Fixed
- •Échec du téléversement dans
Paramètres > Site > Image du logo : move_uploaded_file() échouait silencieusement en raison de l'absence du sous-répertoire storage/logos/. Ajout de la création automatique du sous-répertoire au gestionnaire de téléversement + création du répertoire sur les serveurs de développement et de production (www-data:www-data, 775).
- •Priorité du logo de mise en page restaurée : brièvement inversée en « paramètres du site en premier », puis restaurée en mise en page > site en secours pour répondre à l'exigence « logo spécifique à la mise en page ». Si aucun logo n'est défini dans la mise en page, le logo du site est utilisé automatiquement.
- •Concerne :
skins/layouts/{default, minimal, modern, modern-copy-260413}/header.php et footer.php
Fixed
- •Conservé uniquement la ligne créée en premier pour les doublons de slug
bi-guide / logo-guide (id=186, 187), doublons id=193, 194 supprimés
- •Appliqué aux environnements de développement et de production. Le bug d'INSERT en double dans l'API de menus a déjà été corrigé en v2.3.0
Added
Assets logo créés dans /var/www/_upload/ — à téléverser en production selon les besoins :
Icône (marque uniquement)
- •
voscms-logo-color-{256,512,1024}.png · couleur (deep·ocean·sky·ocean + deep au centre)
- •
voscms-logo-mono-{256,512,1024}.png · sky uni + dégradé d'opacité 1/0.7/0.48/0.7
Wordmark horizontale (pour en-tête) — ratio 820×256
- •
voscms-wordmark-{128h,256h,512h}.png · claire (Vos deep + CMS gris)
- •
voscms-wordmark-dark-{128h,256h,512h}.png · sombre (Vos sky + CMS slate-300)
Wordmark verticale (pour icône d'app / image OG) — ratio 360×420
- •
voscms-stacked-light-{256h,512h,1024h}.png
- •
voscms-stacked-dark-{256h,512h,1024h}.png
Tous les SVG originaux conservés. librsvg2-bin installé fournit le CLI rsvg-convert. Le problème de prise en charge des couleurs OKLCH a été résolu avec la version convertie en hex (voscms-logo-mono-hex.svg).
Added
- •Table DB
rzx_changelog — enregistrements indépendants par version × locale, suivi de translation_source (original/ai/manual) + source_hash
- •Parseur
RzxLib\Core\Changelog\ChangelogParser — standard Keep a Changelog + liste blanche des sections internes (Infrastructure/Internal/Refactor/Chore/Docs/Test sont privées)
- •Importeur
ChangelogImporter — fusion idempotente, protection des traductions manuelles, détection des changements via content_hash
- •Script CLI
scripts/import-changelog.php — options --file --locale --dry-run --silent, support des pré-versions SemVer (2.1.1-hotfix)
- •Interface de traduction
RzxLib\Core\Translate\{TranslatorInterface, NullTranslator, TranslatorFactory} — activée en changeant le driver dans config/translator.php une fois le GPU Gemma 4 (ai.21ces.com) prêt
- •Page système
/changelog enregistrée (config/system-pages.php), vue front-end resources/views/system/changelog/index.php
- •Skin dédié
skins/page/changelog/skin.json — styles de carte (filled/outlined/flat), couleurs par section, badge de version, format de date, affichage de temps relatif, bascule de visibilité des sections internes
- •Page d'édition
/changelog/edit séparée — aperçu d'upload MD, matrice de couverture multilingue, bascule et suppression par version, bouton de traduction IA (bientôt disponible)
- •Automatisation du déploiement — étape
1.5/5 Changelog import ajoutée à deploy-voscms.sh : détection et fusion automatiques des fichiers .md ko + 12 locales
- •Clé de traduction
site.pages.changelog ajoutée pour 13 locales
Changed
- •Ordre des onglets réorganisé :
[Infos de base] [Permissions] [Avancé] [Skin] — les pages système peuvent ajouter leurs propres onglets à la fin
- •Schéma
settings_tabs introduit (config/system-pages.php) — les pages système déclarent un tableau d'onglets de niveau supérieur ; chaque entrée est rendue dynamiquement via key/label/icon/view. Ancien héritage d'include bas de settings_view supprimé
- •Principe établi : Paramètres = apparence + fonctionnalité / Édition = données — les interfaces de gestion de données (upload, version, traduction) sont séparées dans
/changelog/edit
- •Stratégie de sauvegarde MERGE — le gestionnaire
save_settings fusionne avec les paramètres existants. Les données des autres onglets ne sont pas effacées, même si les onglets sont séparés
- •JS
saveSettings() — n'envoie que les champs présents dans le DOM. Sûr lorsque certains champs ne sont pas rendus dans un environnement à onglets séparés
- •Position de la carte layout/skin — remise dans l'onglet Infos de base (retour utilisateur pris en compte). L'onglet Skin est exclusivement réservé aux variables skin.json
- •Suppression du doublon de largeur de page — champ
page_width supprimé de l'onglet Infos de base (consolidé dans content_width du skin)
- •Aplatissement des sous-onglets secondaires dans service/order —
general/domain/hosting/addons de config/service-settings-tabs.php migrés vers settings_tabs et promus en onglets de niveau supérieur
Changed
- •
/{slug}/settings et /{slug}/edit reconnaissent maintenant config/system-pages.php — auparavant, seule la BD rzx_page_contents était consultée, ce qui causait des 404 pour les pages système. Désormais, la requête suit l'ordre BD → config
- •Champ
edit_view ajouté — spécifie directement le chemin du fichier de vue d'édition pour les pages système. Un clic sur /{slug}/edit inclut directement cette vue (suppression du saut de redirection admin)
- •Fallback pages-settings.php — les pages système sans enregistrement en BD construisent maintenant
$pageData depuis la config, évitant la redirection vers la liste de gestion des pages
- •URL de l'icône admin unifiée —
/{slug}/settings et /{slug}/edit utilisent l'URL standard du front-end
Fixed
- •
menus-api.php : corrigé le contrôle de doublon manquant avant INSERT pour le type de page external — évite les lignes en double dans rzx_page_contents lors d'un double clic sur « Enregistrer le menu »
- •Corrigée l'omission de nettoyage des
page_contents du type external + widget lors de la suppression d'un menu — prévient les enregistrements orphelins
Fixed
- •Arrière-plan du titre (
title_bg_type, title_bg_image, title_bg_video, title_bg_overlay, title_text_color), show_title, show_breadcrumb, custom_css, custom_header_html, custom_footer_html — toutes les variables de skin de page standard sont désormais reflétées dans la vue publique
- •Le partial
_page-title-bg.php accepte maintenant la variable $_contentWidth — la zone de titre suit la largeur du contenu
- •Icône admin séparée du titre — placée indépendamment en haut à droite de la zone de contenu ; toujours visible même si
show_title=0
- •Ajout d'une marge supérieure de 20px au-dessus de la zone de titre (équilibre du layout d'arrière-plan)
Added
- •Clé de traduction
site.pages.contact ajoutée pour 13 locales (ko/en/ja/zh_CN/zh_TW/de/es/fr/id/mn/ru/tr/vi) — résout l'omission précédente
- •Guide du système de gestion des pages
docs/PAGE_ADMIN_GUIDE.md — documente la structure des onglets, le schéma, le routage, les permissions et les méthodes d'extension
Added
- •Champs par élément : nombre, suffixe, libellé (multilingue), icône et couleur
- •Le constructeur de widgets administrateur prend en charge l'ajout/modification/suppression d'éléments (nouvelle interface d'édition pour le type
stat_items)
- •16 types d'icônes (users, chart, star, heart, check-circle, clock, calendar, globe, shield, lightning, trophy, cart, dollar, building, chat) + 10 options de couleur
- •Animation de décompte à l'entrée dans le viewport — IntersectionObserver + easeOutCubic 1.4s
- •Seules les valeurs numériques sont comptées (les chaînes comme
24/7 sont affichées telles quelles), formatage avec virgules et décimales conservés
- •
widget.json v1.1.0 → v1.2.0
Fixed
- •Correction du problème où
admin_name était enregistré avec le préfixe enc: et affiché sans déchiffrement
- •Correction du problème où la requête d'avatar faisait un LEFT JOIN incorrect avec une table
staff inexistante — interroge désormais directement rzx_users.profile_image selon la structure unifiée admin_id = users.id
- •Ajout automatique du préfixe baseUrl aux avatars à chemin relatif
Added
- •Boutons
[Obtenir la miniature] [Obtenir la capture d'écran] insérés automatiquement à côté de chaque champ <input type="url"> (y compris le type de variable étendue url) dans tous les tableaux
- •Miniature : rendu natif à 1280×960 → sortie 800×600 (premier viewport d'écran)
- •Capture d'écran : rendu natif à 1280×page_complète → sortie 800×réduite (page complète défilante, hauteur réelle de la page)
- •Interface de barre de progression étape par étape —
Connexion au serveur → Chargement de la page → Capture de l'écran → Génération de l'image → Enregistrement du fichier → En attente de réponse
- •Définition automatique de la miniature capturée comme image principale — marquée
board_files.is_primary=1, prioritaire pour le widget board-showcase
- •Nouvelle route
/board/api/url-capture?type={thumbnail|screenshot}&url=... + proxy api-url-capture.php
- •Action
set_primary ajoutée à /board/api/files — désigne l'un des fichiers joints existants comme image principale
Changed
- •Requête d'images jointes
ORDER BY is_primary DESC, id ASC — les miniatures capturées sont affichées en premier
- •Paramètre
primary_file_pos transmis au serveur lors de la création d'un article pour indiquer l'index du fichier principal
Changed
- •Séparation du produit Marketplace : la fonctionnalité partagée par le plugin
plugins/vos-marketplace/ a été externalisée en tant que produit autonome → github.com/THEVOSjp/Marketplace nouveau dépôt, déploiement indépendant sur market.21ces.com
- •Le plugin ne conserve que l'« interface côté client (exploration, achat, installation, licence) » — les données, vendeurs et règlements sont pris en charge exclusivement par le serveur du marketplace
- •Points d'intégration API côté Core mis à jour
Added
- •Modal après la sélection de la langue — avertissement sur la nécessité de sauvegarder
.env + BD + storage/uploads/, et notice que la perte de l'APP_KEY rend le déchiffrement impossible
- •Confirmation en deux étapes : case à cocher + bouton de confirmation (installation inconditionnelle interdite)
- •Traduction complète ajoutée pour les 13 langues (
backup_title/body/item_env/db/uploads/warn/check/confirm/cancel)
Added
- •
scripts/register-widgets-to-marketplace.php — enregistre en masse 28 widgets basés sur des fichiers dans rzx_mp_items
Changed
- •
plugins/vos-marketplace/src/CatalogClient.php — URL d'API par défaut changée en https://market.21ces.com/api/v1, chemin de fetchItem() mis à jour, format de requête de checkUpdates() mis à jour
- •
plugins/vos-marketplace/plugin.json — valeur par défaut de marketplace_api_url mise à jour
- •
rzxlib/Core/Modules/WidgetLoader.php — l'URL de la miniature inclut désormais le cache-buster ?v={mtime} (pour gérer le cache immutable de Cloudflare)
Fixed
- •
widgets/feature-tour/widget.json — nettoyage des champs
- •Miniatures de certains widgets rafraîchies (staff, testimonials, feature-tour, shop-map, shop-ranking, stylebook)
v2.1.5
2026-04-17 · il y a 6 mois
Added
- •contact-info (v0.1.0) — carte de contact (adresse/téléphone/e-mail/horaires + image + petite carte)
- •location-map (v0.1.0) — carte horizontale (Google Maps + info en 3 colonnes en dessous, largeur ajustable)
Added
- •Refactorisation complète de la page de soumission d'article — 3 onglets (informations de base / release / ventes)
- •Licence (GPL/LGPL/BSD/MIT/CC/PD/commercial), URL du dépôt, URL de démo, plugins dépendants, image bannière
- •Historique des releases, informations de vente (toggle public/payant, prix réduit/date de fin), améliorations UX
Added
- •Menu développeur (ID:20) en 13 langues, description/typing_words du Hero CTA complétés en 12 langues
Changed
- •Distinction des noms de widgets clarifiée (carte / carte de contact), fullWidthTypes ajouté à
page.php
- •contact-form catégorie → étiquette uniquement (code supprimé, paramètres de widget modifiables)
Fixed
- •board-contents/board-showcase : file_type → mime_type
- •boards-api : is_shown_in_list manquant + contrainte JSON options
- •contact-form POST : vidage complet du tampon ob
- •Hero CTA : double échappement de
\n dans typing_words/description
DB Changes
- •rzx_mp_items : license, repo_url, demo_url ajoutés
- •rzx_board_extra_vars : is_shown_in_list ajouté
- •rzx_contact_messages : nouvelle table
v2.1.4
2026-04-17 · il y a 6 mois
Added
- •Widget download-hero — page de téléchargement de logiciel (intégration en direct avec version.json, 4 langues intégrées, fonctionnalités clés / configuration requise / historique des versions)
- •Page /downloads — page système de type widget, traductions de menu en 13 langues,
is_system=1
- •Widget contact-form (v0.1.0) — widget de formulaire de contact privé 1:1 (accessible aux visiteurs non connectés, sélection de catégorie, protection anti-spam par honeypot, envoi AJAX)
- •Widget contact-info — widget d'affichage des coordonnées
- •Widget location-map — widget de carte de localisation
- •Helper partagé rzx_send_mail() — nouvelle fonction d'envoi d'e-mail SMTP dans
rzxlib/Core/Helpers/mail.php
- •Table rzx_contact_messages — table BD pour stocker les demandes de contact
- •Page /contact — page système de type widget, traductions de menu en 13 langues
Fixed
- •Protection contre la suppression des pages système — le contenu de page/les widgets sont conservés lors de la suppression d'une page système du menu (seule l'entrée de menu est retirée)
- •
menus-api.php : double vérification via DB is_system + slug config/system-pages.php
- •
menus-js.php : affiche le message « Sera retiré uniquement du menu » lors de la suppression d'une page système
- •Menu de pages système multilingue — lors de l'ajout d'une page système au menu, les libellés en 13 langues sont automatiquement enregistrés depuis les clés de traduction
site.pages.*
- •Traduction de la page de téléchargements — traductions
site.pages.downloads ajoutées pour 13 langues
Changed
- •Hero de la page d'accueil — bouton Télécharger → téléchargement direct à
/download/voscms-latest.zip, version mise à jour vers v2.1.1
- •Auth.php — appelle en priorité le helper partagé
rzx_send_mail() avant de basculer sur sendSmtpMail
- •index.php — chargement automatique du helper
mail.php ajouté
v2.1.3
2026-04-17 · il y a 6 mois
Changed
- •Onglet Hébergement — carte de résumé + barre de progression de l'utilisation + tableau d'informations de connexion FTP/BD (affiché automatiquement quand configuré par l'administrateur)
- •Onglet Domaine — carte de domaine + paramètre principal + tableau d'informations des serveurs de noms (affiché automatiquement quand configuré par l'administrateur)
- •Onglet Mail — informations du serveur de messagerie (IMAP/SMTP) + carte par compte + changement de mot de passe en ligne
- •Onglet Maintenance — carte d'informations + date planifiée + historique des travaux (affiché automatiquement quand enregistré par l'administrateur)
- •Onglet Services supplémentaires — mise en page de carte unifiée
- •Structure d'informations unifiée identique au partiel administrateur (l'administrateur saisit dans les métadonnées → répercuté automatiquement dans Mon espace)
Changed
- •Zone du journal d'activité réduite du ratio 1/3 à 1/5
- •Suppression du codage en dur de la valeur par défaut NS dans l'onglet domaine administrateur (en préparation de l'intégration de l'API Cloudflare)
Changed
- •Flux de provisionnement entièrement revu : sous-domaine d'abord → domaine acheté connecté ensuite
- •Règle d'ID de provisionnement : nom du sous-domaine ou SLD du domaine acheté
- •Tunnel wildcard Cloudflare utilisé (aucun ajout d'enregistrement A de sous-domaine nécessaire)
- •Configuration des disques du serveur 2 modifiée : NVMe 256 Go + SSD 2 To + HDD 8 To (configuration 3 disques)
v2.1.2
2026-04-16 · il y a 6 mois
Added
- •Système de classification des services — colonne
service_class ajoutée (recurring/one_time/free), completed_at date de fin pour les services ponctuels
- •Détail du service sur Mon espace —
/mypage/services/{order} gestion des onglets par type (hébergement/domaine/mail/maintenance/services supplémentaires)
- •API de gestion des services —
api/service-manage.php (bascule de renouvellement automatique, demande de renouvellement, configuration du domaine principal, changement de mot de passe mail)
- •Gestion des commandes administrateur —
/admin/service-orders liste des commandes + page de détail, modal de statut ponctuel (reçu/en cours/en attente/annulé/terminé)
- •Menu administrateur — menu « Commandes de service » ajouté à la barre latérale (position: 65)
Added
- •phone-display — composant d'affichage du numéro de téléphone (helper
format_phone() côté serveur), sans dépendance JS
- •format_phone() — fonction PHP de formatage du numéro de téléphone international (Corée/Japon/États-Unis/Chine/Royaume-Uni/France/Allemagne/Australie etc.)
- •Configuration de domaine gratuit — gestion de la liste des sous-domaines gratuits dans les paramètres administrateur (
service_free_domains), prise en charge de la sélection multiple de domaines
Fixed
- •Abonnements de service gratuit manquants — les commandes gratuites ne créaient pas de enregistrements d'abonnement pour domaine/complément/maintenance etc. → refactorisé pour créer tous les services en bloc
- •Accord des conditions dans la section paiement — la case des conditions était masquée avec la section paiement pour les commandes gratuites → séparée hors de la section
- •Détection isFree de updateSubmitButton —
btn.closest('form') NULL → corrigé avec document.querySelector
- •Indicateur actif de la barre latérale admin —
$adminPath indéfini causait l'inactivité de tous les menus → déclaration de variable ajoutée
- •Avatar Mon espace —
use Auth + $user = Auth::user() manquants dans services.php/service-detail.php
- •Vérification ponctuelle pour les services supplémentaires — l'indicateur
one_time dans les paramètres admin est maintenant correctement répercuté dans service_class lors de la commande
- •Statut initial du service ponctuel — modifié pour créer en
pending (reçu) au lieu de active
Changed
- •Refactorisation de l'API de commandes — code de création d'abonnement des 3 chemins de paiement (gratuit/carte/virement bancaire) consolidé dans la fonction partagée
$subscriptionData + _insertSubscriptions()
- •UI de la liste des services — développement en ligne → lien carte + page de détail séparée
- •Affichage du numéro de téléphone —
format_phone() appliqué au profil/liste des membres/liste du personnel
- •Dynamisation du domaine gratuit —
.21ces.net codé en dur → référence à la valeur des paramètres admin
v2.1.1-hotfix
2026-04-16 · il y a 6 mois
Fixed
- •Erreurs 404 dans le menu du pied de page — données manquantes pour les pages légales (terms, privacy, refund-policy, data-policy, tokushoho, funds-settlement) dans la table
rzx_page_contents → restaurées depuis la BD de test
- •Échec d'upload d'image/vidéo dans le constructeur de widgets — corrigé le problème où le POST
FormData du wrapper front-end (page-widget-builder.php) n'était pas transmis au gestionnaire AJAX (condition d'upload de fichier ajoutée + traitement ob_end_clean/exit)
- •Permissions du répertoire d'upload — propriétaire de
storage/uploads/widgets/ changé en www-data pour accorder l'accès en écriture à PHP-FPM
Added
- •Menu de demande de service multilingue — traductions de
menu_item.19.title ajoutées pour 13 langues dans la table rzx_translations
- •Widget Hero CTA multilingue — traductions en 13 langues appliquées au titre, sous-titre et texte du bouton de la bannière hero de la page Dev
- •Aperçu du statut d'upload — retour visuel ajouté lors de l'upload d'images/vidéos : en cours (spinner), succès (coche) et échec (message d'erreur)
v2.1.1
2026-04-12 · il y a 6 mois
Added
- •Écran de sélection de langue à l'étape 0 — choisir parmi 13 langues avant le début de l'installation ; toute l'interface s'affiche dans la langue choisie dès lors
- •Fichiers de traduction d'installation séparés —
resources/lang/install.php (13 langues × 45 chaînes)
- •Niveau de membre multilingue — Normal/Silver/Gold/VIP générés automatiquement en 13 langues
Added
- •config/admin-menu.php — menu administrateur principal séparé dans un fichier de configuration (conservé lors des mises à jour du noyau)
- •admin-sidebar.php refactorisé — 731 lignes codées en dur → ~200 lignes de rendu dynamique (basé sur config + plugin.json)
- •vos-shop plugin.json — menu codé en dur migré au format
menus.admin
Added
- •Menu glissant — mobile : barre de bascule avatar+nom → overlay glissant gauche (300ms ease-out)
- •Fond estompé en fondu — fermer en cliquant sur le fond ou le bouton X ; défilement du body verrouillé
Added
- •force_locale — appliquer la langue par défaut de force (le paramètre
?lang=xx permet à l'utilisateur de la modifier)
- •default_language — clé de configuration install.php ↔ Translator unifiée
- •Paramètre URL —
?lang=xx détecté en premier, sauvegardé en session/cookie
Fixed
- •Skin FAQ non appliqué — le SQL de migration exécutait un
INSERT brut pour le forum par défaut avant install.php, ce qui faisait ignorer silencieusement le INSERT IGNORE ; corrigé
- •source_locale manquant dans la table translations — colonne absente dans la migration du noyau → db_trans() échouant entièrement → infos utilisateur/menu/i18n non affichés ; corrigé
- •Indicateur actif de la barre latérale de l'onglet paramètres — attribut
route_prefix ajouté pour que le menu paramètres reste actif sur toutes les sous-routes de paramètres
- •Bug de résidu de session d'installation — lors d'une nouvelle installation sans .env, une ancienne session PHP faisait sauter l'étape 0 ; corrigé
- •nginx 403 — conflit entre le répertoire physique admin/ et la route corrigé (suppression de
try_files $uri/)
- •Version codée en dur dans le script d'obfuscation — obfuscate.php lit maintenant la version dynamiquement depuis version.json
Changed
- •Vue multilingue du widget grid/board-contents — recherche rzx_translations ajoutée (locale actuel → retour vers l'anglais)
- •Catégories d'industrie du site — élargies de 15 à 26 (ajoutées : entreprise, centre commercial, juridique, comptabilité, IT, médias, etc. ; 13 langues)
- •Paramètres du widget grid — render.php de grid-section changé en type de cellule natif (
board-list) ; titre en 13 langues
- •Sélection de langue à l'étape 4 — élargie de 5 à 13 langues ; pré-remplie avec la langue d'installation
- •Sélection du fuseau horaire — élargie à 12 fuseaux horaires couvrant les régions des 13 langues
v1.26.0
2026-04-01 · il y a 7 mois
Added
- •Services en forfait (ensemble) affichés en 3 colonnes en haut de la sélection de service — thème de couleur ambre pour les distinguer visuellement des services individuels
- •Badge SET, étiquette de remise événementielle, noms des services inclus, prix du forfait, prix d'origine barré, taux de remise
- •La sélection d'un forfait sélectionne automatiquement tous les services inclus (prix calculé comme le prix du forfait)
- •Les services inclus dans un forfait ne peuvent pas être activés/désactivés individuellement (prévient les calculs de prix incorrects)
- •Mode de désignation : table
rzx_staff_bundles pour le filtrage des forfaits par membre du personnel
- •Paramètre
bundles transmis à la page de confirmation
- •Support multilingue : clés de traduction kiosk liées aux forfaits ajoutées dans 13 langues
Added
- •Boutons de changement de vue — bascule
[Mois] [Semaine] [Jour] dans la barre supérieure (état actif : bleu)
- •Vue hebdomadaire — axe vertical gauche = jour de la semaine, axe horizontal supérieur = axe temporel
- •Défilement horizontal, blocs de réservation affichés sous forme de barres temporelles
- •Algorithme de couloir : détecte les chevauchements temporels et place automatiquement en dessous, hauteur de ligne variable
- •Barre latérale gauche ↔ défilement vertical de la grille synchronisés
- •Vue journalière — horizontal = axe temporel, vertical = couloirs (même méthode que la vue hebdomadaire)
- •Plage horaire basée sur les heures d'ouverture — basée sur les paramètres
business_hour_start/business_hour_end ; expansion automatique pour les réservations hors plage
- •Transmission de l'heure au clic sur cellule vide — en vue hebdomadaire/journalière : coordonnée X du clic → calcul de l'heure par unités de 15 minutes → heure de début du modal de réservation remplie automatiquement
- •Barre de navigation supérieure fixe —
overflow-x-hidden + sticky appliqués ; reste dans le viewport lors du défilement horizontal
Added
- •Admin > Paramètres > Général — interface de réglage des heures de début/fin d'activité ajoutée
- •Clés de paramétrage BD
business_hour_start, business_hour_end
- •Appliquées à la plage horaire par défaut dans la vue hebdomadaire/journalière du calendrier
Fixed
- •Champs manquants dans POS
add-service — ajout de la transmission de start_time, end_time, staff_id, designation_fee, notes (auparavant : heure codée en dur côté serveur, personnel/notes manquants)
- •Prévention du dépassement de minuit pour end_time — limite
% 24 → min(23:59) appliquée dans ReservationHelper, l'API start-service et calcEnd() du formulaire de réservation
- •Gestion du dépassement de minuit dans la détermination d'utilisation POS —
CustomerBasedAdapter traite end_time < start_time comme un dépassement de minuit
- •Validation du forfait de réservation — corrigé pour permettre la création d'une réservation lorsque seul un forfait est sélectionné
Changed
- •Changements de nom d'onglet : Accueil / Liste d'accueil / Réservations
- •Liste d'accueil : sources
walk_in, pos, kiosk, admin — tous les statuts affichés
- •Réservations : sources
phone, online — tous les statuts affichés
- •Ordre de tri : En attente → Confirmé → En cours → Terminé → Non-présentation → Annulé ; dans le même statut, trié par heure
- •Lignes terminées/annulées/non-présentées : affichées avec
opacity-50, badge non attribué visible
Changed
- •Badge Terminé : changé de gris → vert
- •Badges Annulé/Non-présentation ajoutés (masqués si le nombre est 0)
Added
- •Bas de la carte : bouton de non-présentation ajouté pour les cartes en attente (icône d'interdiction), bouton d'annulation en rouge
- •Modal de détail : bouton d'action non-présentation affiché pour les statuts
pending et confirmed
- •Non-présentation groupée en masse : fonction
POS.noShowAllServices() ajoutée
Fixed
- •Navigation retour du détail de réservation —
<a href="/reservations"> → history.back(), retour à la page précédente
- •Multilingue : clés liées à la bascule de vue du calendrier (mois/semaine/jour), forfait, heures d'ouverture ajoutées pour 13 langues
v1.25.0
2026-04-01 · il y a 7 mois
Architecture
- •POS séparé en structure de plugin indépendante
- •
resources/views/admin/reservations/pos-*.php → déplacé vers le répertoire resources/views/admin/pos/
- •La fonctionnalité POS est activée/désactivée automatiquement selon la présence du répertoire
pos/ (vérification is_dir())
- •Menu latéral : le menu POS est masqué automatiquement si le répertoire
pos/ est absent
- •Routage
index.php : les routes POS sont désactivées si le répertoire pos/ est absent
- •
pos/_init.php → délègue au _init.php commun des réservations (DB, auth, i18n partagés)
- •Les endpoints API restent dans
reservations/_api.php (compatibilité ascendante garantie)
Added
- •Modal de paiement unifié — utilisation simultanée de solde + espèces + carte (paiement combiné)
- •Solde : consultation du solde, saisie manuelle ou utilisation du montant total
- •Espèces : saisie du montant
- •Carte : saisie du montant + bouton de remplissage automatique « utiliser le solde restant »
- •Paiement échelonné : paiement unique / sélection de 2 à 12 mensualités
- •Calcul automatique en temps réel du total, de la monnaie rendue et du montant manquant
- •Pour les paiements par carte Stripe, les espèces/solde ne sont traités qu'après le succès du paiement par carte (sûr en cas d'annulation)
- •Modal de détail de service — affichage du solde
- •Le solde de points du membre est toujours affiché dans la zone d'en-tête (même si le solde est 0)
- •Modal de détail de service — amélioration du badge personnel
- •Le badge assigné/désigné est affiché avant le nom du personnel (auparavant : sous le nom)
- •Déplacement des boutons reçu/impression
- •Déplacés au-dessus de la section des détails client, reçu (gauche) + impression (droite)
- •Amélioration de la fonction d'impression
- •Imprime le contenu du modal de détail de service actuel au lieu d'ouvrir une page externe
Changed
- •Mise en page des cartes — grille → cartes de taille fixe avec flex-wrap
- •Taille de carte fixe : par défaut 320×240px (small : 260×200, large : 380×280)
- •La taille des cartes ne change pas avec la largeur de l'écran ; retour à la ligne automatique
- •Modal de paiement par carte — élargi à 1030px de large, 800px de haut
Fixed
- •Erreur cross-origin de l'API résolue
- •
$baseUrl était fixé sur APP_URL dans .env, entraînant des échecs de fetch depuis d'autres hôtes/HTTPS
- •Tableau de bord : URL de fetch changée en chemin relatif (
/update-api.php)
- •
_init.php des réservations : $baseUrl changé en chaîne vide pour que tous les fetches utilisent des chemins relatifs
- •Problème de contenu mixte entièrement résolu dans l'environnement proxy HTTPS Cloudflare
- •Erreur d'exécution de migration BD — « Failed to fetch » résolu (problème cross-origin)
- •Bug de pré-débit en espèces lors de l'annulation d'un paiement combiné Stripe
- •Avant : les espèces traitées en premier → espèces déjà appliquées lors de l'annulation du paiement par carte
- •Après : les espèces/solde ne sont traités qu'après le succès du paiement par carte Stripe
i18n
- •
pos_pay_after_points — montant après application du solde
- •
pos_pay_proceed — procéder au paiement
- •
pos_pay_remainder — utiliser la totalité du solde restant
- •
pos_pay_installment — paiement échelonné
- •
pos_pay_lump_sum — paiement unique
- •
pos_pay_months — mois
- •
pos_pay_total_pay — total
- •
pos_pay_short — montant manquant
- •
show_receipt — reçu
- •
show_print — imprimer
v1.18.0
2026-03-29 · il y a 7 mois
Added
- •Fonction de formatage de date multilingue —
formatReservationDate($dateString, $locale)
- •Supporte 13 langues (ko, en, ja, zh_CN, zh_TW, de, es, fr, id, mn, ru, tr, vi)
- •Localisation automatique de la date et du jour de la semaine sur la page de détail de réservation
- •Repli : locales non prises en charge → format anglais
Changed
- •Traitement multilingue de la page de détail de réservation
- •Nom du service, nom du personnel et nom du forfait localisés (basé sur la table des traductions en BD)
- •Fonction de formatage de date intégrée
- •Libellé du statut de paiement localisé (champ payment_status)
- •Prise en charge multilingue du statut de paiement
- •Section
payment ajoutée à tous les fichiers de langue (11 langues)
- •Traductions pour : impayé, payé, paiement partiel, remboursé
Fixed
- •Page de détail de réservation : le nom du personnel et du service qui n'étaient pas localisés s'affichent désormais correctement
- •Libellé du statut de paiement : problème résolu où il ne s'affichait qu'en coréen
- •Traitement multilingue unifié basé sur la fonction
_tr()
Layout & UI
- •Largeur de page unifiée (max-w-5xl → max-w-7xl)
- •Pages du tableau (liste, lecture, rédaction) : max-w-5xl → max-w-7xl
- •Page externe (page.php) : valeur par défaut et valeurs de paramètres BD mises à jour
- •Détail de réservation / consultation de réservation / pages du personnel : valeurs de paramètres BD mises à jour
- •Résultat : toutes les largeurs de page correspondent désormais à la page de réservation
Documentation
- •Documentation détaillée de
formatReservationDate() ajoutée dans COMPONENT_MANUAL.md
- •Langues prises en charge et tableau des formats
- •Exemples d'utilisation et structure interne
- •Remarques et fonctions associées
v1.16.0
2026-03-23 · il y a 7 mois
Added
- •Barre de menu inférieure mobile — Personnel / Réservations / Accueil / Connexion (ou Mon compte) / Inscription / Plus, avec mise en évidence de la page courante
- •Panneau mobile « Plus » — menu principal + Mon compte / Déconnexion
- •Paramètres de mise en page/skin réellement appliqués — site_layout, site_page_skin, site_board_skin, site_member_skin → reflétés dans le rendu
- •Paramètre no_layout — contenu uniquement sans mise en page (pour la prévisualisation)
- •Clés de traduction ajoutées — common.nav.staff, common.nav.more (13 langues)
Fixed
- •Mise en page appliquée aux pages membres (login/register/forgot/reset) : en-tête dupliqué supprimé par extraction du
<main> du skin
- •Corrigée l'erreur de déclaration en double de ImageCropper/ProfilePhotoCropper dans le skin membre
- •Corrigé le problème include_once du chargeur de menus : menu base-header manquant lors du chargement dans la closure du skin
- •
apple-mobile-web-app-capable déprécié → mobile-web-app-capable (8 fichiers)
- •Boutons de connexion/inscription du header masqués sur mobile (remplacés par la barre de menu inférieure)
- •Prise en charge iOS safe-area pour la barre de menu inférieure
Changed
- •Pages membres fusionnées de leur propre mise en page vers la mise en page par défaut (login/register/forgot/reset)
- •Marge inférieure du pied de page supprimée (la barre de menu mobile utilise le positionnement fixe)
v1.15.3
2026-03-22 · il y a 7 mois
Added
- •Panneau de paramètres détaillés de mise en page — chargement AJAX du formulaire de configuration basé sur SkinConfigRenderer
- •Paramètres du menu de mise en page — section menus de layout.json → génération automatique du menu déroulant des sitemaps en DB
- •Support des onglets dans SkinConfigRenderer — l'ajout de la propriété
tab aux vars génère automatiquement une UI à onglets
- •Refactorisation de SkinConfigRenderer — méthode unique
renderVar() unifiée, séparation de renderFormFlat/renderFormWithTabs, renderDependsOnJs partagé
- •Extensions de layout.json — menus (GNB/FNB), 14 vars (en-tête/logo/couleur/pied de page/personnalisé), 13 langues
- •Intégration de l'aperçu de mise en page — sélectionner "Désactiver" affiche l'aperçu avec ?no_layout=1
Fixed
- •Requête du menu de gestion de mise en page : correction du nom de table
rzx_menus → rzx_sitemaps
- •Ajustement de la largeur du panneau central + whitespace-nowrap sur les liens d'action
Pending
- •Application des valeurs de configuration de mise en page/skin au rendu réel des pages (prochaine session)
v1.15.2
2026-03-22 · il y a 7 mois
Added
- •Page de gestion des mises en page — disposition en 3 panneaux : gauche aperçu+menu, droite liste des skins, panneau de configuration détaillée
- •Par élément de skin : miniature + liens d'action configuration détaillée/créer une copie/supprimer
- •Options « Désactiver » / « Installer un autre skin »
- •Sauvegarde en 4 catégories : mise en page, page, forum, membre (
site_layout, site_page_skin, site_board_skin, site_member_skin)
Changed
- •« Gestion du design » → renommé en « Gestion des mises en page » (13 langues : admin.php + site.php)
v1.15.1
2026-03-22 · il y a 7 mois
Changed
- •15 pages de gestion du site → en-tête partagé
_head.php appliqué
- •Forums: boards, boards-create, boards-edit, boards-trash
- •Menu: menus
- •Design: design
- •Pages: pages, pages-settings, pages-edit-content, pages-document, pages-compliance, pages-widget-builder
- •Widgets: widgets, widgets-create, widgets-marketplace
- •Les pages en mode embed (boards-edit, pages-settings, pages-edit-content) appliquent
_head.php uniquement hors mode embed
- •Unification complète des en-têtes et mises en page de toutes les pages administrateur
v1.15.0
2026-03-22 · il y a 7 mois
Added
- •Module de widget système — 4 widgets : staff (présentation du personnel), booking (faire une réservation), lookup (consultation de réservation), cta001 (bannière d'appel à l'action pour la réservation)
- •Pages système — staff, booking, lookup enregistrées en BD (is_system=1) + routage (
/staff, /booking, /lookup)
- •Rendu de page basé sur les widgets — les pages staff/booking/lookup affichent les widgets lorsqu'ils sont placés, retour au rendu hérité si aucun widget n'est placé
- •Enregistrement automatique des widgets en BD — l'appel de
syncToDatabase() enregistre automatiquement les widgets lors de l'ajout d'un répertoire de widget
- •Catégorie de widget
system — traduite en 13 langues (widgets.categories + widget_builder.cat)
- •Unification de la liste des pages — rendu en boucle des pages système + jeu d'icônes engrenage/modifier/aperçu unifié
- •Unification de l'en-tête de page administrateur —
$pageSubTitle + $pageSubDesc (sortie commune via _head.php)
- •Clés de traduction ajoutées — staff.admins, staff.attendance.report/stats, points.description, etc.
Fixed
- •
page_slug = 'home' codé en dur dans le widget builder → traitement dynamique via $_GET['slug']
- •AJAX save/preview du widget builder avec
home codé en dur → $pageSlug dynamique
- •URL d'aperçu du widget builder →
$pageSlug dynamique (accueil fixe → par page)
- •require WidgetLoader manquant dans widget preview_widget — corrigé
- •Chemin d'image de la vue carte de service (préfixe
/storage/)
- •Largeur des paramètres kiosk
max-w-3xl → 100% unifiée
- •En-tête POS « Gestion des réservations » → renommé en « POS »
Changed
- •10 pages de gestion du personnel + 4 de gestion des membres → en-tête commun
_head.php appliqué
- •Pages kiosk/bundle avec
_head.php appliqué
- •Paramètres de langue du kiosk grid → flex-wrap responsive
- •Liste des pages : pages système rendues en boucle pilotée par les données
v1.14.1
2026-03-22 · il y a 7 mois
Added
- •Onglet skin de page — informations de base du skin + paramètres de variables étendues (basé sur SkinConfigRenderer)
- •Skin appliqué à tous les types de pages — paramètres de skin appliqués de la même façon à document/widget/externe
- •Système d'arrière-plan de titre — arrière-plan image/vidéo + superposition + couleur du texte (partial commun
_page-title-bg.php)
- •Système depends_on — dépendance déclarative entre champs dans skin.json, le rendu génère automatiquement le JS (support checkbox/radio)
- •Upload de fichier skin — upload d'images/vidéos via multipart (
storage/skins/page/{skin}/)
- •Sélecteur de mise en page/skin en carte — changé en UI de cartes miniatures dans l'onglet info du module
- •Système SEO — helper SEO, modèle de titre, balises meta OG/Twitter, extraction de contenu
- •Upload d'OG Image — saisie d'URL + upload de fichier + aperçu
- •Modal de résultat commun — UI de modal unifié succès/échec de sauvegarde (support 13 langues)
- •Vue carte de service — carte avec image de fond complète + bouton de basculement tableau/carte
- •Classement des services par glisser-déposer — changement d'ordre + sauvegarde en BD dans les deux vues
- •Affectation/désignation du personnel de réservation — 2 boutons (affecter/désigner) dans le détail de réservation
- •UI d'origine de réservation — sélection réservation téléphonique / présentiel / en ligne
- •Paramètres de réservation téléphonique — toggle d'activation/désactivation dans les paramètres de base du service
- •En-têtes de sécurité — X-Frame-Options + CSP frame-ancestors
- •PAGE_SYSTEM.md — documentation de développement du système de pages
- •PRD_OrderSystem.md — document de planification du système de commande en table
- •PRD_KioskSystem.md — document de planification du système borne
Fixed
- •Paramètre favicon BD appliqué (front / admin / skin layout — 4 endroits)
- •URL de migration du tableau de bord
window.location.origin → $baseUrl (environnements sous-répertoire)
- •URL API mode embed des paramètres de page → chemin admin spécifié directement
- •Modal de résultat i18n : utilise les messages de locale au rendu de page plutôt que la réponse API
- •Fallback valeur skin vide dans l'onglet skin (
"" → default)
- •Problème de double consommation de
php://input dans pages-settings.php résolu
Changed
- •Borne / paramètres de borne / pages bundle → en-tête partagé
_head.php appliqué
- •Sauvegarde des paramètres skin JSON → transfert FormData (multipart) (support upload de fichiers)
- •Paramètre
$baseUrl ajouté à SkinConfigRenderer (aperçu image/vidéo)
- •Traductions skin en 13 langues (skin.json + site.php + common.php)
v1.13.0
2026-03-21 · il y a 7 mois
Added
- •Système de pages finalisé — création automatique de pages lors de la création de pages document/widget/externe depuis le menu
- •Rendu de page dynamique —
page.php (document→HTML, widget→WidgetRenderer, externe→iframe/include)
- •Paramètres d'environnement de page — 3 onglets (base / mise en page & skin / SEO), sauvegardé en JSON
page_config_{slug}
- •Édition du contenu de page — édition du titre et du contenu par langue, changement de slug, changement de type, suppression
- •Liste dynamique de gestion de pages — chargement automatique des pages utilisateur depuis la BD, icônes et badges par type
- •Icônes d'administration front — engrenage (paramètres) + crayon (contenu) affichés séparément
- •iframe de page externe — guide « ouvrir dans une nouvelle fenêtre » affiché en cas d'échec de chargement
- •Fichiers PHP/HTML internes — rendus dans la mise en page RezlyX via include
Fixed
- •URL de raccourci du menu
#menu_{id} → enregistre l'URL réelle du menu
- •L'édition du menu affiche la même structure d'interface de raccourci qu'à la création
- •La sauvegarde du menu reflète l'URL du raccourci (
formMenuType → base de visibilité du panneau)
- •Traductions du menu ajoutées pour 13 langues (12 éléments de menu × 13 langues)
- •Chemin de clé de traduction de l'éditeur de document de page corrigé (
admin.site.pages. → site.pages.)
Changed
- •Colonne
page_type ajoutée à rzx_page_contents en BD (document/widget/external)
- •La suppression d'un menu supprime désormais la page associée + les données de traduction
v1.12.5
2026-03-21 · il y a 7 mois
Fixed
- •Correction de l'URL de raccourci de menu — enregistre désormais l'URL réelle du menu au lieu de
#menu_{id}
v1.12.4
2026-03-21 · il y a 7 mois
Fixed
- •Type de liste des paramètres de skin non appliqué — correction du problème où le cache localStorage écrasait les paramètres de skin
- •Lorsque le changement de style est désactivé, seuls les paramètres de skin sont utilisés ; lorsqu'il est activé, localStorage est prioritaire
- •Suppression de l'envoi en double des champs masqués de case à cocher (l'état non coché est désormais géré en JS)
v1.12.3
2026-03-20 · il y a 7 mois
Fixed
- •Clés de traduction du tableau manquantes pour l'anglais/japonais (source_locale, reply, style, board_settings, etc.)
- •Application du fallback multilingue pour les noms de catégorie (locale → en → original)
- •Prise en charge multilingue du corps de la liste du tableau (aperçus webzine/carte/galerie)
v1.12.2
2026-03-20 · il y a 7 mois
Fixed
- •Repli multilingue du corps de la liste du tableau — corps traduit appliqué aux aperçus webzine/carte/galerie (locale → en → original)
- •Fichiers de skin manquants en production — répertoire
skins/default/board/ créé par FTP et skin.json/vignette téléversés
v1.12.1
2026-03-20 · il y a 7 mois
Fixed
- •Paramètres de skin non affichés en production — synchronisation complète des fichiers réorganisée
- •Structure des fichiers CLAUDE.md + BOARD_SYSTEM.md entièrement mise à jour
v1.12.0
2026-03-20 · il y a 7 mois
Added
- •Système de paramètres de skin terminé — génération de formulaires dynamiques basée sur skin.json + application aux tableaux réels
- •Regroupement par sections (base / liste / liens / design / fond du titre / personnalisé)
- •Types de saisie radio et vidéo ajoutés
- •Upload de fichiers image/vidéo (FormData multipart)
- •Fonction de suppression d'image/vidéo
- •Tableau d'informations du skin (auteur / URL / e-mail / date / version / miniature)
- •Image/vidéo de fond du titre — réglages du type de fond, de la hauteur, de l'opacité du calque et de la couleur du texte
- •4 styles de mise en page de liste — liste / webzine / galerie / carte ; fichiers de skin séparés + prise en charge du remplacement
- •Galerie : couverture pleine image + animation de glissement au survol
- •Webzine : miniature + titre + aperçu + carte de métainformations
- •Articles d'annonce séparés dans la liste supérieure (_list-notices.php)
- •Paramètres de skin appliqués — primary_color, border_radius, posts_per_row, allow_style_switch, show_category, tableau lié, Font Awesome, CSS/HTML personnalisé
- •Fusion automatique des valeurs par défaut de skin.json — les valeurs par défaut de skin.json sont appliquées même sans sauvegarde en BD
Fixed
- •skin_config non enregistré en BD (action de mise à jour de boards-api.php ne comprenait pas skin_config)
- •Sauvegarde du skin modifiée de URLSearchParams → FormData (multipart) pour prendre en charge les uploads de fichiers
- •Prise en charge de l'analyse automatique du tableau
$_POST['skin_config']
v1.11.3
2026-03-20 · il y a 7 mois
Fixed
- •Application du fallback multilingue pour les titres des articles précédent/suivant sur la page de détail (locale → en → original)
v1.11.2
2026-03-20 · il y a 7 mois
Fixed
- •Repli multilingue du titre de la liste du tableau — recherche de traductions dans tous les paramètres régionaux (restriction au coréen supprimée), repli en anglais tenant compte de la langue source
v1.11.1
2026-03-20 · il y a 7 mois
Fixed
- •Amélioration de la détection des URLs isolées pour les cartes OG — remonte désormais jusqu'à l'élément parent de bloc, ce qui permet de traiter correctement les URLs encapsulées dans des balises en ligne telles que
<font> / <span>
v1.11.0
2026-03-20 · il y a 7 mois
Added
- •Lien automatique URL — détecte automatiquement les URL dans le corps/éditeur du tableau → les convertit en balises
<a>
- •Carte d'aperçu de lien OG — carte au format bannière SNS (miniature + titre + description + domaine) générée automatiquement
- •Éditeur : saisir/coller une URL + Entrée → appel à l'API OG → insertion de la carte
- •Corps : lien URL autonome → converti automatiquement en carte OG
- •Module OgFetcher — extraction de métadonnées OG/Twitter Card, favicon, gestion automatique de l'encodage
- •API OG — point de terminaison
/board/api/og
- •board-autolink.js — JS unifié de lien automatique + carte OG (chargé globalement depuis base-header)
v1.10.2
2026-03-20 · il y a 7 mois
Fixed
- •Alignement des images dans l'éditeur/le contenu — remplacement de
img { display: block } du preflight Tailwind
- •Création du CSS partagé
board-content.css (affichage éditeur + contenu unifié)
- •Chargement global depuis
base-header.php (toutes les pages frontend)
- •Ajout des styles globaux de l'éditeur dans
multilang-modal.php (toutes les instances Summernote de l'admin)
- •Suppression de la classe
prose du corps du tableau ; les styles en ligne de l'éditeur sont désormais préservés à 100%
Changed
- •Règles de style du contenu du tableau documentées dans CLAUDE.md (la classe
board-content est obligatoire)
v1.10.1
2026-03-20 · il y a 7 mois
Fixed
- •Correction du bug où les données de la catégorie précédente étaient chargées dans la modale multilingue lors de l'ajout d'une catégorie de tableau (génération d'une clé langKey temporaire unique)
- •Ajout de la valeur par défaut 3 pour
comment_max_depth dans la migration 021
v1.10.0
2026-03-20 · il y a 7 mois
Added
- •Variables étendues du tableau — module de composant ExtraVarRenderer (15 types : rendu input/display par type)
- •Internationalisation des variables étendues — stockage indépendant par langue des valeurs de variables étendues (intégration rzx_translations, chaîne de repli)
- •Stockage multilingue séparé des publications — l'édition dans la langue d'origine sauvegarde directement dans board_posts ; les autres langues sauvegardent les traductions dans rzx_translations
- •Chaîne de repli de lecture des publications — affiche titre/corps/variables étendues dans l'ordre : locale actuel → en → original
- •Réponses imbriquées — prise en charge de commentaires imbriqués sur 3 niveaux, tri récursif en arbre, formulaire de réponse en ligne
- •J'aime/Je n'aime pas les commentaires — bouton like par commentaire + API
- •Accès frontend aux paramètres du tableau — icône engrenage administrateur → /board/{slug}/settings mise en page frontend
- •Lien titre en administration du tableau — cliquer sur le titre dans la liste des tableaux admin navigue vers ce tableau
Fixed
- •Vérification des droits administrateur dans l'API du tableau :
$currentUser['role'] → $_SESSION['admin_id'] (4 fichiers mis à jour)
- •Avertissement en langue d'origine affiché uniquement à l'auteur/administrateur
- •Le lien d'onglet en mode intégré des paramètres du tableau prend en charge l'URL frontend
Changed
- •Ajout de la colonne JSON
extra_vars dans la BD rzx_board_posts
- •Valeur par défaut de
comment_max_depth changée de 0 → 3
- •Barre d'actions des commentaires unifiée (icônes like/dislike/répondre/supprimer)
v1.9.4
2026-03-20 · il y a 7 mois
Added
- •Données de forum par défaut — migrations des forums Annonces, Questions et réponses, FAQ et forum libre (020_default_boards_v193.sql)
v1.9.3
2026-03-20 · il y a 7 mois
Added
- •Réinitialisation des groupes de membres — initialisation avec les données par défaut (7 groupes + traductions en 13 langues)
- •Réinitialisation des paramètres de points — restauration des valeurs de configuration / points de niveau / liens de groupe aux valeurs par défaut (les soldes des membres ne sont pas affectés)
- •Groupes de membres multilingues — composant commun
rzx_multilang_input() appliqué au nom du groupe / description des avantages
- •Glisser-déposer pour les groupes de membres — réorganisation des cartes avec SortableJS + sauvegarde automatique
Fixed
- •Affichage des traductions de carte de groupe de membres par locale (vue carte + modal d'édition)
- •Corruption des données de traduction multilingue des groupes de membres corrigée (re-enregistrement UTF-8 en PHP)
- •Nom de colonne du tableau de configuration du module de points corrigé (board_name → title)
- •Conflit de classement dans la liste des membres de points résolu (unifié en utf8mb4_unicode_ci)
- •Migration de la BD de production (019_point_system_v190.sql)
v1.9.0
2026-03-20 · il y a 7 mois
Added
- •Système de gestion des points (crédits) — structure à 3 onglets (Paramètres de base / Paramètres par module / Liste des points des membres)
- •Structure de points à 3 champs — point (points d'activité), balance (crédits de paiement), total_accumulated (points cumulés, base du calcul de niveau)
- •Pondération des points cumulés — pondération de paiement / pondération d'activité séparées, montée de niveau préférentielle pour les clients payants
- •Échange de points — conversion points → crédits (ratio, unité, points minimum configurables)
- •17 catégories d'attribution/déduction de points — même structure que Rhymix (récupération à la suppression, limite de temps, notices exclues)
- •Paramètres par module — configuration individuelle de 15 éléments de points par tableau
- •Liste des points des membres — 4 colonnes (points/crédits/cumulés/niveau), recherche, édition individuelle
- •Points de niveau — calcul par formule, ajustement dynamique du niveau maximum, liaison aux groupes
- •Documentation du système de points — POINT_SYSTEM.md document de conception détaillé
- •Glisser-déposer de groupes de membres — réordonner les cartes avec SortableJS + sauvegarde automatique
- •Groupes de membres multilingues — composant commun
rzx_multilang_input() appliqué au nom du groupe/description des avantages
- •Données de seed des groupes de membres — 7 groupes × 13 langues de données de traduction multilingues
Changed
- •Ajout des colonnes
balance, total_accumulated à la BD rzx_member_points
- •Modification de
rzx_point_levels.group_id de INT à CHAR(36) dans la BD (compatible UUID)
- •Unification de la collation de
rzx_point_levels et rzx_member_points en utf8mb4_unicode_ci
- •Mise à jour de la mise en page de la page groupée (
sidebar-main-content → modèle tableau de bord flex-1 ml-64)
- •Correction de l'unité monétaire de la page groupée
$config['currency'] → $siteSettings['service_currency']
- •Modification de la durée du service de select → input number + datalist
- •Documentation des règles d'interface d'entrée multilingue dans CLAUDE.md (utilisation obligatoire de rzx_multilang_input)
v1.8.3
2026-03-20 · il y a 7 mois
Added
- •Page de gestion détaillée des bundles — modifier les informations de base du bundle, téléverser l'image de couverture, modifier la composition des services, lier le personnel, basculer actif/inactif
- •Remise événement — prix événement par bundle, période (début/fin), paramètre d'étiquette ; activation automatique dans la période
- •Design des cartes de liste de bundles — disposition en carte grille, en-tête image, badge événement/remise, barre d'action épinglée en bas
- •Image de fond du package recommandé — fond d'image de couverture + superposition de dégradé sur les cartes de bundle dans la page de détail du personnel client
- •Saisie directe de la durée de service — select → saisie numérique (5–480 min, pas de 5 minutes) + liste de recommandations datalist
Changed
- •DB
rzx_service_bundles colonnes ajoutées : event_price, event_start, event_end, event_label
- •API de liste de bundles :
total_duration et colonnes d'événement ajoutées
- •Fichiers de traduction (ko, en, ja) : clés de gestion détaillée des bundles + remise événement ajoutées
v1.8.1
2026-03-19 · il y a 7 mois
Added
- •Page de paramètres POS — taille des cartes, affichage image/prix/téléphone, opacité, onglet par défaut, actualisation automatique, son d'alerte, affectation du personnel obligatoire, affectation automatique
- •Paramètres POS appliqués — taille de carte/image/prix/téléphone/opacité/actualisation automatique/onglet par défaut tous reflétés dans le POS
- •Affectation automatique du personnel — lorsqu'activée dans les paramètres POS, affecte automatiquement le personnel à l'enregistrement kiosk (personnel capable + moins de réservations le même jour)
- •Badge du personnel sur la carte POS — indicateur affecté/non affecté ; bouton Continuer désactivé si non affecté
- •Fond d'image de service POS — image de service représentative en fond dans l'en-tête + la zone client de la fenêtre de détail du service
- •Personnel is_visible — contrôle la visibilité dans la liste ; personnel masqué exclu des réservations/POS/kiosk
- •Bannière de carte du personnel — image de bannière + badge de statut sur la carte du personnel dans l'admin
- •Affectation automatique au kiosk — enregistrement avec staff_id=NULL ; affectation effectuée par l'admin dans le POS
Fixed
- •Affectation de personnel POS : la liste de services se met à jour immédiatement après l'affectation (prévention du cache)
- •Correction du paramètre de l'API d'affectation du personnel (reservation_id → reservation_ids[])
- •Plusieurs tables/colonnes manquantes corrigées en production (migration 018 renforcée)
- •Route de déconnexion administrateur ajoutée
- •Placement de la route pré-authentification du kiosk
v1.7.0
2026-03-18 · il y a 7 mois
Added
- •Système de mise en page de base —
layouts/base-header.php + base-footer.php, ob_start appliqué automatiquement dans index.php, en-tête/pied de page commun pour toutes les pages client
- •Front-end du tableau d'affichage — pages de liste, de détail, d'écriture/édition, éditeur Summernote, pièces jointes par glisser-déposer
- •URLs courtes du tableau d'affichage — accès à
/free, /notice/3, etc. sans le préfixe /board/ ; correspondance automatique des slugs en base de données
- •Page de consultation des réservations — URL courte
/lookup, recherche par numéro de réservation / e-mail / téléphone
- •Page de détail de réservation —
/booking/detail/{numéro}, bulle de salutation du personnel, informations sur le service/paiement/annulation
- •Page d'annulation de réservation —
/booking/cancel/{numéro}, saisie du motif d'annulation
- •Détail de réservation dans Mon espace —
/mypage/reservations/{id}, barre latérale + informations détaillées
- •Tableau d'affichage multilingue —
original_locale (langue du premier brouillon) + source_locale (langue du contenu actuel), chaîne de repli (source → en → original)
- •Messages d'accueil du personnel —
greeting_before (avant le soin) + greeting_after (après le soin), multilingue, affiché selon le statut de la réservation
- •Menu déroulant du profil administrateur — photo de profil/initiales + nom + liens vers la page d'accueil / Mon espace / déconnexion
- •Lien administrateur dans l'en-tête client — en session administrateur, le menu déroulant affiche un lien vers le panneau d'administration
Changed
- •Mise en page unifiée pour toutes les pages client (structures HTML individuelles supprimées, LayoutManager appliqué automatiquement)
- •Condition d'affichage des catégories du tableau changée de
show_category à hide_categories
- •URL du tableau changée de
/board/free à l'URL courte /free par défaut
- •« Admin » dans la barre supérieure de l'administrateur remplacé par le vrai nom de connexion + photo de profil
Fixed
- •Colonne
rzx_users.role manquante → détection de l'administrateur maintenant basée sur $_SESSION['admin_id']
- •Colonne
rzx_users.nick_name manquante → utilisation de name + déchiffrement Encryption
- •
rzx_staff.profile_image → corrigé en nom de colonne avatar
- •Transtypage int→string de
category_id dans le modèle Service
- •La recherche de réservation par e-mail/téléphone utilise une recherche en texte brut (données non chiffrées)
v1.6.1
2026-03-18 · il y a 7 mois
Added
- •6 onglets d'administration du forum — Paramètres de base, Gestion des catégories, Variables supplémentaires, Permissions, Paramètres supplémentaires, Skin
- •Consolidation de l'onglet Paramètres de base — Informations de base + SEO + Sélection de la mise en page + Sélection du skin + Affichage + Liste + Avancé (réductible/développable)
- •Composants communs — 8 fichiers
components/board/section-*.php (basic, seo, layout-select, skin-select, display, list, advanced, js), réutilisables sur les pages de création/édition
- •Composant de saisie multilingue — fonction
rzx_multilang_input(), modes texte/éditeur, bouton globe en ligne
- •Gestion des catégories améliorée — structure en arbre (parent_id), modal d'édition (nom/couleur de police/description/groupes autorisés/développer/catégorie par défaut), tri par glisser-déposer avec SortableJS, chargement dynamique des grades de membres depuis la DB
- •Onglet Variables supplémentaires — table
rzx_board_extra_vars, 15 types de saisie (dont text_multilang, textarea_multilang, textarea_editor), support multilingue, tri par glisser-déposer
- •Onglet Permissions — Permissions d'accès (all/member/grade:*/admin_staff/admin), administrateur de module (recherche d'utilisateur partagée, photo de profil, portée des permissions), info mail de notification
- •Onglet Paramètres supplémentaires — Forum intégré, documents (historique/recommander/signaler), commentaires (nombre/profondeur/approbation/recommander/signaler), éditeur WYSIWYG (matrice des permissions), fichiers (groupe de téléchargement), feeds (RSS public/copyright)
- •Système de skin — format
skin.json, SkinConfigRenderer, support "multilang": true, carte d'info skin
- •Système de mise en page — format
layout.json, sélection en carte dans les paramètres de base
- •Recherche d'utilisateur partagée — composant
user-search.php, chiffrement/déchiffrement, photo de profil, réutilisable partout
- •Administrateur de module — table
rzx_board_admins, permissions publication/commentaire/paramètres, abonnement aux notifications
- •Extension des paramètres avancés — exclure l'admin de l'anonymat, restriction Data URL, abus Unicode, protection des publications/commentaires (nombre de commentaires/réponses/période), protection super-administrateur, adresse e-mail expéditeur
- •UI à interrupteurs — tous les éléments oui/non convertis en interrupteurs (paramètres de base + supplémentaires)
- •Clés de traduction — environ 300 clés, 13 langues
Fixed
- •Erreur SQL dans la corbeille — liaison
LIMIT ? chaîne → littéral entier
- •Summernote non rendu — chargement jQuery/Summernote JS + initialisation après affichage du modal
- •Erreur de classement — COLLATE utf8mb4_unicode_ci spécifié explicitement lors du JOIN de board_admins
- •Réduction/développement non fonctionnel — fonction
toggleSection définie en premier dans <head>
Changed
- •Onglets indépendants (liste/avancé) → intégrés dans l'onglet Paramètres de base avec réduction/développement
- •Sélection du skin → déplacée vers l'onglet Paramètres de base ; l'onglet skin n'affiche que les paramètres
- •E-mail administrateur → changé en "Adresse e-mail expéditeur" dans les paramètres avancés
- •Administrateur de module → déplacé vers l'onglet Permissions
- •"Afficher la catégorie dans la liste" → retiré des paramètres de catégorie, délégué aux paramètres par skin
- •"Afficher la catégorie dans la liste" → retiré des paramètres de catégorie, délégué aux paramètres par skin
- •Groupes autorisés à écrire → chargés dynamiquement depuis la table
rzx_member_grades au lieu d'être codés en dur
v1.6.0
2026-03-17 · il y a 7 mois
Added
- •Système de traduction avec repli multilingue: chaîne de repli intégrée dans
db_trans() (langue configurée → en → langue par défaut → source_locale → n'importe quelle traduction)
- •Bouton multilingue dans les paramètres de forum: bouton multilingue (globe) ajouté à 6 champs dans l'onglet des paramètres de base
- •Repli multilingue dans la vue front du forum: titre, description, SEO, header/footer multilingues appliqués dans
_init.php
- •Repli multilingue des widgets: gestion de la chaîne vide améliorée dans
WidgetRenderer::t(), tBtn()
- •Clés de traduction PWA ajoutées (13 langues :
admin.pwa.update_available, update, later)
Fixed
- •Problème de carte vide du widget Features: l'opérateur
?? traitait la chaîne vide "" comme une valeur valide → corrigé avec un repli basé sur !empty()
- •Erreur Mixed Content en production:
APP_URL http→https corrigé + correction automatique du protocole JS
v1.5.2
2026-03-17 · il y a 7 mois
Added
- •Suppression de service depuis l'historique des services POS (bouton de suppression + API + mise à jour immédiate du DOM)
- •Ajout des clés de traduction de suppression de service pour 13 langues
v1.5.0
2026-03-17 · il y a 7 mois
Added
- •Système d'accueil en borne: confirmation du service → informations client → création de la réservation → émission du numéro d'attente
- •Badge de disponibilité du personnel: affiche occupé/disponible en temps réel lors de la sélection du personnel sur la borne
- •Module de numéro de téléphone international: composant phone-input appliqué au formulaire d'accueil de la borne
- •Seed de données d'exemple de réservations:
database/seed_reservations.php (10 entrées entre POS/borne/en ligne)
- •Fichiers communs de la borne séparés (
_styles.php, _bg.php, _scripts.php)
- •Ajout de 11 clés de traduction de la borne dans 13 langues
Changed
- •Sélection du service en borne: filtrage basé sur les compétences du personnel (mode de désignation)
- •Onglets de catégorie de la borne centrés
Fixed
- •Connexion administrateur impossible en production (hachage du mot de passe corrompu — problème de substitution de la variable
$ de bash)
- •Stabilisation du système de mise à jour: liste de conservation étendue, vérification de l'état, synchronisation de la version de la BD
- •Source unique de version unifiée (
version.json → index.php, synchronisation automatique de la BD)