11 Commits

Author SHA1 Message Date
cedricAbonnel 4e262ddde8 Merge pull request 'release 1.6.1 : fix ordre require login/logout, data/site/ hors git' (#70) from dev into main
Merge PR #70 : release 1.6.1
2026-05-15 10:58:07 +00:00
cedricAbonnel 7737edf402 chore : version 1.6.1 — fix ordre require login/logout, data/site/ hors git
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 12:57:21 +02:00
cedricAbonnel 6d159e7dda fix : ordre require config→bootstrap dans login et logout, data/site/ hors git
- public/login/index.php, login/magic.php, logout.php : config/config.php
  chargé avant bootstrap.php pour que SESSION_NAME soit défini avant session_start()
- data/site/ retiré du suivi git (.gitignore corrigé) : contenu site-spécifique
  déjà présent dans varlog-data/site/ et fr.abonnel.www-data/site/
- CLAUDE.md : chemins articles corrigés (varlog-data/, fr.abonnel.www-data/)
- consignes.md : ajouté (architecture, workflow, règles, procédures déploiement)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 12:52:06 +02:00
cedricAbonnel ebf0e2df65 Merge pull request 'release 1.6.0 : bouton Mettre à jour, branche dev, guard git pull' (#69) from dev into main
release 1.6.0
2026-05-15 09:21:51 +00:00
cedricAbonnel 331e9c9ecd chore : version 1.6.0 — bouton Mettre à jour, branche dev, guard git pull
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 11:16:35 +02:00
cedricAbonnel 0280ef3ca1 docs : architecture articles git (varlog.git + abonnel-www.git), sync bidirectionnelle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 11:16:35 +02:00
cedricAbonnel eddde2165a fix : run_engine_update vérifie origin == folio_repo_url avant git pull
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 11:16:35 +02:00
cedricAbonnel 07d004b3f0 feat : bouton unique Mettre à jour (git pull + SQL + contenu), branche dev
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 11:16:35 +02:00
cedricAbonnel 5cb0e854fd Merge pull request 'release 1.5.0 : config admin FOLIO_REPO_URL, APP_TIMEZONE, push.sh protégé' (#68) from dev into main
release 1.5.0 : config admin FOLIO_REPO_URL, APP_TIMEZONE, push.sh protégé
2026-05-15 08:07:04 +00:00
cedricAbonnel 8f6c17f0f2 chore : version 1.5.0, push.sh bloque main, CHANGELOG
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 09:55:16 +02:00
cedricAbonnel 5452fb4927 Merge pull request 'feat : FOLIO_REPO_URL et APP_TIMEZONE configurables depuis admin' (#67) from feat/folio-repo-url-admin-config into main
Reviewed-on: #67
2026-05-15 07:52:17 +00:00
17 changed files with 305 additions and 226 deletions
-1
View File
@@ -11,5 +11,4 @@ Thumbs.db
# Données des sites (articles, config, cache) — propres à chaque workspace
data/*
!data/.gitkeep
!data/site/
_cache/
+32
View File
@@ -9,6 +9,38 @@ Format : [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/) — versionnag
---
## [1.6.1] - 2026-05-15
### Corrigé
- `login/index.php`, `login/magic.php`, `logout.php` : ordre de chargement corrigé (`config.php` avant `bootstrap.php`) pour que `SESSION_NAME` soit défini avant `session_start()`
- `data/site/` retiré du suivi git du moteur (contenu site-spécifique) ; `.gitignore` mis à jour
---
## [1.6.0] - 2026-05-15
### Ajouté
- Admin → Dashboard : bouton unique **Mettre à jour** (git pull + migrations SQL + migrations contenu) remplace les boutons séparés
- Branche `dev` : branche d'intégration permanente pour le développement quotidien
### Corrigé
- `run_engine_update` : vérifie que le remote git `origin` correspond à `FOLIO_REPO_URL` avant tout `git pull` (évite le pull sur le mauvais dépôt)
---
## [1.5.0] - 2026-05-15
### Ajouté
- Admin → Site : configuration de l'URL du dépôt Folio et de la branche suivie pour les mises à jour, sans modifier le `.env` (`folio_repo_url`, `folio_update_branch` dans `site_settings.json`)
- `APP_TIMEZONE` : fuseau horaire configurable via `.env` (défaut `Europe/Paris`), appliqué globalement dans `bootstrap.php`
### Corrigé
- Bouton « Vérifier » masqué avec message explicatif si `FOLIO_REPO_URL` n'est pas configuré (ni dans `.env` ni dans l'admin)
- `FOLIO_REPO_URL` et `FOLIO_UPDATE_BRANCH` documentés dans `.env.example`
- `scripts/push.sh` : ne pousse plus directement sur `main` — pousse sur la branche courante pour forcer le passage par une PR
---
## [1.4.0] - 2026-05-15
### Ajouté
+39 -15
View File
@@ -11,40 +11,64 @@ Il contient uniquement le code du moteur — pas de données, pas de credentials
| Répertoire local | Site distant | Rôle |
|-----------------|-------------|------|
| `~/Projects/folio/` | — | Copie du dépôt Folio (branche DEV). On code ici. |
| `~/Projects/varlog/` | varlog.a5l.fr | Sync bidirectionnelle des articles varlog. Sert de site de test pour le moteur. |
| `~/Projects/fr.abonnel.www/` | www.abonnel.fr | Sync bidirectionnelle des articles abonnel.fr. A aussi servi au déploiement initial. |
| `~/Projects/varlog/` | varlog.a5l.fr | Workspace varlog (scripts de déploiement/sync). Sert de site de test pour le moteur. |
| `~/Projects/varlog-data/` | varlog.a5l.fr | Articles de varlog. Sync bidirectionnelle. |
| `~/Projects/fr.abonnel.www/` | www.abonnel.fr | Workspace abonnel.fr (scripts de déploiement/sync). |
| `~/Projects/fr.abonnel.www-data/` | www.abonnel.fr | Articles de abonnel.fr. Sync bidirectionnelle. |
**abonnel.fr** utilise Folio mais se met à jour seul via son UpdateChecker interne (vérifie `version.txt` sur Gitea). Aucune action manuelle nécessaire côté serveur.
## Articles (`data/`)
Les articles ne sont pas versionnés dans ce dépôt. Ils ont leur propre git local dans chaque workspace site (`~/Projects/varlog/data/`, `~/Projects/fr.abonnel.www/data/`), synchronisé de façon bidirectionnelle avec le serveur distant.
Les articles ne sont pas versionnés dans ce dépôt. Ils ont leur propre dépôt git (`~/Projects/varlog-data/`, `~/Projects/fr.abonnel.www-data/`), synchronisé de façon bidirectionnelle avec le serveur distant.
## Modifier le moteur
Pour toute correction ou fonctionnalité : **créer un ticket et une PR**.
### Branches
1. Coder ici dans `~/Projects/folio/` (branche feature)
2. **Tester sur varlog.a5l.fr** :
| Branche | Rôle |
|---------|------|
| `dev` | Branche d'intégration permanente. **Tout le développement courant se fait ici.** |
| `main` | Branche de production. **Jamais de commit direct.** |
| `feat/*` | Branches feature optionnelles pour du travail isolé, mergées dans `dev`. |
### Workflow
1. Toujours travailler sur `dev` (ou une branche feature mergée dans `dev`) :
```bash
git checkout dev
```
2. **Tester sur varlog.a5l.fr** à chaque itération (rsync des fichiers locaux, DB persistante) :
```bash
~/Projects/varlog/scripts/sync.sh
# puis tester sur http://varlog.acegrp.lan
```
3. Une fois validé, ouvrir une PR sur Gitea. Le commit doit inclure :
- `public/version.txt` (bump semver)
- `CHANGELOG.md` (entrée `### Ajouté / Corrigé / Modifié`)
3. Quand `dev` est stable et prête pour la production :
- Bumper `public/version.txt` (semver)
- Ajouter une entrée `CHANGELOG.md` (`### Ajouté / Corrigé / Modifié`)
- Ouvrir une **PR `dev` → `main`** sur Gitea
4. Merger la PR → abonnel.fr se met à jour automatiquement.
**Règle absolue : ne jamais commiter directement sur `main`.** Le script `scripts/push.sh` bloque cette action.
### Pourquoi `dev` et non des branches feature à la volée
- La DB de varlog (test) accumule les migrations au fil du temps — changer de branche ne fait pas reculer les migrations.
- Travailler toujours sur `dev` évite toute désynchronisation entre le code rsyncé et la DB.
## Données articles (`DATA_PATH`)
Les articles sont stockés dans un répertoire **hors du dépôt Folio**, configurable via `DATA_PATH` dans `.env`.
Les articles sont stockés dans un répertoire **hors du dépôt Folio**, configurable via `DATA_PATH` dans `.env` (défaut production : `/srv/data/folio`).
| Environnement | Chemin local | Chemin serveur |
|--------------|-------------|----------------|
| varlog | `~/Projects/varlog-data/` | `/srv/data/folio` |
| abonnel.fr | `~/Projects/fr.abonnel.www-data/` | `/srv/data/folio` |
| Environnement | Dépôt local articles | Dépôt Gitea | Serveur |
|--------------|---------------------|------------|---------|
| varlog | `~/Projects/varlog-data/` | `cedricAbonnel/varlog` | `varlog:/srv/data/folio` |
| abonnel.fr | `~/Projects/fr.abonnel.www-data/` | `cedricAbonnel/abonnel-www` | `abonnel-wiki:/srv/data/folio` |
Les scripts de sync (`pull-data.sh`, `push-data.sh`, `sync.sh`) utilisent `DATA_DIR` (overridable via env) pointant vers ces chemins locaux.
Sync bidirectionnelle via **git** (pas rsync). Scripts dans `~/Projects/varlog/scripts/` et `~/Projects/fr.abonnel.www/scripts/` :
- `pull-data.sh` : commit auto serveur + git pull local
- `push-data.sh` : git commit local + git push + git pull serveur
- `sync.sh` : moteur (rsync) + articles (git bidirectionnel)
## Asymétrie de déploiement moteur
+108
View File
@@ -0,0 +1,108 @@
# Consignes — Folio
## Architecture
**Folio** est un moteur de blog PHP.
### Dépôts et rôles
| Répertoire local | Rôle | Remote Gitea |
|-----------------|------|-------------|
| `~/Projects/folio/` | Copie du moteur Folio, branche `dev`. **Tout le développement se fait ici.** | `git.abonnel.fr/cedricAbonnel/folio` |
| `~/Projects/varlog/` | Workspace du site varlog (scripts, config). | — |
| `~/Projects/varlog-data/` | Articles de varlog.a5l.fr. Sync bidirectionnelle. | `cedricAbonnel/varlog` |
| `~/Projects/fr.abonnel.www/` | Workspace du site abonnel.fr (scripts, config). | — |
| `~/Projects/fr.abonnel.www-data/` | Articles de www.abonnel.fr. Sync bidirectionnelle. | `cedricAbonnel/abonnel-www` |
### Environnements
| Site | Rôle | Mise à jour moteur | Articles |
|------|------|--------------------|---------|
| varlog.a5l.fr | Test | rsync depuis `~/Projects/folio/` | `varlog-data/``varlog:/srv/data/folio` |
| www.abonnel.fr | Production | Auto (UpdateChecker vérifie `version.txt` sur Gitea) | `fr.abonnel.www-data/``abonnel-wiki:/srv/data/folio` |
### Articles (`DATA_PATH`)
Les articles ne sont **jamais** dans le dépôt folio. Ils vivent dans un répertoire séparé, configurable via `DATA_PATH` dans le `.env` de chaque instance.
- Serveur varlog : `DATA_PATH=/srv/data/folio`
- Serveur abonnel.fr : `DATA_PATH=/srv/data/folio`
- En local pour tester : pointer `DATA_PATH` vers `~/Projects/varlog-data/`
La sync des articles se fait via git (pas rsync) avec les scripts `pull-data.sh` et `push-data.sh`.
---
## Workflow moteur
1. Travailler sur `dev` dans `~/Projects/folio/`
2. Tester sur varlog.a5l.fr :
```bash
~/Projects/varlog/scripts/sync.sh
# puis vérifier sur http://varlog.acegrp.lan (ou varlog.a5l.fr)
```
3. Quand `dev` est stable :
- Bumper `public/version.txt` (semver)
- Ajouter une entrée dans `CHANGELOG.md`
- Ouvrir une **PR `dev` → `main`** sur Gitea
4. Merger la PR → abonnel.fr se met à jour automatiquement.
**Règle absolue : jamais de commit direct sur `main`.**
---
## Mise à jour du moteur (varlog)
Le poste local n'a pas de base de données. Tout ce qui touche à la DB ou au contenu s'exécute **sur le serveur varlog** via SSH — les scripts locaux ne font qu'ouvrir une connexion SSH et lancer le PHP distant.
**Cycle de développement :**
1. Modifier le code dans `~/Projects/folio/` (local)
2. Déployer et tester :
```bash
# Rsync moteur (folio → varlog) + sync articles bidirectionnel
~/Projects/varlog/scripts/sync.sh
# puis tester sur http://varlog.acegrp.lan
```
3. Si des migrations de schéma BDD sont nécessaires :
```bash
~/Projects/varlog/scripts/db-migrate.sh # exécute le PHP sur varlog via SSH
```
4. Si des migrations de contenu sont nécessaires :
```bash
~/Projects/varlog/scripts/content-migrate.sh # exécute le PHP sur varlog via SSH
```
**Déploiement complet en une commande (lint + rsync + DB + contenu + commit serveur) :**
```bash
~/Projects/varlog/scripts/deploy.sh "message de commit"
```
Chemin serveur : `varlog:/var/www/lan.acegrp.varlog/`
---
## Mise à jour manuelle du moteur (abonnel.fr)
À utiliser uniquement si l'UpdateChecker échoue :
```bash
cp /var/www/lan.acegrp.abonnel-www/.env /tmp/.env.bak
rm -rf /var/www/lan.acegrp.abonnel-www
git clone --depth=1 https://cedricAbonnel:TOKEN@git.abonnel.fr/cedricAbonnel/folio.git /var/www/lan.acegrp.abonnel-www
cp /tmp/.env.bak /var/www/lan.acegrp.abonnel-www/.env
cd /var/www/lan.acegrp.abonnel-www && composer install --no-dev --optimize-autoloader
php database/migrate.php
git -C /var/www/lan.acegrp.abonnel-www config user.email 'cedric@abonnel.fr'
git -C /var/www/lan.acegrp.abonnel-www config user.name 'Cédrix'
```
---
## Règles à respecter
- Ne **jamais** écraser le `.env` serveur (ni scp, ni réécriture). Indiquer les variables à l'utilisateur pour qu'il les saisisse lui-même.
- Ne **jamais** versionner `data/`, `.env`, ou `vendor/` dans le dépôt folio.
- Toujours bumper la version **et** mettre à jour le changelog dans le même commit que la PR.
-18
View File
@@ -1,18 +0,0 @@
{
"uuid": "a3d8f2c1-7b4e-4f9a-8c3d-2e5a9b6f1d4c",
"slug": "about",
"title": "À propos",
"author": "cedric@abonnel.fr",
"published": true,
"published_at": "2021-01-16 04:02:40",
"created_at": "2021-01-16 04:02:40",
"updated_at": "2026-05-13 00:00:00",
"revisions": [],
"cover": "",
"files_meta": [],
"external_links": [],
"seo_title": "",
"seo_description": "",
"og_image": "",
"category": ""
}
-39
View File
@@ -1,39 +0,0 @@
# À propos
Qui se cache derrière varlog ?
Je m'appelle **Cédric**. Passionné d'informatique depuis longtemps, je gère un **HomeLab** à la maison — un petit laboratoire personnel où je fais tourner des serveurs, expérimente des configs réseau et casse des choses pour mieux les comprendre.
varlog est mon carnet de bord technique. J'y documente ce que je fais, ce que j'apprends, et parfois ce qui tourne mal — les incidents sont souvent les meilleures leçons.
Le blog a été lancé publiquement aux **JDLL 2025** (Journées Du Logiciel Libre), à Lyon.
## Ce dont je parle ici
### HomeLab & infrastructure
Proxmox, virtualisation, domotique (Zigbee, MQTT, Home Assistant), supervision avec Uptime Kuma, auto-hébergement de services (Gitea, Keycloak…), incidents réseau et leurs post-mortems.
### Réseaux & télécom
Passionné par les réseaux mobiles (3G/4G/5G/6G), la fibre optique (50G-PON), les stratégies des opérateurs et les infrastructures qui font fonctionner tout ça sans qu'on y pense.
### Linux & développement
Debian au quotidien, scripts, administration système, et un peu de PHP — dont ce blog lui-même, développé maison sous le nom de code *Folio*.
### Numérique & société
Souveraineté numérique, données personnelles, IA et plateformes qui monétisent nos contenus — des sujets qui m'intéressent autant qu'ils m'inquiètent.
### Le reste
Bricolage, travaux, anecdotes techniques, lectures, liseuses Kobo, et quelques billets qui n'entrent dans aucune case. La vie ne se range pas en catégories.
## Contact
Vous pouvez me joindre via le [formulaire de contact](/contact). Je lis tous les messages, même si je ne réponds pas toujours vite.
---
Le contenu de ce blog est publié sous licence [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) sauf mention contraire. Le moteur *Folio* est distribué sous [licence MIT](/LICENSE).
-18
View File
@@ -1,18 +0,0 @@
{
"uuid": "b2c7e1f4-4a3d-4e8b-9f2a-1d6c8e3f5a7b",
"slug": "legal",
"title": "Mentions légales",
"author": "cedric@abonnel.fr",
"published": true,
"published_at": "2021-01-16 04:02:40",
"created_at": "2021-01-16 04:02:40",
"updated_at": "2026-05-13 00:00:00",
"revisions": [],
"cover": "",
"files_meta": [],
"external_links": [],
"seo_title": "",
"seo_description": "",
"og_image": "",
"category": ""
}
-43
View File
@@ -1,43 +0,0 @@
# Mentions légales
Conformément à la loi n° 2004-575 du 21 juin 2004 pour la confiance dans l'économie numérique (LCEN).
## Éditeur du site
**Responsable de publication :** Cédric Abonnel
**Qualité :** Particulier — site personnel non commercial
**Contact :** [formulaire de contact](/contact)
## Hébergement
**Type :** Auto-hébergement sur infrastructure personnelle (HomeLab)
**Exploitant :** Cédric Abonnel
**Fournisseur d'accès à internet :** Infrastructure personnelle auto-hébergée
## Propriété intellectuelle
Le **contenu éditorial** de ce site (articles, textes, images produites par l'auteur) est publié sous licence [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/), sauf mention contraire.
Le **moteur du site** (*Folio*) est un logiciel libre distribué sous [licence MIT](/LICENSE).
Les composants tiers (Bootstrap, PHPMailer, police Inter…) sont soumis à leurs licences respectives, détaillées sur la [page des licences](/licenses).
## Données personnelles (RGPD)
Ce site est un blog personnel **sans publicité, sans pistage, sans système de commentaires** ni inscription publique.
Les seules données traitées automatiquement sont les **journaux de connexion du serveur web** (adresse IP, horodatage, page demandée), conservés conformément aux obligations légales (article L34-1 du Code des postes et des communications électroniques — durée maximale : 1 an).
Ces données ne sont ni vendues, ni transmises à des tiers, ni utilisées à des fins commerciales.
Conformément au RGPD (règlement UE 2016/679), vous disposez d'un droit d'accès, de rectification et de suppression des données vous concernant. Pour exercer ces droits : [formulaire de contact](/contact).
## Cookies
Ce site utilise uniquement un **cookie de session technique**, nécessaire au fonctionnement de l'authentification. Il n'est déposé que lors d'une connexion au compte d'administration et n'est pas utilisé à des fins de suivi ou de profilage. Aucun cookie tiers n'est déposé.
## Responsabilité
L'éditeur s'efforce de maintenir les informations publiées à jour et exactes, mais ne peut garantir l'exhaustivité ou l'absence d'erreurs du contenu.
Les liens vers des sites tiers sont fournis à titre informatif. L'éditeur n'est pas responsable du contenu de ces sites externes.
-18
View File
@@ -1,18 +0,0 @@
{
"uuid": "fdff8ad3-d369-4bd7-bbb9-e14d433868d7",
"slug": "licenses",
"title": "Licences",
"author": "cedric@abonnel.fr",
"published": true,
"published_at": "2021-01-16 04:02:40",
"created_at": "2021-01-16 04:02:40",
"updated_at": "2021-01-16 04:02:40",
"revisions": [],
"cover": "",
"files_meta": [],
"external_links": [],
"seo_title": "",
"seo_description": "",
"og_image": "",
"category": ""
}
-38
View File
@@ -1,38 +0,0 @@
# Licences
Composants logiciels utilisés par ce site et leurs licences.
## Ce site
| Composant | Licence | Usage |
|-----------|---------|-------|
| **Folio** — moteur de blog PHP | MIT | Moteur de ce blog — par Cédric Abonnel ([voir la licence](/LICENSE)) |
| **Contenu éditorial** | CC BY 4.0 | Articles et textes du blog — [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/) |
## Bibliothèques (production)
| Composant | Version | Licence | Usage |
|-----------|---------|---------|-------|
| **Bootstrap** | 5.3.3 | MIT | Framework CSS/JS — auto-hébergé ([voir la licence](/assets/css/LICENSE-Bootstrap.txt)) |
| **PHPMailer** | 6.12.0 | LGPL-2.1 | Envoi d'e-mails SMTP |
| **phpdotenv** | 5.6.2 | BSD-3-Clause | Variables d'environnement |
| **openid-connect-php** | 1.0.2 | Apache-2.0 | Authentification SSO (OIDC) |
| **Police Inter** | v20 | OFL-1.1 | Typographie — auto-hébergée ([voir la licence](/assets/fonts/LICENSE-Inter.txt)) |
## Outils de développement
| Composant | Version | Licence | Usage |
|-----------|---------|---------|-------|
| **PHPStan** | 1.12.32 | MIT | Analyse statique PHP |
| **PHP-CS-Fixer** | 3.89.1 | MIT | Formatage du code |
| **Claude Code CLI** | — | Commercial | Outil de développement (Anthropic) — [Conditions d'utilisation](https://www.anthropic.com/legal/aup) |
## Infrastructure
| Composant | Licence | Usage |
|-----------|---------|-------|
| **PHP 8.3** | PHP License v3.01 | Langage côté serveur |
| **PostgreSQL** | PostgreSQL License | Base de données relationnelle |
| **Apache HTTP Server** | Apache-2.0 | Serveur web |
+78 -1
View File
@@ -45,7 +45,7 @@ $action = $_GET['action'] ?? 'list';
$uuid = $_GET['uuid'] ?? '';
$slug = $_GET['slug'] ?? '';
$_noindexActions = ['create', 'edit', 'admin', 'categories', 'diff', 'add_files', 'import_image', 'import_image_step2', 'sources', 'profile', 'delete_file', 'delete_external_link', 'rename_category', 'delete_category', 'toggle_private_category', 'admin_save_site', 'not_found', 'add_feed', 'delete_feed', 'add_link', 'delete_link', 'reorder_links', 'react', 'comment', 'verify_comment', 'comment_moderate', 'comment_delete', 'comment_resend', 'create_tag_type', 'delete_tag_type', 'edit_tags', 'book_save', 'book_delete', 'admin_save_as_groups', 'admin_save_folio_config'];
$_noindexActions = ['create', 'edit', 'admin', 'categories', 'diff', 'add_files', 'import_image', 'import_image_step2', 'sources', 'profile', 'delete_file', 'delete_external_link', 'rename_category', 'delete_category', 'toggle_private_category', 'admin_save_site', 'not_found', 'add_feed', 'delete_feed', 'add_link', 'delete_link', 'reorder_links', 'react', 'comment', 'verify_comment', 'comment_moderate', 'comment_delete', 'comment_resend', 'create_tag_type', 'delete_tag_type', 'edit_tags', 'book_save', 'book_delete', 'admin_save_as_groups', 'admin_save_folio_config', 'run_engine_update'];
$metaRobots = in_array($action, $_noindexActions, true) ? 'noindex, nofollow' : null;
unset($_noindexActions);
@@ -2816,6 +2816,83 @@ switch ($action) {
header('Location: /admin?tab=dashboard&notice=' . ($_cmErrors ? 'migration_error' : 'migrated'));
exit;
case 'run_engine_update':
requireAuth();
if (!isAdmin() || $_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(403);
exit;
}
// 1. git pull — vérifier que origin pointe vers le dépôt folio configuré
$_folioRepo = rtrim(folioRepoUrl(), '/');
exec('git -C ' . escapeshellarg(BASE_PATH) . ' remote get-url origin 2>&1', $_originOut, $_originCode);
$_originUrl = rtrim(trim(implode('', $_originOut)), '/');
// Normaliser : supprimer les credentials éventuels de l'URL (token@host → host)
$_originNorm = preg_replace('#https?://[^@]+@#', 'https://', $_originUrl);
$_repoNorm = preg_replace('#https?://[^@]+@#', 'https://', $_folioRepo);
if ($_originCode !== 0 || $_originNorm !== $_repoNorm) {
$_SESSION['_update_log'] = "Le remote git 'origin' (" . $_originUrl . ") ne correspond pas à FOLIO_REPO_URL (" . $_folioRepo . "). git pull annulé.";
header('Location: /admin?tab=dashboard&notice=update_git_error');
exit;
}
exec('cd ' . escapeshellarg(BASE_PATH) . ' && git pull origin main 2>&1', $_gitOut, $_gitCode);
if ($_gitCode !== 0) {
$_SESSION['_update_log'] = implode("\n", $_gitOut);
header('Location: /admin?tab=dashboard&notice=update_git_error');
exit;
}
// 2. composer install (non-bloquant si absent)
exec('which composer 2>/dev/null', $_composerPath);
if (!empty($_composerPath)) {
exec('cd ' . escapeshellarg(BASE_PATH) . ' && composer install --no-dev --optimize-autoloader -q 2>&1');
}
// 3. Migrations SQL
$pdo->exec('CREATE TABLE IF NOT EXISTS schema_migrations (name TEXT NOT NULL PRIMARY KEY, applied_at TIMESTAMP NOT NULL DEFAULT NOW())');
$_sqlApplied = array_flip($pdo->query('SELECT name FROM schema_migrations ORDER BY name')->fetchAll(PDO::FETCH_COLUMN));
$_sqlFiles = glob(BASE_PATH . '/database/migration_*.sql') ?: [];
sort($_sqlFiles);
foreach ($_sqlFiles as $_sqlFile) {
$_sqlName = basename($_sqlFile);
if (isset($_sqlApplied[$_sqlName])) {
continue;
}
$pdo->exec((string) file_get_contents($_sqlFile));
$pdo->prepare('INSERT INTO schema_migrations (name) VALUES (:n)')->execute([':n' => $_sqlName]);
}
// 4. Migrations de contenu
$_cmDataDir = DATA_PATH;
$_cmTrack = $_cmDataDir . '/.content_migrations.json';
$_cmFlag = $_cmDataDir . '/.maintenance';
$_cmApplied = file_exists($_cmTrack) ? (json_decode((string) file_get_contents($_cmTrack), true) ?? []) : [];
$_cmFiles = glob(BASE_PATH . '/scripts/content/migration_*.php') ?: [];
sort($_cmFiles);
$_cmPending = array_values(array_filter($_cmFiles, fn ($f) => !isset($_cmApplied[basename($f)])));
$_cmErrors = 0;
if (!empty($_cmPending)) {
file_put_contents($_cmFlag, date('Y-m-d H:i:s'));
$dataDir = $_cmDataDir;
foreach ($_cmPending as $_cmFile) {
try {
require $_cmFile;
$_cmApplied[basename($_cmFile)] = date('Y-m-d H:i:s');
file_put_contents($_cmTrack, json_encode($_cmApplied, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n");
} catch (Throwable $_cmEx) {
$_cmErrors++;
break;
}
}
if (file_exists($_cmFlag)) {
unlink($_cmFlag);
}
}
$_updateChecker->clearCache();
header('Location: /admin?tab=dashboard&notice=' . ($_cmErrors ? 'update_content_error' : 'engine_updated'));
exit;
case 'force_update_check':
requireAuth();
if (!isAdmin() || $_SERVER['REQUEST_METHOD'] !== 'POST') {
+4 -1
View File
@@ -35,9 +35,12 @@ if (!function_exists('url')) {
}
}
if (!defined('BASE_PATH')) {
define('BASE_PATH', dirname(__DIR__, 2));
}
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__DIR__, 2) . '/bootstrap.php';
require_once dirname(__DIR__, 2) . '/config/config.php';
require_once dirname(__DIR__, 2) . '/bootstrap.php';
require_once dirname(__DIR__, 2) . '/src/SiteSettings.php';
require_once dirname(__DIR__, 2) . '/src/mailer.php';
+4 -1
View File
@@ -5,9 +5,12 @@
// version : 20251011
declare(strict_types=1);
if (!defined('BASE_PATH')) {
define('BASE_PATH', dirname(__DIR__, 2));
}
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__DIR__, 2) . '/bootstrap.php';
require_once dirname(__DIR__, 2) . '/config/config.php';
require_once dirname(__DIR__, 2) . '/bootstrap.php';
// si tu as un service pour ouvrir une session
+3 -5
View File
@@ -4,12 +4,10 @@ declare(strict_types=1);
define('BASE_PATH', realpath(__DIR__ . '/../'));
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
require_once BASE_PATH . '/src/auth.php';
require_once BASE_PATH . '/vendor/autoload.php';
require_once BASE_PATH . '/config/config.php';
require_once BASE_PATH . '/bootstrap.php';
require_once BASE_PATH . '/src/auth.php';
$logoutUrl = ssoLogoutUrl();
+1 -1
View File
@@ -1 +1 @@
1.4.0
1.6.1
+12 -3
View File
@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# Pousse le code Folio vers git.abonnel.fr/cedricAbonnel/folio
# Pousse la branche courante vers git.abonnel.fr/cedricAbonnel/folio
# Ne pousse JAMAIS directement sur main — passer par une PR.
# Usage : ./scripts/push.sh "message de commit"
set -euo pipefail
@@ -20,6 +21,13 @@ if [ ! -d .git ]; then
echo "→ Dépôt git initialisé"
fi
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [[ "$BRANCH" == "main" ]]; then
echo "✗ Refus de pousser directement sur main."
echo " Travailler sur 'dev' ou une branche feature : git checkout dev"
exit 1
fi
# Extraire la version depuis CHANGELOG.md (première entrée ## [X.Y.Z])
FOLIO_VERSION=$(grep -m1 '^\#\# \[[0-9]' CHANGELOG.md | sed 's/.*\[\([^]]*\)\].*/\1/')
if [[ -z "$FOLIO_VERSION" ]]; then
@@ -32,5 +40,6 @@ echo "→ Version : $FOLIO_VERSION"
git add -A
git diff --cached --quiet && echo "(rien à committer)" && exit 0
git commit -m "$MSG"
git push origin main
echo "✓ Poussé vers folio"
git push origin "$BRANCH"
echo "✓ Poussé vers folio (branche $BRANCH)"
echo " → Ouvrir une PR sur https://git.abonnel.fr/cedricAbonnel/folio/pulls/new/$BRANCH"
+24 -24
View File
@@ -126,13 +126,17 @@ function adminStatusBadge(array $a, int $now): string
<tr>
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">Dernière version disponible</th>
<td class="d-flex align-items-center gap-2 flex-wrap">
<span><?= htmlspecialchars($_remoteLabel) ?><?= $_remoteLabel !== '—' && $_remoteLabel !== $_deployedLabel ? ' <span class="badge bg-warning text-dark ms-1">Mise à jour disponible</span>' : '' ?></span>
<?php if ($_repoConfigured): ?>
<form method="POST" action="/?action=force_update_check" class="d-inline">
<button type="submit" class="btn btn-outline-secondary btn-sm py-0">Vérifier</button>
</form>
<span><?= htmlspecialchars($_remoteLabel) ?></span>
<?php if ($_remoteLabel !== '—' && $_remoteLabel !== $_deployedLabel): ?>
<form method="POST" action="/?action=run_engine_update" class="d-inline">
<button type="submit" class="btn btn-primary btn-sm">Mettre à jour vers v<?= htmlspecialchars($_remoteLabel) ?></button>
</form>
<?php elseif ($_repoConfigured): ?>
<form method="POST" action="/?action=force_update_check" class="d-inline">
<button type="submit" class="btn btn-outline-secondary btn-sm py-0">Vérifier</button>
</form>
<?php else: ?>
<span class="text-muted small">(<code>FOLIO_REPO_URL</code> non configuré)</span>
<span class="text-muted small">(<code>FOLIO_REPO_URL</code> non configuré)</span>
<?php endif; ?>
</td>
</tr>
@@ -140,24 +144,20 @@ function adminStatusBadge(array $a, int $now): string
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">Branche suivie</th>
<td><code><?= htmlspecialchars($_branch) ?></code><?= $_lastChecked !== null ? ' <span class="text-muted ms-2">· vérifié le ' . date('d/m/Y à H:i', $_lastChecked) . '</span>' : '' ?></td>
</tr>
<?php if (!empty($_notices)): ?>
<tr>
<th class="text-muted fw-normal ps-0 pe-2 align-top">Actions requises</th>
<td class="d-flex flex-wrap gap-2 align-items-center">
<?php foreach ($_notices as $_n): ?>
<?php if ($_n['type'] === 'warning'): ?>
<form method="POST" action="/?action=run_content_migrations">
<button type="submit" class="btn btn-warning btn-sm">Mettre à jour le contenu</button>
</form>
<?php endif; ?>
<?php endforeach; ?>
</td>
</tr>
<?php endif; ?>
<?php if (($_GET['notice'] ?? '') === 'migrated'): ?>
<tr><td colspan="2"><div class="alert alert-success py-1 mb-0 small">Migrations appliquées avec succès.</div></td></tr>
<?php elseif (($_GET['notice'] ?? '') === 'migration_error'): ?>
<tr><td colspan="2"><div class="alert alert-danger py-1 mb-0 small">Une erreur est survenue pendant la migration.</div></td></tr>
<?php if (($_GET['notice'] ?? '') === 'engine_updated'): ?>
<tr><td colspan="2"><div class="alert alert-success py-1 mb-0 small">Moteur mis à jour avec succès (code, base de données, contenu).</div></td></tr>
<?php elseif (($_GET['notice'] ?? '') === 'update_git_error'): ?>
<tr><td colspan="2">
<div class="alert alert-danger py-1 mb-0 small">
Erreur git pull — vérifiez les droits d'accès au dépôt.
<?php if (!empty($_SESSION['_update_log'])): ?>
<pre class="mt-1 mb-0 small"><?= htmlspecialchars($_SESSION['_update_log']) ?></pre>
<?php unset($_SESSION['_update_log']); ?>
<?php endif; ?>
</div>
</td></tr>
<?php elseif (($_GET['notice'] ?? '') === 'update_content_error'): ?>
<tr><td colspan="2"><div class="alert alert-warning py-1 mb-0 small">Code et base de données mis à jour, mais une migration de contenu a échoué.</div></td></tr>
<?php endif; ?>
</tbody>
</table>