Page publique /books — catalogue de tous les livres #99

Closed
opened 2026-05-16 13:30:31 +00:00 by cedricAbonnel · 0 comments
Owner

Contexte

Il n'existe pas de page publique listant tous les books. Un book individuel est accessible via /book/{slug}, mais aucune page d'index ne permet de les découvrir. L'admin dispose de /admin/books, mais c'est réservé aux admins.

L'objectif est une page /books publique, accessible sans connexion, qui liste tous les books publiés (ceux ayant au moins un article publié).


Existant utile

Élément Détail
BookManager::getAll() Retourne tous les books triés par titre
BookManager::findForArticle() Recherche le book d'un article
templates/book.php Template d'un book individuel (pour s'en inspirer visuellement)
templates/post_list.php Contient _cardCoverStyle() et coverGradient() — réutilisables
Route existante case 'book':/book/{slug} (un seul book)

Un book JSON dans DATA_PATH/books/ a cette structure :

{
  "slug": "mon-livre",
  "title": "Mon livre",
  "description": "Description courte.",
  "articles": ["slug-article-1", "slug-article-2"]
}

Route à ajouter

/bookscase 'books_list':

case 'books_list':
    $allBooks = $books->getAll();
    // Pour chaque book, compter les articles publiés et récupérer la cover du premier
    $booksData = [];
    foreach ($allBooks as $book) {
        $published = [];
        foreach ($book['articles'] ?? [] as $aSlug) {
            $a = $articles->getBySlug($aSlug);
            if ($a && $a['published'] && strtotime($a['published_at'] ?? '') <= time()) {
                $published[] = $a;
            }
        }
        if (empty($published)) continue; // ne pas afficher les books sans pages publiées
        $booksData[] = [
            'book'       => $book,
            'count'      => count($published),
            'first'      => $published[0],   // pour la cover
        ];
    }
    include BASE_PATH . '/templates/books_list.php';
    break;

Le routing public/index.php gère déjà les URLs propres du type /book/{slug} via le .htaccess. La même mécanique est à appliquer pour /booksaction=books_list.


Template templates/books_list.php

Chaque book est affiché comme une card :

  • Cover : image de couverture du premier article du book, sinon dégradé de catégorie
  • Titre du book
  • Description (si présente)
  • Nombre de pages publiées (ex. « 4 pages »)
  • Lien/book/{slug}
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│   [cover img]   │  │   [cover img]   │  │   [cover img]   │
│                 │  │                 │  │                 │
│ Titre du livre  │  │ Titre du livre  │  │ Titre du livre  │
│ Description…    │  │ Description…    │  │ Description…    │
│ 5 pages  →lire  │  │ 3 pages  →lire  │  │ 8 pages  →lire  │
└─────────────────┘  └─────────────────┘  └─────────────────┘

Utiliser la grille CSS existante post-grid ou créer book-grid si les proportions diffèrent (les cards de book sont plus hautes que les cards d'article).

Si aucun book n'a de pages publiées : message vide lisible ("Aucun livre disponible pour l'instant.").


URL et .htaccess

Vérifier que la règle de réécriture existante couvre /books (règle générique qui passe tout vers index.php). Si ce n'est pas le cas, ajouter :

RewriteRule ^books/?$ index.php?action=books_list [L,QSA]

Ajouter également un lien dans la navigation (footer ou navbar) si pertinent.


SEO

  • <title> : « Livres — {siteTitle} »
  • <meta name="description"> : ex. « Retrouvez tous les livres et séries d'articles publiés sur {siteTitle}. »
  • <link rel="canonical"> : {APP_URL}books
  • metaRobots : index, follow

Fichiers à créer / modifier

Fichier Action
public/index.php Ajouter case 'books_list': + données
templates/books_list.php Créer — liste des books en cards
.htaccess (varlog/server/) Vérifier/ajouter la règle /books si nécessaire

Critères d'acceptation

  • /books retourne HTTP 200 sans connexion
  • Seuls les books avec ≥ 1 article publié sont affichés
  • Chaque card affiche : cover (image ou gradient), titre, description, nombre de pages
  • Clic sur la card → /book/{slug}
  • Page vide gracieuse si aucun book n'est disponible
  • Balises SEO correctes (title, description, canonical)
  • Lien /books accessible depuis la navigation ou le footer
## Contexte Il n'existe pas de page publique listant tous les books. Un book individuel est accessible via `/book/{slug}`, mais aucune page d'index ne permet de les découvrir. L'admin dispose de `/admin/books`, mais c'est réservé aux admins. L'objectif est une page **`/books`** publique, accessible sans connexion, qui liste tous les books publiés (ceux ayant au moins un article publié). --- ## Existant utile | Élément | Détail | |---------|--------| | `BookManager::getAll()` | Retourne tous les books triés par titre | | `BookManager::findForArticle()` | Recherche le book d'un article | | `templates/book.php` | Template d'un book individuel (pour s'en inspirer visuellement) | | `templates/post_list.php` | Contient `_cardCoverStyle()` et `coverGradient()` — réutilisables | | Route existante | `case 'book':` → `/book/{slug}` (un seul book) | Un book JSON dans `DATA_PATH/books/` a cette structure : ```json { "slug": "mon-livre", "title": "Mon livre", "description": "Description courte.", "articles": ["slug-article-1", "slug-article-2"] } ``` --- ## Route à ajouter **`/books`** → `case 'books_list':` ```php case 'books_list': $allBooks = $books->getAll(); // Pour chaque book, compter les articles publiés et récupérer la cover du premier $booksData = []; foreach ($allBooks as $book) { $published = []; foreach ($book['articles'] ?? [] as $aSlug) { $a = $articles->getBySlug($aSlug); if ($a && $a['published'] && strtotime($a['published_at'] ?? '') <= time()) { $published[] = $a; } } if (empty($published)) continue; // ne pas afficher les books sans pages publiées $booksData[] = [ 'book' => $book, 'count' => count($published), 'first' => $published[0], // pour la cover ]; } include BASE_PATH . '/templates/books_list.php'; break; ``` Le routing `public/index.php` gère déjà les URLs propres du type `/book/{slug}` via le `.htaccess`. La même mécanique est à appliquer pour `/books` → `action=books_list`. --- ## Template `templates/books_list.php` Chaque book est affiché comme une **card** : - **Cover** : image de couverture du premier article du book, sinon dégradé de catégorie - **Titre** du book - **Description** (si présente) - **Nombre de pages publiées** (ex. « 4 pages ») - **Lien** → `/book/{slug}` ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ [cover img] │ │ [cover img] │ │ [cover img] │ │ │ │ │ │ │ │ Titre du livre │ │ Titre du livre │ │ Titre du livre │ │ Description… │ │ Description… │ │ Description… │ │ 5 pages →lire │ │ 3 pages →lire │ │ 8 pages →lire │ └─────────────────┘ └─────────────────┘ └─────────────────┘ ``` Utiliser la grille CSS existante `post-grid` ou créer `book-grid` si les proportions diffèrent (les cards de book sont plus hautes que les cards d'article). Si aucun book n'a de pages publiées : message vide lisible ("Aucun livre disponible pour l'instant."). --- ## URL et `.htaccess` Vérifier que la règle de réécriture existante couvre `/books` (règle générique qui passe tout vers `index.php`). Si ce n'est pas le cas, ajouter : ```apache RewriteRule ^books/?$ index.php?action=books_list [L,QSA] ``` Ajouter également un lien dans la navigation (footer ou navbar) si pertinent. --- ## SEO - `<title>` : « Livres — {siteTitle} » - `<meta name="description">` : ex. « Retrouvez tous les livres et séries d'articles publiés sur {siteTitle}. » - `<link rel="canonical">` : `{APP_URL}books` - `metaRobots` : `index, follow` --- ## Fichiers à créer / modifier | Fichier | Action | |---------|--------| | `public/index.php` | Ajouter `case 'books_list':` + données | | `templates/books_list.php` | Créer — liste des books en cards | | `.htaccess` (varlog/server/) | Vérifier/ajouter la règle `/books` si nécessaire | --- ## Critères d'acceptation - [ ] `/books` retourne HTTP 200 sans connexion - [ ] Seuls les books avec ≥ 1 article publié sont affichés - [ ] Chaque card affiche : cover (image ou gradient), titre, description, nombre de pages - [ ] Clic sur la card → `/book/{slug}` - [ ] Page vide gracieuse si aucun book n'est disponible - [ ] Balises SEO correctes (title, description, canonical) - [ ] Lien `/books` accessible depuis la navigation ou le footer
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cedricAbonnel/folio#99