# Architecture

> Phase d'audit — document d'analyse. Aucun code applicatif n'est produit à ce stade.
> Source de vérité du comportement : `W:\daniel-old` (lecture seule) + production https://daniel-tiziani.com/.

## 1. Architecture actuelle (ancien site `daniel-old`)

### 1.1 Vue d'ensemble

L'ancien site est un **générateur de galeries piloté par le système de fichiers**, avec une base
MySQL utilisée uniquement comme **cache/index dérivé** (reconstruit intégralement à chaque mise à
jour). Il n'existe **pas de véritable interface d'administration** : l'« administration » consiste à
déposer des images par FTP dans `image_in/`, puis à déclencher un script de régénération.

```
  ┌─────────────┐    FTP     ┌──────────────┐   /update.php (Basic Auth)   ┌────────────────────┐
  │  Artiste    │ ─────────► │  image_in/   │ ───────────────────────────► │ Pipeline libs/*.php│
  └─────────────┘  (dépôt)   │ (source)     │                              │ (régénération)     │
                             └──────────────┘                              └─────────┬──────────┘
                                                                                     │ écrit
                                              ┌──────────────────────────────────────┼───────────┐
                                              ▼                                       ▼           ▼
                                     ┌─────────────────┐                    ┌──────────────┐ ┌─────────┐
                                     │ Tables MySQL    │                    │  img/{id}/   │ │ text.txt│
                                     │ folders / files │  (cache dérivé)    │ big+thumb+fold│ │ (copié) │
                                     └────────┬────────┘                    └──────┬───────┘ └────┬────┘
                                              │  lecture                           │ <img>        │
                                              ▼                                    ▼              ▼
                                         ┌───────────────────────────────────────────────────────────┐
   Visiteur  ──── GET /slug ───────────► │  index.php (front controller, rendu public Bootstrap 3)    │
                                         └───────────────────────────────────────────────────────────┘
```

**Conséquence majeure :** la base de données n'est **pas** la source de vérité. Les tables `folders`
et `files` sont `TRUNCATE`-ées puis reconstruites à chaque exécution de `update.php`. La source de
vérité réelle est l'arborescence de `image_in/` et les conventions de nommage des fichiers.

### 1.2 Pile technique (telle que constatée)

| Couche      | Ancien site                                                            |
|-------------|------------------------------------------------------------------------|
| Hébergement | Mutualisé cPanel (LiteSpeed `lsapi` / Apache), `/home/danieltiziani/`  |
| PHP         | **PHP 7.3** (`ea-php73`, voir `.htaccess` / `.user.ini`)               |
| Base        | MySQL, base `danielti_gal`, connexion PDO, `SET NAMES 'utf8'` (3 octets)|
| Front CSS   | Bootstrap 3 (`bootstrap.min.css`) + thème *Start Bootstrap 4 Col Portfolio* (`4-col-portfolio.css`) |
| Front JS    | jQuery + Bootstrap JS + **Fancybox 2.1.5** (lightbox)                  |
| Images      | Bibliothèque **GD** via la classe `Zebra_Image` (incluse dans `function.php`) |
| Routage     | `.htaccess` → front controller `index.php` (tout ce qui n'est pas fichier/dossier réel) |

### 1.3 Contraintes d'hébergement relevées (`.htaccess`, `.user.ini`, `php.ini`)

- `upload_max_filesize = 2M`, `post_max_size = 8M` — **très bas** pour de l'upload d'images d'art.
- `max_execution_time = 30`, `max_input_time = 60`, `memory_limit = 128M`.
- Forçage HTTPS (301) et redirection non-www → www (301).
- `Options -Indexes`, cache navigateur via `mod_expires` (images 1 mois, CSS/JS 1 an).
- Environnement cible annoncé (AGENTS.md) : **PHP 8.4 / MariaDB 10.11** en prod, **PHP 8.3 / MySQL 8.4**
  en local (Laragon). La pile actuelle (PHP 7.3 / MySQL) est donc **obsolète** et doit être modernisée.

### 1.4 Modèle de données actuel (dérivé, jetable)

Deux tables, reconstruites à chaque update :

**`folders`** (une ligne par galerie/dossier) — colonnes utilisées par le code :
`id`, `name`, `url`, `short_url`, `level`, `goodname` (nom affiché), `way` (sens de tri),
`statut` (0/1, visible si =1), `first_image` (image de couverture), `good_url` (slug public),
`arianne` (fil d'Ariane pré-calculé en HTML), `parent_id`.

**`files`** (une ligne par image) — colonnes :
`id`, `name`, `url`, `short_url`, `goodname` (nom affiché / alt), `filename` (nom normalisé sur disque),
`parent_id` (galerie de rattachement), `pictdate` (date EXIF, sert au tri).

`way` : `0` = ordre alphabétique du nom de fichier · `1` = date EXIF croissante · `2` = date EXIF décroissante.

### 1.5 Conventions de nommage (la « logique métier » cachée)

Toute la sémantique passe par les **noms de fichiers et de dossiers** dans `image_in/` :

- `0001##Nom affiché (dimensions).jpg` → le `##` sépare un **préfixe de tri** du **nom affiché**
  (`goodname`, utilisé comme `alt` et titre Fancybox).
- Suffixe `--` ou `++` sur un **nom de dossier**, ou présence de `image_in/--.txt` / `++.txt`
  → impose le **sens de tri** (date décroissante / croissante).
- `text.txt` dans un dossier → **texte HTML de présentation** de la galerie (copié vers `img/{id}/text.txt`).
- À défaut de marqueur, tri par **date EXIF `DateTimeOriginal`**.

### 1.6 Rendu public (`index.php`)

- Route `REQUEST_URI` → `folders.good_url` → `id` (sinon redirection vers l'accueil).
- Galerie = `files WHERE parent_id = id`, triées selon `way`.
- **12 premières miniatures** chargées immédiatement, le reste en **lazy-load** (classe `hidden`,
  révélé au scroll et par Fancybox).
- Lightbox **Fancybox**, `alt`/titre depuis `goodname`.
- Sous-galeries affichées en **tuiles « dossier »** (image de couverture depuis `img/{id}/fold/`).
- **Fil d'Ariane** (`arianne`) pré-généré en HTML et stocké en base.
- `text.txt` injecté tel quel comme HTML.
- **`<title>` et `<meta>` identiques sur toutes les pages** : `DANIEL TIZIANI` (codé en dur), `lang="en"`.

### 1.7 Inventaire de contenu constaté

8 galeries, **toutes au même niveau** (aucune imbrication réelle utilisée) + l'accueil (`id=1`) :

| Galerie               | URL publique          | Nb images (approx.) |
|-----------------------|-----------------------|---------------------|
| Anfractuosité         | `/anfractuosite`      | ~13                 |
| Bouches à clef        | `/bouches-a-clef`     | 22                  |
| Cartes géo            | `/cartes-geo`         | 5                   |
| Chien Méchant & Cie   | `/chien-mechant-cie`  | 5                   |
| GRAVURES NOIRES       | `/gravures-noires`    | 12                  |
| Gravures Pliages      | `/gravures-pliages`   | 9                   |
| Modèle Berger         | `/modele-berger`      | ~13                 |
| Sols & Graphismes     | `/sols-graphismes`    | 21                  |

L'accueil (`id=1`) ne contient **pas d'images propres** : seulement le texte de présentation
bilingue (FR/EN), l'email de contact (`daniel.tiziani@dbmail.com`) et la liste des galeries.
Total : **~100 images** d'œuvres à migrer.

## 2. Architecture cible (proposée)

### 2.1 Principes directeurs (issus de AGENTS.md)

- CMS **maison**, **sans WordPress**, sans framework lourd, compatible **hébergement mutualisé**.
- Compatible **PHP 8.3 (local) / PHP 8.4 (prod)** et **MySQL 8 / MariaDB 10.11**.
- **PDO + requêtes préparées**, `password_hash`/`password_verify`, sessions sécurisées, **CSRF**.
- **Aucun secret versionné** : configuration locale non versionnée.
- Base SQL **neuve** (jamais d'import de l'ancienne base).
- Rendu public **fidèle à la production**.
- **Prévoir l'i18n** : monolingue au lancement, langue par défaut **FR/EN** (`default_lang`), mais conçu
  pour ajouter une 2ᵉ langue facilement (contenus traduisibles, **pas de chaînes en dur**) — D-25.

### 2.2 Schéma cible (renversement du modèle)

Le changement structurel central : **la base devient la source de vérité**, le système de fichiers
ne stocke plus que des binaires d'images. Plus de régénération destructive globale ; chaque action
(créer galerie, uploader image, réordonner) écrit directement en base et génère les dérivés à la volée.

```
   ┌────────────┐   login + CSRF   ┌──────────────────────┐   PDO préparé   ┌────────────────┐
   │  Admin     │ ───────────────► │  CMS (back-office)    │ ──────────────► │  Base SQL neuve│
   └────────────┘                  │  /admin              │                 │ (source vérité)│
                                   └───────────┬──────────┘                 └───────┬────────┘
                                               │ upload                             │ lecture
                                               ▼                                    ▼
                                   ┌──────────────────────┐                ┌────────────────────┐
                                   │ ImageService (GD)    │ ─ dérivés ───► │  storage / media   │
                                   │ original + thumb +   │                │ (originaux + tailles)│
                                   │ cover                │                └─────────┬──────────┘
                                   └──────────────────────┘                          │ <img>
                                                                                     ▼
   Visiteur ─ GET /slug ─► ┌───────────────────────────────────────────────────────────────────┐
                           │  Front controller public (routeur + vues, design proche prod)      │
                           └───────────────────────────────────────────────────────────────────┘
```

### 2.3 Arborescence cible proposée

Structure **à la racine** (le dépôt = `public_html` en prod — décision D-17). Les dossiers privés sont
**bloqués par `.htaccess`** car ils ne peuvent pas être placés hors racine. Le `.gitignore` déjà présent
(`config/local.php`, `storage/cache`, `storage/logs`, `storage/uploads/tmp`) est cohérent avec :

```
W:\daniel\   ( = public_html en prod : RACINE WEB )
│
│  ── Public (servi par le serveur) ──
├─ index.php               # front controller public (à la racine)
├─ admin/                  # back-office (route /admin)
├─ assets/                 # css, js, thème (Bootstrap 5, TinyMCE, GLightbox…)
├─ media/                  # dérivés d'images publics (web, miniature, couverture)
├─ .htaccess               # routage + cache + DURCISSEMENT (bloque les dossiers privés ci-dessous)
│
│  ── Privé (accès direct interdit par .htaccess) ──
├─ src/                    # classes PHP : Core (Router/PDO/Csrf/Auth), Controllers, Models, Services
├─ templates/              # gabarits public + admin
├─ config/                 # config.php (versionné) + local.php (secrets, NON versionné)
├─ database/               # schema.sql, seed.sql
├─ storage/                # uploads/ (originaux), cache/, logs/
└─ docs/                   # cette documentation
```

> Conséquence de D-17 : la racine du projet **étant** la racine web, la protection repose entièrement
> sur le `.htaccess` (`Require all denied` / `RewriteRule` sur `src/`, `config/`, `storage/`, `database/`,
> `templates/`) et sur le fait que `config/local.php` n'est jamais versionné.

### 2.4 Modules fonctionnels cibles

- **Front public** : accueil, page galerie (grille + lightbox + texte), **menu de navigation
  responsive avec hamburger** (cf. `cms.md` §12), **lazy-load paramétrable** des images (§13),
  **page Mentions légales** activable avec lien en pied de page (§14), 404 propre, formulaire de
  contact (si activé), SEO par page.
- **Back-office CMS** : authentification admin, gestion des galeries, des images (nom obligatoire,
  ordre manuel, alt, statut), de la page d'accueil, des paramètres du site, **gestion simple des
  couleurs/thème** (§11), des champs SEO, du formulaire de contact (activable/désactivable).
- **Services transverses** : traitement d'images (**GD** : profils configurables par type + **WebP**, D-26),
  envoi d'email, génération de slugs, génération de `sitemap.xml`, gestion des redirections,
  **injection du thème (variables CSS)**.

## 3. Composants identifiés

### 3.1 Ancien site — cartographie des fichiers

| Fichier                     | Rôle                                                                 | Sort cible |
|-----------------------------|----------------------------------------------------------------------|------------|
| `index.php`                 | Front controller public (rendu galeries)                             | Remplacé   |
| `update.php`                | Déclencheur : redirige vers `libs/update.php`                        | Supprimé   |
| `libs/update.php`           | **Étape 1** : scan `image_in`, reconstruit `folders`+`files`, copie `text.txt` | Supprimé |
| `libs/do_image.php`         | **Étape 2** (bouclée) : redimensionne chaque image + miniature, lit date EXIF | Supprimé |
| `libs/do_first_image.php`   | Redirection intermédiaire — **paraît cassée/morte** (voir risques)   | Supprimé   |
| `libs/do_image_status.php`  | **Étape 3** : couvertures `fold/`, `good_url`, hiérarchie, fil d'Ariane | Supprimé |
| `libs/function.php`         | Config + helpers + classe `Zebra_Image`. **Contient des secrets en clair** | Remplacé (logique réécrite, secrets hors dépôt) |
| `libs/chemin.php`           | Helper de debug (`realpath`)                                         | Supprimé   |
| `libs/.htaccess`            | HTTP Basic Auth sur `/libs/`                                         | Remplacé par vraie auth |
| `info.php`                  | `phpinfo()` **exposé publiquement**                                  | Supprimé   |
| `image_in/`                 | Zone de dépôt FTP (source réelle)                                    | Remplacé par upload CMS |
| `img/{id}/` (+ `thumb/`,`fold/`) | Sorties générées (3 tailles)                                   | Remplacé par `media/` |
| `css/`, `js/`               | Bootstrap 3, jQuery, Fancybox 2.1.5                                  | À moderniser (voir décisions) |
| `.htaccess` (racine)        | HTTPS, non-www→www, front controller, cache                         | Repris/adapté |
| `robots.txt`                | **Vide**                                                            | À écrire   |

### 3.2 Nouveau site — état actuel (`W:\daniel`)

Échafaudage uniquement, **aucun code applicatif** :

- Docs de pilotage : `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `GIT_UPDATE.md`, `.claude/agents/*`.
- `docs/*.md` : stubs (complétés par cette phase d'audit).
- `database/schema.sql`, `database/seed.sql` : **vides** (commentaires d'en-tête seulement).
- `index.php` : stub `echo "Daniel nouveau site OK"`.
- `.gitignore` : prévoit `config/local.php`, `storage/cache`, `storage/logs`, `storage/uploads/tmp`.
- Dépôt Git initialisé avec `origin/main`.

## 4. Dépendances

### 4.1 Dépendances de l'ancien site

- **Serveur** : Apache/LiteSpeed + cPanel, module `mod_rewrite`, `mod_expires`, `mod_headers`.
- **PHP 7.3** avec extensions : **PDO_MySQL**, **GD**, **EXIF** (`exif_read_data`), `mbstring` implicite.
- **Front (vendored, non géré par un gestionnaire de paquets)** : Bootstrap 3, jQuery, Fancybox 2.1.5.
- **`Zebra_Image`** : classe tierce embarquée dans `function.php` (redimensionnement/recadrage GD).

### 4.2 Dépendances cibles (proposées, à valider)

- **PHP 8.3/8.4** + extensions **PDO_MySQL**, **GD** (ou Imagick si dispo), **EXIF**, **mbstring**, **fileinfo**.
- **MySQL 8 / MariaDB 10.11**, **utf8mb4**.
- **Aucun framework PHP lourd.** Micro-noyau maison (routeur, PDO, vues).
- **Front : Bootstrap 5** (décision D-11), **sans jQuery** — navbar/hamburger natif, grille 4/2/1,
  **variables CSS** pour la gestion des couleurs (D-13). Vendored, sans build obligatoire.
- **Lightbox GLightbox** (légère, sans jQuery) en remplacement de Fancybox (décision D-15).
- **Éditeur HTML : TinyMCE** (auto-hébergé, toolbar minimale ; D-18) + **sanitization serveur** (Q-03).
- **Email : PHPMailer** (SMTP, configuration locale ultérieure ; D-20).
- **Anti-spam : Google reCAPTCHA** sur le contact (clés en config locale, plus tard ; D-21).
- Pas de build obligatoire (CSS/JS servis directement) sauf validation explicite.

> Détails des choix, hypothèses et questions ouvertes : voir `decisions.md`.
> Plan de bascule et risques : voir `migration.md`. Conception CMS : voir `cms.md`.
