initial commit
This commit is contained in:
commit
5ebc506921
975 changed files with 154341 additions and 0 deletions
390
doc/admin/api.md
Normal file
390
doc/admin/api.md
Normal file
|
|
@ -0,0 +1,390 @@
|
|||
Une API de type REST est disponible dans Paheko.
|
||||
|
||||
Pour accéder à l'API il faut un identifiant et un mot de passe, à créer dans le menu ==Configuration==, onglet ==Fonctions avancées==, puis ==API==.
|
||||
|
||||
L'API peut ensuite recevoir des requêtes REST sur l'URL `https://adresse_association/api/{chemin}/`.
|
||||
|
||||
Remplacer =={chemin}== par un des chemins de l'API (voir ci-dessous). La méthode HTTP à utiliser est spécifiée pour chaque chemin.
|
||||
|
||||
Pour les requêtes de type `POST`, les paramètres peuvent être envoyés par le client sous forme de formulaire HTTP classique (`application/x-www-form-urlencoded`) ou sous forme d'objet JSON. Dans ce cas le `Content-Type` doit être positionné sur `application/json`.
|
||||
|
||||
Les réponses sont faites en JSON par défaut.
|
||||
|
||||
<<toc level=3>>
|
||||
|
||||
# Utiliser l'API
|
||||
|
||||
N'importe quel client HTTP capable de gérer TLS (HTTPS) et l'authentification basique fonctionnera.
|
||||
|
||||
En ligne de commande il est possible d'utiliser `curl`. Exemple pour télécharger la base de données :
|
||||
|
||||
```
|
||||
curl https://test:coucou@[identifiant_association].paheko.cloud/api/download -o association.sqlite
|
||||
```
|
||||
|
||||
On peut aussi utiliser `wget` en n'oubliant pas l'option `--auth-no-challenge` sinon l'authentification ne fonctionnera pas :
|
||||
|
||||
```
|
||||
wget https://test:coucou@[identifiant_association].paheko.cloud/api/download --auth-no-challenge -O association.sqlite
|
||||
```
|
||||
|
||||
Exemple pour créer une écriture sous forme de formulaire :
|
||||
|
||||
```
|
||||
curl -v "http://test:test@[identifiant_association].paheko.cloud/api/accounting/transaction" -F id_year=1 -F label=Test -F "date=01/02/2023" …
|
||||
```
|
||||
|
||||
Ou sous forme d'objet JSON :
|
||||
|
||||
```
|
||||
curl -v "http://test:test@[identifiant_association].paheko.cloud/api/accounting/transaction" -H 'Content-Type: application/json' -d '{"id_year":1, "label": "Test écriture", "date": "01/02/2023"}'
|
||||
```
|
||||
|
||||
|
||||
# Authentification
|
||||
|
||||
Il ne faut pas oublier de fournir le nom d'utilisateur et mot de passe en HTTP :
|
||||
|
||||
```
|
||||
curl http://test:abcd@paheko.monasso.tld/api/download/
|
||||
```
|
||||
|
||||
# Erreurs
|
||||
|
||||
En cas d'erreur un code HTTP 4XX sera fourni, et le contenu sera un objet JSON avec une clé `error` contenant le message d'erreur.
|
||||
|
||||
# Chemins
|
||||
|
||||
## sql (POST)
|
||||
|
||||
Permet d'exécuter une requête SQL `SELECT` (uniquement, pas de requête UPDATE, DELETE, INSERT, etc.) sur la base de données. La requête SQL doit être passée dans le corps de la requête HTTP, ou dans le paramètre `sql`. Le résultat est retourné dans la clé `results` de l'objet JSON.
|
||||
|
||||
S'il n'y a pas de limite à la requête, une limite à 1000 résultats sera ajoutée obligatoirement.
|
||||
|
||||
```
|
||||
curl https://test:abcd@paheko.monasso.tld/api/sql/ -d 'SELECT * FROM membres LIMIT 5;'
|
||||
```
|
||||
|
||||
**ATTENTION :** Les requêtes en écriture (`INSERT, DELETE, UPDATE, CREATE TABLE`, etc.) ne sont pas acceptées, il n'est pas possible de modifier la base de données directement via Paheko, afin d'éviter les soucis de données corrompues.
|
||||
|
||||
Depuis la version 1.2.8, il est possible d'utiliser le paramètre `format` pour choisir le format renvoyé :
|
||||
|
||||
* `json` (défaut) : renvoie un objet JSON, dont la clé est `"results"` et contient un tableau de la liste des membres trouvés
|
||||
* `csv` : renvoie un fichier CSV
|
||||
* `ods` : renvoie un tableau LibreOffice Calc (ODS)
|
||||
* `xlsx` : renvoie un tableau Excel (XLSX)
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
curl https://test:abcd@paheko.monasso.tld/api/sql/ -F sql='SELECT * FROM membres LIMIT 5;' -F format=csv
|
||||
```
|
||||
|
||||
## Téléchargements
|
||||
|
||||
### download (GET)
|
||||
|
||||
Télécharger la base de données complète. Renvoie directement le fichier SQLite de la base de données.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
curl https://test:abcd@paheko.monasso.tld/api/download -o db.sqlite
|
||||
```
|
||||
|
||||
### download/files (GET)
|
||||
|
||||
*(Depuis la version 1.3.4)*
|
||||
|
||||
Télécharger un fichier ZIP contenant tous les fichiers (documents, fichiers des écritures, des membres, modules modifiés, etc.).
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
curl https://test:abcd@paheko.monasso.tld/api/download/files -o backup_files.zip
|
||||
```
|
||||
|
||||
## Site web
|
||||
|
||||
### web/list (GET)
|
||||
|
||||
Renvoie la liste des pages du site web.
|
||||
|
||||
### web/attachment/{PAGE_URI}/{FILENAME} (GET)
|
||||
|
||||
Renvoie le fichier joint correspondant à la page et nom de fichier indiqués.
|
||||
|
||||
### web/page/{PAGE_URI} (GET)
|
||||
|
||||
Renvoie un objet JSON avec toutes les infos de la page donnée.
|
||||
|
||||
Rajouter le paramètre `?html` à l'URL pour obtenir en plus une clé `html` dans l'objet JSON qui contiendra la page au format HTML.
|
||||
|
||||
### web/html/{PAGE_URI} (GET)
|
||||
|
||||
Renvoie uniquement le contenu de la page au format HTML.
|
||||
|
||||
## Membres
|
||||
|
||||
### user/import (PUT)
|
||||
|
||||
Permet d'importer un fichier de tableur (CSV/XLSX/ODS) de la liste des membres, comme si c'était fait depuis l'interface de Paheko.
|
||||
|
||||
Cette route nécessite une clé d'API ayant les droits d'administration, car importer un fichier peut permettre de modifier l'identifiant de connexion d'un administrateur et donc potentiellement d'obtenir l'accès à l'interface d'administration.
|
||||
|
||||
Paheko s'attend à ce que la première est ligne du tableau contienne le nom des colonnes, et que le nom des colonnes correspond au nom des champs de la fiche membre (ou à leur nom unique). Par exemple si votre fiche membre contient les champs *Nom et prénom* et *Adresse postale*, alors le fichier fourni devra ressembler à ceci :
|
||||
|
||||
| Nom et prénom | Adresse postale |
|
||||
| :- | :- |
|
||||
| Ada Lovelace | 42 rue du binaire, 21000 DIJON |
|
||||
|
||||
Ou à ceci :
|
||||
|
||||
| nom_prenom | adresse_postale |
|
||||
| :- | :- |
|
||||
| Ada Lovelace | 42 rue du binaire, 21000 DIJON |
|
||||
|
||||
La méthode renvoie un code HTTP `200 OK` si l'import s'est bien passé, sinon un code 400 et un message d'erreur JSON dans le corps de la réponse.
|
||||
|
||||
Utilisez la route `user/import/preview` avant pour vérifier que l'import correspond à ce que vous attendez.
|
||||
|
||||
Exemple pour modifier le nom du membre n°42 :
|
||||
|
||||
```
|
||||
echo 'numero,nom' > membres.csv
|
||||
echo '42,"Nouveau nom"' >> membres.csv
|
||||
curl https://test:abcd@monpaheko.tld/api/user/import -T membres.csv
|
||||
```
|
||||
|
||||
#### Paramètres
|
||||
|
||||
Les paramètres sont à spécifier dans l'URL, dans la query string.
|
||||
|
||||
Depuis la version 1.2.8 il est possible d'utiliser un paramètre supplémentaire `mode` contenant une de ces options pour spécifier le mode d'import :
|
||||
|
||||
* `auto` (défaut si le mode n'est pas spécifié) : met à jour la fiche d'un membre si son numéro existe, sinon crée un membre si le numéro de membre indiqué n'existe pas ou n'est pas renseigné
|
||||
* `create` : ne fait que créer de nouvelles fiches de membre, si le numéro de membre existe déjà une erreur sera produite
|
||||
* `update` : ne fait que mettre à jour les fiches de membre en utilisant le numéro de membre comme référence, si le numéro de membre n'existe pas une erreur sera produite
|
||||
|
||||
Depuis la version 1.3.0 il est possible de spécifier :
|
||||
|
||||
* le nombre de lignes à ignorer avec le paramètre `skip_lines=X` : elles ne seront pas importées. Par défaut la première ligne est ignorée.
|
||||
* la correspondance des colonnes avec des paramètres `column[x]` ou `x` est le numéro de la colonne (la numérotation commence à zéro), et la valeur contient le nom unique du champ de la fiche membre.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
curl https://test:abcd@monpaheko.tld/api/user/import?mode=create&column[0]=nom_prenom&column[1]=code_postal&skip_lines=0 -T membres.csv
|
||||
```
|
||||
|
||||
### user/import (POST)
|
||||
|
||||
Identique à la même méthode en `PUT`, mais les paramètres sont passés dans le corps de la requête, avec le fichier, dont le nom sera alors `file`.
|
||||
|
||||
```
|
||||
curl https://test:abcd@monpaheko.tld/api/user/import \
|
||||
-F mode=create \
|
||||
-F 'column[0]=nom_prenom' \
|
||||
-F 'column[1]=code_postal' \
|
||||
-F skip_lines=0 \
|
||||
-F file=@membres.csv
|
||||
```
|
||||
|
||||
### user/import/preview (PUT)
|
||||
|
||||
Identique à `user/import`, mais l'import n'est pas enregistré, et la route renvoie les modifications qui seraient effectuées en important le fichier :
|
||||
|
||||
* `errors` : liste des erreurs d'import
|
||||
* `created` : liste des membres ajoutés, chaque objet contenant tous les champs de la fiche membre qui serait créée
|
||||
* `modified` : liste des membres modifiés, chaque membre aura une clé `id` et une clé `name`, ainsi qu'un objet `changed` contenant la liste des champs modifiés. Chaque champ modifié aura 2 propriétés `old` et `new`, contenant respectivement l'ancienne valeur du champ et la nouvelle.
|
||||
* `unchanged` : liste des membres mentionnés dans l'import, mais qui ne seront pas affectés. Pour chaque membre une clé `name` et une clé `id` indiquant le nom et l'identifiant unique numérique du membre
|
||||
|
||||
Note : si `errors` n'est pas vide, alors il sera impossible d'importer le fichier avec `user/import`.
|
||||
|
||||
Exemple de retour :
|
||||
|
||||
```
|
||||
{
|
||||
"created": [
|
||||
{
|
||||
"numero": 3434351,
|
||||
"nom": "Bla Bli Blu"
|
||||
}
|
||||
],
|
||||
"modified": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Ada Lovelace",
|
||||
"changed": {
|
||||
"nom": {
|
||||
"old": "Ada Lvelavce",
|
||||
"new": "Ada Lovelace"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"unchanged": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Paul Muad'Dib"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### user/import/preview (POST)
|
||||
|
||||
Idem quel la méthode en `PUT` mais accepte les paramètres dans le corps de la requête (voir ci-dessus).
|
||||
|
||||
## Activités
|
||||
|
||||
### services/subscriptions/import (PUT)
|
||||
|
||||
_(Depuis Paheko 1.3.2)_
|
||||
|
||||
Permet d'importer les inscriptions des membres aux activités à partir d'un fichier CSV. Les activités et tarifs doivent déjà exister avant l'import.
|
||||
|
||||
Les colonnes suivantes peuvent être utilisées :
|
||||
|
||||
* Numéro de membre`**`
|
||||
* Activité`**`
|
||||
* Tarif
|
||||
* Date d'inscription`**`
|
||||
* Date d'expiration
|
||||
* Montant à régler
|
||||
* Payé ?
|
||||
|
||||
Les colonnes suivies de deux astérisques (`**`) sont obligatoires.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
echo '"Numéro de membre","Activité","Tarif","Date d'inscription","Date d'expiration","Montant à régler","Payé ?"' > /tmp/inscriptions.csv
|
||||
echo '42,"Cours de théâtre","Tarif adulte","01/09/2023","01/07/2023","123,50","Non"' >> /tmp/inscriptions.csv
|
||||
curl https://test:abcd@monpaheko.tld/api/services/subscriptions/import -T /tmp/inscriptions.csv
|
||||
```
|
||||
|
||||
## Erreurs
|
||||
|
||||
Paheko dispose d'un système dédié à la gestion des erreurs internes, compatible avec les formats des logiciels AirBrake et errbit.
|
||||
|
||||
### errors/report (POST)
|
||||
|
||||
Permet d'envoyer un rapport d'erreur (au format airbrake/errbit/Paheko), comme si c'était une erreur locale.
|
||||
|
||||
### errors/log (GET)
|
||||
|
||||
Renvoie le log d'erreurs système, au format airbrake/errbit ([voir la doc AirBrake pour un exemple du format](https://airbrake.io/docs/api/#create-notice-v3))
|
||||
|
||||
## Comptabilité
|
||||
|
||||
### accounting/years (GET)
|
||||
|
||||
Renvoie la liste des exercices.
|
||||
|
||||
### accounting/charts (GET)
|
||||
|
||||
Renvoie la liste des plans comptables.
|
||||
|
||||
### accounting/charts/{ID_CHART}/accounts (GET)
|
||||
|
||||
Renvoie la liste des comptes pour le plan comptable indiqué (voir `id_chart` dans la liste des exercices).
|
||||
|
||||
### accounting/years/{ID_YEAR}/journal (GET)
|
||||
|
||||
Renvoie le journal général des écritures de l'exercice indiqué.
|
||||
|
||||
Note : il est possible d'utiliser `current` comme paramètre pour `{ID_YEAR}` pour désigner l'exercice ouvert en cours. S'il y a plusieurs exercices ouverts, alors le plus ancien sera choisi.
|
||||
|
||||
### accounting/years/{ID_YEAR}/account/journal (GET)
|
||||
|
||||
Renvoie le journal des écritures d'un compte pour l'exercice indiqué.
|
||||
|
||||
Le compte est spécifié soit via le paramètre `code`, soit via le paramètre `id`. Exemple : `/accounting/years/4/account/journal?code=512A`
|
||||
|
||||
Note : il est possible d'utiliser `current` comme paramètre pour `{ID_YEAR}` pour désigner l'exercice ouvert en cours. S'il y a plusieurs exercices ouverts, alors le plus ancien sera choisi.
|
||||
|
||||
### accounting/transaction/{ID_TRANSACTION} (GET)
|
||||
|
||||
Renvoie les détails de l'écriture indiquée.
|
||||
|
||||
### accounting/transaction/{ID_TRANSACTION} (POST)
|
||||
|
||||
Modifie l'écriture indiquée. Voir plus bas le format attendu.
|
||||
|
||||
### accounting/transaction/{ID_TRANSACTION}/users (GET)
|
||||
|
||||
Renvoie la liste des membres liés à une écriture.
|
||||
|
||||
### accounting/transaction/{ID_TRANSACTION}/users (POST)
|
||||
|
||||
Met à jour la liste des membres liés à une écriture, en utilisant les ID de membres passés dans un tableau nommé `users`.
|
||||
|
||||
```
|
||||
curl -v "http://…/api/accounting/transaction/9337/users" -F 'users[]=2'
|
||||
```
|
||||
|
||||
### accounting/transaction/{ID_TRANSACTION}/users (DELETE)
|
||||
|
||||
Efface la liste des membres liés à une écriture.
|
||||
|
||||
### accounting/transaction/{ID_TRANSACTION}/subscriptions (GET)
|
||||
|
||||
(Depuis la version 1.3.6)
|
||||
|
||||
Renvoie la liste des inscriptions (aux activités) liées à une écriture.
|
||||
|
||||
### accounting/transaction/{ID_TRANSACTION}/subscriptions (POST)
|
||||
|
||||
(Depuis la version 1.3.6)
|
||||
|
||||
Met à jour la liste des inscriptions liées à une écriture, en utilisant les ID d'inscriptions passés dans un tableau nommé `subscriptions`.
|
||||
|
||||
```
|
||||
curl -v "http://…/api/accounting/transaction/9337/subscriptions" -F 'subscriptions[]=2'
|
||||
```
|
||||
|
||||
### accounting/transaction/{ID_TRANSACTION}/subscriptions (DELETE)
|
||||
|
||||
(Depuis la version 1.3.6)
|
||||
|
||||
Efface la liste des inscriptions liées à une écriture.
|
||||
|
||||
### accounting/transaction (POST)
|
||||
|
||||
Crée une nouvelle écriture, renvoie les détails si l'écriture a été créée. Voir plus bas le format attendu.
|
||||
|
||||
#### Structure pour créer / modifier une écriture
|
||||
|
||||
Les champs à spécifier pour créer ou modifier une écriture sont les suivants :
|
||||
|
||||
* `id_year`
|
||||
* `date` (format YYYY-MM-DD)
|
||||
* `type` peut être un type d'écriture simplifié (2 lignes) : `EXPENSE` (dépense), `REVENUE` (recette), `TRANSFER` (virement), `DEBT` (dette), `CREDIT` (créance), ou `ADVANCED` pour une écriture multi-ligne
|
||||
* `amount` (uniquement pour les écritures simplifiées) : contient le montant de l'écriture
|
||||
* `credit` (uniquement pour les écritures simplifiées) : contient le numéro du compte porté au crédit
|
||||
* `debit` (uniquement pour les écritures simplifiées) : contient le numéro du compte porté au débit
|
||||
* `lines` (pour les écritures multi-lignes) : un tableau dont chaque ligne doit contenir :
|
||||
* `account` (numéro du compte) ou `id_account` (ID unique du compte)
|
||||
* `credit` : montant à inscrire au crédit (doit être zéro ou non renseigné si `debit` est renseigné, et vice-versa)
|
||||
* `debit` : montant à inscrire au débit
|
||||
* `label` (facultatif) : libellé de la ligne
|
||||
* `reference` (facultatif) : référence de la ligne (aussi appelé référence du paiement pour les écritures simplifiées)
|
||||
* `id_project` : ID unique du projet à affecter
|
||||
|
||||
Champs optionnels :
|
||||
|
||||
* `reference` : numéro de pièce comptable
|
||||
* `notes` : remarques (texte multi ligne)
|
||||
* `id_project` : ID unique du projet à affecter (pour les écritures simplifiées uniquement)
|
||||
* `payment_reference` (uniquement pour les écritures simplifiées) : référence de paiement
|
||||
* `linked_users` : Tableau des IDs des membres à lier à l'écriture *(depuis 1.3.3)*
|
||||
* `linked_transactions` : Tableau des IDs des écritures à lier à l'écriture *(depuis 1.3.5)*
|
||||
* `linked_subscriptions` : Tableau des IDs des inscriptions à lier à l'écriture *(depuis 1.3.6)*
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
curl -F 'id_year=12' -F 'label=Test' -F 'date=01/02/2022' -F 'type=EXPENSE' -F 'amount=42' -F 'debit=512A' -F 'credit=601' …
|
||||
```
|
||||
493
doc/admin/brindille.md
Normal file
493
doc/admin/brindille.md
Normal file
|
|
@ -0,0 +1,493 @@
|
|||
Title: Documentation du langage Brindille dans Paheko
|
||||
|
||||
{{{.nav
|
||||
* [Modules](modules.html)
|
||||
* **[Documentation Brindille](brindille.html)**
|
||||
* [Fonctions](brindille_functions.html)
|
||||
* [Sections](brindille_sections.html)
|
||||
* [Filtres](brindille_modifiers.html)
|
||||
}}}
|
||||
|
||||
<<toc aside>>
|
||||
|
||||
# Introduction
|
||||
|
||||
La syntaxe utilisée dans les squelettes du site web et des modules s'appelle **Brindille**.
|
||||
|
||||
Si vous avez déjà fait de la programmation, elle ressemble à un mélange de Mustache, Smarty, Twig et PHP.
|
||||
|
||||
Son but est de permettre une grande flexibilité, sans avoir à utiliser un "vrai" langage de programmation, mais en s'en rapprochant suffisamment quand même.
|
||||
|
||||
## Fichiers
|
||||
|
||||
Un fichier texte contenant du code Brindille est appelé un **squelette**.
|
||||
|
||||
Seuls les fichiers ayant une des extensions `.tpl`, `.html`, `.htm`, `.skel` ou `.xml` seront traités par Brindille.
|
||||
De même, les fichiers qui n'ont pas d'extension seront également traités par Brindille.
|
||||
|
||||
Les autres types de fichiers seront renvoyés sans traitement, comme des fichiers "bruts". En d'autres termes, il n'est pas possible de mettre du code *Brindille* dans des fichiers qui ne sont pas des fichiers textes.
|
||||
|
||||
# Syntaxe de base
|
||||
|
||||
## Variables
|
||||
|
||||
En programmation, une variable est une référence vers une donnée stockée en mémoire.
|
||||
|
||||
Dans Brindille, une variable commence par le symbole dollar `$` et suivi d'un nom.
|
||||
|
||||
Le nom est composé de lettres minuscules (sans accents), de chiffres et de tirets bas (`[a-z0-9_]`).
|
||||
|
||||
Exemples de variables :
|
||||
|
||||
```
|
||||
$config
|
||||
$compte_32
|
||||
$nom_de_variable_long
|
||||
```
|
||||
|
||||
### Types de variables
|
||||
|
||||
Dans Brindille, une variable peut avoir un des types suivants :
|
||||
|
||||
* `null` : utilisé pour une variable qui n'est pas définie, ou une variable définie qui n'a pas de valeur
|
||||
* `boolean` : valeur booléenne, peut seulement avoir `true` ou `false` comme valeur
|
||||
* `integer` : nombre entier (sans virgule). Exemple : `4200`.
|
||||
* `float` : nombre à virgule flottante, exemple `3.14`. Leur usage est déconseillé, car les erreurs de calcul sont possibles, les ordinateurs ne sachant pas compter de manière précise avec les nombres à virgule flottante. Exemple : `0.2+0.3` est différent de `0.5`.
|
||||
* `string` : chaîne de texte (aussi appelé chaîne de caractères, car c'est une suite de caractères). Exemple : `coucou`.
|
||||
* `array` : tableau.
|
||||
|
||||
### Tableaux
|
||||
|
||||
Les tableaux sont une sorte de dictionnaire, ou pour chaque entrée (appelée "clé") on peut associer une valeur. qui peut être de n'importe lequel des types listés ci-dessus, y compris un autre tableau.
|
||||
|
||||
Les tableaux peuvent être de deux types :
|
||||
|
||||
1. tableau indexé (liste) : dans ce cas les clés ne sont pas choisies, on ajoute simplement des valeurs, et l'ordinateur incrémente le numéro de la clé à chaque nouvelle entrée dans le tableau. La numérotation commence au chiffre zéro.
|
||||
2. tableau associatif (dictionnaire) : les clés sont des nombres ou des chaînes de texte, et permettent, comme dans un dictionnaire, de choisir la clé.
|
||||
|
||||
Exemple de tableau indexé :
|
||||
|
||||
```
|
||||
[
|
||||
0 => 'Texte 1',
|
||||
1 => 'Texte 2'
|
||||
]
|
||||
```
|
||||
|
||||
Exemple de tableau associatif :
|
||||
|
||||
```
|
||||
[
|
||||
'un' => 'Texte 1',
|
||||
'deux' => 'Texte 2'
|
||||
]
|
||||
```
|
||||
|
||||
## Affichage de variable
|
||||
|
||||
Une variable est affichée à l'aide de la syntaxe : `{{$date}}` affichera la valeur brute de la date par exemple : `2020-01-31 16:32:00`.
|
||||
|
||||
La variable peut être modifiée à l'aide de filtres de modification, qui sont ajoutés avec le symbole de la barre verticale (pipe `|`) : `{{$date|date_long}}` affichera une date au format long : `jeudi 7 mars 2021`.
|
||||
|
||||
Ces filtres peuvent accepter des paramètres, séparés par deux points `:`. Exemple : `{{$date|date:"d/m/Y"}}` affichera `31/01/2020`.
|
||||
|
||||
Par défaut la variable sera recherchée dans le contexte actuel de la section, si elle n'est pas trouvée elle sera recherchée dans le contexte parent (section parente), etc. jusqu'à trouver la variable.
|
||||
|
||||
### Protection contre le HTML (échappement)
|
||||
|
||||
Par défaut le filtre `escape` est appliqué à toutes les variables affichées, pour protéger les variables contre les injections de code HTML.
|
||||
|
||||
Ce filtre modifie (on dit qu'il "échappe") les caractères HTML `<>&"'` présents dans une chaîne de texte en entités HTML, évitant que le HTML éventuellement présent dans la chaîne de texte soit interprété par le navigateur.
|
||||
|
||||
Ce filtre est appliqué en dernier, après les autres filtres. Il est possible de contourner cet automatisme en rajoutant le filtre `escape` ou `raw` explicitement. `raw` désactive tout échappement, alors que `escape` est utilisé pour changer l'ordre d'échappement. Exemple :
|
||||
|
||||
```
|
||||
{{:assign text = "Coucou\nça va ?" }}
|
||||
{{$text|escape|nl2br}}
|
||||
```
|
||||
|
||||
Donnera bien `Coucou<br />ça va ?`. Si on n'avait pas indiqué le filtre `escape` le résultat serait `Coucou<br />ça va ?`.
|
||||
|
||||
### Variables de tableaux
|
||||
|
||||
Il est possible de faire référence à une clé d'un tableau avec la notation à points : `{{$article.date}}` renverra la clé `date` du tableau stocké dans la variable `$article`.
|
||||
|
||||
### Échappement des caractères spéciaux dans les chaînes de caractère
|
||||
|
||||
Pour inclure un caractère spécial (retour de ligne, guillemets ou apostrophe) dans une chaîne de caractère il suffit d'utiliser un antislash :
|
||||
|
||||
```
|
||||
{{:assign text="Retour \n à la ligne"}}
|
||||
{{:assign text="Utiliser des \"apostrophes\"}}
|
||||
```
|
||||
|
||||
## Ordre de recherche des variables
|
||||
|
||||
Par défaut les variables sont recherchées dans l'ordre inverse, c'est à dire que sont d'abord recherchées les variables avec le nom demandé dans la section courante. Si la variable n'existe pas dans la section courante, alors elle est recherchée dans la section parente, et ainsi de suite jusqu'à ce que la variable soit trouvée, où qu'il n'y ait plus de section parente.
|
||||
|
||||
Prenons cet exemple :
|
||||
|
||||
```
|
||||
{{#articles uri="Actualite"}}
|
||||
<h1>{{$title}}</h1>
|
||||
{{#images parent=$path limit=1}}
|
||||
<img src="{{$thumb_url}}" alt="{{$title}}" />
|
||||
{{/images}}
|
||||
{{/articles}}
|
||||
```
|
||||
|
||||
Dans la section `articles`, `$title` est une variable de l'article, donc la variable est celle de l'article.
|
||||
|
||||
Dans la section `images`, les images n'ayant pas de titre, la variable sera celle de l'article de la section parente, alors que `$thumb_url` sera lié à l'image.
|
||||
|
||||
## Conflit de noms de variables
|
||||
|
||||
Imaginons que nous voulions mettre un lien vers l'article sur l'image de l'exemple précédent :
|
||||
|
||||
```
|
||||
{{#articles uri="Actualite"}}
|
||||
<h1>{{$title}}</h1>
|
||||
{{#images parent=$path limit=1}}
|
||||
|
||||
{{/images}}
|
||||
{{/articles}}
|
||||
```
|
||||
|
||||
Problème, ici `$url` fera référence à l'URL de l'image elle-même, et non pas l'URL de l'article.
|
||||
|
||||
La solution est d'ajouter un point au début du nom de variable : `{{$.url}}`.
|
||||
|
||||
Un point au début d'un nom de variable signifie que la variable est recherchée à partir de la section précédente. Il est possible d'utiliser plusieurs points, chaque point correspond à un niveau à remonter. Ainsi `$.url` cherchera la variable dans la section parente (et ses sections parentes si elle n'existe pas, etc.). De même, `$..url` cherchera dans la section parente de la section parente.
|
||||
|
||||
## Création manuelle de variable
|
||||
|
||||
### Variable simple
|
||||
|
||||
La création d'une variable se fait via l'appel de la fonction `{{:assign}}`.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{:assign source='wiki'}}
|
||||
{{* est identique à : *}}
|
||||
{{:assign var='source' value='wiki'}}
|
||||
```
|
||||
|
||||
Un deuxième appel à `{{:assign}}` avec le même nom de variable écrase la valeur précédente
|
||||
|
||||
```
|
||||
{{:assign var='source' value='wiki'}}
|
||||
{{:assign var='source' value='documentation'}}
|
||||
|
||||
{{$source}}
|
||||
{{* => Affiche documentation *}}
|
||||
```
|
||||
|
||||
### Nom de variable dynamique
|
||||
|
||||
Il est possible de créer une variable dont une partie du nom est dynamique.
|
||||
|
||||
```
|
||||
{{:assign type='user'}}
|
||||
{{:assign var='allowed_%s'|args:$type value='jeanne'}}
|
||||
{{:assign type='side'}}
|
||||
{{:assign var='allowed_%s'|args:$type value='admin'}}
|
||||
|
||||
{{$allowed_user}} => jeanne
|
||||
{{$allowed_side}} => admin
|
||||
```
|
||||
|
||||
[Documentation complète de la fonction {{:assign}}](brindille_functions.html#assign).
|
||||
|
||||
### Tableaux *(array)*
|
||||
|
||||
Pour créer des tableaux, il suffit d'utiliser des points `.` dans le nom de la variable (ex : `colors.yellow`). Il n'y a pas besoin d'initialiser le tableau avant de le remplir.
|
||||
|
||||
```
|
||||
{{:assign var='colors.admin' value='blue'}}
|
||||
{{:assign var='colors.website' value='grey'}}
|
||||
{{:assign var='colors.debug' value='yellow'}}
|
||||
```
|
||||
|
||||
On accède ensuite à la valeur d'un élément du tableau avec la même syntaxe : `{{$colors.website}}`
|
||||
|
||||
Méthode rapide de création du même tableau :
|
||||
|
||||
```
|
||||
{{:assign var='colors' admin='blue' website='grey' debug='yellow'}}
|
||||
```
|
||||
|
||||
Pour ajouter un élément à la suite du tableau sans spécifier de clef *(push)*, il suffit de terminer le nom de la variable par un point `.` sans suffixe.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{* Ajouter les valeurs 17, 43 et 214 dans $processed_ids *}}
|
||||
|
||||
{{:assign var='processed_ids.' value=17}}
|
||||
{{:assign var='processed_ids.' value=43}}
|
||||
{{:assign var='processed_ids.' value=214}}
|
||||
```
|
||||
|
||||
Donnera le tableau suivant :
|
||||
|
||||
```
|
||||
[
|
||||
0 => 17,
|
||||
1 => 43,
|
||||
2 => 214
|
||||
]
|
||||
```
|
||||
|
||||
#### Clef dynamique de tableau
|
||||
|
||||
Il est possible d'accéder dynamiquement à un des éléments d'un tableau de la manière suivante :
|
||||
|
||||
```
|
||||
{{:assign location='admin'}}
|
||||
{{:assign var='location_color' from='colors.%s'|args:$location}}
|
||||
|
||||
{{$location_color}} => blue
|
||||
```
|
||||
|
||||
Exemple plus complexe :
|
||||
|
||||
```
|
||||
{{:assign var='type_whitelist.text' value=1}}
|
||||
{{:assign var='type_whitelist.html' value=1}}
|
||||
|
||||
{{#foreach from=$documents item='document'}}
|
||||
{{:assign var='allowed' value='type_whitelist.%s'|args:$document->type}}
|
||||
{{if $allowed !== null}}
|
||||
{{:include file='document/'|cat:$type:'.tpl' keep='document'}}
|
||||
{{/if}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
Il est également possible de créer un membre dynamique d'un tableau en conjuguant les syntaxes précédentes.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{:assign var='type_whitelist.%s'|args:$type value=1}}
|
||||
```
|
||||
|
||||
## Conditions
|
||||
|
||||
Il est possible d'utiliser des conditions de type **"si"** (`if`), **"sinon si"** (`elseif`) et **"sinon"** (`else`). Celles-ci sont terminées par un block **"fin si"** (`/if`).
|
||||
|
||||
```
|
||||
{{if $date|date:"%Y" > 2020}}
|
||||
La date est en 2020
|
||||
{{elseif $article.status == 'draft'}}
|
||||
La page est un brouillon
|
||||
{{else}}
|
||||
Autre chose.
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
Une condition peut être évaluée comme *vraie*, dans ce cas la partie qui suit le bloc `{{if …}}` sera exécutée.
|
||||
|
||||
Si la condition est évaluée comme *fausse*, alors la partie qui suit le bloc `{{if …}}` ne sera pas exécutée. Dans ce cas, soit une condition `{{elseif …}}` suivante est vraie et exécutée, mais sinon c'est le contenu du bloc `{{else}}` qui est exécuté et affiché.
|
||||
|
||||
Dans une condition on peut utiliser :
|
||||
|
||||
* une variable : `$nom_variable`
|
||||
* une variable avec des filtres : `$nom_variable|filtre1:parametre1`
|
||||
* une valeur (nombre, constante) : `42`, `-42`, `42.02` `null`, `true`, `false`
|
||||
* des opérateurs de comparaison
|
||||
* des opérateurs logiques
|
||||
|
||||
Attention : on ne peut pas grouper les conditions avec des parenthèses.
|
||||
|
||||
Les comparaisons supportées sont les suivantes :
|
||||
|
||||
| Opérateur de comparaison | Explication |
|
||||
| :- | :- |
|
||||
| `==` | égalité faible, ne prend pas en compte le type : `1 == true` et `2 == 2.00` serons évalués comme vrais |
|
||||
| `===` | égalité forte, prend en compte le type : `1 === 1` sera vrai, mais `1 === true` sera faux |
|
||||
| `!=` | différent de, en comparaison faible |
|
||||
| `!==` | différent de, en comparaison forte |
|
||||
| `>` | supérieur à |
|
||||
| `>=` | supérieur ou égal à |
|
||||
| `<` | inférieur à |
|
||||
| `<=` | inférieur ou égal à |
|
||||
|
||||
Il est aussi possible de précéder une variable de l'opérateur `!`, c'est un raccourci pour `$variable == false`.
|
||||
|
||||
Voir [les opérateurs de comparaison PHP pour plus de détails](https://www.php.net/manual/fr/language.operators.comparison.php).
|
||||
|
||||
Les opérateurs logiques supportés sont :
|
||||
|
||||
| Opérateur | Explication |
|
||||
| :- | :- |
|
||||
| `&&` | Vrai si les conditions à gauche et à droite sont vraies |
|
||||
| `||` | Vrai si une des conditions à gauche ou à droite est vraie |
|
||||
|
||||
Exemples :
|
||||
|
||||
* `false && true` : sera évalué comme faux
|
||||
* `false || true` : sera évalué comme vrai
|
||||
|
||||
|
||||
### Tester si une variable existe
|
||||
|
||||
Brindille ne fait pas de différences entre une variable qui n'existe pas, et une variable définie à `null`.
|
||||
On peut donc tester l'existence d'une variable en la comparant à `null` comme ceci :
|
||||
|
||||
```
|
||||
{{if $session !== null}}
|
||||
Session en cours pour l'utilisateur/trice {{$session.user.name}}.
|
||||
{{else}}
|
||||
Session inexistante.
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
## Fonctions
|
||||
|
||||
### Fonctions natives
|
||||
|
||||
Une fonction va répondre à certains paramètres et renvoyer un résultat ou réaliser une action.
|
||||
|
||||
**Un bloc de fonction commence par le signe deux points `:`.**
|
||||
|
||||
```
|
||||
{{:http code=404}}
|
||||
```
|
||||
|
||||
Contrairement aux autres types de blocs, et comme pour les variables, il n'y a pas de bloc fermant (avec un slash `/`).
|
||||
|
||||
## Sections
|
||||
|
||||
Une section est une partie de la page qui sera répétée une fois, plusieurs fois, ou zéro fois, selon ses paramètres et le résultat (c'est une "boucle"). Une section commence par un bloc avec un signe hash (`#`) et se termine par un bloc avec un slash (`/`).
|
||||
|
||||
Un exemple simple avec une section qui n'aura qu'une seule répétition :
|
||||
|
||||
```
|
||||
{{#categories uri=$_GET.uri}}
|
||||
<h1>{{$title}}</h1>
|
||||
{{/categories}}
|
||||
```
|
||||
|
||||
Il est possible d'utiliser une condition `{{else}}` avant la fin du bloc pour avoir du contenu alternatif si la section ne se répète pas (dans ce cas si aucune catégorie ne correspond au critère).
|
||||
|
||||
Un exemple de sous-section
|
||||
|
||||
```
|
||||
{{#categories uri=$_GET.uri}}
|
||||
<h1>{{$title}}</h1>
|
||||
|
||||
{{#articles parent=$path order="published DESC" limit="10"}}
|
||||
<h2></h2>
|
||||
<p>{{$content|truncate:600:"..."}}</p>
|
||||
{{else}}
|
||||
<p>Aucun article trouvé.</p>
|
||||
{{/articles}}
|
||||
|
||||
{{/categories}}
|
||||
```
|
||||
|
||||
Voir la référence des sections pour voir quelles sont les sections possibles et quel est leur comportement.
|
||||
|
||||
## Bloc litéral
|
||||
|
||||
Pour qu'une partie du code ne soit pas interprété, pour éviter les conflits avec certaines syntaxes, il est possible d'utiliser un bloc `literal` :
|
||||
|
||||
```
|
||||
{{literal}}
|
||||
<script>
|
||||
// Ceci ne sera pas interprété
|
||||
function test (a) {{
|
||||
}}
|
||||
</script>
|
||||
{{/literal}}
|
||||
```
|
||||
|
||||
|
||||
## Commentaires
|
||||
|
||||
Les commentaires sont figurés dans des blocs qui commencent et se terminent par une étoile (`*`) :
|
||||
|
||||
```
|
||||
{{* Ceci est un commentaire
|
||||
Il sera supprimé du résultat final
|
||||
Il peut contenir du code qui ne sera pas interprété :
|
||||
{{if $test}}
|
||||
OK
|
||||
{{/if}}
|
||||
*}}
|
||||
```
|
||||
|
||||
|
||||
# Liste des variables définies par défaut
|
||||
|
||||
Ces variables sont définies tout le temps :
|
||||
|
||||
| Nom de la variable | Valeur |
|
||||
| :- | :- |
|
||||
| `$_GET` | Tableau contenant tous les paramètres passés dans la chaîne de requêtre de l'URL. |
|
||||
| `$_POST` | Tableau de tous les éléments de formulaire envoyés lors d'une requête POST. |
|
||||
| `$root_url` | Adresse racine du site web Paheko. |
|
||||
| `$request_url` | Adresse de la page courante. |
|
||||
| `$admin_url` | Adresse de la racine de l'administration Paheko. |
|
||||
| `$visitor_lang` | Langue préférée du visiteur, sur 2 lettres (exemple : `fr`, `en`, etc.). |
|
||||
| `$logged_user` | Informations sur le membre actuellement connecté dans l'administration (vide si non connecté). |
|
||||
| `$dialog` | Vaut `TRUE` si la page est dans un dialogue (iframe sous forme de pop-in dans l'administration). |
|
||||
| `$now` | Contient la date et heure courante. |
|
||||
| `$config.org_name` | Nom de l'association |
|
||||
| `$config.org_email` | Adresse e-mail de l'association |
|
||||
| `$config.org_phone` | Numéro de téléphone de l'association |
|
||||
| `$config.org_address` | Adresse postale de l'association |
|
||||
| `$config.org_web` | Adresse du site web de l'association |
|
||||
| `$config.files.logo` | Adresse du logo de l'association, si définit dans la personnalisation |
|
||||
| `$config.files.favicon` | Adresse de l'icône de favoris de l'association, si défini dans la personnalisation |
|
||||
| `$config.files.signature` | Adresse de l'image de signature, si défini dans la personnalisation |
|
||||
|
||||
À celles-ci s'ajoutent [les variables spéciales des modules](modules.html#variables_speciales) lorsque le script est chargé dans un module.
|
||||
|
||||
# Erreurs
|
||||
|
||||
Si une erreur survient dans un squelette, que ça soit au niveau d'une erreur de syntaxe, ou une erreur dans une fonction, filtre ou section, alors elle sera affichée selon les règles suivantes :
|
||||
|
||||
* si le membre connecté est administrateur, une erreur est affichée avec le code du squelette ;
|
||||
* sinon l'erreur est affichée sans le code.
|
||||
|
||||
|
||||
# Avertissement sur la sécurité des requêtes SQL
|
||||
|
||||
Attention, en utilisant la section `{{#select ...}}`, ou une des sections SQL (voir plus bas), avec des paramètres qui ne seraient pas protégés, il est possible qu'une personne mal intentionnée ait accès à des parties de la base de données à laquelle vous ne désirez pas donner accès.
|
||||
|
||||
Pour protéger contre cela il est essentiel d'utiliser les paramètres nommés.
|
||||
|
||||
Exemple de requête dangereuse :
|
||||
|
||||
```
|
||||
{{#sql select="*" tables="users" where="id = %s"|args:$_GET.id}}
|
||||
...
|
||||
{{/sql}}
|
||||
```
|
||||
|
||||
On se dit que la requête finale sera donc : `SELECT * FROM users WHERE id = 42;` si le numéro 42 est passé dans le paramètre `id` de la page.
|
||||
|
||||
Imaginons qu'une personne mal-intentionnée indique dans le paramètre `id` de la page la chaîne de caractère suivante : `0 OR 1`. Dans ce cas la requête exécutée sera `SELECT * FROM users WHERE id = 0 OR 1;`. Cela aura pour effet de lister tous les membres, au lieu d'un seul.
|
||||
|
||||
Pour protéger contre cela il convient d'utiliser un paramètre nommé :
|
||||
|
||||
```
|
||||
{{#sql select="*" tables="users" where="id = :id" :id=$_GET.id}}
|
||||
```
|
||||
|
||||
Dans ce cas la requête malveillante générée sera `SELECT * FROM users WHERE id = '0 OR 1';`. Ce qui aura pour effet de ne lister aucun membre.
|
||||
|
||||
## Mesures prises pour la sécurité des données
|
||||
|
||||
Dans Brindille, il n'est pas possible de modifier ou supprimer des éléments dans la base de données avec les requêtes SQL directement. Seules les requêtes SQL en lecture (`SELECT`) sont permises.
|
||||
|
||||
Cependant certaines fonctions permettent de modifier ou créer des éléments précis (écritures par exemple), ce qui peut avoir un effet de remplir ou modifier des données par une personne mal-intentionnée, donc attention à leur utilisation.
|
||||
|
||||
Les autres mesures prises sont :
|
||||
|
||||
* impossibilité d'accéder à certaines données sensibles (mot de passe, logs de connexion, etc.)
|
||||
* incitation forte à utiliser les paramètres nommés dans la documentation
|
||||
* protection automatique des variables dans la section `{{#select}}`
|
||||
* fourniture de fonctions pour protéger les chaînes de caractères contre l'injection SQL
|
||||
828
doc/admin/brindille_functions.md
Normal file
828
doc/admin/brindille_functions.md
Normal file
|
|
@ -0,0 +1,828 @@
|
|||
Title: Référence des fonctions Brindille
|
||||
|
||||
{{{.nav
|
||||
* [Modules](modules.html)
|
||||
* [Documentation Brindille](brindille.html)
|
||||
* **[Fonctions](brindille_functions.html)**
|
||||
* [Sections](brindille_sections.html)
|
||||
* [Filtres](brindille_modifiers.html)
|
||||
}}}
|
||||
|
||||
<<toc aside>>
|
||||
|
||||
# Fonctions généralistes
|
||||
|
||||
## assign
|
||||
|
||||
Permet d'assigner une valeur dans une variable.
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `.` | optionnel | Assigner toutes les variables du contexte (section) actuel |
|
||||
| `var` | optionnel | Nom de la variable à créer ou modifier |
|
||||
| `value` | optionnel | Valeur de la variable |
|
||||
| `from` | optionnel | Recopier la valeur depuis la variable ayant le nom fourni dans ce paramètre. |
|
||||
|
||||
Tous les autres paramètres sont considérés comme des variables à assigner.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{:assign blabla="Coucou"}}
|
||||
|
||||
{{$blabla}}
|
||||
```
|
||||
|
||||
Il est possible d'assigner toutes les variables d'une section dans une variable en utilisant le paramètre point `.` (`.="nom_de_variable"`). Cela permet de capturer le contenu d'une section pour le réutiliser à un autre endroit.
|
||||
|
||||
```
|
||||
{{#pages uri="Informations" limit=1}}
|
||||
{{:assign .="infos"}}
|
||||
{{/pages}}
|
||||
|
||||
{{$infos.title}}
|
||||
```
|
||||
|
||||
Il est aussi possible de remonter dans les sections parentes en utilisant plusieurs points. Ainsi deux points remonteront à la section parente, trois points à la section parente de la section parente, etc.
|
||||
|
||||
```
|
||||
{{#foreach from=$infos item="info"}}
|
||||
{{#foreach from=$info item="sous_info"}}
|
||||
{{if $sous_info.titre == 'Coucou'}}
|
||||
{{:assign ..="info_importante"}}
|
||||
{{/if}}
|
||||
{{/foreach}}
|
||||
{{/foreach}}
|
||||
|
||||
{{$info_importante.titre}}
|
||||
```
|
||||
|
||||
En utilisant le paramètre spécial `var`, tous les autres paramètres passés sont ajoutés à la variable donnée en valeur :
|
||||
|
||||
```
|
||||
{{:assign var="tableau" label="Coucou" name="Pif le chien"}}
|
||||
{{$tableau.label}}
|
||||
{{$tableau.name}}
|
||||
```
|
||||
|
||||
De la même manière on peut écraser une variable avec le paramètre spécial `value`:
|
||||
|
||||
```
|
||||
{{:assign var="tableau" value=$infos}}
|
||||
```
|
||||
|
||||
Il est également possible de créer des tableaux avec la syntaxe `.` dans le nom de la variable :
|
||||
|
||||
```
|
||||
{{:assign var="liste.comptes.530" label="Caisse"}}
|
||||
{{:assign var="liste.comptes.512" label="Banque"}}
|
||||
|
||||
{{#foreach from=$liste.comptes}}
|
||||
{{$key}} = {{$value.label}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
Il est possible de rajouter des éléments à un tableau simplement en utilisant un point seul :
|
||||
|
||||
```
|
||||
{{:assign var="liste.comptes." label="530 - Caisse"}}
|
||||
{{:assign var="liste.comptes." label="512 - Banque"}}
|
||||
```
|
||||
|
||||
Enfin, il est possible de faire référence à une variable de manière dynamique en utilisant le paramètre spécial `from` :
|
||||
|
||||
```
|
||||
{{:assign var="tableau" a="Coucou" b="Test !"}}
|
||||
{{:assign var="titre" from="tableau.%s"|args:"b"}}
|
||||
{{$titre}} -> Affichera "Test !", soit la valeur de {{$tableau.b}}
|
||||
```
|
||||
|
||||
## break
|
||||
|
||||
Interrompt une section.
|
||||
|
||||
## continue
|
||||
|
||||
Passe à l'itération suivante d'une section. Le code situé entre cette instruction et la fin de la section ne sera pas exécuté.
|
||||
|
||||
```
|
||||
{{#foreach from=$list item="event"}}
|
||||
{{if $event.date == '2023-01-01'}}
|
||||
{{:continue}}
|
||||
{{/if}}
|
||||
{{$event.title}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
Il est possible de passer à l'itération suivante d'une section parente en utilisant un chiffre en paramètre :
|
||||
|
||||
```
|
||||
{{#foreach from=$list item="event"}}
|
||||
{{$event.title}}
|
||||
{{#foreach from=$event.people item="person"}}
|
||||
{{if $person.name == 'bohwaz'}}
|
||||
{{:continue 2}}
|
||||
{{/if}}
|
||||
- {{$person.name}}
|
||||
{{/foreach}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
## debug
|
||||
|
||||
Cette fonction permet d'afficher le contenu d'une ou plusieurs variables :
|
||||
|
||||
```
|
||||
{{:debug test=$title}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
array(1) {
|
||||
["test"] => string(6) "coucou"
|
||||
}
|
||||
```
|
||||
|
||||
Si aucun paramètre n'est spécifié, alors toutes les variables définies sont renvoyées. Utile pour découvrir quelles sont les variables accessibles dans une section par exemple.
|
||||
|
||||
|
||||
## error
|
||||
|
||||
Affiche un message d'erreur et arrête le traitement à cet endroit.
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `message` | **obligatoire** | Message d'erreur à afficher |
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{if $_POST.nombre != 42}}
|
||||
{{:error message="Le nombre indiqué n'est pas 42"}}
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
## form_errors
|
||||
|
||||
Affiche les erreurs du formulaire courant (au format HTML).
|
||||
|
||||
## http
|
||||
|
||||
Permet de modifier les entêtes HTTP renvoyés par la page. Cette fonction doit être appelée au tout début du squelette, avant tout autre code ou ligne vide.
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `code` | *optionnel* | Modifie le code HTTP renvoyé. [Liste des codes HTTP](https://fr.wikipedia.org/wiki/Liste_des_codes_HTTP) |
|
||||
| `redirect` | *optionnel* | Rediriger vers l'adresse URL indiquée en valeur. |
|
||||
| `type` | *optionnel* | Modifie le type MIME renvoyé |
|
||||
| `download` | *optionnel* | Force la page à être téléchargée sous le nom indiqué. |
|
||||
| `inline` | *optionnel* | Force la page à être affichée, et peut ensuite être téléchargée sous le nom indiqué (utile pour la généraion de PDF : permet d'afficher le PDF dans le navigateur avant de le télécharger). |
|
||||
|
||||
Note : si le type `application/pdf` est indiqué (ou juste `pdf`), la page sera convertie en PDF à la volée. Il est possible de forcer le téléchargement du fichier en utilisant le paramètre `download`.
|
||||
|
||||
Exemples :
|
||||
|
||||
```
|
||||
{{:http code=404}}
|
||||
{{:http redirect="/Nos-Activites/"}}
|
||||
{{:http redirect="https://mon-site-web.tld/"}}
|
||||
{{:http type="application/svg+xml"}}
|
||||
{{:http type="pdf" download="liste_membres_ca.pdf"}}
|
||||
```
|
||||
|
||||
## include
|
||||
|
||||
Permet d'inclure un autre squelette.
|
||||
|
||||
Paramètres :
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `file` | **obligatoire** | Nom du squelette à inclure |
|
||||
| `keep` | *optionnel* | Liste de noms de variables à conserver |
|
||||
| `capture` | *optionnel* | Si renseigné, au lieu d'afficher le squelette, son contenu sera enregistré dans la variable de ce nom. |
|
||||
| … | *optionnel* | Tout autre paramètre sera utilisé comme variable qui n'existea qu'à l'intérieur du squelette inclus. |
|
||||
|
||||
```
|
||||
{{* Affiche le contenu du squelette "navigation.html" dans le même répertoire que le squelette d'origine *}}
|
||||
{{:include file="./navigation.html"}}
|
||||
```
|
||||
|
||||
Par défaut, les variables du squelette parent sont transmis au squelette inclus, mais les variables définies dans le squelette inclus ne sont pas transmises au squelette parent. Exemple :
|
||||
|
||||
```
|
||||
{{* Squelette page.html *}}
|
||||
{{:assign title="Super titre !"}}
|
||||
{{:include file="./_head.html"}}
|
||||
{{$nav}}
|
||||
```
|
||||
```
|
||||
{{* Squelette _head.html *}}
|
||||
<h1>{{$title}}</h1>
|
||||
{{:assign nav="Accueil > %s"|args:$title}}
|
||||
```
|
||||
|
||||
Dans ce cas, la dernière ligne du premier squelette (`{{$nav}}`) n'affichera rien, car la variable définie dans le second squelette n'en sortira pas. Pour indiquer qu'une variable doit être transmise au squelette parent, il faut utiliser le paramètre `keep`:
|
||||
|
||||
```
|
||||
{{:include file="./_head.html" keep="nav"}}
|
||||
```
|
||||
|
||||
On peut spécifier plusieurs noms de variables, séparés par des virgules, et utiliser la notation à points :
|
||||
|
||||
```
|
||||
{{:include file="./_head.html" keep="nav,article.title,name"}}
|
||||
{{$nav}}
|
||||
{{$article.title}}
|
||||
{{$name}}
|
||||
```
|
||||
|
||||
On peut aussi capturer le résultat d'un squelette dans une variable :
|
||||
|
||||
```
|
||||
{{:include file="./_test.html" capture="test"}}
|
||||
{{:assign var="test" value=$test|replace:'TITRE':'Ceci est un titre'}}
|
||||
{{$test}}
|
||||
```
|
||||
|
||||
Il est possible d'assigner de nouvelles variables au contexte du include en les déclarant comme paramètres tout comme on le ferait avec `{{:assign}}` :
|
||||
|
||||
```
|
||||
{{:include file="./_head.html" title='%s documentation'|args:$doc.label visitor=$user}}
|
||||
```
|
||||
|
||||
## captcha
|
||||
|
||||
Permet de générer une question qui doit être répondue correctement par l'utilisateur pour valider une action. Utile pour empêcher les robots spammeurs d'effectuer une action.
|
||||
|
||||
L'utilisation simplifiée utilise un de ces deux paramètres :
|
||||
|
||||
| Paramètre | Fonction |
|
||||
| :- | :- |
|
||||
| `html` | Si `true`, crée un élément de formulaire HTML et le texte demandant à l'utilisateur de répondre à la question |
|
||||
| `verify` | Si `true`, vérifie que l'utilisateur a correctement répondu à la question |
|
||||
|
||||
L'utilisation avancée utilise d'abord ces deux paramètres :
|
||||
|
||||
| Paramètre | Fonction |
|
||||
| :- | :- |
|
||||
| `assign_hash` | Nom de la variable où assigner le hash (à mettre dans un `<input type="hidden" />`) |
|
||||
| `assign_number` | Nom de la variable où assigner le nombre de la question (à afficher à l'utilisateur) |
|
||||
|
||||
Puis on vérifie :
|
||||
|
||||
| Paramètre | Fonction |
|
||||
| :- | :- |
|
||||
| `verify_hash` | Valeur qui servira comme hash de vérification (valeur du `<input type="hidden" />`) |
|
||||
| `verify_number` | Valeur qui représente la réponse de l'utilisateur |
|
||||
| `assign_error` | Si spécifié, le message d'erreur sera placé dans cette variable, sinon il sera affiché directement. |
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{if $_POST.send}}
|
||||
{{:captcha verify_hash=$_POST.h verify_number=$_POST.n assign_error="error"}}
|
||||
{{if $error}}
|
||||
<p class="alert">Mauvaise réponse</p>
|
||||
{{else}}
|
||||
...
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
<form method="post" action="">
|
||||
{{:captcha assign_hash="hash" assign_number="number"}}
|
||||
<p>Merci de recopier le nombre suivant en chiffres : <tt>{{$number}}</tt></p>
|
||||
<p>
|
||||
<input type="text" name="n" placeholder="1234" />
|
||||
<input type="hidden" name="h" value="{{$hash}}" />
|
||||
<input type="submit" name="send" />
|
||||
</p>
|
||||
</form>
|
||||
```
|
||||
|
||||
## mail
|
||||
|
||||
Permet d'envoyer un e-mail à une ou des adresses indiquées (sous forme de tableau).
|
||||
|
||||
Restrictions :
|
||||
|
||||
* le message est toujours envoyé en format texte ;
|
||||
* l'expéditeur est toujours l'adresse de l'association ;
|
||||
* l'envoi est limité à une seule adresse e-mail externe (adresse qui n'est pas celle d'un membre) dans une page ;
|
||||
* l'envoi est limité à maximum 10 adresses e-mails internes (adresses de membres) dans une page ;
|
||||
* un message envoyé à une adresse e-mail externe ne peut pas contenir une adresse web (`https://...`) autre que celle de l'association.
|
||||
|
||||
Note : il est également conseillé d'utiliser la fonction `captcha` pour empêcher l'envoi de spam.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `to` | **obligatoire** | Adresse email destinataire (seule l'adresse e-mail elle-même est acceptée, pas de nom) |
|
||||
| `subject` | **obligatoire** | Sujet du message |
|
||||
| `body` | **obligatoire** | Corps du message |
|
||||
| `block_urls` | *optionnel* | (`true` ou `false`) Permet de bloquer l'envoi si le message contient une adresse `https://…` |
|
||||
| `attach_file` | *optionnel* | Chemin vers un ou plusieurs documents à joindre au message (situé dans les documents) |
|
||||
| `attach_from` | *optionnel* | Chemin vers un ou plusieurs squelettes à joindre au message (par exemple pour joindre un document généré) |
|
||||
|
||||
Pour le destinataire, il est possible de spécifier un tableau :
|
||||
|
||||
```
|
||||
{{:assign var="recipients[]" value="membre1@framasoft.net"}}
|
||||
{{:assign var="recipients[]" value="membre2@chatons.org"}}
|
||||
{{:mail to=$recipients subject="Coucou" body="Contenu du message\nNouvelle ligne"}}
|
||||
```
|
||||
|
||||
Exemple de formulaire de contact :
|
||||
|
||||
```
|
||||
{{if !$_POST.email|check_email}}
|
||||
<p class="alert">L'adresse e-mail indiquée est invalide.</p>
|
||||
{{elseif $_POST.message|trim == ''}}
|
||||
<p class="alert">Le message est vide</p>
|
||||
{{elseif $_POST.send}}
|
||||
{{:captcha verify=true}}
|
||||
{{:mail to=$config.org_email subject="Formulaire de contact" body="%s a écrit :\n\n%s"|args:$_POST.email:$_POST.message block_urls=true}}
|
||||
<p class="ok">Votre message nous a bien été transmis !</p>
|
||||
{{/if}}
|
||||
|
||||
<form method="post" action="">
|
||||
<dl>
|
||||
<dt><label>Votre e-mail : <input type="email" required name="email" /></label></dt>
|
||||
<dt><label>Votre message : <textarea required name="message" cols="50" rows="5"></textarea></label></dt>
|
||||
<dt>{{:captcha html=true}}</dt>
|
||||
</dl>
|
||||
<p><input type="submit" name="send" value="Envoyer !" /></p>
|
||||
</form>
|
||||
```
|
||||
|
||||
## redirect
|
||||
|
||||
Redirige vers une nouvelle page.
|
||||
|
||||
Avec le paramètre `force`, si la page actuelle est ouverte dans une fenêtre modale (grâce à la cible `_dialog`), alors la fenêtre modale est fermée, et la redirection se passe dans la page parente.
|
||||
|
||||
Avec le paramètre `to`, si la page actuelle est ouverte dans une fenêtre modal (grâce à la cible `_dialog`), alors la fenêtre modale est fermée, et la page parente est rechargée. Si la page n'est pas ouvertre dans dans une fenêtre modale, la redirection est effectuée.
|
||||
|
||||
Seules les adresses internes sont acceptées, il n'est pas possible de rediriger vers une adresse extérieure.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `force` | optionnel | Adresse de redirection forcée |
|
||||
| `to` | optionnel | Adresse de redirection si pas dans une fenêtre modale |
|
||||
|
||||
Si `to=null` est utilisé, alors la fenêtre modale sera fermée. Ou, si la page n'est pas dans une fenêtre modale, la page courante sera rechargée.
|
||||
|
||||
## api
|
||||
|
||||
Permet d'appeler l'API de Paheko, que ça soit sur l'instance locale, en cours, ou une autre instance externe.
|
||||
|
||||
Voir la [documentation de l'API](https://paheko.cloud/api) pour la liste des fonctions disponibles.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `method` | obligatoire | Méthode de requête : `GET`, `POST`, etc. |
|
||||
| `path` | obligatoire | Chemin de la méthode de l'API à appeler. |
|
||||
| `fail` | optionnel | Booléen. Si `true`, alors une erreur sera affichée si la requête échoue. Si `false`, aucune erreur ne sera affichée. Défaut : `true`. |
|
||||
| `assign` | optionnel | Capturer le résultat dans cette variable. |
|
||||
| `assign_code` | optionnel | Capturer le code de retour dans cette variable. |
|
||||
|
||||
Par défaut, les requêtes sont réalisées sur la base de données locale, dans ce cas les paramètres suivants sont également disponibles :
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `access` | optionnel | Niveau d'autorisation de l'API (défaut : `admin`). |
|
||||
|
||||
|
||||
```
|
||||
{{:assign var="users." value=42}}
|
||||
{{:api
|
||||
method="POST"
|
||||
path="accounting/transaction"
|
||||
assign="result"
|
||||
|
||||
id_year=1
|
||||
type="revenue"
|
||||
date="01/01/2023"
|
||||
label="Don de Ada Lovelace"
|
||||
reference="DON-0001"
|
||||
payment_reference="Credit Mutuel 00042"
|
||||
amount="51,49"
|
||||
debit="756"
|
||||
credit="512A"
|
||||
linked_users=$users
|
||||
}}
|
||||
|
||||
L'écriture n°{{$result.id}} a été créée.
|
||||
```
|
||||
|
||||
Mais cette fonction permet également d'appeler une API Paheko distante, dans ce cas les paramètres suivants sont nécessaires :
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `url` | obligatoire | Adresse HTTP de l'instance Paheko distante. |
|
||||
| `user` | obligatoire | Identifiant d'accès à l'API distante. |
|
||||
| `password` | obligatoire | Mot de passe d'accès à l'API distante. |
|
||||
|
||||
```
|
||||
{{:api
|
||||
method="POST"
|
||||
path="sql"
|
||||
sql="SELECT * FROM users;"
|
||||
url="https://mon-asso.paheko.cloud/"
|
||||
user="zmgyfr1qnm"
|
||||
password="OAqFTLFzujJWr6lLn1Mu7w"
|
||||
assign="result"
|
||||
assign_code="code"
|
||||
fail=false
|
||||
}}
|
||||
|
||||
{{if $code == 200}}
|
||||
Il y a {{$result.count}} résultats.
|
||||
{{else}}
|
||||
La requête a échoué : code {{$code}} — {{$result.error}}
|
||||
{{/if}}
|
||||
|
||||
```
|
||||
|
||||
# Fonctions relatives aux Modules
|
||||
|
||||
## save
|
||||
|
||||
Enregistre des données, sous la forme d'un document, dans la base de données, pour le module courant.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `key` | optionnel | Clé unique du document |
|
||||
| `id` | optionnel | Numéro unique du document |
|
||||
| `validate_schema` | optionnel | Fichier de schéma JSON à utiliser pour valider les données avant enregistrement |
|
||||
| `validate_only` | optionnel | Liste des paramètres à valider (par exemple pour ne faire qu'une mise à jour partielle), séparés par des virgules. |
|
||||
| `assign_new_id` | optionnel | Si renseigné, le nouveau numéro unique du document sera indiqué dans cette variable. |
|
||||
| … | optionnel | Autres paramètres : traités comme des valeurs à enregistrer dans le document |
|
||||
|
||||
Si ni `key` ni `id` ne sont indiqués, un nouveau document sera créé avec un nouveau numéro (ID) unique.
|
||||
|
||||
Si le document indiqué existe déjà, il sera mis à jour. Les valeurs nulles (`NULL`) seront effacées.
|
||||
|
||||
```
|
||||
{{:save key="facture_43" nom="Atelier mobile" montant=250}}
|
||||
```
|
||||
|
||||
Enregistrera dans la base de données le document suivant sous la clé `facture_43` :
|
||||
|
||||
```
|
||||
{"nom": "Atelier mobile", "montant": 250}
|
||||
```
|
||||
|
||||
Exemple de mise à jour :
|
||||
|
||||
```
|
||||
{{:save key="facture_43" montant=300}}
|
||||
```
|
||||
|
||||
Exemple de récupération du nouvel ID :
|
||||
|
||||
```
|
||||
{{:save titre="Coucou !" assign_new_id="id"}}
|
||||
Le document n°{{$id}} a bien été enregistré.
|
||||
```
|
||||
|
||||
### Validation avec un schéma JSON
|
||||
|
||||
```
|
||||
{{:save titre="Coucou" texte="Très long" validate_schema="./document.schema.json"}}
|
||||
```
|
||||
|
||||
Pour ne valider qu'une partie du schéma, par exemple si on veut faire une mise à jour du document :
|
||||
|
||||
```
|
||||
{{:save key="test" titre="Coucou" validate_schema="./document.schema.json" validate_only="titre"}}
|
||||
```
|
||||
|
||||
## delete
|
||||
|
||||
Supprime un document lié au module courant.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `key` | optionnel | Clé unique du document |
|
||||
| `id` | optionnel | Numéro unique du document |
|
||||
|
||||
Il est possible de spécifier d'autres paramètres, ou une clause `where` et des paramètres dont le nom commence par deux points.
|
||||
|
||||
* Supprimer le document avec la clé `facture_43` : `{{:delete key="facture_43"}}`
|
||||
* Supprimer le document avec la clé `ABCD` et dont la propriété `type` du document correspond à la valeur `facture` : `{{:delete key="ABCD" type="facture"}}`
|
||||
* Supprimer tous les documents : `{{:delete}}`
|
||||
* Supprimer tous les documents ayant le type `facture` : `{{:delete type="facture"}}`
|
||||
* Supprimer tous les documents de type `devis` ayant une date dans le passé : `{{:delete :type="devis" where="$$.type = :type AND $$.date < datetime()"}}`
|
||||
|
||||
## read
|
||||
|
||||
Lire un fichier stocké dans les fichiers du code du module.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `file` | obligatoire | Chemin du fichier à lire |
|
||||
| `assign` | optionnel | Variable dans laquelle placer le contenu du fichier. |
|
||||
|
||||
Si le paramètre `assign` n'est pas utilisé, le contenu du fichier sera affiché directement.
|
||||
|
||||
Exemple pour lire un fichier JSON :
|
||||
|
||||
```
|
||||
{{#read file="baremes.json" assign="baremes"}}
|
||||
{{:assign baremes=$baremes|json_decode}}
|
||||
Barème kilométrique pour une voiture de 3 CV : {{$baremes.voiture.3cv}}
|
||||
```
|
||||
|
||||
Exemple pour lire un fichier CSV :
|
||||
|
||||
```
|
||||
{{#read file="baremes.csv" assign="baremes"}}
|
||||
{{:assign baremes=$baremes|trim|explode:"\n"}}
|
||||
|
||||
{{#foreach from=$baremes item="line"}}
|
||||
{{:assign bareme=$line|str_getcsv}}
|
||||
Nom du barème : {{$bareme.0}}
|
||||
Calcul : {{$bareme.1}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
## admin_header
|
||||
|
||||
Affiche l'entête de l'administration de l'association.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `title` | *optionnel* | Titre de la page |
|
||||
| `layout` | *optionnel* | Aspect de la page. Peut être `public` pour une page publique simple (sans le menu), ou `raw` pour une page vierge (sans aucun menu ni autre élément). Défaut : vide (affichage du menu) |
|
||||
| `current` | *optionnel* | Indique quel élément dans le menu de gauche doit être marqué comme sélectionné |
|
||||
| `custom_css` | *optionnel* | Fichier CSS supplémentaire à appeler dans le `<head>` |
|
||||
|
||||
```
|
||||
{{:admin_header title="Gestion des dons" current="acc"}}
|
||||
```
|
||||
|
||||
Liste des choix possibles pour `current` :
|
||||
|
||||
* `home` : menu Accueil
|
||||
* `users` : menu Membres
|
||||
* `users/new` : sous-menu "Ajouter" de Membres
|
||||
* `users/services` : sous-menu "Activités et cotisations" de Membres
|
||||
* `users/mailing` : sous-menu "Message collectif" de Membres
|
||||
* `acc` : menu Comptabilité
|
||||
* `acc/new` : sous-menu "Saisie" de Comptabilité
|
||||
* `acc/accounts` : sous-menu "Comptes"
|
||||
* `acc/simple` : sous-menu "Suivi des écritures"
|
||||
* `acc/years` : sous-menu "Exercices et rapports"
|
||||
* `docs` : menu Documents
|
||||
* `web` : menu Site web
|
||||
* `config` : menu Configuration
|
||||
* `me` : menu "Mes infos personnelles"
|
||||
* `me/services` : sous-menu "Mes activités et cotisations"
|
||||
|
||||
Exemple d'utilisation de `custom_css` depuis un module :
|
||||
|
||||
```
|
||||
{{:admin_header title="Mon module" custom_css="./style.css"}}
|
||||
```
|
||||
|
||||
## admin_footer
|
||||
|
||||
Affiche le pied de page de l'administration de l'association.
|
||||
|
||||
```
|
||||
{{:admin_footer}}
|
||||
```
|
||||
|
||||
## delete_form
|
||||
|
||||
Affiche un formulaire demandant la confirmation de suppression d'un élément.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `legend` | **obligatoire** | Libellé de l'élément `<legend>` du formulaire |
|
||||
| `warning` | **obligatoire** | Libellé de la question de suppression (en gros en rouge) |
|
||||
| `alert` | *optionnel* | Message d'alerte supplémentaire (bloc jaune) |
|
||||
| `info` | *optionnel* | Informations liées à la suppression (expliquant ce qui va être impacté par la suppression) |
|
||||
| `confirm` | *optionnel* | Libellé de la case à cocher pour la suppression, si ce paramètre est absent ou `NULL`, la case à cocher ne sera pas affichée. |
|
||||
|
||||
Le formulaire envoie un `POST` avec le bouton ayant le nom `delete`. Si le paramètre `confirm` est renseigné, alors la case à cochée aura le nom `confirm_delete`.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{#load id=$_GET.id assign="invoice"}}
|
||||
{{else}}
|
||||
{{:error message="Facture introuvable"}}
|
||||
{{/load}}
|
||||
|
||||
{{#form on="delete"}}
|
||||
{{if !$_POST.confirm_delete}}
|
||||
{{:error message="Merci de cocher la case"}}
|
||||
{{/if}}
|
||||
{{:delete id=$invoice.id}}
|
||||
{{/form}}
|
||||
|
||||
{{:form_errors}}
|
||||
|
||||
{{:delete_form
|
||||
legend="Suppression d'une facture"
|
||||
warning="Supprimer la facture n°%d ?"|args:$invoice.id
|
||||
info="Le devis lié sera également supprimé"
|
||||
alert="La facture sera définitivement perdue !"
|
||||
confirm="Cocher cette case pour confirmer la suppression de la facture"
|
||||
}}
|
||||
```
|
||||
|
||||
## input
|
||||
|
||||
Crée un champ de formulaire HTML. Cette fonction est une extension à la balise `<input>` en HTML, mais permet plus de choses.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `name` | **obligatoire** | Nom du champ |
|
||||
| `type` | **obligatoire** | Type de champ |
|
||||
| `required` | *optionnel* | Mettre à `true` si le champ est obligatoire |
|
||||
| `label` | *optionnel* | Libellé du champ |
|
||||
| `help` | *optionnel* | Texte d'aide, affiché sous le champ |
|
||||
| `default` | *optionnel* | Valeur du champ par défaut, si le formulaire n'a pas été envoyé, et que la valeur dans `source` est vide |
|
||||
| `source` | *optionnel* | Source de pré-remplissage du champ. Si le nom du champ est `montant`, alors la valeur de `[source].montant` sera affichée si présente. |
|
||||
|
||||
Si `label` ou `help` sont spécifiés, le champ sera intégré à une balise HTML `<dd>`, et le libellé sera intégré à une balise `<dt>`. Dans ce cas il faut donc que le champ soit dans une liste `<dl>`. Si ces deux paramètres ne sont pas spécifiés, le champ sera le seul tag HTML.
|
||||
|
||||
```
|
||||
<dl>
|
||||
{{:input name="amount" type="money" label="Montant" required=true}}
|
||||
</dl>
|
||||
```
|
||||
|
||||
Note : le champ aura comme `id` la valeur `f_[name]`. Ainsi un champ avec `amount` comme `name` aura `id="f_amount"`.
|
||||
|
||||
### Valeur du champ
|
||||
|
||||
La valeur du champ est remplie avec :
|
||||
|
||||
* la valeur dans `$_POST` qui correspond au `name` ;
|
||||
* sinon la valeur dans `source` (tableau) avec le même nom (exemple : `$source[name]`) ;
|
||||
* sinon la valeur de `default` est utilisée.
|
||||
|
||||
Note : le paramètre `value` n'est pas supporté sauf pour checkbox et radio.
|
||||
|
||||
### Types de champs supportés
|
||||
|
||||
* les types classiques de `input` en HTML : text, search, email, url, file, date, checkbox, radio, password, etc.
|
||||
* Note : pour checkbox et radio, il faut utiliser le paramètre `value` en plus pour spécifier la valeur.
|
||||
* `textarea`
|
||||
* `money` créera un champ qui attend une valeur de monnaie au format décimal
|
||||
* `datetime` créera un champ date et un champ texte pour entrer l'heure au format `HH:MM`
|
||||
* `radio-btn` créera un champ de type radio mais sous la forme d'un gros bouton
|
||||
* `select` crée un sélecteur de type `<select>`. Dans ce cas il convient d'indiquer un tableau associatif dans le paramètre `options`.
|
||||
* `select_groups` crée un sélecteur de type `<select>`, mais avec des `<optgroup>`. Dans ce cas il convient d'indiquer un tableau associatif à deux niveaux dans le paramètre `options`.
|
||||
* `list` crée un champ permettant de sélectionner un ou des éléments (selon si le paramètre `multiple` est `true` ou `false`) dans un formulaire externe. Le paramètre `can_delete` indique si l'utilisateur peut supprimer l'élément déjà sélectionné (si `multiple=false`). La sélection se fait à partir d'un formulaire dont l'URL doit être spécifiée dans le paramètre `target`. Les formulaires actuellement supportés sont :
|
||||
* `!acc/charts/accounts/selector.php?targets=X` pour sélectionner un compte du plan comptable, où X est une liste de types de comptes qu'il faut permettre de choisir (séparés par des `:`)
|
||||
* `!users/selector.php` pour sélectionner un membre
|
||||
|
||||
## button
|
||||
|
||||
Affiche un bouton, similaire à `<button>` en HTML, mais permet d'ajouter une icône par exemple.
|
||||
|
||||
```
|
||||
{{:button type="submit" name="save" label="Créer ce membre" shape="plus" class="main"}}
|
||||
```
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `type` | optionnel | Type du bouton |
|
||||
| `name` | optionnel | Nom du bouton |
|
||||
| `label` | optionnel | Label du bouton |
|
||||
| `shape` | optionnel | Affiche une icône en préfixe du label |
|
||||
| `class` | optionnel | Classe CSS |
|
||||
| `title` | optionnel | Attribut HTML `title` |
|
||||
| `disabled` | optionnel | Désactive le bouton si `true` |
|
||||
|
||||
|
||||
## link
|
||||
|
||||
Affiche un lien.
|
||||
|
||||
```
|
||||
{{:link href="!users/new.php" label="Créer un nouveau membre"}}
|
||||
```
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `href` | **obligatoire** | Adresse du lien |
|
||||
| `label` | **obligatoire** | Libellé du lien |
|
||||
| `target` | *optionnel* | Cible du lien, utiliser `_dialog` pour que le lien s'ouvre dans une fenêtre modale. |
|
||||
|
||||
|
||||
Préfixer l'adresse par "!" donnera une URL absolue en préfixant l'adresse par l'URL de l'administration.
|
||||
Sans "!", l'adresse générée sera relative au contexte d'appel (module/plugin ou squelette site web).
|
||||
|
||||
|
||||
## linkbutton
|
||||
|
||||
Affiche un lien sous forme de faux bouton, avec une icône si le paramètre `shape` est spécifié.
|
||||
|
||||
```
|
||||
{{:linkbutton href="!users/new.php" label="Créer un nouveau membre" shape="plus"}}
|
||||
```
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `href` | **obligatoire* | Adresse du lien |
|
||||
| `label` | **obligatoire** | Libellé du bouton |
|
||||
| `target` | *optionnel* | Cible de l'ouverture du lien |
|
||||
| `shape` | *optionnel* | Affiche une icône en préfixe du label |
|
||||
|
||||
Si on utilise `target="_dialog"` alors le lien s'ouvrira dans une fenêtre modale (iframe) par dessus la page actuelle.
|
||||
|
||||
Si on utilise `target="_blank"` alors le lien s'ouvrira dans un nouvel onglet.
|
||||
|
||||
## icon
|
||||
|
||||
Affiche une icône.
|
||||
|
||||
```
|
||||
{{:icon shape="print"}}
|
||||
```
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `shape` | **obligatoire** | Forme de l'icône. |
|
||||
|
||||
|
||||
### Formes d'icônes disponibles
|
||||
|
||||

|
||||
|
||||
## user_field
|
||||
|
||||
Affiche un champ de la fiche membre.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `name` | **obligatoire** | Nom du champ. |
|
||||
| `value` | **obligatoire** | Valeur du champ. |
|
||||
|
||||
## edit_user_field
|
||||
|
||||
Afficher un champ de formulaire pour modifier un champ de la fiche membre.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `name` | **obligatoire** | Nom du champ. |
|
||||
| `source` | *optionnel* | Source de pré-remplissage du champ. Si le nom du champ est `montant`, alors la valeur de `[source].montant` sera utilisée comme valeur du champ. |
|
||||
|
||||
# Gestion de fichiers dans les modules
|
||||
|
||||
Les modules peuvent stocker des fichiers, mais seulement dans leur propre contexte. Un module ne peut pas gérer les fichiers du site web, des écritures comptables, des membres, ou des autres modules, il ne peut gérer que ses propres fichiers.
|
||||
|
||||
Quand les données d'un module sont supprimé, les fichiers du module sont aussi supprimés.
|
||||
|
||||
Mais si le module stocke des fichiers liés à un document JSON (par exemple dans un sous-répertoire pour chaque module), c'est au code du module de s'assurer que les fichiers seront supprimés lors de la suppression du document.
|
||||
|
||||
Par défaut, tous les fichiers des modules sont en accès restreint : ils ne peuvent être vus et modifiés que par les membres connectés qui sont au niveau d'accès indiqué dans les paramètres `restrict_section` et `restrict_level` du fichier `module.ini`.
|
||||
|
||||
Pour qu'un fichier soit visible publiquement aux personnes non connectées, il faut le placer dans le sous-répertoire `public` du module.
|
||||
|
||||
Attention : de par ce fonctionnement, **tous les fichiers** d'un module sont potentiellement accessibles par **tous les membres ayant accès au module** et connaissant le nom du fichier.
|
||||
|
||||
Il est donc recommandé de ne pas utiliser ce mécanisme pour stocker des données personnelles ou des données sensibles.
|
||||
|
||||
## admin_files
|
||||
|
||||
Affiche (dans le contexte de l'administration) la liste des fichiers dans un sous-répertoire, et éventuellement la possibilité d'en ajouter ou de les supprimer.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `path` | optionnel | Chemin du sous-répertoire où sont stockés les fichiers |
|
||||
| `upload` | optionnel | Booléen. Si `true`, l'utilisateur pourra ajouter des fichiers. (Défaut : `false`) |
|
||||
| `edit` | optionnel | Booléen. Si `true`, l'utilisateur pourra modifier ou supprimer les fichiers existants. (Défaut : `false`) |
|
||||
| `use_trash` | optionnel | Booléen. Si `false`, le fichier sera supprimé, sans passer par la corbeille. Défaut : `true` |
|
||||
|
||||
Exemple pour afficher la liste des fichiers du sous-répertoire `facture43` et permettre de rajouter de nouveaux fichiers :
|
||||
|
||||
```
|
||||
{{:admin_files path="facture43" upload=true edit=false}}
|
||||
```
|
||||
|
||||
## delete_file
|
||||
|
||||
Supprimer un fichier ou un répertoire lié au module courant.
|
||||
|
||||
| Paramètre | Obligatoire ou optionnel ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `path` | obligatoire | Chemin du fichier ou répertoire |
|
||||
|
||||
Exemple pour supprimer un fichier seul :
|
||||
|
||||
```
|
||||
{{:delete_file path="facture43/justificatif.pdf"}}
|
||||
```
|
||||
|
||||
Pour supprimer un répertoire et tous les fichiers dedans :
|
||||
|
||||
```
|
||||
{{:delete_file path="facture43"}}
|
||||
```
|
||||
785
doc/admin/brindille_modifiers.md
Normal file
785
doc/admin/brindille_modifiers.md
Normal file
|
|
@ -0,0 +1,785 @@
|
|||
Title: Référence des filtres Brindille
|
||||
|
||||
{{{.nav
|
||||
* [Modules](modules.html)
|
||||
* [Documentation Brindille](brindille.html)
|
||||
* [Fonctions](brindille_functions.html)
|
||||
* [Sections](brindille_sections.html)
|
||||
* **[Filtres](brindille_modifiers.html)**
|
||||
}}}
|
||||
|
||||
<<toc aside>>
|
||||
|
||||
# Filtres PHP
|
||||
|
||||
Ces filtres viennent directement de PHP et utilisent donc les mêmes paramètres. Voir la documentation PHP pour plus de détails.
|
||||
|
||||
| Nom | Description | Documentation PHP |
|
||||
| :- | :- | :- |
|
||||
| `htmlentities` | Convertit tous les caractères éligibles en entités HTML | [Documentation PHP](https://www.php.net/htmlentities) |
|
||||
| `htmlspecialchars` | Convertit les caractères spéciaux en entités HTML | [Documentation PHP](https://www.php.net/htmlspecialchars) |
|
||||
| `trim` | Supprime les espaces et lignes vides au début et à la fin d'un texte | [Documentation PHP](https://www.php.net/trim) |
|
||||
| `ltrim` | Supprime les espaces et lignes vides au début d'un texte | [Documentation PHP](https://www.php.net/ltrim) |
|
||||
| `rtrim` | Supprime les espaces et lignes vides à la fin d'un texte | [Documentation PHP](https://www.php.net/rtrim) |
|
||||
| `md5` | Génère un hash MD5 d'un texte | [Documentation PHP](https://www.php.net/md5) |
|
||||
| `sha1` | Génère un hash SHA1 d'un texte | [Documentation PHP](https://www.php.net/sha1) |
|
||||
| `strlen` | Nombre de caractères dans une chaîne de texte | [Documentation PHP](https://www.php.net/strlen) |
|
||||
| `strpos` | Position d'un élément dans une chaîne de texte | [Documentation PHP](https://www.php.net/strpos) |
|
||||
| `strrpos` | Position d'un dernier élément dans une chaîne de texte | [Documentation PHP](https://www.php.net/strrpos) |
|
||||
| `substr` | Découpe une chaîne de caractère | [Documentation PHP](https://www.php.net/substr) |
|
||||
| `strtotime` | Transforme une date en timestamp UNIX | [Documentation PHP](https://www.php.net/strtotime) |
|
||||
| `strip_tags` | Supprime les tags HTML | [Documentation PHP](https://www.php.net/strip_tags) |
|
||||
| `nl2br` | Remplace les retours à la ligne par des tags HTML `<br/>` | [Documentation PHP](https://www.php.net/nl2br) |
|
||||
| `wordwrap` | Ajoute des retours à la ligne tous les 75 caractères | [Documentation PHP](https://www.php.net/wordwrap) |
|
||||
| `abs` | Renvoie la valeur absolue d'un nombre (exemple : -42 sera transformé en 42) | [Documentation PHP](https://www.php.net/abs) |
|
||||
| `gettype` | Renvoie le type d'une variable | |
|
||||
| `intval` | Transforme une valeur en entier (integer) | [Documentation PHP](https://www.php.net/intval) |
|
||||
| `boolval` | Transforme une valeur en booléen (true ou false) | [Documentation PHP](https://www.php.net/boolval) |
|
||||
| `floatval` | Transforme une valeur en nombre flottant (à virgule) | [Documentation PHP](https://www.php.net/floatval) |
|
||||
| `strval` | Transforme une valeur en chaîne de texte | [Documentation PHP](https://www.php.net/strval) |
|
||||
| `arrayval` | Transforme une valeur en tableau | [Documentation PHP](https://www.php.net/manual/fr/language.types.type-juggling.php) |
|
||||
| `json_decode` | Transforme une chaîne JSON en valeur | [Documentation PHP](https://www.php.net/json_decode) |
|
||||
| `json_encode` | Transforme une valeur en chaîne JSON | [Documentation PHP](https://www.php.net/json_encode) |
|
||||
| `http_build_query` | Transformer un tableau en chaîne *query string* pour URL | [Documentation PHP](https://www.php.net/http_build_query) |
|
||||
| `str_getcsv` | Transformer une chaîne de texte de format CSV en tableau | [Documentation PHP](https://www.php.net/str_getcsv) |
|
||||
|
||||
# Filtres utiles pour les e-mails
|
||||
|
||||
## check_email
|
||||
|
||||
Permet de vérifier la validité d'une adresse email. Cette fonction vérifie la syntaxe de l'adresse mais aussi que le nom de domaine indiqué possède bien un enregistrement de type MX.
|
||||
|
||||
Renvoie `true` si l'adresse est valide.
|
||||
|
||||
```
|
||||
{{if !$_POST.email|check_email}}
|
||||
<p class="alert">L'adresse e-mail indiquée est invalide.</p>
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
## protect_contact
|
||||
|
||||
Crée un lien protégé pour une adresse email, pour éviter que l'adresse ne soit recueillie par les robots spammeurs (empêche également le copier-coller et le lien ne fonctionnera pas avec javascript désactivé).
|
||||
|
||||
# Filtres de tableaux
|
||||
|
||||
## has
|
||||
|
||||
Renvoie vrai si le tableau contient l'élément passé en paramètre.
|
||||
|
||||
```
|
||||
{{:assign var="table" a="bleu" b="orange"}}
|
||||
{{if $table|has:"bleu"}}
|
||||
Oui, il y a du bleu
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
## in
|
||||
|
||||
Renvoie vrai si l'élément fait partie du tableau passé en paramètre.
|
||||
|
||||
C'est exactement la même chose que `has`, mais exprimé à l'envers.
|
||||
|
||||
```
|
||||
{{:assign var="table" a="bleu" b="orange"}}
|
||||
{{if "bleu"|in:$table}}
|
||||
Oui, il y a du bleu
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
## has_key
|
||||
|
||||
Renvoie vrai si le tableau contient la clé passée en paramètre.
|
||||
|
||||
```
|
||||
{{:assign var="table" a="bleu" b="orange"}}
|
||||
{{if $table|has_key:"b"}}
|
||||
Oui, il y a la clé "b"
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
## key_in
|
||||
|
||||
Renvoie vrai si la clé fait partie du tableau passé en paramètre.
|
||||
|
||||
C'est exactement la même chose que `has_key`, mais exprimé à l'envers.
|
||||
|
||||
```
|
||||
{{:assign var="table" a="bleu" b="orange"}}
|
||||
{{if "b"|key_in:$table}}
|
||||
Oui, il y a la clé "b"
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
## keys
|
||||
|
||||
Renvoie les clés du tableau, sous forme de tableau.
|
||||
|
||||
```
|
||||
{{:assign var="table" a="bleu" b="orange"}}
|
||||
{{:assign var="cles" value=$table|keys}}
|
||||
{{$cles|implode:","}}
|
||||
```
|
||||
|
||||
Donnera :
|
||||
|
||||
```
|
||||
a,b
|
||||
```
|
||||
|
||||
## values
|
||||
|
||||
Renvoie les valeurs du tableau, sous forme de tableau.
|
||||
|
||||
Cela revient en fait à supprimer les clés associatives.
|
||||
|
||||
```
|
||||
{{:assign var="table" a="bleu" b="orange"}}
|
||||
{{#foreach from=$table key="cle" item="valeur"}}
|
||||
{{$cle}} = {{$valeur}}
|
||||
{{/foreach}}
|
||||
--
|
||||
{{:assign var="valeurs" value=$table|values}}
|
||||
{{#foreach from=$valeurs key="cle" item="valeur"}}
|
||||
{{$cle}} = {{$valeur}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
Donnera :
|
||||
|
||||
```
|
||||
a = bleu
|
||||
b = orange
|
||||
--
|
||||
0 = bleu
|
||||
1 = orange
|
||||
```
|
||||
|
||||
## count
|
||||
|
||||
Compte le nombre d'entrées dans un tableau.
|
||||
|
||||
```
|
||||
{{$products|count}}
|
||||
= 5
|
||||
```
|
||||
|
||||
## explode
|
||||
|
||||
Sépare une chaîne de texte en tableau à partir d'une chaîne de séparation.
|
||||
|
||||
```
|
||||
{{:assign var="table" value="a,b,c"|explode:","}}
|
||||
- {{$table.0}}
|
||||
- {{$table.1}}
|
||||
- {{$table.2}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
```
|
||||
|
||||
## implode
|
||||
|
||||
Réunit un tableau sous forme de chaîne de texte en utilisant éventuellement une chaîne de liaison entre chaque élément du tableau.
|
||||
|
||||
```
|
||||
{{:assign var="table" a="bleu" b="orange"}}
|
||||
{{$table|implode}}
|
||||
{{$table|implode:" - "}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
bleuorange
|
||||
bleu - orange
|
||||
```
|
||||
|
||||
## map
|
||||
|
||||
Applique un filtre sur chaque élément du tableau.
|
||||
|
||||
Le premier paramètre doit être le nom du filtre. Les autres paramètres seront passés au filtre.
|
||||
|
||||
```
|
||||
{{:assign var="table" a="01" b="02"}}
|
||||
{{:assign var="table" value=$table|map:intval}}
|
||||
- {{$table.a}}
|
||||
- {{$table.b}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
- 1
|
||||
- 2
|
||||
```
|
||||
|
||||
## ksort, sort
|
||||
|
||||
Trie un tableau par ordre alpha-numérique, sans tenir compte des majuscules/minuscules. `ksort` trie le tableau en utilisant les clés, et `sort` trie le tableau en utilisant les valeurs.
|
||||
|
||||
```
|
||||
{{:assign var="table" b="3" a="2" c="1"}}
|
||||
{{$table|sort|implode:","}}
|
||||
{{$table|ksort|implode:","}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
1,2,3
|
||||
2,3,1
|
||||
```
|
||||
|
||||
## max, min
|
||||
|
||||
Renvoie respectivement la valeur la plus haute ou la plus basse d'un tableau de valeurs numériques.
|
||||
|
||||
```
|
||||
{{:assign var="table" b="3" a="2" c="1"}}
|
||||
{{$table|max}}
|
||||
{{$table|min}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
3
|
||||
1
|
||||
```
|
||||
|
||||
# Filtres de texte
|
||||
|
||||
## args
|
||||
|
||||
Remplace des arguments dans le texte selon le schéma utilisé par [sprintf](https://www.php.net/sprintf).
|
||||
|
||||
```
|
||||
{{"Il y a %d résultats dans la recherche sur le terme '%s'."|args:$results_count:$query}}
|
||||
= Il y a 5 résultat dans la recherche sur le terme 'test'.
|
||||
```
|
||||
|
||||
## cat
|
||||
|
||||
Concaténer un texte avec un autre.
|
||||
|
||||
```
|
||||
{{"Tangerine"|cat:" Dream"}}
|
||||
= Tangerine Dream
|
||||
```
|
||||
|
||||
## count_words
|
||||
|
||||
Compte le nombre de mots dans un texte.
|
||||
|
||||
## escape
|
||||
|
||||
Échappe le contenu pour un usage dans un document HTML. Ce filtre est appliqué par défaut à tout ce qui est affiché (variables, etc.) sauf à utiliser le filtre `raw` (voir plus bas).
|
||||
|
||||
## excerpt
|
||||
|
||||
Produit un extrait d'un texte.
|
||||
|
||||
Supprime les tags HTML, tronque au nombre de caractères indiqué en second argument (si rien n'est indiqué, alors 600 est utilisé), et englobe dans un paragraphe `<p>...</p>`.
|
||||
|
||||
Équivalent de :
|
||||
|
||||
```
|
||||
<p>{{$html|strip_tags|truncate:600|nl2br}}</p>
|
||||
```
|
||||
|
||||
## extract_leading_number
|
||||
|
||||
Extrait le numéro au début d'une chaîne de texte.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{:assign title="02. Cours sur la physique nucléaire"}}
|
||||
{{$title|extract_leading_number}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
02
|
||||
```
|
||||
|
||||
## format_phone_number
|
||||
|
||||
Formatte un numéro de téléphone selon le format du pays de l'association.
|
||||
|
||||
Seule la France est supportée pour le moment.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{:assign number="0102030405"}}
|
||||
{{$number|format_phone_number}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
01 02 03 04 05
|
||||
```
|
||||
|
||||
## markdown
|
||||
|
||||
Transforme un texte en HTML en utilisant la syntaxe Markdown.
|
||||
|
||||
Il est conseillé de rajouter le filtre `|raw` pour ne pas échapper le HTML produit, si on veut afficher le texte formatté dans une page HTML.
|
||||
|
||||
```
|
||||
{{$texte|markdown|raw}}
|
||||
```
|
||||
|
||||
## raw
|
||||
|
||||
Passer ce filtre désactive la protection automatique contre le HTML (échappement) dans le texte. À utiliser en connaissance de cause avec les contenus qui contiennent du HTML et sont déjà filtrés !
|
||||
|
||||
```
|
||||
{{"<b>Test"}} = <b>Test
|
||||
{{"<b>Test"|raw}} = <b>Test
|
||||
```
|
||||
|
||||
|
||||
## replace
|
||||
|
||||
Remplace des parties du texte par une autre partie.
|
||||
|
||||
```
|
||||
{{"Tata yoyo"|replace:"yoyo":"yaya"}}
|
||||
= Tata yaya
|
||||
```
|
||||
|
||||
## regexp_replace
|
||||
|
||||
Remplace des valeurs en utilisant une expression rationnelles (regexp) ([documentation PHP](https://www.php.net/manual/fr/regexp.introduction.php)).
|
||||
|
||||
```
|
||||
{{"Tartagueule"|regexp_replace:"/ta/i":"tou"}}
|
||||
= tourtougueule
|
||||
```
|
||||
|
||||
|
||||
## remove_leading_number
|
||||
|
||||
Supprime le numéro au début d'un titre.
|
||||
|
||||
Cela permet de définir un ordre spécifique aux pages et catégories dans les listes.
|
||||
|
||||
```
|
||||
{{"03. Beau titre"|remove_leading_number}}
|
||||
Beau titre
|
||||
```
|
||||
|
||||
|
||||
## truncate
|
||||
|
||||
Tronque un texte à une longueur définie.
|
||||
|
||||
| Argument | Fonction | Valeur par défaut (si omis) |
|
||||
| :- | :- | :- |
|
||||
| 1 | longueur en nombre de caractères | 80 |
|
||||
| 2 | texte à placer à la fin (si tronqué) | … |
|
||||
| 3 | coupure stricte, si `true` alors un mot pourra être coupé en deux, si `false` le texte sera coupé au dernier mot complet | `false` |
|
||||
|
||||
```
|
||||
{{:assign texte="Ceci n'est pas un texte."}}
|
||||
{{$texte|truncate:19:"(...)":true}}
|
||||
{{$texte|truncate:19:"":false}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
Ceci n'est pas un (...)
|
||||
Ceci n'est pas un t
|
||||
```
|
||||
|
||||
## typo
|
||||
|
||||
Formatte un texte selon les règles typographiques françaises : ajoute des espaces insécables devant ou derrière les ponctuations françaises (`« » ? ! :`).
|
||||
|
||||
## urlencode
|
||||
|
||||
Encode une chaîne de texte pour utilisation dans une adresse URL (alias de `rawurlencode` en PHP).
|
||||
|
||||
## xml_escape
|
||||
|
||||
Échappe le contenu pour un usage dans un document XML.
|
||||
|
||||
## Autres filtres de texte
|
||||
|
||||
Les filtres suivants modifient la casse (majuscule/minuscules) d'un texte et ne fonctionneront correctement que si l'extension `mbstring` est installée sur le serveur. Sinon les lettres accentuées ne seront pas modifiées.
|
||||
|
||||
Note : il est donc préférable d'utiliser la propriété CSS [`text-transform`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-transform) pour modifier la casse si l'usage n'est que pour l'affichage, et non pas pour enregistrer les données.
|
||||
|
||||
* `tolower` : transforme un texte en minuscules
|
||||
* `toupper` : transforme un texte en majuscules
|
||||
* `ucfirst` : met la première lettre du texte en majuscule
|
||||
* `ucwords` : met la première lettre de chaque mot en majuscule
|
||||
* `lcfirst` : met la première lettre du texte en minuscule
|
||||
|
||||
# Filtres sur les sommes en devises
|
||||
|
||||
## money
|
||||
|
||||
Formatte une valeur de monnaie pour l'affichage.
|
||||
|
||||
Une valeur de monnaie doit **toujours** inclure les cents (exprimée sous forme d'entier). Ainsi `15,02` doit être exprimée sous la forme `1502`.
|
||||
|
||||
Paramètres optionnels :
|
||||
|
||||
1. `true` (défaut) pour ne rien afficher si la valeur est zéro, ou `false` pour afficher `0,00`
|
||||
2. `true` pour afficher le signe `+` si le nombre est positif (`-` est toujours affiché si le nombre est négatif)
|
||||
|
||||
```
|
||||
{{* 12 345,67 = 1234567 *}}
|
||||
{{:assign amount=1234567}}
|
||||
{{$amount|money}}
|
||||
12 345,67
|
||||
```
|
||||
|
||||
## money_currency
|
||||
|
||||
Comme `money` (même paramètres), formatte une valeur de monnaie (entier) pour affichage, mais en ajoutant la devise.
|
||||
|
||||
```
|
||||
{{:assign amount=1502}}
|
||||
{{$amount|money_currency}}
|
||||
15,02 €
|
||||
```
|
||||
|
||||
## money_html
|
||||
|
||||
Idem que `money`, mais pour l'affichage en HTML :
|
||||
|
||||
```
|
||||
{{* 12 345,67 = 1234567 *}}
|
||||
{{:assign amount=1234567}}
|
||||
{{$amount|money_html}}
|
||||
<span class="money">12 345,67</span>
|
||||
```
|
||||
|
||||
## money_currency_html
|
||||
|
||||
Idem que `money_currency`, mais pour l'affichage en HTML :
|
||||
|
||||
```
|
||||
{{:assign amount=1502}}
|
||||
{{$amount|money_currency_html}}
|
||||
<span class="money">15,02 €</span>
|
||||
```
|
||||
|
||||
## money_raw
|
||||
|
||||
Formatte une valeur de monnaie (entier) de manière brute : les milliers n'auront pas de séparateur.
|
||||
|
||||
```
|
||||
{{:assign amount=1234567}}
|
||||
{{$amount|money_raw}}
|
||||
12345,67
|
||||
```
|
||||
|
||||
## money_int
|
||||
|
||||
Transforme un nombre à partir d'une chaîne de caractère (par exemple `12345,67`) en entier (`1234567`) pour stocker une valeur de monnaie.
|
||||
|
||||
```
|
||||
{{:assign montant=$_POST.montant|trim|money_int}}
|
||||
```
|
||||
|
||||
# Filtres SQL
|
||||
|
||||
## quote_sql
|
||||
|
||||
Protège une chaîne contre les attaques SQL, pour l'utilisation dans une condition.
|
||||
|
||||
**Note : il est FORTEMENT déconseillé d'intégrer directement des sources extérieures dans les requêtes SQL, il est préférable d'utiliser les paramètres dans la boucle `sql` et ses dérivées, comme ceci : `{{#sql select="id, nom" tables="users" where="lettre_infos = :lettre" :lettre=$_GET.lettre}}`.**
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{:assign nom=$_GET.nom|quote_sql}}
|
||||
{{#sql select="id, nom" tables="users" where="nom = %s"|args:$nom}}
|
||||
```
|
||||
|
||||
## quote_sql_identifier
|
||||
|
||||
La même chose que `quote_sql`, mais pour les identifiants (par exemple nom de table ou de colonne).
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{:assign colonne=$_GET.colonne|quote_sql_identifier}}
|
||||
{{#sql select="id, %s"|args:$colonne tables="users"}}
|
||||
```
|
||||
|
||||
Il est possible d'utiliser un préfixe en argument, utile par exemple quand on a plusieurs tables avec le même nom de colonne :
|
||||
|
||||
```
|
||||
{{:assign colonne=$_GET.colonne|quote_sql_identifier:"u1"}}
|
||||
{{#sql select="u1.id, %s"|args:$colonne tables="users AS u1 INNER JOIN users AS u2 ON u2.id_parent = u1.id"}}
|
||||
```
|
||||
|
||||
## sql_where
|
||||
|
||||
Permet de créer une partie d'une clause SQL `WHERE` complexe.
|
||||
|
||||
Le premier paramètre est le nom de la colonne (sans préfixe).
|
||||
|
||||
Paramètres :
|
||||
|
||||
1. Comparateur : `=, !=, IN, NOT IN, >, >=, <, <=`
|
||||
2. Valeur à comparer (peut être un tableau)
|
||||
|
||||
Exemple pour afficher la liste des membres des catégories n°1 et n°2:
|
||||
|
||||
```
|
||||
{{:assign var="list." value=1}}
|
||||
{{:assign var="list." value=2}}
|
||||
{{#sql select="nom" tables="users" where="id_category"|sql_where:'IN':$id_list}}
|
||||
{{$nom}}
|
||||
{{/sql}}
|
||||
```
|
||||
|
||||
Le requête SQL générée sera alors `SELECT nom FROM users WHERE id_category IN (1, 2)`.
|
||||
|
||||
## sql_user_fields
|
||||
|
||||
Permet de récupérer le contenu de champs de la fiche utilisateur pour une requête SQL.
|
||||
|
||||
C'est particulièrement utile si le module permet de sélectionner dans sa configuration une liste de champs de membre (par exemple pour la carte de membre, ou les reçus fiscaux).
|
||||
|
||||
Si un champ mentionné n'existe plus dans les fiches de membres, il sera ignoré.
|
||||
|
||||
* Le premier paramètre est la liste des champs (tableau ou chaîne de texte)
|
||||
* Le second est le préfixe à utiliser (alias de la table membres), optionnel
|
||||
* Le troisième est la chaîne de texte à utiliser pour coller les champs entre eux
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{:assign var="champs_adresse." value="rue"}}
|
||||
{{:assign var="champs_adresse." value="ville"}}
|
||||
{{:assign var="champs_adresse_sql" value=$champs_adresse|sql_user_fields:"u":" - "}}
|
||||
{{#select !champs_adresse_sql AS adresse FROM users AS u; !champs_adresse_sql=$champs_adresse_sql}}
|
||||
{{$adresse}}
|
||||
{{/select}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
30 rue de Machin Chose — Dijon
|
||||
```
|
||||
|
||||
Et la clause SQL générée sera :
|
||||
|
||||
```
|
||||
LTRIM(COALESCE(' - ' || u.rue, '') || COALESCE(' - ' || u.ville), ' - ')
|
||||
```
|
||||
|
||||
# Filtres de date
|
||||
|
||||
## date
|
||||
|
||||
Formatte une date selon le format spécifié en premier paramètre.
|
||||
|
||||
Le format est identique au [format utilisé par PHP](https://www.php.net/manual/fr/datetime.format.php).
|
||||
|
||||
Si aucun format n'est indiqué, le défaut sera `d/m/Y à H:i`. (en français)
|
||||
|
||||
Exemples :
|
||||
|
||||
```
|
||||
{{:assign this_year=$now|date:'Y'}}
|
||||
{{$date|date:'d/m/Y'}}
|
||||
```
|
||||
|
||||
## strftime
|
||||
|
||||
Formatte une date selon un format spécifié en premier paramètre.
|
||||
|
||||
Le format à utiliser est identique [au format utilisé par la fonction strftime de PHP](https://www.php.net/strftime).
|
||||
|
||||
Un format doit obligatoirement être spécifié.
|
||||
|
||||
En passant un code de langue en second paramètre, cette langue sera utilisée. Sont supportés le français (`fr`) et l'anglais (`en`). Le défaut est le français si aucune valeur n'est passée en second paramètre .
|
||||
|
||||
```
|
||||
{{:assign this_year=$now|date:'%Y'}}
|
||||
{{$date|date:'%d/%m/%Y'}}
|
||||
```
|
||||
|
||||
## relative_date
|
||||
|
||||
Renvoie une date relative à la date du jour : `aujourd'hui`, `hier`, `demain`, ou sinon `mardi 2 janvier` (si la date est de l'année en cours) ou `2 janvier 2021` (si la date est d'une autre année).
|
||||
|
||||
En spécifiant `true` en premier paramètre, l'heure sera ajoutée au format `14h34`.
|
||||
|
||||
## date_short
|
||||
|
||||
Formatte une date au format court : `d/m/Y`.
|
||||
|
||||
En spécifiant `true` en premier paramètre l'heure sera ajoutée : `à H\hi`.
|
||||
|
||||
## date_long
|
||||
|
||||
Formatte une date au format long : `lundi 2 janvier 2021`.
|
||||
|
||||
En spécifiant `true` en premier paramètre l'heure sera ajoutée : `à 20h42`.
|
||||
|
||||
## date_hour
|
||||
|
||||
Formatte une date en renvoyant l'heure uniquement : `20h00`.
|
||||
|
||||
En passant `true` en premier paramètre, les minutes seront omises si elles sont égales à zéro : `20h`.
|
||||
|
||||
## atom_date
|
||||
|
||||
Formatte une date au format ATOM : `Y-m-d\TH:i:sP`
|
||||
|
||||
## parse_date
|
||||
|
||||
Vérifie le format d'une chaîne de texte représentant la date et la transforme en chaîne de date standardisée au format `AAAA-MM-JJ`.
|
||||
|
||||
Les formats acceptés sont :
|
||||
|
||||
* `AAAA-MM-JJ`
|
||||
* `JJ/MM/AAAA`
|
||||
* `JJ/MM/AA`
|
||||
|
||||
## parse_datetime
|
||||
|
||||
Vérifie le format d'une chaîne de texte représentant la date et l'heure et la transforme en chaîne de date et heure standardisée au format `AAAA-MM-JJ HH:mm`.
|
||||
|
||||
Les formats acceptés sont :
|
||||
|
||||
* `AAAA-MM-JJ HH:mm:ss`
|
||||
* `AAAA-MM-JJ HH:mm`
|
||||
* `JJ/MM/AAAA HH:mm`
|
||||
|
||||
## parse_time
|
||||
|
||||
Vérifie le format d'une chaîne de texte représentant l'heure et la transforme en chaîne de date standardisée au format `HH:MM`.
|
||||
|
||||
Les formats acceptés sont :
|
||||
|
||||
* `HH:MM`
|
||||
* `H:M`
|
||||
* `H:MM`
|
||||
* `HH:M`
|
||||
|
||||
Le séparateur peut être `:` ou `h`.
|
||||
|
||||
# Filtres de condition
|
||||
|
||||
Ces filtres sont à utiliser dans les conditions
|
||||
|
||||
## match
|
||||
|
||||
Renvoie `true` si le texte indiqué en premier paramètre est trouvé dans la variable.
|
||||
|
||||
Ce filtre est insensible à la casse.
|
||||
|
||||
```
|
||||
{{if $page.path|match:"/aide"}}Bienvenue dans l'aide !{{/if}}
|
||||
```
|
||||
|
||||
## regexp_match
|
||||
|
||||
Renvoie `true` si l'expression régulière indiquée en premier paramètre est trouvée dans la variable.
|
||||
|
||||
Exemple pour voir si le texte contient les mots "Bonjour" ou "Au revoir" (insensible à la casse) :
|
||||
|
||||
```
|
||||
{{if $texte|regexp_match:"/Bonjour|Au revoir/i"}}
|
||||
Trouvé !
|
||||
{{else}}
|
||||
Rien trouvé :-(
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
# Autres filtres
|
||||
|
||||
## math
|
||||
|
||||
Réalise un calcul mathématique. Cette fonction accepte :
|
||||
|
||||
* les nombres: `42`, `13,37`, `14.05`
|
||||
* les signes : `+ - / *` pour additionner, diminuer, diviser ou multiplier
|
||||
* les parenthèses : `( )`
|
||||
* les fonctions : `round(0.5452, 2)` `ceil(29,09)` `floor(0.99)` mais aussi : min, max, cos, sin, tan, asin, acos, atan, sinh, cosh, tanh, exp, sqrt, abs, log, log10, et pi.
|
||||
|
||||
Le résultat est renvoyé sous la forme d'un entier, ou d'un nombre flottant dont les décimales sont séparées par un point.
|
||||
|
||||
```
|
||||
{{"1+1"|math}}
|
||||
= 2
|
||||
```
|
||||
|
||||
Il est possible de donner d'autres arguments, de la même manière qu'avec `args` pour y inclure des données provenant de variables :
|
||||
|
||||
```
|
||||
{{:assign age=42}}
|
||||
{{"1+%d"|math:$age}}
|
||||
= 43
|
||||
{{:assign prix=39.99 tva=19.1}}
|
||||
{{"round(%f*%f, 2)"|math:$prix:$tva}}
|
||||
= 47.63
|
||||
```
|
||||
|
||||
## or
|
||||
|
||||
Si la variable passée est évalue comme `false` (c'est à dire que sa valeur est un texte vide, ou un nombre qui vaut zéro, ou la valeur `false`), alors le premier paramètre sera utilisé.
|
||||
|
||||
```
|
||||
{{:assign texte=""}}
|
||||
{{$texte|or:"Le texte est vide"}}
|
||||
```
|
||||
|
||||
Il est possible de chaîner les appels à `or` :
|
||||
|
||||
```
|
||||
{{:assign texte1="" texte2="0"}}
|
||||
{{$texte1|or:$texte2|or:"Aucun texte"}}
|
||||
```
|
||||
|
||||
## size_in_bytes
|
||||
|
||||
Renvoie une taille en octets, Ko, Mo, ou Go à partir d'une taille en octets.
|
||||
|
||||
```
|
||||
{{100|size_in_bytes}} = 100 o
|
||||
{{1500|size_in_bytes}} = 1,50 Ko
|
||||
{{1048576|size_in_bytes}} = 1 Mo
|
||||
```
|
||||
|
||||
## spell_out_number
|
||||
|
||||
Épelle un nombre en toutes lettres.
|
||||
|
||||
Le premier paramètre peut être utilisé pour spécifier le code de la langue à utiliser (par défaut c'est le français, donc le code `fr`).
|
||||
|
||||
```
|
||||
{{42|spell_out_number}}
|
||||
```
|
||||
|
||||
Donnera :
|
||||
|
||||
```
|
||||
quarante deux
|
||||
```
|
||||
|
||||
## uuid
|
||||
|
||||
Renvoie un identifiant unique au format UUIDv4.
|
||||
827
doc/admin/brindille_sections.md
Normal file
827
doc/admin/brindille_sections.md
Normal file
|
|
@ -0,0 +1,827 @@
|
|||
Title: Référence des sections Brindille
|
||||
|
||||
{{{.nav
|
||||
* [Modules](modules.html)
|
||||
* [Documentation Brindille](brindille.html)
|
||||
* [Fonctions](brindille_functions.html)
|
||||
* **[Sections](brindille_sections.html)**
|
||||
* [Filtres](brindille_modifiers.html)
|
||||
}}}
|
||||
|
||||
<<toc aside level=2>>
|
||||
|
||||
# Sections généralistes
|
||||
|
||||
## foreach
|
||||
|
||||
Permet d'itérer sur un tableau par exemple. Ainsi chaque élément du tableau exécutera une fois le contenu de la section.
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `from` | **obligatoire** | Variable sur laquelle effectuer l'itération |
|
||||
| `key` | **optionnel** | Nom de la variable à utiliser pour la clé de l'élément |
|
||||
| `item` | **optionnel** | Nom de la variable à utiliser pour la valeur de l'élément |
|
||||
|
||||
Considérons ce tableau :
|
||||
|
||||
```
|
||||
{{:assign var="tableau" a="bleu" b="orange"}}
|
||||
```
|
||||
|
||||
On peut alors itérer pour récupérer les clés (`a` et `b` ainsi que les valeurs `bleu` et `orange`) :
|
||||
|
||||
```
|
||||
{{#foreach from=$tableau key="key" item="value"}}
|
||||
{{$key}} = {{$value}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
Cela affichera :
|
||||
|
||||
```
|
||||
a = bleu
|
||||
b = orange
|
||||
```
|
||||
|
||||
Si on a un tableau à plusieurs niveaux, les éléments du tableau sont automatiquement transformés en variable :
|
||||
|
||||
```
|
||||
{{:assign var="tableau.a" couleur="bleu"}}
|
||||
{{:assign var="tableau.b" couleur="orange"}}
|
||||
```
|
||||
|
||||
```
|
||||
{{#foreach from=$variable}}
|
||||
{{$couleur}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
bleu
|
||||
orange
|
||||
```
|
||||
|
||||
### Itérer sans tableau
|
||||
|
||||
Il est aussi possible de faire `X` itérations, arbitrairement, sans avoir de tableau en entrée, en utilisant le paramètre `count`.
|
||||
|
||||
C'est l'équivalent des boucles `for` dans les autres langages de programmation.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
{{#foreach count=3 key="i"}}
|
||||
- {{$i}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
Affichera :
|
||||
|
||||
```
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
```
|
||||
|
||||
## restrict
|
||||
|
||||
Permet de limiter (restreindre) une partie de la page aux membres qui sont connectés et/ou qui ont certains droits.
|
||||
|
||||
Deux paramètres optionnels peuvent être utilisés ensemble (il n'est pas possible d'utiliser seulement un des deux) :
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `level` | *optionnel* | Niveau d'accès : `read`, `write`, `admin` |
|
||||
| `section` | *optionnel* | Section où le niveau d'accès doit s'appliquer : `users`, `accounting`, `web`, `documents`, `config` |
|
||||
| `block` | *optionnel* | Si ce paramètre est présent et vaut `true`, alors l'accès sera interdit si les conditions d'accès demandées ne sont pas remplies : une page d'erreur sera renvoyée. |
|
||||
|
||||
Exemple pour voir si un membre est connecté :
|
||||
|
||||
```
|
||||
{{#restrict}}
|
||||
Un membre est connecté, mais on ne sait pas avec quels droits.
|
||||
{{else}}
|
||||
Aucun membre n'est connecté.
|
||||
{{/restrict}}
|
||||
```
|
||||
|
||||
Exemple pour voir si un membre qui peut administrer les membres est connecté :
|
||||
|
||||
```
|
||||
{{#restrict section="users" level="admin"}}
|
||||
Un membre est connecté, et il a le droit d'administrer les membres.
|
||||
{{else}}
|
||||
Aucun membre n'est connecté, ou un membre est connecté mais n'est pas administrateur des membres.
|
||||
{{/restrict}}
|
||||
```
|
||||
|
||||
Pour bloquer l'accès aux membres non connectés, ou qui n'ont pas accès en écriture à la comptabilité.
|
||||
|
||||
```
|
||||
{{#restrict block=true section="accounting" level="write"}}
|
||||
{{/restrict}}
|
||||
```
|
||||
|
||||
Le mieux est de mettre ce code au début d'un squelette.
|
||||
|
||||
# Requêtes SQL
|
||||
|
||||
## select
|
||||
|
||||
Exécute une requête SQL `SELECT` et effectue une itération pour chaque résultat de la requête.
|
||||
|
||||
Pour une utilisation plus simplifiée des requêtes, voir aussi la section [sql](#sql).
|
||||
|
||||
Attention : la syntaxe de cette section est différente des autres sections Brindille. En effet après le début (`{{#select`) doit suivre la suite de la requête, et non pas les paramètres :
|
||||
|
||||
```
|
||||
Liste des membres inscrits à la lettre d'informations :
|
||||
{{#select nom, prenom FROM users WHERE lettre_infos = 1;}}
|
||||
- {{prenom}} {{$nom}}<br />
|
||||
{{else}}
|
||||
Aucun membre n'est inscrit à la lettre d'information.
|
||||
{{/select}}
|
||||
```
|
||||
|
||||
Des paramètres nommés de SQL peuvent être présentés après le point-virgule marquant la fin de la requête SQL :
|
||||
|
||||
```
|
||||
{{:assign prenom="Karim"}}
|
||||
{{#select * FROM users WHERE prenom = :prenom;
|
||||
:prenom=$prenom}}
|
||||
...
|
||||
{{/select}}
|
||||
```
|
||||
|
||||
Notez les deux points avant le nom du paramètre. Ces paramètres sont protégés contre les injections SQL (généralement appelés paramètres nommés).
|
||||
|
||||
Pour intégrer des paramètres qui ne sont pas protégés (**attention !**), il faut utiliser le point d'exclamation :
|
||||
|
||||
```
|
||||
{{:assign var="categories." value=1}}
|
||||
{{:assign var="categories." value=2}}
|
||||
{{#select * FROM users WHERE !categories;
|
||||
!categories='id_category'|sql_where:'IN':$categories}}
|
||||
```
|
||||
|
||||
Cela créera la requête suivante : `SELECT * FROM users WHERE id_category IN (1, 2);`
|
||||
|
||||
Il est aussi possible d'intégrer directement des variables dans la requête, en utilisant la syntaxe `{$variable|filtre:argument1:argument2}`, comme une variable classique donc, mais au lieu d'utiliser des doubles accolades, on utilise ici des accolades simples. Ces variables seront automatiquement protégées contre les injections SQL.
|
||||
|
||||
```
|
||||
{{:assign prenom="Camille"}}
|
||||
{{#select * FROM users WHERE initiale_prenom = {$prenom|substr:0:1};}}
|
||||
```
|
||||
|
||||
Cependant, pour plus de lisibilité il est conseillé d'utiliser la syntaxe des paramètres nommés SQL (voir ci-dessus).
|
||||
|
||||
Il est aussi possible d'insérer directement du code SQL (attention aux problèmes de sécurité dans ce cas !), pour cela il faut rajouter un point d'exclamation après l'accolade ouvrante :
|
||||
|
||||
```
|
||||
{{:assign var="prenoms." value="Karim"}}
|
||||
{{:assign var="prenoms." value="Camille"}}
|
||||
{{#select * FROM users WHERE {!"prenom"|sql_where:"IN":$prenoms};}}
|
||||
...
|
||||
{{/select}}
|
||||
```
|
||||
|
||||
Il est aussi possible d'utiliser les paramètres suivants :
|
||||
|
||||
| Paramètre | Fonction |
|
||||
| :- | :- |
|
||||
| `debug` | Si ce paramètre existe, la requête SQL exécutée sera affichée avant le début de la boucle. |
|
||||
| `explain` | Si ce paramètre existe, l'explication de la requête SQL exécutée sera affichée avant le début de la boucle. |
|
||||
| `assign` | Si renseigné, une variable de ce nom sera créée, et le contenu de la ligne y sera assigné. |
|
||||
|
||||
Exemple avec `debug` :
|
||||
|
||||
```
|
||||
{{:assign prenom="Karim"}}
|
||||
{{#select * FROM users WHERE prenom = :prenom; :prenom=$prenom debug=true}}
|
||||
...
|
||||
{{/select}}
|
||||
```
|
||||
|
||||
Affichera juste au dessus du résultat la requête exécutée :
|
||||
|
||||
```
|
||||
SELECT * FROM users WHERE nom = 'Karim'
|
||||
```
|
||||
|
||||
### Paramètre assign
|
||||
|
||||
Exemple avec `assign` :
|
||||
|
||||
```
|
||||
{{#select * FROM users WHERE prenom = 'Camille' LIMIT 1; assign="membre"}}{{/select}}
|
||||
{{$membre.nom}}
|
||||
```
|
||||
|
||||
Il est possible d'utiliser un point final pour que toutes les lignes soient mises dans un tableau :
|
||||
|
||||
```
|
||||
{{#select * FROM users WHERE prenom = 'Camille' LIMIT 10; assign="membres."}}{{/select}}
|
||||
|
||||
{{#foreach from=$membres}}
|
||||
Nom : {{$nom}}<br />
|
||||
Adresse : {{$adresse}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
## sql
|
||||
|
||||
|
||||
Effectue une requête SQL de type `SELECT` dans la base de données, mais de manière simplifiée par rapport à `select`.
|
||||
|
||||
```
|
||||
{{#sql select="*, julianday(date) AS day" tables="membres" where="id_categorie = :id_categorie" :id_categorie=$_GET.id_categorie order="numero DESC" begin=":page*100" limit=100 :page=$_GET.page}}
|
||||
…
|
||||
{{/sql}}
|
||||
```
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `tables` | **obligatoire** | Liste des tables à utiliser dans la requête (séparées par des virgules). |
|
||||
| `select` | *optionnel* | Liste des colonnes à sélectionner, si non spécifié, toutes les colonnes (`*`) seront sélectionnées |
|
||||
|
||||
### Sections qui héritent de `sql`
|
||||
|
||||
Certaines sections (voir plus bas) héritent de `sql` et rajoutent des fonctionnalités. Dans toutes ces sections, il est possible d'utiliser les paramètres facultatifs suivants :
|
||||
|
||||
| Paramètre | Fonction |
|
||||
| :- | :- |
|
||||
| `where` | Condition de sélection des résultats |
|
||||
| `begin` | Début des résultats, si vide une valeur de `0` sera utilisée. |
|
||||
| `limit` | Limitation des résultats. Si vide, une valeur de `10000` sera utilisée. |
|
||||
| `group` | Contenu de la clause `GROUP BY` |
|
||||
| `having` | Contenu de la clause `HAVING` |
|
||||
| `order` | Ordre de tri des résultats. Si vide le tri sera fait par ordre d'ajout dans la base de données. |
|
||||
| `assign` | Si renseigné, une variable de ce nom sera créée, et le contenu de la ligne du résultat y sera assigné. |
|
||||
| `debug` | Si ce paramètre existe, la requête SQL exécutée sera affichée avant le début de la boucle. |
|
||||
| `explain` | Si ce paramètre existe, l'explication de la requête SQL exécutée sera affichée avant le début de la boucle. |
|
||||
| `count` | Booléen ou texte. Si ce paramètre est `TRUE`, le nombre de résultats sera retourné. Si une chaîne de texte est indiquée, elle sera utilisée dans la clause `COUNT(<texte>)`. |
|
||||
|
||||
Il est également possible de passer des arguments dans les paramètres à l'aides des arguments nommés qui commencent par deux points `:` :
|
||||
|
||||
```
|
||||
{{#articles where="title = :montitre" :montitre="Actualité"}}
|
||||
```
|
||||
|
||||
Exemples d'utilisation du paramètre `count` :
|
||||
|
||||
```
|
||||
{{#articles count=true}}
|
||||
Il y a {{$count}} articles.
|
||||
{{/articles}}
|
||||
|
||||
{{#articles count=true assign="result"}}
|
||||
{{/articles}}
|
||||
Il y a {{$result.count}} articles.
|
||||
|
||||
{{#articles count="DISTINCT title"}}
|
||||
Il y a {{$count}} articles avec un titre différent.
|
||||
{{/articles}}
|
||||
```
|
||||
|
||||
# Membres
|
||||
|
||||
## users
|
||||
|
||||
Liste les membres.
|
||||
|
||||
Paramètres possibles :
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `id` | optionnel | Identifiant unique du membre, ou tableau contenant une liste d'identifiants. |
|
||||
| `search_name` | optionnel | Ne lister que les membres dont le nom correspond au texte passé en paramètre. |
|
||||
| `id_parent` | optionnel | Ne lister que les membres rattachés à l'identifiant unique du membre responsable indiqué. |
|
||||
|
||||
Chaque itération renverra la fiche du membre, ainsi que ces variables :
|
||||
|
||||
| Variable | Description |
|
||||
| :- | :- |
|
||||
| `$id` | Identifiant unique du membre |
|
||||
| `$_name` | Nom du membre, tel que défini dans la configuration |
|
||||
| `$_login` | Identifiant de connexion du membre, tel que défini dans la configuration |
|
||||
| `$_number` | Numéro du membre, tel que défini dans la configuration |
|
||||
|
||||
|
||||
## subscriptions
|
||||
|
||||
Liste les inscriptions à une ou des activités.
|
||||
|
||||
Paramètres possibles :
|
||||
|
||||
| Paramètre | | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `user` | optionnel | Identifiant unique du membre |
|
||||
| `active` | optionnel | Si `TRUE`, seules les inscriptions à jour sont listées |
|
||||
| `id_service` | optionnel | Ne renvoie que les inscriptions à l'activité correspondant à cet ID. |
|
||||
|
||||
# Comptabilité
|
||||
|
||||
## accounts
|
||||
|
||||
Liste les comptes d'un plan comptable.
|
||||
|
||||
| Paramètre | Fonction |
|
||||
| :- | :- |
|
||||
| `codes` (optionel) | Ne renvoyer que les comptes ayant ces codes (séparer par des virgules). |
|
||||
| `id` (optionel) | Ne renvoyer que le compte ayant cet ID. |
|
||||
|
||||
## balances
|
||||
|
||||
Renvoie la balance des comptes.
|
||||
|
||||
| Paramètre | Fonction |
|
||||
| :- | :- |
|
||||
| `codes` (optionel) | Ne renvoyer que les balances des comptes ayant ces codes (séparer par des virgules). |
|
||||
| `year` (optionel) | Ne renvoyer que les balances des comptes utilisés sur l'année (indiquer ici un ID de year). |
|
||||
|
||||
## transactions
|
||||
|
||||
Renvoie des écritures.
|
||||
|
||||
| Paramètre | | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `id` | optionnel | Indiquer un ID d'écriture pour récupérer ses informations. |
|
||||
| `user` | optionnel | Indiquer ici un ID utilisateur pour lister les écritures liées à un membre. |
|
||||
|
||||
## years
|
||||
|
||||
Liste les exercices comptables
|
||||
|
||||
| Paramètre | Fonction |
|
||||
| :- | :- |
|
||||
| `closed` (optionel) | Mettre `closed=true` pour ne lister que les exercices clôturés, ou `closed=false` pour ne lister que les exercices ouverts. |
|
||||
|
||||
# Pour le site web
|
||||
|
||||
## breadcrumbs
|
||||
|
||||
Permet de récupérer la liste des pages parentes d'une page afin de constituer un [fil d'ariane](https://fr.wikipedia.org/wiki/Fil_d'Ariane_(ergonomie)) permettant de remonter dans l'arborescence du site
|
||||
|
||||
Un seul paramètre est possible :
|
||||
|
||||
| Paramètre | Fonction |
|
||||
| :- | :- |
|
||||
| `uri` (obligatoire) | Adresse unique de la page parente |
|
||||
| ou `id_page` (obligatoire) | Numéro unique (ID) de la page parente |
|
||||
|
||||
Chaque itération renverra trois variables :
|
||||
|
||||
| Variable | Contenu |
|
||||
| :- | :- |
|
||||
| `$id` | Numéro unique (ID) de la page ou catégorie |
|
||||
| `$title` | Titre de la page ou catégorie |
|
||||
| `$uri` | Nom unique de la page ou catégorie |
|
||||
| `$url` | Adresse HTTP de la page ou catégorie |
|
||||
|
||||
### Exemple
|
||||
|
||||
```
|
||||
<ul>
|
||||
{{#breadcrumbs id_page=$page.id}}
|
||||
<li>{{$title}}</li>
|
||||
{{/breadcrumbs}}
|
||||
</ul>
|
||||
```
|
||||
|
||||
## pages, articles, categories <sup>(sql)</sup>
|
||||
|
||||
Note : ces sections héritent de `sql` (voir plus haut).
|
||||
|
||||
* `pages` renvoie une liste de pages, qu'elles soient des articles ou des catégories
|
||||
* `categories` ne renvoie que des catégories
|
||||
* `articles` ne renvoie que des articles
|
||||
|
||||
À part cela ces trois types de section se comportent de manière identique.
|
||||
|
||||
| Paramètre | Fonction |
|
||||
| :- | :- |
|
||||
| `search` | Renseigner ce paramètre avec un terme à rechercher dans le texte ou le titre. Dans ce cas par défaut le tri des résultats se fait sur la pertinence, sauf si le paramètre `order` est spécifié. |
|
||||
| `future` | Renseigner ce paramètre à `false` pour que les articles dont la date est dans le futur n'apparaissent pas, `true` pour ne renvoyer QUE les articles dans le futur, et `null` (ou ne pas utiliser ce paramètre) pour que tous les articles, passés et futur, apparaissent. |
|
||||
| `uri` | Adresse unique de la page/catégorie à retourner. |
|
||||
| `id_parent` | Numéro unique (ID) de la catégorie parente. Utiliser `null` pour n'afficher que les articles ou catégories de la racine du site. |
|
||||
| `parent` | Adresse unique (URI) de la catégorie parente. Exemple pour renvoyer la liste des articles de la sous-catégorie "Événements" de la catégorie "Notre atelier" : `evenements`. Utiliser `null` pour n'afficher que les articles ou catégories de la racine du site. Ajouter un point d'exclamation au début de la valeur pour inverser la condition. |
|
||||
|
||||
Par exemple lister 5 articles de la catégorie "Actualité", qui ne sont pas dans le futur, triés du plus récent au plus ancien :
|
||||
|
||||
```
|
||||
{{#articles future=false parent="actualite" order="published DESC" limit=5}}
|
||||
<h3>{{$title}}</h3>
|
||||
{{/articles}}
|
||||
```
|
||||
|
||||
Chaque élément de ces boucles contiendra les variables suivantes :
|
||||
|
||||
| Nom de la variable | Description | Exemple |
|
||||
| :- | :- | :- |
|
||||
| `id` | Numéro unique de la page (ID) | `1312` |
|
||||
| `id_parent` | Numéro unique de la catégorie parente (ID) | `42` |
|
||||
| `type` | Type de page : `1` = catégorie, `2` = article | `2` |
|
||||
| `uri` | Adresse unique de la page | `bourse-aux-velos` |
|
||||
| `url` | Adresse HTTP de la page | `https://site.association.tld/bourse-aux-velos` |
|
||||
| `path` | Chemin complet de la page | `actualite/atelier/bourse-aux-velos` |
|
||||
| `parent` | Chemin de la catégorie parente | `actualite/atelier`|
|
||||
| `title` | Titre de la page | `Bourse aux vélos` |
|
||||
| `content` | Contenu brut de la page | `# Titre …` |
|
||||
| `html` | Rendu HTML du contenu de la page | `<div class="web-content"><h1>Titre</h1>…</div>` |
|
||||
| `has_attachments` | `true` si la page a des fichiers joints, `false` sinon | `true` |
|
||||
| `published` | Date de publication | `2023-01-01 01:01:01` |
|
||||
| `modified` | Date de modification | `2023-01-01 01:01:01` |
|
||||
|
||||
Si une recherche a été effectuée, deux autres variables sont fournies :
|
||||
|
||||
| Nom de la variable | Description | Exemple |
|
||||
| :- | :- | :- |
|
||||
| `snippet` | Extrait du contenu contenant le texte recherché (entouré de balises `<mark>`) | `L’ONU appelle la France à s’attaquer aux « profonds problèmes » de <mark>racisme</mark> au sein des forces de…` |
|
||||
| `url_highlight` | Adresse de la page, où le texte recherché sera mis en évidence | `https://.../onu-racisme#:~:text=racisme%20au%20sein` |
|
||||
|
||||
|
||||
## attachments, documents, images <sup>(sql)</sup>
|
||||
|
||||
Note : ces sections héritent de `sql` (voir plus haut).
|
||||
|
||||
* `attachments` renvoie une liste de fichiers joints à une page du site web
|
||||
* `documents` renvoie une liste de fichiers joints qui ne sont pas des images
|
||||
* `images` renvoie une liste de fichiers joints qui sont des images
|
||||
|
||||
À part cela ces trois types de section se comportent de manière identique.
|
||||
|
||||
Note : seul les fichiers de la section site web sont accessibles, les fichiers de membres, de comptabilité, etc. ne sont pas disponibles.
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `parent` | **obligatoire** si `id_parent` n'est pas renseigné | Nom unique (URI) de l'article ou catégorie parente dont ont veut lister les fichiers |
|
||||
| `id_parent` | **obligatoire** si `parent` n'est pas renseigné | Numéro unique (ID) de l'article ou catégorie parente dont ont veut lister les fichiers |
|
||||
| `except_in_text` | *optionnel* | passer `true` à ce paramètre , et seuls les fichiers qui ne sont pas liés dans le texte de la page seront renvoyés |
|
||||
|
||||
# Sections relatives aux modules
|
||||
|
||||
## form
|
||||
|
||||
Permet de gérer la soumission d'un formulaire (`<form method="post"…>` en HTML).
|
||||
|
||||
Si l'élément dont le nom spécifié dans le paramètre `on` a été envoyé en `POST`, alors le code à l'intérieur de la section est exécuté.
|
||||
|
||||
Toute erreur à l'intérieur de la section arrêtera son exécution, et le message sera ajouté aux erreurs du formulaire.
|
||||
|
||||
Une vérification de sécurité [anti-CSRF](https://fr.wikipedia.org/wiki/Cross-site_request_forgery) est également appliquée. Si cette vérification échoue, le message d'erreur "Merci de bien vouloir renvoyer le formulaire." sera renvoyé. Pour que cela marche il faut que le formulaire dispose d'un bouton de type "submit", généré à l'aide de la fonction `button`. Exemple : `{{:button type="submit" name="save" label="Enregistrer"}}`.
|
||||
|
||||
En cas d'erreurs, le reste du contenu de la section ne sera pas exécuté. Les messages d'erreurs seront placés dans un tableau dans la variable `$form_errors`.
|
||||
|
||||
Il est aussi possible de les afficher simplement avec la fonction `{{:form_errors}}`. Cela revient à faire une boucle sur la variable `$form_errors`.
|
||||
|
||||
```
|
||||
{{#form on="save"}}
|
||||
{{if $_POST.titre|trim === ''}}
|
||||
{{:error message="Le titre est vide."}}
|
||||
{{/if}}
|
||||
{{* La ligne suivante ne sera pas exécutée si le titre est vide. *}}
|
||||
{{:save title=$_POST.titre|trim}}
|
||||
{{else}}
|
||||
{{:form_errors}}
|
||||
{{/form}}
|
||||
```
|
||||
|
||||
Il est possible d'utiliser `{{:form_errors}}` en dehors du bloc `{{else}}` :
|
||||
|
||||
```
|
||||
{{#form on="save"}}
|
||||
…
|
||||
{{/form}}
|
||||
…
|
||||
{{:form_errors}}
|
||||
```
|
||||
|
||||
<!--
|
||||
NOTE (bohwaz, 24/05/2023) : l'utilisation des règles de validation de Laravel me semble donner du code peu lisible, ce n'est donc pas documenté/complètement implémenté pour le moment.
|
||||
|
||||
Si l'élément dont le nom spécifié dans le paramètre `on` a été envoyé en `POST`, alors le formulaire est vérifié selon les autres paramètres. Une vérification de sécurité anti-CSRF est également appliquée. Si cette vérification échoue, le message d'erreur "Merci de bien vouloir renvoyer le formulaire." sera renvoyé.
|
||||
|
||||
Chaque paramètre supplémentaire indique un champ du formulaire qui doit être récupéré et validé. Le nom du paramètre doit correspondre au nom du champ dans le formulaire. La valeur du paramètre doit contenir une liste de règles de validations, séparées par des virgules `,`. Chaque règle peut prendre des paramètres, après deux points `:`.
|
||||
|
||||
Exemple pour un champ de formulaire nommé `titre` dont on veut qu'il soit présent et fasse entre 5 et 100 caractères : `titre="required,min:5,max:100"`
|
||||
|
||||
Si le titre fait moins de 5 caractères, le message d'erreur suivant sera renvoyé : `Le champ "titre" fait moins de 5 caractères.`
|
||||
|
||||
On peut spécifier une règle spéciale nommée `label` pour changer le nom du champ : `titre="required,min:5,max:100,label:Titre du texte"`. Cela modifiera le message d'erreur : `Le champ "Titre du texte" fait moins de 5 caractères.`
|
||||
|
||||
Chacun de ces paramètres sera disponible à l'intérieur de la section sous la forme d'une variable :
|
||||
|
||||
```
|
||||
{{#form titre="required,min:5"}}
|
||||
{{:save title=$titre}}
|
||||
{{/form}}
|
||||
```
|
||||
|
||||
|
||||
Toute erreur dans le corps de la section `{{#form}}…{{/form}}` fera arrêter l'exécution, et le message d'erreur sera ajouté à la liste des erreurs du formulaire :
|
||||
|
||||
```
|
||||
{{#form on="save"}}
|
||||
{{if !$_POST.titre|trim}}
|
||||
{{:error message="Pas de titre !"}}
|
||||
{{/if}}
|
||||
{{* La ligne suivante ne sera pas exécutée si le titre est vide. *}}
|
||||
{{:save title=$_POST.titre}}
|
||||
{{/form}}
|
||||
```
|
||||
|
||||
### Transformation des variables
|
||||
|
||||
Certaines règles de validation ont un effet de transformation sur les variables présentes dans le corps de la section :
|
||||
|
||||
* `string` s'assure que la variable est une chaîne de texte
|
||||
* `int` transforme la variable en nombre entier
|
||||
* `float` transforme la variable en nombre flottant
|
||||
* `bool` transforme la variable en booléen
|
||||
* `date` ou `date_format` transforment la variable en date
|
||||
|
||||
### Exemple
|
||||
|
||||
Considérons ce formulaire par exemple :
|
||||
|
||||
```
|
||||
<form method="post" action="">
|
||||
<fieldset>
|
||||
<legend>Enregistrer un paiement</legend>
|
||||
<dl>
|
||||
{{:input type="text" required=true name="titre" label="Titre"}}
|
||||
{{:input type="money" required=true name="montant" label="Montant"}}
|
||||
</dl>
|
||||
<p class="submit">
|
||||
{{:button type="submit" label="Enregistrer" name="save"}}
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
```
|
||||
|
||||
On pourrait l'enregistrer comme ceci :
|
||||
|
||||
```
|
||||
{{if $_POST.save}}
|
||||
{{if $_POST.titre|trim === ''}}
|
||||
{{:assign error="Le titre est vide"}}
|
||||
{{elseif $_POST.montant|trim === '' || $_POST.montant|money_int < 0}}
|
||||
{{:assign error="Le montant est vide ou négatif"}}
|
||||
{{else}}
|
||||
{{:save title=$_POST.titre|trim amount=$_POST.montant|money_int}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{if $error}}
|
||||
<p class="error block">{{$error}}</p>
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
Mais alors dans ce cas il faut multiplier les conditions pour les champs.
|
||||
|
||||
La section `{{#form …}}` permet de simplifier ces tests, et s'assurer qu'aucune attaque CSRF n'a lieu :
|
||||
|
||||
```
|
||||
{{#form on="save"
|
||||
titre="required,string,min:1,label:Titre"
|
||||
montant="required,money,min:0,label:Montant du paiement"
|
||||
}}
|
||||
{{:save title=$titre amount=$montant}}
|
||||
{{else}}
|
||||
{{:form_errors}}
|
||||
{{/form}}
|
||||
|
||||
```
|
||||
|
||||
### Règles de validation
|
||||
|
||||
| Nom de la règle | Description | Paramètres |
|
||||
| :- | :- | :- |
|
||||
| `required` | ...
|
||||
-->
|
||||
|
||||
## load <sup>(sql)</sup>
|
||||
|
||||
Note : cette section hérite de `sql` (voir plus haut). De ce fait, le nombre de résultats est limité à 10000 par défaut, si le paramètre `limit` n'est pas renseigné.
|
||||
|
||||
Charge un ou des documents pour le module courant.
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `module` | optionnel | Nom unique du module lié (par exemple : `recu_don`). Si non spécifié, alors le nom du module courant sera utilisé. |
|
||||
| `key` | optionnel | Clé unique du document |
|
||||
| `id` | optionnel | Numéro unique du document |
|
||||
| `each` | optionnel | Traiter une clé du document comme un tableau |
|
||||
|
||||
Il est possible d'utiliser d'autres paramètres : `{{#load cle="valeur"}}`. Cela va comparer `"valeur"` avec la valeur de la clé `cle` dans le document JSON. C'est l'équivalent d'écrire `where="json_extract(document, '$.cle') = 'valeur'"`.
|
||||
|
||||
Pour des conditions plus complexes qu'une simple égalité, il est possible d'utiliser la syntaxe courte `$$…` dans le paramètre `where`. Ainsi `where="$$.nom LIKE 'Bourse%'` est l'équivalent de `where="json_extract(document, '$.nom') LIKE 'Bourse%'"`.
|
||||
|
||||
Voir [la documentation de SQLite pour plus de détails sur la syntaxe de json_extract](https://www.sqlite.org/json1.html#jex).
|
||||
|
||||
Note : un index SQL dynamique est créé pour chaque requête utilisant une clause `json_extract`.
|
||||
|
||||
Chaque itération renverra ces deux variables :
|
||||
|
||||
| Variable | Valeur |
|
||||
| :- | :- |
|
||||
| `$key` | Clé unique du document |
|
||||
| `$id` | Numéro unique du document |
|
||||
|
||||
Ainsi que chaque élément du document JSON lui-même.
|
||||
|
||||
### Exemples
|
||||
|
||||
Afficher le nom du document dont la clé est `facture_43` :
|
||||
|
||||
```
|
||||
{{#load key="facture_43"}}
|
||||
{{$nom}}
|
||||
{{/load}}
|
||||
```
|
||||
|
||||
Afficher la liste des devis du module `invoice` depuis un autre module par exemple :
|
||||
|
||||
```
|
||||
{{#load module="invoice" type="quote"}}
|
||||
<h1>Titre du devis : {{$subject}}</h1>
|
||||
<h2>Montant : {{$total}}</h2>
|
||||
{{/load}}
|
||||
```
|
||||
|
||||
### Utilisation du paramètre `each`
|
||||
|
||||
Le paramètre `each` est utile pour faire une boucle sur un tableau contenu dans le document. Ce paramètre doit contenir un chemin JSON valide. Par exemple `membres[1].noms` pour boucler sur le tableau `noms`, du premier élément du tableau `membres`. Voir la documentation [de la fonction json_each de SQLite pour plus de détails](https://www.sqlite.org/json1.html#jeach).
|
||||
|
||||
Pour chaque itération de la section, la variable `{{$value}}` contiendra l'élément recherché dans le critère `each`.
|
||||
|
||||
Par exemple nous pouvons avoir un élément `membres` dans notre document JSON qui contient un tableau de noms de membres :
|
||||
|
||||
```
|
||||
{{:assign var="membres." value="Greta Thunberg}}
|
||||
{{:assign var="membres." value="Valérie Masson-Delmotte"}}
|
||||
{{:save membres=$membres}}
|
||||
```
|
||||
|
||||
Nous pouvons utiliser `each` pour faire une liste :
|
||||
|
||||
```
|
||||
{{#load each="membres"}}
|
||||
- {{$value}}
|
||||
{{/load}}
|
||||
```
|
||||
|
||||
Ou pour récupérer les documents qui correspondent à un critère :
|
||||
|
||||
```
|
||||
{{#load each="membres" where="value = 'Greta Thunberg'"}}
|
||||
Le document n°{{$id}} est celui qui parle de Greta.
|
||||
{{/load}}
|
||||
```
|
||||
|
||||
## list
|
||||
|
||||
Attention : cette section n'hérite **PAS de `sql`**.
|
||||
|
||||
Un peu comme `{{#load}}` cette section charge les documents d'un module, mais au sein d'une liste (tableau HTML).
|
||||
|
||||
Cette liste gère automatiquement l'ordre selon les préférences des utilisateurs, ainsi que la pagination.
|
||||
|
||||
Cette section est très puissante et permet de générer des listes simplement, une fois qu'on a saisi la logique de son fonctionnement.
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `schema` | **requis** si `select` n'est pas fourni | Chemin vers un fichier de schéma JSON qui représenterait le document |
|
||||
| `select` | **requis** si `schema` n'est pas fourni | Liste des colonnes à sélectionner, sous la forme `$$.colonne AS "Colonne"`, chaque colonne étant séparée par un point-virgule. |
|
||||
| `module` | *optionnel* | Nom unique du module lié (par exemple : `recu_don`). Si non spécifié, alors le nom du module courant sera utilisé. |
|
||||
| `columns` | *optionnel* | Permet de n'afficher que certaines colonnes du schéma. Indiquer ici le nom des colonnes, séparées par des virgules. |
|
||||
| `order` | *optionnel* | Colonne utilisée par défaut pour le tri (si l'utilisateur n'a pas choisi le tri sur une autre colonne). Si `select` est utilisé, il faut alors indiquer ici le numéro de la colonne, et non pas son nom. |
|
||||
| `desc` | *optionnel* | Si ce paramètre est à `true`, l'ordre de tri sera inversé. |
|
||||
| `max` | *optionnel* | Nombre d'éléments à afficher dans la liste, sur chaque page. |
|
||||
| `where` | *optionnel* | Condition `WHERE` de la requête SQL. |
|
||||
| `debug` | *optionnel* | Si ce paramètre existe, la requête SQL exécutée sera affichée avant le début de la boucle. |
|
||||
| `explain` | *optionnel* | Si ce paramètre existe, l'explication de la requête SQL exécutée sera affichée avant le début de la boucle. |
|
||||
| `disable_user_ordering` | *optionnel* | Booléen. Si ce paramètre est `true`, il ne sera pas possible à l'utilisateur d'ordonner les colonnes. |
|
||||
|
||||
Pour déterminer quelles colonnes afficher dans le tableau, il faut utiliser soit le paramètre `schema` pour indiquer un fichier de schéma JSON qui sera utilisé pour donner le libellé des colonnes (via la `description` indiquée dans le schéma), soit le paramètre `select`, où il faut alors indiquer le nom et le libellé des colonnes sous la forme `$$.colonne1 AS "Libellé"; $$.colonne2 AS "Libellé 2"`.
|
||||
|
||||
Comme pour `load`, il est possible d'utiliser des paramètres supplémentaires : `cle="valeur"`. Cela va comparer `"valeur"` avec la valeur de la clé `cle` dans le document JSON. C'est l'équivalent d'écrire `where="json_extract(document, '$.cle') = 'valeur'"`.
|
||||
|
||||
Pour des conditions plus complexes qu'une simple égalité, il est possible d'utiliser la syntaxe courte `$$…` dans le paramètre `where`. Ainsi `where="$$.nom LIKE 'Bourse%'` est l'équivalent de `where="json_extract(document, '$.nom') LIKE 'Bourse%'"`.
|
||||
|
||||
Voir [la documentation de SQLite pour plus de détails sur la syntaxe de json_extract](https://www.sqlite.org/json1.html#jex).
|
||||
|
||||
Note : un index SQL dynamique est créé pour chaque requête utilisant une clause `json_extract`.
|
||||
|
||||
Chaque itération renverra toujours ces deux variables :
|
||||
|
||||
| Variable | Valeur |
|
||||
| :- | :- |
|
||||
| `$key` | Clé unique du document |
|
||||
| `$id` | Numéro unique du document |
|
||||
|
||||
Ainsi que chaque élément du document JSON lui-même.
|
||||
|
||||
La section ouvre un tableau HTML et le ferme automatiquement, donc le contenu de la section **doit** être une ligne de tableau HTML (`<tr>`).
|
||||
|
||||
Dans chaque ligne du tableau il faut respecter l'ordre des colonnes indiqué dans `columns` ou `select`. Une dernière colonne est réservée aux boutons d'action : `<td class="actions">...</td>`.
|
||||
|
||||
**Attention :** une seule liste peut être utilisée dans une même page. Avoir plusieurs listes provoquera des problèmes au niveau du tri des colonnes.
|
||||
|
||||
### Exemples
|
||||
|
||||
Lister le nom, la date et le montant des reçus fiscaux, à partir du schéma JSON suivant :
|
||||
|
||||
```
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"date": {
|
||||
"description": "Date d'émission",
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"adresse": {
|
||||
"description": "Adresse du bénéficiaire",
|
||||
"type": "string"
|
||||
},
|
||||
"nom": {
|
||||
"description": "Nom du bénéficiaire",
|
||||
"type": "string"
|
||||
},
|
||||
"montant": {
|
||||
"description": "Montant",
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Le code de la section sera alors comme suivant :
|
||||
|
||||
```
|
||||
{{#list schema="./recu.schema.json" columns="nom, date, montant"}}
|
||||
<tr>
|
||||
<th>{{$nom}}</th>
|
||||
<td>{{$date|date_short}}</td>
|
||||
<td>{{$montant|raw|money_currency}}</td>
|
||||
<td class="actions">
|
||||
{{:linkbutton shape="eye" label="Ouvrir" href="./voir.html?id=%d"|args:$id target="_dialog"}}
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<p class="alert block">Aucun reçu n'a été trouvé.</p>
|
||||
{{/list}}
|
||||
```
|
||||
|
||||
Si le paramètre `columns` avait été omis, la colonne `adresse` aurait également été incluse.
|
||||
|
||||
Il est à noter que si l'utilisation directe du schéma est bien pratique, cela ne permet pas de récupérer des informations plus complexes dans la structure JSON, par exemple une sous-clé ou l'application d'une fonction SQL. Dans ce cas il faut obligatoirement utiliser `select`. Par exemple ici on veut pouvoir afficher l'année, et trier sur l'année par défaut :
|
||||
|
||||
```
|
||||
{{#list select="$$.nom AS 'Nom du donateur' ; strftime('%Y', $$.date) AS 'Année'" order=2}}
|
||||
<tr>
|
||||
<th>{{$nom}}</th>
|
||||
<td>{{$col2}}</td>
|
||||
<td class="actions">
|
||||
{{:linkbutton shape="eye" label="Ouvrir" href="./voir.html?id=%d"|args:$id target="_dialog"}}
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<p class="alert block">Aucun reçu n'a été trouvé.</p>
|
||||
{{/list}}
|
||||
```
|
||||
|
||||
On peut utiliser le nom des clés du document JSON, mais sinon pour faire référence à la valeur d'une colonne spécifique dans la boucle, il faut utiliser son numéro d'ordre (qui commence à `1`, pas zéro). Ici on veut afficher l'année, donc la seconde colonne, donc `$col1`.
|
||||
|
||||
Noter aussi l'utilisation du numéro de la colonne de l'année (`2`) pour le paramètre `order`, qui avec `select` doit indiquer le numéro de la colonne à utiliser pour l'ordre.
|
||||
|
||||
<!--
|
||||
TODO:
|
||||
## files
|
||||
|
||||
Liste les fichiers du module courant, éventuellement limité à un sous-répertoire designé.
|
||||
|
||||
| Paramètre | Optionnel / obligatoire ? | Fonction |
|
||||
| :- | :- | :- |
|
||||
| `path` | optionnel | Désigne le sous-répertoire éventuel pour limiter la liste. |
|
||||
| `recursive` | optionnel | Booléen. Indique si on veut aussi lister les fichiers dans les sous-répertoires. Défaut : `false`. |
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
<table>
|
||||
{{#files path="facture43" recursive=false}}
|
||||
<tr>
|
||||
<td>{{if $is_dir}}Répertoire{{else}}{{$mime}}{{/if}}</td>
|
||||
<td>{{$name}}</td>
|
||||
<td>{{$size|size_in_bytes}}</td>
|
||||
</tr>
|
||||
{{/files}}
|
||||
</table>
|
||||
```
|
||||
-->
|
||||
44
doc/admin/keyboard.md
Normal file
44
doc/admin/keyboard.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
Title: Raccourcis claviers dans l'édition de texte — Paheko
|
||||
|
||||
{{{.nav
|
||||
* **[Raccourcis claviers](keyboard.html)**
|
||||
* [Syntaxe MarkDown complète](markdown.html)
|
||||
* [Référence rapide MarkDown](markdown_quickref.html)
|
||||
}}}
|
||||
|
||||
# Raccourcis clavier
|
||||
|
||||
Depuis l'édition du texte :
|
||||
|
||||
| Raccourci | Action |
|
||||
| :- | :- |
|
||||
| <kbd>Ctrl</kbd> + <kbd>G</kbd> | Mettre en gras |
|
||||
| <kbd>Ctrl</kbd> + <kbd>I</kbd> | Mettre en italique |
|
||||
| <kbd>Ctrl</kbd> + <kbd>T</kbd> | Mettre en titre |
|
||||
| <kbd>Ctrl</kbd> + <kbd>L</kbd> | Transformer en lien |
|
||||
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>I</kbd> | Insérer une image |
|
||||
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>F</kbd> | Insérer un fichier |
|
||||
| <kbd>Ctrl</kbd> + <kbd>P</kbd> | Prévisualiser |
|
||||
| <kbd>Ctrl</kbd> + <kbd>S</kbd> | Enregistrer |
|
||||
| <kbd>F11</kbd> | Activer ou désactiver l'édition plein écran |
|
||||
| <kbd>F1</kbd> | Afficher l'aide |
|
||||
| <kbd>Echap</kbd> | Prévisualiser (rappuyer pour revenir à l'édition) |
|
||||
|
||||
|
||||
Depuis la prévisualisation :
|
||||
|
||||
| Raccourci | Action |
|
||||
| :- | :- |
|
||||
| <kbd>Ctrl</kbd> + <kbd>P</kbd> | Retour à l'édition |
|
||||
|
||||
Depuis l'aide ou l'insertion de fichier :
|
||||
|
||||
| Raccourci | Action |
|
||||
| :- | :- |
|
||||
| <kbd>Echap</kbd> | Fermer et revenir à l'édition |
|
||||
|
||||
# Ajouter un fichier ou une image
|
||||
|
||||
Il est aussi possible de faire glisser et déposer une image ou un fichier sur le champ d'édition du texte pour l'envoyer et l'insérer.
|
||||
|
||||
De même, il est aussi possible d'utiliser le copier/coller dans le texte pour insérer un fichier ou une image.
|
||||
709
doc/admin/markdown.md
Normal file
709
doc/admin/markdown.md
Normal file
|
|
@ -0,0 +1,709 @@
|
|||
Title: Référence complète MarkDown — Paheko
|
||||
|
||||
{{{.nav
|
||||
* [Raccourcis claviers](keyboard.html)
|
||||
* **[Syntaxe MarkDown complète](markdown.html)**
|
||||
* [Référence rapide MarkDown](markdown_quickref.html)
|
||||
}}}
|
||||
|
||||
<<toc aside>>
|
||||
|
||||
# Syntaxe MarkDown
|
||||
|
||||
Paheko permet d'utiliser la syntaxe [MarkDown](https://fr.wikipedia.org/wiki/Markdown) dans les pages du site web.
|
||||
|
||||
Cette syntaxe est la plus répandue dans les outils d'édition de texte, si vous ne la connaissez pas encore, voici les règles qu'on peut utiliser pour formatter du texte avec MarkDown dans la plupart des outils (dont Paheko), ainsi que [les règles spécifiques supportées par Paheko](#extensions).
|
||||
|
||||
## Styles de texte
|
||||
|
||||
### Italique
|
||||
|
||||
Pour mettre un texte en italique il faut l'entourer de tirets bas ou d'astérisques :
|
||||
|
||||
```
|
||||
Ce texte est en *italique, dingue !*
|
||||
```
|
||||
|
||||
Donnera :
|
||||
|
||||
> Ce texte est en *italique, dingue !*
|
||||
|
||||
### Gras
|
||||
|
||||
Pour le gras, procéder de la même manière, mais avec deux tirets bas ou deux astérisques :
|
||||
|
||||
```
|
||||
Ce texte est **très gras**.
|
||||
```
|
||||
|
||||
> Ce texte est **très gras**.
|
||||
|
||||
### Gras et italique
|
||||
|
||||
Pour combiner, utiliser trois tirets ou trois astérisques :
|
||||
|
||||
```
|
||||
Ce texte est ***gras et italique***.
|
||||
```
|
||||
|
||||
> Ce texte est ***gras et italique***.
|
||||
|
||||
### Barré
|
||||
|
||||
Utiliser un symbole tilde pour barrer un texte :
|
||||
|
||||
```
|
||||
Texte ~~complètement barré~~.
|
||||
```
|
||||
|
||||
> Texte ~~complètement barré~~.
|
||||
|
||||
### Surligné
|
||||
|
||||
Il est possible de marquer une phrase ou un mot comme surligné en l'entourant de deux signes égal :
|
||||
|
||||
```
|
||||
Ce texte est ==surligné==.
|
||||
```
|
||||
|
||||
> Ce texte est ==surligné==.
|
||||
|
||||
|
||||
### Code
|
||||
|
||||
Il est possible d'indiquer du code dans une ligne de texte avec un caractère *backtick* (accent grave en français, obtenu avec les touches [Alt Gr + 7](https://superuser.com/questions/254076/how-do-i-type-the-tick-and-backtick-characters-on-windows)) :
|
||||
|
||||
```
|
||||
Le code `<html>` c'est rigolo !
|
||||
```
|
||||
|
||||
> Le code `<html>` c'est rigolo !
|
||||
|
||||
### Avertissement sur les styles de texte
|
||||
|
||||
Un style de texte ne s'applique que dans un même paragraphe, il n'est pas possible d'appliquer un style sur plusieurs paragraphes :
|
||||
|
||||
Dans l'exemple suivant, les astérisques ne seront pas remplacées par du gras, elles resteront telles quelles :
|
||||
|
||||
```
|
||||
Ce texte n'est pas très **gras.
|
||||
|
||||
Et celui-ci encore moins**.
|
||||
```
|
||||
|
||||
> Ce texte n'est pas très **gras.
|
||||
>
|
||||
> Et celui-ci encore moins**.
|
||||
|
||||
## Liens
|
||||
|
||||
Créez un lien en mettant le texte désiré entre crochets et le lien associé entre parenthèses :
|
||||
|
||||
```
|
||||
Je connais un super gestionnaire [d'association](https://paheko.cloud/) !
|
||||
```
|
||||
|
||||
Donne :
|
||||
|
||||
> Je connais un super gestionnaire [d'association](https://paheko.cloud/) !
|
||||
|
||||
Il est possible de faire un lien vers une autre page du site web en utilisant son adresse unique :
|
||||
|
||||
```
|
||||
N'oubliez pas de [vous inscrire à notre atelier](atelier-soudure).
|
||||
```
|
||||
|
||||
Il est aussi possible de simplement inclure une adresse URL et elle sera automatiquement transformée en lien :
|
||||
|
||||
```
|
||||
https://paheko.cloud/
|
||||
```
|
||||
|
||||
## Blocs
|
||||
|
||||
### Paragraphes et retours à la ligne
|
||||
|
||||
Une ligne vide indique un changement de paragraphe :
|
||||
|
||||
```
|
||||
Ceci est un paragraphe.
|
||||
|
||||
Ceci est est un autre.
|
||||
```
|
||||
|
||||
Un retour à la ligne simple est traité comme tel :
|
||||
|
||||
```
|
||||
Ceci est un
|
||||
paragraphe.
|
||||
```
|
||||
|
||||
> Ceci est un
|
||||
> paragraphe.
|
||||
|
||||
### Titres et sous-titres
|
||||
|
||||
Pour faire un titre, vous devez mettre un ou plusieurs caractères *hash* (`#`) au début de la ligne.
|
||||
|
||||
Un titre avec un seul caractère est un titre principal (niveau 1), avec deux caractères c'est un sous-titre (niveau 2), etc. jusqu'au niveau 6.
|
||||
|
||||
```
|
||||
# Titre principal (niveau 1)
|
||||
## Sous-titre (niveau 2)
|
||||
### Sous-sous-titre (niveau 3)
|
||||
#### Niveau 4
|
||||
##### Niveau 5
|
||||
###### Dernier niveau de sous-titre (6)
|
||||
```
|
||||
|
||||
Donnera :
|
||||
|
||||
> # Titre principal (niveau 1) {.no_toc}
|
||||
> ## Sous-titre (niveau 2) {.no_toc}
|
||||
> ### Sous-sous-titre (niveau 3) {.no_toc}
|
||||
> #### Niveau 4 {.no_toc}
|
||||
> ##### Niveau 5 {.no_toc}
|
||||
> ###### Dernier niveau de sous-titre (6) {.no_toc}
|
||||
|
||||
|
||||
### Listes
|
||||
|
||||
Vous pouvez créer des listes avec les caractères astérisque (`*`) et tiret `-` en début de ligne pour des listes non ordonnées :
|
||||
|
||||
```
|
||||
* une élément
|
||||
* un autre
|
||||
- un sous élément
|
||||
- un autre sous élément
|
||||
* un dernier élément
|
||||
```
|
||||
|
||||
> * une élément
|
||||
> * un autre
|
||||
> - un sous élément
|
||||
> - un autre sous élément
|
||||
> * un dernier élément
|
||||
|
||||
Ou avec des nombres pour des listes ordonnées :
|
||||
|
||||
```
|
||||
1. élément un
|
||||
2. élément deux
|
||||
```
|
||||
|
||||
> 1. élément un
|
||||
> 2. élément deux
|
||||
|
||||
L'ordre des nombres n'est pas important, seul le premier nombre est utilisé pour déterminer à quel numéro commencer la liste.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
3. A
|
||||
5. B
|
||||
4. C
|
||||
```
|
||||
|
||||
> 3. A
|
||||
> 5. B
|
||||
> 4. C
|
||||
|
||||
Il est ainsi possible d'utiliser uniquement le même numéro pour ne pas avoir à numéroter sa liste :
|
||||
|
||||
```
|
||||
1. Un
|
||||
1. Deux
|
||||
```
|
||||
|
||||
> 1. Un
|
||||
> 1. Deux
|
||||
|
||||
### Citations
|
||||
|
||||
Les citations se font en ajoutant le signe *supérieur à* (`>`) au début de la ligne :
|
||||
|
||||
```
|
||||
> Programming is not a science. Programming is a craft.
|
||||
```
|
||||
|
||||
> Programming is not a science. Programming is a craft.
|
||||
|
||||
### Code
|
||||
|
||||
Créez un bloc de code en indentant chaque ligne avec quatre espaces, ou en mettant trois accents graves ``` ` ``` (*backtick*, obtenu avec [Alt Gr + 7](https://superuser.com/questions/254076/how-do-i-type-the-tick-and-backtick-characters-on-windows)) sur la ligne au dessus et en dessous de votre code:
|
||||
|
||||
```
|
||||
<html>...</html>
|
||||
```
|
||||
|
||||
Résultat :
|
||||
|
||||
```
|
||||
<html>...</html>
|
||||
```
|
||||
|
||||
### Tableaux
|
||||
|
||||
Pour créer un tableau vous devez séparer les colonnes avec des barres verticales (`|`, obtenu avec les touches [AltGr + 6](https://fr.wikipedia.org/wiki/Barre_verticale#Saisie)).
|
||||
|
||||
La première ligne contient les noms des colonnes, la seconde ligne contient la ligne de séparation (chaque cellule doit contenir un ou plusieurs tirets), et les lignes suivantes représentent le contenu du tableau.
|
||||
|
||||
```
|
||||
| Colonne 1 | Colonne 2 |
|
||||
| - | - | - |
|
||||
| AB | CD |
|
||||
```
|
||||
|
||||
| Colonne 1 | Colonne 2 |
|
||||
| - | - |
|
||||
| AB | CD |
|
||||
|
||||
Par défaut les colonnes sont centrées. On peut aussi aligner le texte à gauche ou à droite en mettant deux points après le ou les tirets de la ligne suivant l'entête :
|
||||
|
||||
```
|
||||
| Aligné à gauche | Centré | Aligné à droite |
|
||||
| :--------------- |:---------------:| :--------------:|
|
||||
| Aligné à gauche | ce texte | Aligné à droite |
|
||||
| Aligné à gauche | est | Aligné à droite |
|
||||
| Aligné à gauche | centré | Aligné à droite |
|
||||
```
|
||||
|
||||
| Aligné à gauche | Centré | Aligné à droite |
|
||||
| :--------------- |:---------------:| :--------------:|
|
||||
| Aligné à gauche | ce texte | Aligné à droite |
|
||||
| Aligné à gauche | est | Aligné à droite |
|
||||
| Aligné à gauche | centré | Aligné à droite |
|
||||
|
||||
### Ligne de séparation
|
||||
|
||||
Il suffit de mettre au moins 3 tirets à la suite sur une ligne séparée pour ajouter une ligne de séparation :
|
||||
|
||||
```
|
||||
---
|
||||
```
|
||||
|
||||
Résultat :
|
||||
|
||||
---
|
||||
|
||||
### Commentaires
|
||||
|
||||
Pour ajouter un commentaire qui ne sera pas affiché dans le texte, utiliser la syntaxe suivante :
|
||||
|
||||
```
|
||||
<!-- Ceci est un commentaire -->
|
||||
```
|
||||
|
||||
## Notes de bas de page
|
||||
|
||||
Pour créer une note de base de page, il faut mettre entre crochets un signe circonflexe (obtenu en appuyant sur la touche circonflexe, puis sur espace) suivi du numéro ou du nom de la note. Enfin, à la fin du texte il faudra répéter les crochets, le signe circonflexe, suivi de deux points et de la définition.
|
||||
|
||||
```
|
||||
Texte très intéressant[^1]. Approuvé par 100% des utilisateurs[^Source].
|
||||
|
||||
[^1]: Ceci est une note de bas de page
|
||||
[^Source]: Enquête Paheko sur la base de 1 personne interrogée.
|
||||
```
|
||||
|
||||
Donnera ceci :
|
||||
|
||||
> Texte très intéressant[^1]. Approuvé par 100% des utilisateurs[^Source].
|
||||
>
|
||||
> [^1]: Ceci est une note de bas de page
|
||||
> [^Source]: Enquête Paheko sur la base de 1 personne interrogée.
|
||||
|
||||
|
||||
## Insertion de vidéos depuis un service de vidéo
|
||||
|
||||
Certains services vidéo comme les instances Peertube permettent l'intégration des vidéos.
|
||||
|
||||
Pour cela il faut recopier le code d'intégration donné par le service vidéo. Voici un exemple :
|
||||
|
||||
```
|
||||
<iframe title="ENQUÊTE : Brûler la Forêt pour Sauver le Climat ? | EP 3 - Le bois énergie" width="560" height="315" src="https://peertube.stream/videos/embed/12c52265-e3b3-4bad-93f3-f2c1df5bbe4f" frameborder="0" allowfullscreen="" sandbox="allow-same-origin allow-scripts allow-popups"></iframe>
|
||||
```
|
||||
|
||||
Résultat :
|
||||
|
||||
<iframe title="ENQUÊTE : Brûler la Forêt pour Sauver le Climat ? | EP 3 - Le bois énergie" width="560" height="315" src="https://peertube.stream/videos/embed/12c52265-e3b3-4bad-93f3-f2c1df5bbe4f" frameborder="0" allowfullscreen="" sandbox="allow-same-origin allow-scripts allow-popups"></iframe>
|
||||
|
||||
## Identifiant et classe CSS sur les titres
|
||||
|
||||
Il est possible de spécifier l'ID et la classe CSS d'un titre en les rajoutant à la fin du titre, entre accolades, comme ceci :
|
||||
|
||||
```
|
||||
## Titre de niveau 2 {#titre2} {.text-center}
|
||||
```
|
||||
|
||||
Le code HTML résultant sera comme ceci :
|
||||
|
||||
```
|
||||
<h2 id="titre2" class="text-center">Titre de niveau 2</h2>
|
||||
```
|
||||
|
||||
## Classes CSS
|
||||
|
||||
Il est possible de donner une classe CSS parente à un ensemble d'éléments en les mettant au centre d'un bloc définissant cette classe :
|
||||
|
||||
```
|
||||
{{{.custom-quote .custom-block
|
||||
|
||||
Paragraphe
|
||||
|
||||
> Citation
|
||||
}}}
|
||||
```
|
||||
|
||||
Créera le code HTML suivant :
|
||||
|
||||
```
|
||||
<div class="custom-quote custom-block">
|
||||
|
||||
<p>Paragraphe</p>
|
||||
|
||||
<blockquote><p>Citation</p></blockquote>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Tags HTML
|
||||
|
||||
Certains tags HTML sont autorisés :
|
||||
|
||||
| Tag | Utilisation | Exemple |
|
||||
| :- | :- | :- |
|
||||
| `<kbd>` | Touches de clavier | <kbd>Ctrl</kbd> + <kbd>B</kbd> |
|
||||
| `<samp>` | Exemple de programme en console | <samp>bohwaz@platypus ~ % sudo apt install paheko</samp> |
|
||||
| `<var>` | Variable dans un programme informatique | <var>ab</var> + <var>cd</var> = 42 |
|
||||
| `<del>` | Texte supprimé | Texte <del>supprimé</del> |
|
||||
| `<ins>` | Texte ajouté | Texte <ins>ajouté</ins> |
|
||||
| `<sup>` | Texte en exposant | Texte<sup>exposant</sup> |
|
||||
| `<sub>` | Texte en indice | Texte<sub>indice</sub> |
|
||||
| `<mark>` | Texte surligné | Texte <mark>surligné</mark> |
|
||||
| `<audio>` | Insérer un lecteur audio dans la page | `<audio src="mon_fichier.mp3">` |
|
||||
| `<video>` | Insérer une vidéo dans la page | `<video src="mon_fichier.webm">` |
|
||||
|
||||
Mais leurs possibilités sont limitées, notamment sur les attributs autorisés.
|
||||
|
||||
# Extensions
|
||||
|
||||
Paheko propose des extensions au langage MarkDown, qui n'existent pas dans les autres logiciels utilisant aussi MarkDown.
|
||||
|
||||
Toutes ces extensions se présentent sous la forme d'un code situé entre deux signes **inférieur à** (`<<`) et deux signes **supérieur à** (`>>`), à ne pas confondre avec les guillements français (`«` et `»`).
|
||||
|
||||
## Images jointes
|
||||
|
||||
Il est possible d'intégrer une image jointe à la page web en plaçant le code suivant sur une ligne (sans autre texte) :
|
||||
|
||||
```
|
||||
<<image|Nom_fichier.jpg|Alignement|Légende>>
|
||||
```
|
||||
|
||||
* `Nom_fichier.jpg` : remplacer par le nom du fichier de l'image (parmi les images jointes à la page)
|
||||
* `Alignement` : remplacer par l'alignement :
|
||||
* `gauche` ou `left` : l'image sera placée à gauche en petit (200 pixels), le texte remplira l'espace laissé sur la droite de l'image ;
|
||||
* `droite` ou `right` : l'image sera placée à droite en petit, le texte remplira l'espace laissé sur la gauche de l'image ;
|
||||
* `centre` ou `center` : l'image sera placée au centre en taille moyenne (500 pixels), le texte sera placé au dessus et en dessous.
|
||||
* Légende : indiquer ici une courte description de l'image.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
<<image|mon_image.png|center|Ceci est une belle image>>
|
||||
```
|
||||
|
||||
Il est aussi possible d'utiliser la syntaxe avec des paramètres nommés :
|
||||
|
||||
```
|
||||
<<image file="Nom_fichier.jpg" align="center" caption="Légende">>
|
||||
```
|
||||
|
||||
Les images qui ne sont pas mentionnées dans le texte seront affichées après le texte sous forme de galerie.
|
||||
|
||||
## Galerie d'images
|
||||
|
||||
Il est possible d'afficher une galerie d'images (sous forme d'images miniatures) avec la balise `<<gallery` qui contient la liste des images à mettre dans la galerie :
|
||||
|
||||
```
|
||||
<<gallery
|
||||
Nom_fichier.jpg
|
||||
Nom_fichier_2.jpg
|
||||
>>
|
||||
```
|
||||
|
||||
Si aucun nom de fichier n'est indiqué, alors toutes les images jointes à la page seront affichées :
|
||||
|
||||
```
|
||||
<<gallery>>
|
||||
```
|
||||
|
||||
### Diaporama d'images
|
||||
|
||||
On peut également afficher cette galerie sous forme de diaporama. Dans ce cas une seule image est affichée, et on peut passer de l'une à l'autre.
|
||||
|
||||
La syntaxe est la même, mais on ajoute le mot `slideshow` après le mot `gallery` :
|
||||
|
||||
```
|
||||
<<gallery slideshow
|
||||
Nom_fichier.jpg
|
||||
Nom_fichier_2.jpg
|
||||
>>
|
||||
```
|
||||
|
||||
## Fichiers joints
|
||||
|
||||
Pour créer un bouton permettant de voir ou télécharger un fichier joint à la page web, il suffit d'utiliser la syntaxe suivante :
|
||||
|
||||
```
|
||||
<<file|Nom_fichier.ext|Libellé>>
|
||||
```
|
||||
|
||||
* `Nom_fichier.ext` : remplacer par le nom du fichier (parmi les fichiers joints à la page)
|
||||
* `Libellé` : indique le libellé du qui sera affiché sur le bouton, si aucun libellé n'est indiqué alors c'est le nom du fichier qui sera affiché
|
||||
|
||||
## Vidéos
|
||||
|
||||
Pour inclure un lecteur vidéo dans la page web à partir d'un fichier vidéo joint à la page, il faut utiliser le code suivant :
|
||||
|
||||
```
|
||||
<<video|Nom_du_fichier.ext>>
|
||||
```
|
||||
|
||||
On peut aussi spécifier d'autres paramètres :
|
||||
|
||||
* `file` : nom du fichier vidéo
|
||||
* `poster` : nom de fichier d'une image utilisée pour remplacer la vidéo avant qu'elle ne soit lue
|
||||
* `subtitles` : nom d'un fichier de sous-titres au format VTT ou SRT
|
||||
* `width` : largeur de la vidéo (en pixels)
|
||||
* `height` : hauteur de la vidéo (en pixels)
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
<<video file="Ma_video.webm" poster="Ma_video_poster.jpg" width="640" height="360" subtitles="Ma_video_sous_titres.vtt">>
|
||||
```
|
||||
|
||||
## Sommaire / table des matières automatique
|
||||
|
||||
Il est possible de placer le code `<<toc>>` pour générer un sommaire automatiquement à partir des titres et sous-titres :
|
||||
|
||||
```
|
||||
<<toc>>
|
||||
```
|
||||
|
||||
Affichera un sommaire comme celui-ci :
|
||||
|
||||
<<toc>>
|
||||
|
||||
Il est possible de limiter les niveaux en utilisant le paramètre `level` comme ceci :
|
||||
|
||||
```
|
||||
<<toc level=1>>
|
||||
```
|
||||
|
||||
N'affichera que les titres de niveau 1 (précédés d'un seul signe hash `#`), comme ceci :
|
||||
|
||||
<<toc level=1>>
|
||||
|
||||
Enfin il est possible de placer la table des matières sur le côté du texte, en utilisant le paramètre `aside` :
|
||||
|
||||
```
|
||||
<<toc level=1 aside>>
|
||||
```
|
||||
|
||||
Note : en plus de la syntaxe `<<toc>>`, Paheko supporte aussi les syntaxes suivantes par compatibilité avec [les autres moteurs de rendu MarkDown](https://alexharv074.github.io/2018/08/28/auto-generating-markdown-tables-of-contents.html) : `{:toc}` `[[_TOC_]]` `[toc]`.
|
||||
|
||||
### Exclure un sous-titre du sommaire
|
||||
|
||||
Il est aussi possible d'indiquer qu'un titre ne doit pas être inclus dans le sommaire en utilisant la classe `no_toc` comme ceci :
|
||||
|
||||
```
|
||||
## Sous-titre non-inclus {.no_toc}
|
||||
```
|
||||
|
||||
## Grilles et colonnes
|
||||
|
||||
Pour une mise en page plus avancée, il est possible d'utiliser les *grilles*, adaptation des [grids en CSS](https://developer.mozilla.org/fr/docs/Web/CSS/CSS_Grid_Layout). Il faut utiliser la syntaxe `<<grid>>...Contenu...<</grid>>`.
|
||||
|
||||
Attention, les blocs `<<grid>>` et `<</grid>>` doivent obligatoirement être placés sur des lignes qui ne contiennent rien d'autre.
|
||||
|
||||
**Note :** sur petit écran (mobile ou tablette) les grilles et colonnes sont désactivées, tout sera affiché dans une seule colonne, comme si les grilles n'étaient pas utilisées.
|
||||
|
||||
Pour spécifier le nombre de colonnes on peut utiliser un raccourci qui *mime* les colonnes, comme ceci :
|
||||
|
||||
```
|
||||
<<grid !!>>
|
||||
```
|
||||
|
||||
Ce code indique qu'on veut créer une grille de 2 colonnes de largeur identique.
|
||||
|
||||
Dans les raccourcis, le point d'exclamation `!` indique une colonne simple, et le hash `#` indique une colonne qui prend le reste de la place selon le nombre de colonnes total.
|
||||
|
||||
D'autres exemples de raccourcis :
|
||||
|
||||
* `!!` : deux colonnes de largeur égale
|
||||
* `!!!` : trois colonnes de largeur égale
|
||||
* `!##` : deux colonnes, la première occupant un tiers de la largeur, la seconde occupant les deux tiers
|
||||
* `!##!` : 4 colonnes, la première occupant un quart de la largeur, la seconde occupant la moitié, la dernière occupant le quart
|
||||
|
||||
Alternativement, pour plus de contrôle, ce bloc accepte les paramètres suivants :
|
||||
|
||||
* `short` : notation courte décrite ci-dessus
|
||||
* `gap` : espacement entre les blocs de la grille
|
||||
* `template` : description CSS complète de la grille (propriété [`grid-template`](https://developer.mozilla.org/fr/docs/Web/CSS/grid-template))
|
||||
|
||||
Après ce premier bloc `<<grid>>` qui définit la forme de la grille, on peut entrer le contenu de la première colonne.
|
||||
|
||||
Pour créer la seconde colonne il faut simplement placer un nouveau bloc `<<grid>>` vide (aucun paramètre) sur une ligne.
|
||||
|
||||
Enfin on termine en fermant la grille avec un block `<</grid>>`. Voici un exemple complet :
|
||||
|
||||
```
|
||||
<<grid !!!>>
|
||||
Col. 1
|
||||
<<grid>>
|
||||
Col. 2
|
||||
<<grid>>
|
||||
Col. 3
|
||||
<</grid>>
|
||||
```
|
||||
|
||||
<<grid short="!!!" debug>>
|
||||
Col. 1
|
||||
<<grid>>
|
||||
Col. 2
|
||||
<<grid>>
|
||||
Col. 3
|
||||
<</grid>>
|
||||
|
||||
Exemple avec 3 colonnes, dont 2 petites et une large :
|
||||
|
||||
```
|
||||
<<grid !##!>>
|
||||
Col. 1
|
||||
<<grid>>
|
||||
Colonne 2 large
|
||||
<<grid>>
|
||||
Col. 3
|
||||
<</grid>>
|
||||
```
|
||||
|
||||
<<grid short="!##!" debug>>
|
||||
Col. 1
|
||||
<<grid>>
|
||||
Colonne 2 large
|
||||
<<grid>>
|
||||
Col. 3
|
||||
<</grid>>
|
||||
|
||||
Il est possible de créer plus de blocs qu'il n'y a de colonnes, cela créera une nouvelle ligne avec le même motif :
|
||||
|
||||
```
|
||||
<<grid !!>>
|
||||
L1 C1
|
||||
<<grid>>
|
||||
L1 C2
|
||||
<<grid>>
|
||||
L2 C1
|
||||
<<grid>>
|
||||
L2 C2
|
||||
<</grid>>
|
||||
```
|
||||
|
||||
<<grid short="!!" debug>>
|
||||
L1 C1
|
||||
<<grid>>
|
||||
L1 C2
|
||||
<<grid>>
|
||||
L2 C1
|
||||
<<grid>>
|
||||
L2 C2
|
||||
<</grid>>
|
||||
|
||||
Enfin, il est possible d'utiliser la notation CSS [`grid-row`](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row) et [`grid-column`](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column) pour chaque bloc, permettant de déplacer les blocs, ou de faire en sorte qu'un bloc s'étende sur plusieurs colonnes ou plusieurs lignes. Pour cela il faut utiliser le paramètre `row` ou `column` qui précède le bloc :
|
||||
|
||||
```
|
||||
<<grid short="#!!" column="span 2">>
|
||||
A
|
||||
<<grid row="span 2">>
|
||||
B
|
||||
<<grid>>
|
||||
C
|
||||
<<grid>>
|
||||
D
|
||||
<</grid>>
|
||||
```
|
||||
|
||||
<<grid short="#!!" debug column="span 2">>
|
||||
A
|
||||
<<grid row="span 2">>
|
||||
B
|
||||
<<grid>>
|
||||
C
|
||||
<<grid>>
|
||||
D
|
||||
<</grid>>
|
||||
|
||||
Noter que dans ce cas on doit utiliser la notation `short="…"` pour pouvoir utiliser les autres paramètres.
|
||||
|
||||
Enfin, il est possible d'aligner un bloc verticalement par rapport aux autres en utilisant le paramètre `align` (équivalent de la propriété CSS [`align-self`](https://developer.mozilla.org/en-US/docs/Web/CSS/align-self)).
|
||||
|
||||
|
||||
|
||||
## Alignement du texte
|
||||
|
||||
Il suffit de placer sur une ligne seule le code `<<center>>` pour centrer du texte :
|
||||
|
||||
```
|
||||
<<center>>
|
||||
Texte centré
|
||||
<</center>>
|
||||
```
|
||||
|
||||
On peut procéder de même avec `<<left>>` et `<<right>>` pour aligner à gauche ou à droite.
|
||||
|
||||
## Couleurs
|
||||
|
||||
Comme sur les [Skyblogs](https://decoblog.skyrock.com/), il est possible de mettre en couleur le texte et le fond, et même de créer des dégradés !
|
||||
|
||||
Utiliser la syntaxe `<<color COULEUR>>...texte...<</color>>` pour changer la couleur du texte, ou `<<bgcolor COULEUR>>...texte...<</bgcolor>>` pour la couleur du fond.
|
||||
|
||||
Il est possible d'indiquer plusieurs couleurs, séparées par des espaces, pour créer des dégradés.
|
||||
|
||||
```
|
||||
<<color red>>Rouge !<</color>>
|
||||
<<bgcolor yellow>>Fond jaune pétant !<</bgcolor>>
|
||||
<<color cyan green salmon>>Dégradé de texte !<</color>>
|
||||
<<bgcolor chocolate khaki orange>>Dégradé du fond<</bgcolor>>
|
||||
|
||||
<<bgcolor darkolivegreen darkseagreen >>
|
||||
<<color darkred>>
|
||||
|
||||
## Il est aussi possible de faire des blocs colorés
|
||||
|
||||
Avec des paragraphes
|
||||
|
||||
> Et citations
|
||||
|
||||
<</color>>
|
||||
<</bgcolor>>
|
||||
```
|
||||
|
||||
> <<color red>>Rouge !<</color>>
|
||||
> <<bgcolor yellow>>Fond jaune pétant !<</bgcolor>>
|
||||
> <<color cyan green salmon>>Dégradé de texte !<</color>>
|
||||
> <<bgcolor chocolate khaki orange>>Dégradé du fond<</bgcolor>>
|
||||
>
|
||||
> <<bgcolor greenyellow indianred>>
|
||||
> <<color darkred darkgreen>>
|
||||
> ## Il est aussi possible de faire des blocs colorés {.no_toc}
|
||||
>
|
||||
> Avec des paragraphes
|
||||
>
|
||||
> > Et citations
|
||||
>
|
||||
> <</color>>
|
||||
> <</bgcolor>>
|
||||
|
||||
Il est possible d'utiliser les couleurs avec [leur nom](https://developer.mozilla.org/en-US/docs/Web/CSS/named-color) ou leur code hexadécimal (exemple : `#ff0000` pour rouge).
|
||||
|
||||
**Attention : cette fonctionnalité est rigolote mais doit être utilisé avec parcimonie, en effet cela risque de rendre le texte illisible, notamment pour les personnes daltoniennes.**
|
||||
55
doc/admin/markdown_quickref.md
Normal file
55
doc/admin/markdown_quickref.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
Title: Référence rapide MarkDown — Paheko
|
||||
|
||||
{{{.nav
|
||||
* [Raccourcis claviers](keyboard.html)
|
||||
* [Syntaxe MarkDown complète](markdown.html)
|
||||
* **[Référence rapide MarkDown](markdown_quickref.html)**
|
||||
}}}
|
||||
|
||||
# Référence rapide MarkDown
|
||||
|
||||
|Nom | Syntaxe | Rendu | Notes |
|
||||
| :- | :- | :- | :- |
|
||||
| Italique | `*italique*` | *italique* | |
|
||||
| Gras | `**gras**` | **gras** | |
|
||||
| Gras et italique | `***gras et italique***` | ***gras et italique*** | |
|
||||
| Barré | `~~barré~~` | ~~barré~~ | [^P] |
|
||||
| Surligné | `==surligné==` | ==surligné== | [^P] |
|
||||
| Lien | `[Libellé du lien](adresse)` | [Libellé du lien](https://paheko.cloud/) | |
|
||||
| Titre niveau 1 | `# Titre 1` | <h1>Titre 1</h1> | |
|
||||
| Titre niveau 2 | `## Titre 2` | <h2>Titre 2</h2> | |
|
||||
| Titre niveau 3 | `### Titre 3` | <h3>Titre 3</h3> | |
|
||||
| Titre niveau 4 | `#### Titre 4` | <h4>Titre 4</h4> | |
|
||||
| Titre niveau 5 | `##### Titre 5` | <h5>Titre 5</h5> | |
|
||||
| Titre niveau 6 | `###### Titre 6` | <h6>Titre 6</h6> | |
|
||||
| Liste | <pre><code>\* Liste 1<br>\* Liste 2</code></pre> | <ul><li>Liste 1</li><li>Liste 2</li></ul> | |
|
||||
| Liste imbriquée | <pre><code>\* Liste 1<br> \* Sous-liste 1</code></pre> | <ul><li>Liste 1<ul><li>Sous-liste 1</li></ul></li></ul> | |
|
||||
| Liste numérotée | <pre><code>1. Liste 1<br>2. Liste 2</code></pre> | <ol><li>Liste 1</li><li>Liste 2</li></ol> | |
|
||||
| Code dans du texte | Voir ce <code>\`code\`</code> | Voir ce `code` | |
|
||||
| Bloc de code | <pre><code>\```<br>Bloc de code<br>\```</code></pre> | <pre><code>Bloc de code</code></pre> | |
|
||||
| Citation | <pre><code>> Citation<br>> Citation</code></pre> | <blockquote>Citation<br>Citation</blockquote> | |
|
||||
| Tableau | <pre><code>\| Colonne 1 \| Colonne 2 \|<br>\| - \| - \|<br>\| A \| B \|</code></pre> | <table><thead><tr><th>Colonne 1</th><th>Colonne 2</th></tr></thead><tbody><tr><td>A</td><td>B</td></tr></tbody></table> | |
|
||||
| Ligne horizontale | `----` | <hr /> | |
|
||||
| Référence à une note de bas de page | `[^1]` | [^1] | [^P] |
|
||||
| Définition d'une note de bas de page | <pre><code>\[^1]: Définition</code></pre> | [^1] | [^P] |
|
||||
| Bloc avec classe CSS | <pre><code>{{{.boutons<br />* [Paheko](https://paheko.cloud/)<br />}}}</code></pre> | <div class="boutons"><ul><li><a href="https://paheko.cloud/">Paheko</a></li></ul></div> | [^P] |
|
||||
| Sommaire / table des matières | `<<toc>>` | *(ne peut être montré sur cette page)* | [^P] |
|
||||
| Image jointe | `<<image|nom_image.jpg|center|Légende>>` | *(ne peut être montré sur cette page)* | [^P] |
|
||||
| Fichier joint | `<<file|nom_fichier.pdf|Libellé>>` | *(ne peut être montré sur cette page)* | [^P] |
|
||||
| Grille à 2 colonnes | <pre><code>\<<grid !!>><br>Colonne 1<br><br>\<<grid>><br>Colonne 2<br><br>\<</grid>></code></pre> | *(ne peut être montré sur cette page)* | [^P] |
|
||||
| Texte centré | `<<center>>Centre<</center>>` | <div style="text-align: center;">Centre</div> | [^P] |
|
||||
| Texte aligné à droite | `<<right>>Droite<</right>>` | <div style="text-align: right;">Droite</div> | [^P] |
|
||||
| Texte coloré | `<<color red>>Rouge<</color>>` | <<color red>>Rouge<</color>> | [^P] |
|
||||
| Fond coloré | `<<bgcolor green>>Vert<</color>>` | <<bgcolor green>>Vert<</color>> | [^P] |
|
||||
| Dégradé de texte | `<<color orange cyan>>Orange à cyan<</color>>` | <<color orange cyan>>Orange à cyan<</color>> | [^P] |
|
||||
| Dégradé de fond | `<<bgcolor orange cyan>>Orange à cyan<</color>>` | <<bgcolor orange cyan>>Orange à cyan<</color>> | [^P] |
|
||||
| Clavier | `<kbd>Ctrl</kbd> + <kbd>C</kbd>` | <kbd>Ctrl</kbd> + <kbd>C</kbd> | |
|
||||
| Exemple console | `<samp>Exemple</samp>` | <samp>Exemple</samp> | |
|
||||
| Variable maths | `<var>ab</var> + <var>cd</var> = 42` | <var>ab</var> + <var>cd</var> = 42 | |
|
||||
| Texte supprimé | `<del>supprimé</del>` | <del>supprimé</del> | |
|
||||
| Texte ajouté | `<ins>ajouté</ins>` | <ins>ajouté</ins> | |
|
||||
| Exposant | `Texte<sup>exposant</sup>` | Texte<sup>exposant</sup> | |
|
||||
| Indice | `Texte<sub>indice</sub>` | Texte<sub>indice</sub> | |
|
||||
|
||||
[^1]: Exemple de note de bas de page
|
||||
[^P]: Indique une syntaxe qui ne fait pas partie du standard Markdown, mais est spécifique à Paheko.
|
||||
338
doc/admin/modules.md
Normal file
338
doc/admin/modules.md
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
Title: Développer des modules pour Paheko
|
||||
|
||||
{{{.nav
|
||||
* **[Modules](modules.html)**
|
||||
* [Documentation Brindille](brindille.html)
|
||||
* [Fonctions](brindille_functions.html)
|
||||
* [Sections](brindille_sections.html)
|
||||
* [Filtres](brindille_modifiers.html)
|
||||
}}}
|
||||
|
||||
<<toc aside>>
|
||||
|
||||
# Introduction
|
||||
|
||||
Depuis la version 1.3, Paheko dispose d'extensions modifiables, nommées **Modules**.
|
||||
|
||||
Les modules permettent de créer et modifier des formulaires, des modèles de documents simples, à imprimer, mais aussi de créer des "mini-applications" directement dans l'administration de l'association, avec le minimum de code, sans avoir à apprendre à programmer PHP.
|
||||
|
||||
Les modules utilisent le langage [Brindille](brindille.html), aussi utilisé pour le site web (qui est lui-même un module). Avec Brindille on parle d'un **squelette** pour un fichier texte contenant du code Brindille.
|
||||
|
||||
Les modules ne permettent pas d'exécuter du code PHP, ni de modifier la base de données en dehors des données du module, contrairement aux [plugins](https://fossil.kd2.org/paheko/wiki?name=Documentation/Plugin&p). Grâce à Brindille, les administrateurs de l'association peuvent modifier ou créer de nouveaux modules sans risques pour le serveur, car le code Brindille ne permet pas d'exécuter de fonctions dangereuses. Les **plugins** eux sont écrits en PHP et ne peuvent pas être modifiés par une association. Du fait des risques de sécurité, seuls les plugins officiels sont proposés sur Paheko.cloud.
|
||||
|
||||
# Exemples
|
||||
|
||||
Paheko fournit quelques modules par défaut, qui peuvent être modifiés ou servir d'inspiration pour de nouveaux modules :
|
||||
|
||||
* Reçu de don simple
|
||||
* Reçu de paiement simple
|
||||
* Reçu fiscal
|
||||
* Cartes de membres
|
||||
* Heures d'ouverture
|
||||
* Modèles d'écritures comptables
|
||||
|
||||
Ces exemples sont développés directement avec Brindille et peuvent être modifiés ou lus depuis le menu **Configuration**, onglet **Extensions**.
|
||||
|
||||
Un module fourni dans Paheko peut être modifié, et en cas de problème il peut être remis à son état d'origine.
|
||||
|
||||
D'autres exemples d'utilisation sont imaginables :
|
||||
|
||||
* Auto-remplissage de la déclaration de la liste des dirigeants à la préfecture
|
||||
* Compte de résultat et bilan conforme au modèle du plan comptable
|
||||
* Formulaires partagés entre la partie privée, et le site web (voir par exemple le module "heures d'ouverture")
|
||||
* Gestion de matériel prêté par l'association
|
||||
|
||||
# Pré-requis
|
||||
|
||||
Une connaissance de la programmation informatique est souhaitable pour commencer à modifier ou créer des modules, mais cela n'est pas requis, il est possible d'apprendre progressivement.
|
||||
|
||||
# Résumé technique
|
||||
|
||||
* Utilisation de la syntaxe Brindille
|
||||
* Les modules peuvent utiliser toutes les fonctions et boucles de Brindille
|
||||
* Les modules peuvent stocker et récupérer des données dans la base SQLite dans une table clé-valeur spécifique à chaque module
|
||||
* Les données du module sont stockées en JSON, on peut faire des requêtes complètes avec l'extension [JSON de SQLite](https://www.sqlite.org/json1.html)
|
||||
* Les données peuvent être validées avant enregistrement en utilisant [JSON Schema](https://json-schema.org/understanding-json-schema/)
|
||||
* Un module peut également accéder aux données des autres modules
|
||||
* Un module peut aussi accéder à toutes les données de la base de données, sauf certaines données à risque (voir plus bas)
|
||||
* Un module ne peut pas modifier les données de la base de données
|
||||
* Paheko crée automatiquement des index sur les requêtes SQL des modules, permettant de rendre les requêtes rapides
|
||||
|
||||
# Structure des répertoires
|
||||
|
||||
Chaque module a un nom unique (composé uniquement de lettres minuscules, de tirets bas et de chiffres) et dispose d'un sous-répertoire dans le dossier `modules`. Ainsi le module `recu_don` serait dans le répertoire `modules/recu_don`.
|
||||
|
||||
Dans ce répertoire le module peut avoir autant de fichiers qu'il veut, mais certains fichiers ont une fonction spéciale :
|
||||
|
||||
* `module.ini` : contient les informations sur le module, voir ci-dessous pour les détails
|
||||
* `config.html` : si ce squelette existe, un bouton "Configurer" apparaîtra dans la liste des modules (Configuration -> Modules) et affichera ce squelette dans un dialogue
|
||||
* `icon.svg` : icône du module, qui sera utilisée sur la page d'accueil, si le bouton est activé, et dans la liste des modules. Attention l'élément racine du fichier doit porter l'id `img` pour que l'icône fonctionne (`<svg id="img"...>`), notamment pour que les couleurs du thème s'appliquent à l'icône.
|
||||
* `README.md` : si ce fichier existe, son contenu sera affiché dans les détails du module
|
||||
|
||||
## Snippets
|
||||
|
||||
Les modules peuvent également avoir des `snippets`, ce sont des squelettes qui seront inclus à des endroits précis de l'interface, permettant de rajouter des fonctionnalités, ils sont situés dans le sous-répertoire `snippets` du module :
|
||||
|
||||
* `snippets/transaction_details.html` : sera inclus en dessous de la fiche d'une écriture comptable
|
||||
* `snippets/transaction_new.html` : sera inclus au début du formulaire de saisie d'écriture
|
||||
* `snippets/user_details.html` : sera inclus en dessous de la fiche d'un membre
|
||||
* `snippets/my_details.html` : sera inclus en dessous de la page "Mes informations personnelles"
|
||||
* `snippets/my_services.html` : sera inclus en dessous de la page "Mes inscriptions et cotisations"
|
||||
* `snippets/home_button.html` : sera inclus dans la liste des boutons de la page d'accueil (ce fichier ne sera pas appelé si `home_button` est à `true` dans `module.ini`, il le remplace)
|
||||
|
||||
### Snippets MarkDown
|
||||
|
||||
Il est également possible, depuis Paheko 1.3.2, d'étendre les fonctionnalités Markdown du site web en créant un snippet dans le répertoire `snippets/markdown/`, par exemple `snippets/markdown/map.html`.
|
||||
|
||||
Le snippet sera appelé quand on utilise le tag du même nom dans le contenu du site web. Ici par exemple ça serait `<<map>>`.
|
||||
|
||||
Le nom du snippet doit commencer par une lettre minuscule et peut être suivi de lettres minuscules, de chiffres, ou de tirets bas. Exemples : `map2024` `map_openstreetmap`, etc.
|
||||
|
||||
Le snippet reçoit ces variables :
|
||||
|
||||
* `$params` : les paramètres du tag
|
||||
* `$block` : booléen, `TRUE` si le tag est seul sur une ligne, ou `FALSE` s'il se situe à l'intérieur d'un texte
|
||||
* `$content` : le contenu du bloc, si celui-ci est sur plusieurs lignes
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
<<map center="Auckland, New Zealand"
|
||||
|
||||
Ceci est la capitale de Nouvelle-Zélande !
|
||||
>>
|
||||
|
||||
Voici un marqueur : <<map marker>>
|
||||
```
|
||||
|
||||
Dans le premier appel, `map.html` recevra ces variables :
|
||||
|
||||
```
|
||||
$params = ['center' => 'Auckland, New Zealand']
|
||||
$content = "Ceci est la capitale de Nouvelle-Zélande !"
|
||||
$block = TRUE
|
||||
```
|
||||
|
||||
Dans le second appel, le snippet recevra celles-ci :
|
||||
|
||||
```
|
||||
$params = [0 => 'marker']
|
||||
$content = NULL
|
||||
$block = FALSE
|
||||
```
|
||||
|
||||
## Fichier module.ini
|
||||
|
||||
Ce fichier décrit le module, au format INI (`clé=valeur`), en utilisant les clés suivantes :
|
||||
|
||||
* `name` (obligatoire) : nom du module
|
||||
* `description` : courte description de la fonctionnalité apportée par le module
|
||||
* `author` : nom de l'auteur
|
||||
* `author_url` : adresse web HTTP menant au site de l'auteur
|
||||
* `home_button` : indique si un bouton pour ce module doit être affiché sur la page d'accueil (`true` ou `false`)
|
||||
* `menu` : indique si ce module doit être listé dans le menu de gauche (`true` ou `false`)
|
||||
* `restrict_section` : indique la section auquel le membre doit avoir accès pour pouvoir voir le menu de ce module, parmi `web, documents, users, accounting, connect, config`
|
||||
* `restrict_level` : indique le niveau d'accès que le membre doit avoir dans la section indiquée pour pouvoir voir le menu de ce module, parmi `read, write, admin`.
|
||||
|
||||
Attention : les directives `restrict_section` et `restrict_level` ne contrôlent *que* l'affichage du lien vers le module dans le menu et dans les boutons de la page d'accueil, mais pas l'accès aux pages du module.
|
||||
|
||||
# Variables spéciales
|
||||
|
||||
Toutes les pages d'un module disposent de la variable `$module` qui contient l'entité du module en cours :
|
||||
|
||||
* `$module.name` contient le nom unique (`recu_don` par exemple)
|
||||
* `$module.label` le libellé du module
|
||||
* `$module.description` la description
|
||||
* `$module.config` la configuration du module
|
||||
* `$module.url` l'adresse URL du module (`https://site-association.tld/m/recu_don/` par exemple)
|
||||
|
||||
# Stockage de données
|
||||
|
||||
Un module peut stocker des données de deux manières : dans sa configuration, ou dans son stockage de documents JSON.
|
||||
|
||||
## Configuration
|
||||
|
||||
La première manière est de stocker des informations dans la configuration du module. Pour cela on utilise la fonction `save` et la clé `config` :
|
||||
|
||||
```
|
||||
{{:save key="config" accounts_list="512A,512B" check_boxes=true}}
|
||||
```
|
||||
|
||||
On pourra retrouver ces valeurs dans la variable `$module.config` :
|
||||
|
||||
```
|
||||
{{if $module.config.check_boxes}}
|
||||
{{$module.config.accounts_list}}
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
## Stockage de documents JSON
|
||||
|
||||
Chaque module peut stocker ses données dans une base de données clé-document qui stockera les données dans des documents au format JSON dans une table SQLite.
|
||||
|
||||
Grâce aux [fonctions JSON de SQLite](https://www.sqlite.org/json1.html) on pourra ensuite effectuer des recherches sur ces documents.
|
||||
|
||||
Pour enregistrer il suffit d'utiliser la fonction `save` :
|
||||
|
||||
```
|
||||
{{:save key="facture001" type="facture" date="2022-01-01" label="Vente de petits pains au chocolat" total="42"}}
|
||||
```
|
||||
|
||||
Si la clé indiquée (dans le paramètre `key`) n'existe pas, l'enregistrement sera créé, sinon il sera mis à jour avec les valeurs données.
|
||||
|
||||
### Validation
|
||||
|
||||
On peut utiliser un [schéma JSON](https://json-schema.org/understanding-json-schema/) pour valider que le document qu'on enregistre est valide :
|
||||
|
||||
```
|
||||
{{:save validate_schema="./document.schema.json" type="facture" date="2022-01-01" label="Vente de petits pains au chocolat" total="42"}}
|
||||
```
|
||||
|
||||
Le fichier `document.schema.json` devra être dans le même répertoire que le squelette et devra contenir un schéma valide. Voici un exemple :
|
||||
|
||||
```
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"date": {
|
||||
"description": "Date d'émission",
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"type": {
|
||||
"description": "Type de document",
|
||||
"type": "string",
|
||||
"enum": ["devis", "facture"]
|
||||
},
|
||||
"total": {
|
||||
"description": "Montant total",
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"label": {
|
||||
"description": "Libellé",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description",
|
||||
"type": ["string", "null"]
|
||||
}
|
||||
},
|
||||
"required": [ "type", "date", "total", "label"]
|
||||
}
|
||||
```
|
||||
|
||||
Si le document fourni n'est pas conforme au schéma, il ne sera pas enregistré et une erreur sera affichée.
|
||||
|
||||
#### Propriété non requise
|
||||
|
||||
Si vous souhaitez utiliser dans votre document une propriété non requise, il ne faut pas la fournir en paramètre de la fonction `save`.
|
||||
|
||||
Si elle est fournie mais vide, il faut aussi autoriser le type `null` (en minuscules) au type de votre propriété.
|
||||
|
||||
Exemple :
|
||||
|
||||
[...]
|
||||
"description": {
|
||||
"description": "Description",
|
||||
"type": ["string", "null"]
|
||||
}
|
||||
[...]
|
||||
|
||||
### Stockage JSON dans SQLite (pour information)
|
||||
|
||||
Explication du fonctionnement technique derrière la fonction `save`.
|
||||
|
||||
En pratique chaque enregistrement sera placé dans une table SQL dont le nom commence par `module_data_`. Ici la table sera donc nommée `module_data_factures` si le nom unique du module est `factures`.
|
||||
|
||||
Le schéma de cette table est le suivant :
|
||||
|
||||
```
|
||||
CREATE TABLE module_data_factures (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
key TEXT NULL,
|
||||
document TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX module_data_factures_key ON module_data_factures (key);
|
||||
```
|
||||
|
||||
Comme on peut le voir, chaque ligne dans la table peut avoir une clé unique (`key`), et un ID ou juste un ID auto-incrémenté. La clé unique n'est pas obligatoire, mais peut être utile pour différencier certains documents.
|
||||
|
||||
Par exemple le code suivant :
|
||||
|
||||
```
|
||||
{{:save key="facture_43" nom="Facture de courses"}}
|
||||
```
|
||||
|
||||
Est l'équivalent de la requête SQL suivante :
|
||||
|
||||
```
|
||||
INSERT OR REPLACE INTO module_data_factures (key, document) VALUES ('facture_43', '{"nom": "Facture de courses"}');
|
||||
```
|
||||
|
||||
### Récupération et liste de documents
|
||||
|
||||
Il sera ensuite possible d'utiliser la boucle `load` pour récupérer les données :
|
||||
|
||||
```
|
||||
{{#load id=42}}
|
||||
Ce document est de type {{$type}} créé le {{$date}}.
|
||||
<h2>{{$label}}</h2>
|
||||
À payer : {{$total}} €
|
||||
{{else}}
|
||||
Le document numéro 42 n'a pas été trouvé.
|
||||
{{/load}}
|
||||
```
|
||||
|
||||
Cette boucle `load` permet aussi de faire des recherches sur les valeurs du document :
|
||||
|
||||
```
|
||||
<ul>
|
||||
{{#load where="$$.type = 'facture'" order="date DESC"}}
|
||||
<li>{{$label}} ({{$total}} €)</li>
|
||||
{{/load}}
|
||||
</ul>
|
||||
```
|
||||
|
||||
La syntaxe `$$.type` indique d'aller extraire la clé `type` du document JSON.
|
||||
|
||||
C'est un raccourci pour la syntaxe SQLite `json_extract(document, '$.type')`.
|
||||
|
||||
# Export et import de modules
|
||||
|
||||
Il est possible d'exporter un module modifié. Cela créera un fichier ZIP contenant à la fois le code modifié et le code non modifié.
|
||||
|
||||
De la même manière il est possible d'importer un module à partir d'un fichier ZIP d'export. Si vous créez votre fichier ZIP manuellement, attention à respecter le fait que le code du module doit se situer dans le répertoire `modules/nom_du_module` du fichier ZIP. Tout fichier ou répertoire situé en dehors de cette arborescence provoquera une erreur et l'impossibilité d'importer le module.
|
||||
|
||||
# Restrictions
|
||||
|
||||
* Il n'est pas possible de télécharger ou envoyer des données depuis un autre serveur
|
||||
* Il n'est pas possible d'écrire un fichier local
|
||||
|
||||
## Envoi d'e-mail
|
||||
|
||||
Voir [la documentation de la fonction `{{:mail}}`](brindille_functions.html#mail)
|
||||
|
||||
## Tables et colonnes de la base de données
|
||||
|
||||
Pour des raisons de sécurité, les modules ne peuvent pas accéder à toutes les données de la base de données.
|
||||
|
||||
Les colonnes suivantes de la table `users` (liste des membres) renverront toujours `NULL` :
|
||||
|
||||
* `password`
|
||||
* `pgp_key`
|
||||
* `otp_secret`
|
||||
|
||||
Tenter de lire les données des tables suivantes résultera également en une erreur :
|
||||
|
||||
* emails
|
||||
* emails_queue
|
||||
* compromised_passwords_cache
|
||||
* compromised_passwords_cache_ranges
|
||||
* api_credentials
|
||||
* plugins_signals
|
||||
* config
|
||||
* users_sessions
|
||||
* logs
|
||||
160
doc/admin/skriv.md
Normal file
160
doc/admin/skriv.md
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
Title: Référence rapide SkrivML - Paheko
|
||||
|
||||
<<toc aside>>
|
||||
|
||||
# Syntaxe SkrivML
|
||||
|
||||
Paheko propose la syntaxe [SkrivML](https://fossil.kd2.org/paheko/doc/trunk/doc/skrivml.html) pour le formatage du texte des pages du site web.
|
||||
|
||||
## Styles de texte
|
||||
|
||||
| Style | Syntaxe |
|
||||
| :- | :- |
|
||||
| *Italique* | `Entourer le texte de ''deux apostrophes''` |
|
||||
| **Gras** | `Entourer le texte de **deux astérisques**` |
|
||||
| Texte <ins>Souligné</ins> | `Entourer le texte de deux __tirets bas__.` |
|
||||
| ~~Barré~~ | `Deux --tirets hauts-- pour barrer.` |
|
||||
| Texte <sup>Exposant</sup> | `XXI^^ème^^ siècle` |
|
||||
| Texte <sub>Indice</sub> | `CO,,2,,` |
|
||||
|
||||
**Attention :** ces styles ne fonctionnent que si le code entoure des mots complets, ça ne fonctionne pas au milieu de mots.
|
||||
|
||||
```
|
||||
Un **mot** en gras. Mais on ne peut pas cou**per** un mot avec du gras.
|
||||
```
|
||||
|
||||
> Un **mot** en gras. Mais on ne peut pas cou\*\*per** un mot avec du gras.
|
||||
|
||||
## Titres
|
||||
|
||||
Doivent être précédé d'un ou plusieurs signe égal. Peuvent aussi être suivi du même nombre de signe égal.
|
||||
|
||||
```
|
||||
= Titre niveau 1
|
||||
== Titre niveau 2
|
||||
=== Titre niveau 3 ===
|
||||
==== Titre de niveau 4 ====
|
||||
```
|
||||
|
||||
## Listes
|
||||
|
||||
Listes non ordonnées :
|
||||
|
||||
```
|
||||
* Item 1
|
||||
* Item 2
|
||||
** Sous-item 2.1
|
||||
** Sous-item 2.2
|
||||
*** Sous-item 2.2.1
|
||||
```
|
||||
|
||||
Listes ordonnées :
|
||||
|
||||
```
|
||||
# Item 1
|
||||
# Item 2
|
||||
## Sub-item 2.1
|
||||
## Sub-item 2.2
|
||||
### Sub-item 2.2.1
|
||||
```
|
||||
|
||||
## Liens
|
||||
|
||||
Lien interne :
|
||||
|
||||
```
|
||||
Voir [[cette page|adresse-unique-autre-page]].
|
||||
```
|
||||
|
||||
Lien externe :
|
||||
|
||||
```
|
||||
[[https://paheko.cloud/]]
|
||||
```
|
||||
## Tableaux
|
||||
|
||||
```
|
||||
!! Colonne 1 !! Colonne 2
|
||||
|| Cellule 1 || Cellule 2
|
||||
|| Cellule 3 || Cellule 4
|
||||
```
|
||||
|
||||
## Autres
|
||||
|
||||
Consulter la documentation complète de [SkrivML](https://fossil.kd2.org/garradin/doc/trunk/doc/skrivml.html).
|
||||
|
||||
# Extensions
|
||||
|
||||
Toutes les extensions se présentent sous la forme d'un code situé entre deux signes **inférieur à** (`<<`) et deux signes **supérieur à** (`>>`), à ne pas confondre avec les guillements français (`«` et `»`).
|
||||
|
||||
## Images jointes
|
||||
|
||||
Il est possible d'intégrer une image jointe à la page web en plaçant le code suivant sur une ligne (sans autre texte) :
|
||||
|
||||
```
|
||||
<<image|Nom_fichier.jpg|Alignement|Légende>>
|
||||
```
|
||||
|
||||
* `Nom_fichier.jpg` : remplacer par le nom du fichier de l'image (parmi les images jointes à la page)
|
||||
* `Alignement` : remplacer par l'alignement :
|
||||
* `gauche` ou `left` : l'image sera placée à gauche en petit (200 pixels), le texte remplira l'espace laissé sur la droite de l'image ;
|
||||
* `droite` ou `right` : l'image sera placée à droite en petit, le texte remplira l'espace laissé sur la gauche de l'image ;
|
||||
* `centre` ou `center` : l'image sera placée au centre en taille moyenne (500 pixels), le texte sera placé au dessus et en dessous.
|
||||
* Légende : indiquer ici une courte description de l'image.
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
<<image|mon_image.png|center|Ceci est une belle image>>
|
||||
```
|
||||
|
||||
Il est aussi possible d'utiliser la syntaxe avec des paramètres nommés :
|
||||
|
||||
```
|
||||
<<image file="Nom_fichier.jpg" align="center" caption="Légende">>
|
||||
```
|
||||
|
||||
Les images qui ne sont pas mentionnées dans le texte seront affichées après le texte sous forme de galerie.
|
||||
|
||||
## Fichiers joints
|
||||
|
||||
Pour créer un bouton permettant de voir ou télécharger un fichier joint à la page web, il suffit d'utiliser la syntaxe suivante :
|
||||
|
||||
```
|
||||
<<file|Nom_fichier.ext|Libellé>>
|
||||
```
|
||||
|
||||
* `Nom_fichier.ext` : remplacer par le nom du fichier (parmi les fichiers joints à la page)
|
||||
* `Libellé` : indique le libellé du qui sera affiché sur le bouton, si aucun libellé n'est indiqué alors c'est le nom du fichier qui sera affiché
|
||||
|
||||
|
||||
# Raccourcis clavier
|
||||
|
||||
Depuis l'édition du texte :
|
||||
|
||||
| Raccourci | Action |
|
||||
| :- | :- |
|
||||
| <kbd>Ctrl</kbd> + <kbd>G</kbd> | Mettre en gras |
|
||||
| <kbd>Ctrl</kbd> + <kbd>I</kbd> | Mettre en italique |
|
||||
| <kbd>Ctrl</kbd> + <kbd>T</kbd> | Mettre en titre |
|
||||
| <kbd>Ctrl</kbd> + <kbd>L</kbd> | Transformer en lien |
|
||||
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>I</kbd> | Insérer une image |
|
||||
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>F</kbd> | Insérer un fichier |
|
||||
| <kbd>Ctrl</kbd> + <kbd>P</kbd> | Prévisualiser |
|
||||
| <kbd>Ctrl</kbd> + <kbd>S</kbd> | Enregistrer |
|
||||
| <kbd>F11</kbd> | Activer ou désactiver l'édition plein écran |
|
||||
| <kbd>F1</kbd> | Afficher l'aide |
|
||||
| <kbd>Echap</kbd> | Prévisualiser (rappuyer pour revenir à l'édition) |
|
||||
|
||||
|
||||
Depuis la prévisualisation :
|
||||
|
||||
| Raccourci | Action |
|
||||
| :- | :- |
|
||||
| <kbd>Ctrl</kbd> + <kbd>P</kbd> | Retour à l'édition |
|
||||
|
||||
Depuis l'aide ou l'insertion de fichier :
|
||||
|
||||
| Raccourci | Action |
|
||||
| :- | :- |
|
||||
| <kbd>Echap</kbd> | Fermer et revenir à l'édition |
|
||||
96
doc/admin/web.md
Normal file
96
doc/admin/web.md
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
Title: Squelettes du site web dans Paheko
|
||||
|
||||
{{{.nav
|
||||
* [Documentation Brindille](brindille.html)
|
||||
* [Fonctions](brindille_functions.html)
|
||||
* [Sections](brindille_sections.html)
|
||||
* [Filtres](brindille_modifiers.html)
|
||||
}}}
|
||||
|
||||
# Les squelettes du site web
|
||||
|
||||
Les squelettes sont un ensemble de fichiers qui permettent de modéliser l'apparence du site web selon ses préférences et besoins.
|
||||
|
||||
La syntaxe utilisée dans les squelettes s'appelle **[Brindille](brindille.html)**. Voir la [documentation de Brindille](brindille.html) pour son fonctionnement.
|
||||
|
||||
# Exemples de sites réalisés avec Paheko
|
||||
|
||||
* [Faidherbe Alumni](https://www.alumni-faidherbe.fr/)
|
||||
* [ASBM Mortagne](https://asbm-mortagne.fr/)
|
||||
* [Vélocité 63](https://www.velocite63.fr/)
|
||||
* [La rustine, Dijon](https://larustine.org/)
|
||||
* [Tauto école](https://tauto-ecole.net/) [(les squelettes sont disponibles ici)](https://gitlab.com/noizette/squelettes-garradin-tauto-ecole/)
|
||||
* [La boîte à vélos](https://boiteavelos.chenove.net/)
|
||||
|
||||
# Fonctionnement des squelettes
|
||||
|
||||
Par défaut sont fournis plusieurs squelettes qui permettent d'avoir un site web basique mais fonctionnel : page d'accueil, menu avec les catégories de premier niveau, et pour afficher les pages, les catégories, les fichiers joints et images. Il y a également un squelette `atom.xml` permettant aux visiteurs d'accéder aux dernières pages publiées.
|
||||
|
||||
Les squelettes peuvent être modifiés via l'onglet **Configuration** de la section **Site web** du menu principal.
|
||||
|
||||
Une fois un squelette modifié, il apparaît dans la liste comme étant modifié, sinon il apparaît comme *défaut*. Si vous avez commis une erreur, il est possible de restaurer le squelette d'origine.
|
||||
|
||||
## Adresses des pages du site
|
||||
|
||||
Les squelettes sont appelés en fonction des règles suivantes (dans l'ordre) :
|
||||
|
||||
| Squelette appelé | Cas où le squelette est appelé |
|
||||
| :---- | :---- |
|
||||
| `adresse` | Si l'adresse `adresse` est appelée, et qu'un squelette du même nom existe |
|
||||
| `adresse/index.html` | Si l'adresse `adresse/` est appelée, et qu'un squelette `index.html` dans le répertoire du même nom existe |
|
||||
| `category.html` | Toute autre adresse se terminant par un slash `/`, si une catégorie du même nom existe |
|
||||
| `article.html` | Toute autre adresse, si une page du même nom existe |
|
||||
| `404.html` | Si aucune règle précédente n'a fonctionné |
|
||||
|
||||
Ainsi l'adresse `https://monsite.paheko.cloud/Actualite/` appellera le squelette `category.html`, mais l'adresse `https://monsite.paheko.cloud/Actualite` (sans slash à la fin) appellera le squelette `article.html` si un article avec l'URI `Actualite` existe. Si un squelette `Actualite` (sans extension) existe, c'est lui qui sera appelé en priorité et ni `category.html` ni `article.html` ne seront appelés.
|
||||
|
||||
Autre exemple : `https://monsite.paheko.cloud/atom.xml` appellera le squelette `atom.xml` s'il existe.
|
||||
|
||||
Ceci vous permet de créer de nouvelles pages dynamiques sur le site, par exemple pour notre atelier vélo nous avons une page `https://larustine.org/velos` qui appelle le squelette `velos` (sans extension), qui va afficher la liste des vélos actuellement en stock dans notre hangar.
|
||||
|
||||
Le type de fichier étant déterminé selon l'extension (`.html, .css, etc.`) pour les fichiers traités par Brindille, un fichier sans extension sera considéré comme un fichier texte par le navigateur. Si on veut que le squelette `velos` (sans extension) s'affiche comme du HTML il faut forcer le type en mettant le code `{{:http type="text/html"}}` au début du squelette (première ligne).
|
||||
|
||||
## Fichier content.css
|
||||
|
||||
Ce fichier est particulier, car il définit le style du contenu des pages et des catégories.
|
||||
|
||||
Ainsi il est également utilisé quand vous éditez un contenu dans l'administration. Donc si vous souhaitez modifier le style d'un élément du texte, il vaux mieux modifier ce fichier, sinon le rendu sera différent entre l'administration et le site public.
|
||||
|
||||
# Cache
|
||||
|
||||
Depuis la version 1.3, Paheko dispose d'un cache statique du site web.
|
||||
|
||||
Cela veut dire que les pages du site web sont enregistrées sous la forme de fichiers HTML statiques, et le serveur web renvoie directement ce fichier sans faire appel à Paheko et son code PHP.
|
||||
|
||||
Les fichiers liés aux pages web sont également mis en cache de cette manière, en utilisant des liens symboliques.
|
||||
|
||||
Ce cache permet d'avoir un site web très rapide, même s'il reçoit des millions de visites.
|
||||
|
||||
## Désactiver le cache
|
||||
|
||||
Le seul inconvénient c'est qu'une page mise en cache étant statique, si vous utilisez du contenu dynamique (par exemple afficher un texte différent selon la langue du visiteur) dans le squelette Brindille, alors cela ne fonctionnera plus.
|
||||
|
||||
Dans ce cas-là, vous pouvez assigner la variable `nocache` dans le squelette pour désactiver le cache pour cette page :
|
||||
|
||||
```
|
||||
{{:assign nocache=true}}
|
||||
```
|
||||
|
||||
Pour permettre des usages du type "affichage en temps presque réel des horaires d'ouverture", le cache d'une page HTML est effacé et remis à jour au bout d'une heure.
|
||||
|
||||
## Exceptions
|
||||
|
||||
Il est à noter que le cache n'est pas appelé dans les cas suivants :
|
||||
|
||||
* si la requête vers la page est d'un autre type que `GET` ou `HEAD`, ainsi par exemple l'envoi d'un formulaire (`POST`) ne sera jamais mis en cache ;
|
||||
* si la requête vers la page contient des paramètres dans l'adresse (par exemple `velos.html?list=1` : cette page ne sera pas mise en cache) ;
|
||||
* si le visiteur est connecté à l'administration de l'association. Ainsi si vous avez des parties du squelette qui varient en fonction de si la personne est connectée, le cache ne posera pas de problème.
|
||||
|
||||
Le cache est intégralement effacé à chaque modification du site web.
|
||||
|
||||
Le cache ne concerne que les pages et fichiers du site web public. Il ne concerne pas les modules, les extensions, ou l'administration.
|
||||
|
||||
Attention :
|
||||
|
||||
* avec un serveur sous Windows, le cache est désactivé car Windows ne sait pas gérer les liens symboliques ;
|
||||
* seul Apache sait gérer le cache statique, le cache est désactivé avec les autres serveurs web (nginx, etc.).
|
||||
BIN
doc/icon.png
Normal file
BIN
doc/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 522 B |
213
doc/index.md
Normal file
213
doc/index.md
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
# La gestion d'association libre et simple
|
||||
|
||||
<div id="prez">
|
||||
<figure>
|
||||
<img src="./selfhost2.png" alt="Illustration d'une personne aidant une autre à installer Paheko sur un ordinateur" />
|
||||
</figure>
|
||||
|
||||
### Paheko — la gestion d'association simple</h3>
|
||||
|
||||
**Paheko** <small>(anciennement appelé *Garradin*)</small> signifie *coopérer* en *Māori*. C'est un logiciel de gestion d'association, libre, simple et efficace, développé depuis 2012. Son but est de :
|
||||
|
||||
* **réduire le temps** passé sur les tâches administratives ;
|
||||
* re-**donner de l'autonomie aux adhérent⋅e⋅s** dans la gestion de leurs données ;
|
||||
* **simplifier la gestion administrative** de l'association, pour inciter à y participer ;
|
||||
* **minimiser le nombre de logiciels à installer et maintenir** en intégrant les outils habituels.
|
||||
|
||||
Pour en savoir plus : [voir les principales fonctionnalités](#features).
|
||||
</div>
|
||||
|
||||
<div id="warn">
|
||||
<p><strong>Attention : ce site est dédié au logiciel libre Paheko.</strong><br />
|
||||
Son installation, sur un serveur ou sur un ordinateur personnel, nécessite quelques compétences techniques.</p>
|
||||
<p>Si votre association n'a pas ces compétences, nous recommandons l'utilisation de notre service d'hébergement :<br /><strong class="cloud"><a href="https://paheko.cloud/" target="_blank"><img src="./icon.png" alt="" /> Paheko.cloud</a></strong>
|
||||
<small>(<strong>Essai gratuit</strong>, puis contribution à prix libre, à partir de 5 € par an)</small>
|
||||
</div>
|
||||
<nav id="gnav">
|
||||
|
||||
* [Guides d'installation](wiki:Installation)
|
||||
* [Documentation](wiki:Documentation)
|
||||
* [Entraide](wiki:Entraide)
|
||||
* <a href="https://paheko.cloud/" target="_blank">Essayer gratuitement sur <b><img src="./icon.png" alt="" /> Paheko.cloud</b></a>
|
||||
|
||||
<ul id="news">
|
||||
<li><a href="$ROOT/wiki/?name=Changelog">Nouveautés</a></li>
|
||||
<li><a href="$ROOT/uvlist">Anciennes versions</a></li>
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
|
||||
<p id="give"><a href="https://kd2.org/soutien.html" target="_blank">Soutenir Paheko en effectuant un don :-)</a></p>
|
||||
|
||||
<form method="GET" action="$ROOT/wiki" id="search_all" onsubmit="var t = this.querySelector('[type=radio]:checked'); this.querySelector('[name=s]').name=t.dataset.name; this.action=t.dataset.action; this.target=t.dataset.target;">
|
||||
<fieldset class="searchForm searchFormWiki">
|
||||
<legend>Rechercher</legend>
|
||||
<input type="search" name="s" size="40" value="" />
|
||||
<label><input type="radio" name="t" value="" data-name="s" data-action="/paheko/wiki" data-target="" checked="checked" /> Chercher dans la documentation technique</label>
|
||||
<label><input type="radio" name="t" value="1" data-action="https://paheko.cloud/search" data-name="search" data-target="_blank" /> Chercher dans l'aide utilisateur</label>
|
||||
<input type="submit" value="Rechercher" />
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<script type="text/javascript">
|
||||
function isNewerVersion (oldVer, newVer) {
|
||||
const oldParts = oldVer.split('.')
|
||||
const newParts = newVer.split('.')
|
||||
for (var i = 0; i < newParts.length; i++) {
|
||||
const a = ~~newParts[i] // parse int
|
||||
const b = ~~oldParts[i] // parse int
|
||||
if (a > b) return true
|
||||
if (a < b) return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fetch('/paheko/juvlist?'+(+(new Date))).then((r) => {
|
||||
r.json().then((list) => {
|
||||
let last = {};
|
||||
let selected;
|
||||
|
||||
list.forEach((file) => {
|
||||
var v = file.name.match(/^paheko-(\d+\.\d+\.\d+)\.(deb|exe|tar\.gz)$/);
|
||||
|
||||
if (!v || v[1].match(/-(alpha|rc|beta)/)) {
|
||||
return;
|
||||
}
|
||||
|
||||
file.type = v[2];
|
||||
file.version = v[1];
|
||||
file.human_size = (Math.round((file.size / 1024 / 1024) * 10) / 10 + ' Mo').replace(/\./, ',');
|
||||
|
||||
if (!last.hasOwnProperty(file.type) || isNewerVersion(last[file.type].version, file.version)) {
|
||||
last[file.type] = file;
|
||||
|
||||
if (file.type == 'tar.gz') {
|
||||
selected = file;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let days = ((+new Date)/1000 - selected.mtime) / 3600 / 24;
|
||||
|
||||
if (days < 31) {
|
||||
time = Math.ceil(days) + ' jours';
|
||||
}
|
||||
else if (days >= 31) {
|
||||
time = Math.round(days / 30.5) + ' mois';
|
||||
}
|
||||
|
||||
document.querySelector('#news').innerHTML = `<li class="last"><strong>Dernière version : ${last['tar.gz'].version}</strong></li>
|
||||
<li class="last"><em>il y a ${time}</em></li>` + document.querySelector('#news').innerHTML;
|
||||
|
||||
var links = `<div id="download">
|
||||
<h2>Télécharger :</h2>
|
||||
|
||||
<nav>`;
|
||||
|
||||
if ('tar.gz' in last) {
|
||||
links += `
|
||||
<div>
|
||||
|
||||
<h3><a href="$ROOT/uv/${last['tar.gz'].name}"><img src="data:image/svg+xml;base64,PHN2ZwogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICB3aWR0aD0iMjQiCiAgaGVpZ2h0PSIyNCIKICB2aWV3Qm94PSIwIDAgMjQgMjQiCiAgZmlsbD0ibm9uZSIKICBzdHJva2U9ImN1cnJlbnRDb2xvciIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cmVjdCB4PSIyIiB5PSIyIiB3aWR0aD0iMjAiIGhlaWdodD0iOCIgcng9IjIiIHJ5PSIyIiAvPgogIDxyZWN0IHg9IjIiIHk9IjE0IiB3aWR0aD0iMjAiIGhlaWdodD0iOCIgcng9IjIiIHJ5PSIyIiAvPgogIDxsaW5lIHgxPSI2IiB5MT0iNiIgeDI9IjYuMDEiIHkyPSI2IiAvPgogIDxsaW5lIHgxPSI2IiB5MT0iMTgiIHgyPSI2LjAxIiB5Mj0iMTgiIC8+Cjwvc3ZnPgo=" alt="" /><span>Serveur</span></a></h3>
|
||||
<p>pour auto-hébergement<br />
|
||||
<em>(.tar.gz, ${last['tar.gz'].human_size})</em><br />
|
||||
<small><a href="$ROOT/wiki/?name=Installation">Guides d'installation</a></small>
|
||||
</p>
|
||||
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if ('deb' in last) {
|
||||
links += `
|
||||
<div>
|
||||
|
||||
<h4><a href="$ROOT/uv/${last['deb'].name}"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGoAAAB8AgMAAAD8wM2CAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAAlwSFlzAAAF3gAABd4BiRluJgAAAAxQTFRFAAAAR3BMAAAAAAAAoOHXxQAAAAR0Uk5T/QBQozL7B+YAAAPySURBVEjHndc9aBxHFADgd7u64hTv4eYgxRVulijYpQURpDgIKVwILtbN7GAt9jquEl/gItUOl5gUhgjUbNKkMBhhkDE2rhOY2LhwYVvNgiEu0qhOwKiISSAzszPz3q7mhIlKfczuzJv3swds4d8Y3tEu/fNyb4FxCQBl2HJFkIRtpI0spGYIVkM2qS0JWV5bFLKiNnwhsZm1KmAja2nA5ta6AZMnmCXonWDJCdY5btxZ9D8tDtkpgD5fYKVUFzQKWqT+P9ARD5yh80UB1b/jkPHkh1346dTPwXXJ8gG8Wn6NF0hsuXMaXkXDsMVnYBifCxucgXMwxIsn9hz69z6G00F7LP+8MYXdoD355qvP2KNx0KTOaP4XqOAcz6XSZmnAbrrMT4/bt6Y8+WLbyrCSiH2it7IqMEFpzqtnTcsiaPNfGf9bZ3cSsN/fvinFa0zQxtm/3GPbE0wmas/VXnpqnxDIszslKyqO1YmWwWRtMzFlkbZNxEzGlSnRbtvGEbu0V5d20rZZx7eLqG2yh22mZdyFWPiNehNud5nf6BgPWmEddps2cinLfcl7k0DqN25YhiXpe5ozgS1Aus04y7GtzN1mnBVoM9ebnI2wVRWxrF/gbI7tL49tP3Amsb9P4IO6Pp3B+wNMgKSuCWscditMnGhuDuFtRufLzLzdWhbdZKThH5jma23S6TAyKIbmRNZEvzG/VkwkrOVLPTrrVkzkrY0/wvGl4n6e2myYMjLQlkxgrI0OBi0rvcnbeHR1z0vmdq3BrGzZwFkWj9gim9CwKDtPLI++a1vqrOg8JsbV2dFmnd8a66jNG8Z18/UmW+sOTOOqDaKdxrrbZB3E6411V6Q3VR73qSX7P0piA2pnISoGaF1qfwCs+LisTSNid1W1vOfuIVOdCu9BxHrouvublGyOObGhO0V8aE2oiOJDv9adIn5q7ZrOLX/x67rikwvGcujrHPFJuK4rfvWGse39Uh8jQlMVX101dst2B/fQW2aOf27syBbuqrdCveCisdQWT+KNv6nYZWJj33wu1BEgJvwMri2r8H2Zv4vaWBcNO4W1bWJ+o89syFNl37tKrl+cuQDtoOV2L8LZNWWf2qqzQSuc5Wg8bc4CJnb9M/1Z6LqjRjwKbxvKXPpdtd/RZJ+Z/3zQ+5z6dBSHYxA+v9T1X8dvzBcqLlfId7LEj2ihY30RS4R+YO8wapxaZmolL1sfoMY2zHXzfstS+0h9R9N+ecy469fX45KajkXuZ8CmQQ5v1bfNA6ltC2fHpn5ntob3cUTmynTNxqzOCdGYfw8PmWtpWzqPGjP1yS8u58WHm73WfN/3xfnQ7jv426l8h99V/wEOtd7r5KQmrQAAAABJRU5ErkJggg==" alt="" /><span>Linux</span></a></h4>
|
||||
<p>hors-ligne, pour ordinateur<br />
|
||||
<em>(.deb, ${last['deb'].human_size})</em><br />
|
||||
<small><a href="$ROOT/wiki/?name=Fonctionnement+hors-ligne">Guide d'installation</a></small>
|
||||
</p>
|
||||
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if ('exe' in last) {
|
||||
links += `
|
||||
<div>
|
||||
|
||||
<h4><a href="$ROOT/uv/${last['exe'].name}"><img src="data:image/svg+xml;base64,PHN2ZyBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAyNCAyNCIgdmlld0JveD0iMCAwIDI0IDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Im0yMiAyLTEwLjggMS42djhsMTAuOC0uMXptLTExLjggMTAuNS04LjItLjF2Ni44bDguMSAxLjF6bS04LjItNy43djYuOGg4LjF2LTcuOXptOS4xIDcuN3Y3LjlsMTAuOSAxLjZ2LTkuNHoiLz48L3N2Zz4=" alt="" /><span>Windows</span></a></h4>
|
||||
<p>hors-ligne, pour ordinateur<br />
|
||||
<em>(.exe, ${last['exe'].human_size})</em><br />
|
||||
<small><a href="$ROOT/wiki/?name=Installation/Windows">Guide d'installation</a></small>
|
||||
</p>
|
||||
|
||||
</div>`;
|
||||
}
|
||||
|
||||
links += `
|
||||
</nav>
|
||||
|
||||
</div>`;
|
||||
|
||||
document.querySelector('#news').insertAdjacentHTML('afterend', links);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<a name="features"></a>
|
||||
|
||||
## C'est quoi ?
|
||||
|
||||
* **100% libre :** placé sous la licence [AGPL v3](https://www.gnu.org/licenses/why-affero-gpl.fr.html).
|
||||
* Gestion des **adhérent⋅e⋅s** : fiches de membre personnalisables, recherches personnalisées…
|
||||
* Gestion des **cotisations** et **activités** : suivi des adhérent⋅e⋅s à jour, des paiements en attente, **rappels automatiques** de cotisation par e-mail, etc.
|
||||
* Envoi de **newsletters** avec suivi des adresses e-mail invalides
|
||||
* **Comptabilité** puissante (à double entrée), **simple à utiliser par les débutant⋅e⋅s** : recettes, dépenses, suivi des dettes et créances, bilan et compte de résultat annuel, **comptabilité analytique**, export PDF, **reçus fiscaux**, etc.
|
||||
* Stockage et **partage** de **documents** : édition collaborative, synchronisation des fichiers sur un ordinateur, etc.
|
||||
* Gestion du **site web** de l'association
|
||||
* Comptabilisation du **temps bénévole** et sa **valorisation**
|
||||
* Gestion de la **caisse informatisée** d'un atelier ou d'une boutique
|
||||
* Réservation de **créneaux et d'événements**
|
||||
* **Conforme au RGPD** : export des données de l'adhérent⋅e, désabonnement des e-mails, chiffrement des mots de passe…
|
||||
|
||||
**<a href="http://paheko.cloud/a-propos" target="_blank">Présentation des fonctionnalités sur le site Paheko</a>**
|
||||
|
||||
## Dans quels buts ?
|
||||
|
||||
Le but est de permettre :
|
||||
|
||||
* la gestion des __adhérent⋅e⋅s__ : ajout, modification, suppression, possibilité de choisir les informations présentes sur les fiches adhérent, envoi de mails collectifs aux adhérent⋅e⋅s
|
||||
* la tenue de la __comptabilité__ : avoir une gestion comptable complète à même de satisfaire un expert-comptable tout en restant à la portée de celles et ceux qui ne savent pas ce qu'est la comptabilité à double entrée, permettre la production des rapports et bilans annuels et de suivre au jour le jour le budget de l'association
|
||||
* la gestion des __cotisations__ et __activités__ : suivi des cotisations à jour, inscriptions et paiement des activités, rappels automatiques par e-mail, etc.
|
||||
* le travail __collaboratif__ et __collectif__ : gestion fine des droits d'accès aux fonctions, échange de mails entre membres…
|
||||
* la __simplification administrative__ : prise de notes en réunion, archivage et partage de fichiers (afin d'éliminer le besoin d'archiver les documents papier), etc.
|
||||
* la publication d'un __site web__ pour l'association, simple mais suffisamment flexible pour pouvoir adapter le fonctionnement à la plupart des besoins
|
||||
* l'__autonomisation des adhérents__ : possibilité de mettre à jour leurs informations par eux-même, ou de s'inscrire seul depuis un ordinateur ou un smartphone
|
||||
* la possibilité d'adapter aux besoins spécifiques de chaque association via des [__extensions__](wiki:Extensions).
|
||||
|
||||
* Fonctionnalités qu'il reste à implémenter : voir [la feuille de route (roadmap)](wiki:Roadmap).
|
||||
* Paheko ne convient pas ? [Voir la liste des alternatives, libres ou propriétaires](wiki:Alternatives)
|
||||
|
||||
## Un seul logiciel
|
||||
|
||||
Paheko réunit en un seul outil les besoins suivants :
|
||||
|
||||
* gestion des membres : remplace Ciel Associations, EBP, Assoconnect ou Galette ;
|
||||
* comptabilité : remplace Assoconnect, Odoo, Dolibarr, Grisbi, GNUcash, Sage, etc. ;
|
||||
* gestion et partage de fichiers, remplace NextCloud, Google Drive ou Dropbox ;
|
||||
* site web : remplace WordPress, Drupal, etc. ;
|
||||
* suivi du bénévolat : remplace Bénévalibre et les tableaux Excel.
|
||||
|
||||
## Documentation et entraide
|
||||
|
||||
* D'abord lire la [documentation](/wiki/?name=Documentation) et notamment la [foire aux questions](wiki:FAQ)
|
||||
* Voir la page [Entraide](/wiki/?name=Entraide) pour accéder aux listes de discussion et au salon de discussion IRC
|
||||
|
||||
## Participer
|
||||
|
||||
Tout coup de main est le bienvenu, pas besoin d'avoir des connaissances techniques ! Nous avons un [guide de contribution](wiki:Contribuer) pour vous aider à voir comment vous pouvez participer à Paheko :)
|
||||
|
||||
### Développement
|
||||
|
||||
Paheko est un logiciel libre, développé en PHP, utilisant la base de données SQLite, et avec une interface utilisant HTML, CSS et un peu de Javascript.
|
||||
|
||||
Nous acceptons les contributions (plugins, patch, code, tickets, etc.) avec plaisir, consultez la [documentation développeur⋅euse](wiki:Documentation développeur) pour découvrir comment vous pouvez contribuer.
|
||||
BIN
doc/selfhost2.png
Normal file
BIN
doc/selfhost2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
1430
doc/skrivml.html
Normal file
1430
doc/skrivml.html
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue