docs: Minz Framwork (#5102)

* done

* Update docs/fr/developers/Minz/index.md

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
This commit is contained in:
maTh
2023-02-23 22:20:36 +01:00
committed by GitHub
parent 6764758658
commit 859c48383a
7 changed files with 521 additions and 551 deletions

View File

@@ -22,195 +22,9 @@ Another solution consists of an extension system. By allowing users to write the
Note: it is quite conceivable that the functionalities of an extension can later be officially integrated into the FreshRSS code. Extensions make it easy to propose a proof of concept.
## Understanding basic mechanics (Minz and MVC)
## Minz Framework
**TODO** : move to 02_Minz.md
This data sheet should refer to the official FreshRSS and Minz documentation (the PHP framework on which FreshRSS is based). Unfortunately, this documentation does not yet exist. In a few words, here are the main things you should know. It is not necessary to read all the chapters in this section if you dont need to use a feature in your extension (if you dont need to translate your extension, no need to know more about the `Minz_Translate` module for example).
### MVC Architecture
Minz relies on and imposes an MVC architecture on projects using it. This architecture consists of three main components:
* The model: this is the base object that we will manipulate. In FreshRSS, categories, flows and articles are templates. The part of the code that makes it possible to manipulate them in a database is also part of the model but is separated from the base model: we speak of DAO (for "Data Access Object"). The templates are stored in a `Models` folder.
* The view: this is what the user sees. The view is therefore simply HTML code mixed with PHP to display dynamic information. The views are stored in a `views` folder.
* The controller: this is what makes it possible to link models and views. Typically, a controller will load templates from the database (like a list of items) to "pass" them to a view for display. Controllers are stored in a `Controllers` directory.
### Routing
In order to link a URL to a controller, first you have to go through a "routing" phase. In FreshRSS, this is particularly simple because it suffices to specify the name of the controller to load into the URL using a `c` parameter.
For example, the address <http://example.com?c=hello> will execute the code contained in the `hello` controller.
One concept that has not yet been discussed is the "actions" system. An action is executed *on* a controller. Concretely, a controller is represented by a class and its actions by methods. To execute an action, it is necessary to specify an `a` parameter in the URL.
Code example:
```php
<?php
class FreshRSS_hello_Controller extends FreshRSS_ActionController {
public function indexAction() {
$this->view->a_variable = 'FooBar';
}
public function worldAction() {
$this->view->a_variable = 'Hello World!';
}
}
?>
```
When loading the address <http://example.com?c=hello&a=world>, the `world` action is executed on the `hello` controller.
Note: if `c` or `a` is not specified, the default value for each of these variables is `index`.
So the address <http://example.com?c=hello> will execute the `index` action of the `hello` controller.
From now on, the `hello/world` naming convention will be used to refer to a controller/action pair.
### Views
Each view is associated with a controller and an action. The view associated with `hello/world` will be stored in a very specific file: `views/hello/world. phtml`. This convention is imposed by Minz.
As explained above, the views consist of HTML mixed with PHP. Code example:
```html
<p>
This is a parameter passed from the controller: <?= $this->a_variable ?>
</p>
```
The variable `$this->a_variable` is passed by the controller (see previous example). The difference is that in the controller it is necessary to pass `$this->view`, while in the view `$this` suffices.
### Working with GET / POST
It is often necessary to take advantage of parameters passed by GET or POST. In Minz, these parameters are accessible using the `Minz_Request` class.
Code example:
```php
<?php
$default_value = 'foo';
$param = Minz_Request::param('bar', $default_value);
// Display the value of the parameter `bar` (passed via GET or POST)
// or "foo" if the parameter does not exist.
echo $param;
// Sets the value of the `bar` parameter
Minz_Request::_param('bar', 'baz');
// Will necessarily display "baz" since we have just forced its value.
// Note that the second parameter (default) is optional.
echo Minz_Request::param('bar');
?>
```
The `Minz_Request::isPost()` method can be used to execute a piece of code only if it is a POST request.
Note: it is preferable to use `Minz_Request` only in controllers. It is likely that you will encounter this method in FreshRSS views, or even in templates, but be aware that this is **not** good practice.
### Access session settings
The access to session parameters is strangely similar to the GET / POST parameters but passes through the `Minz_Session` class this time! There is no example here because you can repeat the previous example by changing all `Minz_Request` to `Minz_Session`.
### Working with URLs
To take full advantage of the Minz routing system, it is strongly discouraged to write hard URLs in your code. For example, the following view should be avoided:
```html
<p>
Go to page <a href="http://example.com?c=hello&amp;a=world">Hello world</a>!
</p>
```
If one day it was decided to use a "url rewriting" system to have addresses in a <http://example.com/controller/action> format, all previous addresses would become ineffective!
So use the `Minz_Url` class and its `display()` method instead. `Minz_Url::display()` takes an array of the following form as its argument:
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
'params' => [
'foo' => 'bar',
],
];
// Show something like .?c=hello&amp;a=world&amp;foo=bar
echo Minz_Url::display($url_array);
?>
```
Since this can become a bit tedious to use in the long run, especially in views, it is preferable to use the `_url()` shortcut:
```php
<?php
// Displays the same as above
echo _url('hello', 'world', 'foo', 'bar');
?>
```
Note: as a general rule, the shortened form (`_url()`) should be used in views, while the long form (`Minz_Url::display()`) should be used in controllers.
### Redirections
It is often necessary to redirect a user to another page. To do so, the `Minz_Request` class offers another useful method: `forward()`. This method takes the same URL format as the one seen just before as its argument.
Code example:
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
];
// Tells Minz to redirect the user to the hello / world page.
// Note that this is a redirection in the Minz sense of the term, not a redirection that the browser will have to manage (HTTP code 301 or 302)
// The code that follows forward() will thus be executed!
Minz_Request::forward($url_array);
// To perform a type 302 redirect, add "true".
// The code that follows will never be executed.
Minz_Request::forward($url_array, true);
?>
```
It is very common to want display a message to the user while performing a redirect, to tell the user how the action was carried out (validation of a form for example). Such a message is passed through a `notification` session variable (note: we will talk about feedback from now on to avoid confusion with a notification that can occur at any time). To facilitate this kind of very frequent action, there are two shortcuts that both perform a 302 redirect by assigning a feedback message:
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
];
$feedback_good = 'All went well!';
$feedback_bad = 'Oops, something went wrong.';
Minz_Request::good($feedback_good, $url_array);
// or
Minz_Request::bad($feedback_bad, $url_array);
?>
```
### Translation Management
This part [is explained here](/docs/en/internationalization.md).
### Configuration management
see [Minz documentation](/docs/en/developers/Minz/index.md)
## Write an extension for FreshRSS

View File

@@ -1,19 +1,193 @@
# Minz
# Minz Framework
Minz is the homemade PHP framework used by FreshRSS.
The documentation is still incomplete and it would be great to explain:
This data sheet should refer to the official FreshRSS and Minz documentation (the PHP framework on which FreshRSS is based). Unfortunately, this documentation does not yet exist. In a few words, here are the main things you should know. It is not necessary to read all the chapters in this section if you dont need to use a feature in your extension (if you dont need to translate your extension, no need to know more about the `Minz_Translate` module for example).
- routing, controllers and actions
- configuration
- models and database
- views
- URLs management
- sessions
- internationalisation
- extensions
- mailer
## MVC Architecture
Minz relies on and imposes an MVC architecture on projects using it. This architecture consists of three main components:
* The model: this is the base object that we will manipulate. In FreshRSS, categories, flows and articles are templates. The part of the code that makes it possible to manipulate them in a database is also part of the model but is separated from the base model: we speak of DAO (for "Data Access Object"). The templates are stored in a `Models` folder.
* The view: this is what the user sees. The view is therefore simply HTML code mixed with PHP to display dynamic information. The views are stored in a `views` folder.
* The controller: this is what makes it possible to link models and views. Typically, a controller will load templates from the database (like a list of items) to "pass" them to a view for display. Controllers are stored in a `Controllers` directory.
## Routing
In order to link a URL to a controller, first you have to go through a "routing" phase. In FreshRSS, this is particularly simple because it suffices to specify the name of the controller to load into the URL using a `c` parameter.
For example, the address <http://example.com?c=hello> will execute the code contained in the `hello` controller.
One concept that has not yet been discussed is the "actions" system. An action is executed *on* a controller. Concretely, a controller is represented by a class and its actions by methods. To execute an action, it is necessary to specify an `a` parameter in the URL.
Code example:
```php
<?php
class FreshRSS_hello_Controller extends FreshRSS_ActionController {
public function indexAction() {
$this->view->a_variable = 'FooBar';
}
public function worldAction() {
$this->view->a_variable = 'Hello World!';
}
}
?>
```
When loading the address <http://example.com?c=hello&a=world>, the `world` action is executed on the `hello` controller.
Note: if `c` or `a` is not specified, the default value for each of these variables is `index`.
So the address <http://example.com?c=hello> will execute the `index` action of the `hello` controller.
From now on, the `hello/world` naming convention will be used to refer to a controller/action pair.
## Views
Each view is associated with a controller and an action. The view associated with `hello/world` will be stored in a very specific file: `views/hello/world. phtml`. This convention is imposed by Minz.
As explained above, the views consist of HTML mixed with PHP. Code example:
```html
<p>
This is a parameter passed from the controller: <?= $this->a_variable ?>
</p>
```
The variable `$this->a_variable` is passed by the controller (see previous example). The difference is that in the controller it is necessary to pass `$this->view`, while in the view `$this` suffices.
## Working with GET / POST
It is often necessary to take advantage of parameters passed by GET or POST. In Minz, these parameters are accessible using the `Minz_Request` class.
Code example:
```php
<?php
$default_value = 'foo';
$param = Minz_Request::param('bar', $default_value);
// Display the value of the parameter `bar` (passed via GET or POST)
// or "foo" if the parameter does not exist.
echo $param;
// Sets the value of the `bar` parameter
Minz_Request::_param('bar', 'baz');
// Will necessarily display "baz" since we have just forced its value.
// Note that the second parameter (default) is optional.
echo Minz_Request::param('bar');
?>
```
The `Minz_Request::isPost()` method can be used to execute a piece of code only if it is a POST request.
Note: it is preferable to use `Minz_Request` only in controllers. It is likely that you will encounter this method in FreshRSS views, or even in templates, but be aware that this is **not** good practice.
## Access session settings
The access to session parameters is strangely similar to the GET / POST parameters but passes through the `Minz_Session` class this time! There is no example here because you can repeat the previous example by changing all `Minz_Request` to `Minz_Session`.
## Working with URLs
To take full advantage of the Minz routing system, it is strongly discouraged to write hard URLs in your code. For example, the following view should be avoided:
```html
<p>
Go to page <a href="http://example.com?c=hello&amp;a=world">Hello world</a>!
</p>
```
If one day it was decided to use a "url rewriting" system to have addresses in a <http://example.com/controller/action> format, all previous addresses would become ineffective!
So use the `Minz_Url` class and its `display()` method instead. `Minz_Url::display()` takes an array of the following form as its argument:
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
'params' => [
'foo' => 'bar',
],
];
// Show something like .?c=hello&amp;a=world&amp;foo=bar
echo Minz_Url::display($url_array);
?>
```
Since this can become a bit tedious to use in the long run, especially in views, it is preferable to use the `_url()` shortcut:
```php
<?php
// Displays the same as above
echo _url('hello', 'world', 'foo', 'bar');
?>
```
Note: as a general rule, the shortened form (`_url()`) should be used in views, while the long form (`Minz_Url::display()`) should be used in controllers.
## Redirections
It is often necessary to redirect a user to another page. To do so, the `Minz_Request` class offers another useful method: `forward()`. This method takes the same URL format as the one seen just before as its argument.
Code example:
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
];
// Tells Minz to redirect the user to the hello / world page.
// Note that this is a redirection in the Minz sense of the term, not a redirection that the browser will have to manage (HTTP code 301 or 302)
// The code that follows forward() will thus be executed!
Minz_Request::forward($url_array);
// To perform a type 302 redirect, add "true".
// The code that follows will never be executed.
Minz_Request::forward($url_array, true);
?>
```
It is very common to want display a message to the user while performing a redirect, to tell the user how the action was carried out (validation of a form for example). Such a message is passed through a `notification` session variable (note: we will talk about feedback from now on to avoid confusion with a notification that can occur at any time). To facilitate this kind of very frequent action, there are two shortcuts that both perform a 302 redirect by assigning a feedback message:
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
];
$feedback_good = 'All went well!';
$feedback_bad = 'Oops, something went wrong.';
Minz_Request::good($feedback_good, $url_array);
// or
Minz_Request::bad($feedback_bad, $url_array);
?>
```
## Translation Management
This part [is explained here](/docs/en/internationalization.md).
## Migration
Existing documentation includes:
- [How to manage migrations](migrations.md)
* [How to manage migrations](migrations.md)

View File

@@ -1,29 +0,0 @@
# Minz
## Modèles
> **À FAIRE**
## Contrôleurs et actions
> **À FAIRE**
## Vues
> **À FAIRE**
## Routage
> **À FAIRE**
## Écriture des URL
> **À FAIRE**
## Internationalisation
> **À FAIRE**
## Comprendres les mécanismes internes
> **À FAIRE**

View File

@@ -36,329 +36,9 @@ puissent par la suite être intégrées dans le code initial de FreshRSS de
façon officielle. Cela permet de proposer un « proof of concept » assez
facilement.
## Comprendre les mécaniques de base (Minz et MVC)
## Minz Framework
**TODO** : bouger dans 02_Minz.md
Cette fiche technique devrait renvoyer vers la documentation officielle de
FreshRSS et de Minz (le framework PHP sur lequel repose
FreshRSS). Malheureusement cette documentation nexiste pas encore. Voici
donc en quelques mots les principaux éléments à connaître. Il nest pas
nécessaire de lire lensemble des chapitres de cette section si vous navez
pas à utiliser une fonctionnalité dans votre extension (si vous navez pas
besoin de traduire votre extension, pas besoin den savoir plus sur le
module `Minz_Translate` par exemple).
### Architecture MVC
Minz repose et impose une architecture MVC pour les projets lutilisant. On
distingue dans cette architecture trois composants principaux :
* Le Modèle : cest lobjet de base que lon va manipuler. Dans FreshRSS,
les catégories, les flux et les articles sont des modèles. La partie du
code qui permet de les manipuler en base de données fait aussi partie du
modèle mais est séparée du modèle de base : on parle de DAO (pour « Data
Access Object »). Les modèles sont stockés dans un répertoire `Models`.
* La Vue : cest ce qui représente ce que verra lutilisateur. La vue est
donc simplement du code HTML que lon mixe avec du PHP pour afficher les
informations dynamiques. Les vues sont stockées dans un répertoire
`views`.
* Le Contrôleur : cest ce qui permet de lier modèles et vues entre
eux. Typiquement, un contrôleur va charger des modèles à partir de la base
de données (une liste darticles par exemple) pour les « passer » à une
vue afin quelle les affiche. Les contrôleurs sont stockés dans un
répertoire `Controllers`.
### Routage
Afin de lier une URL à un contrôleur, on doit passer par une phase dite de «
routage ». Dans FreshRSS, cela est particulièrement simple car il suffit
dindiquer le nom du contrôleur à charger dans lURL à laide dun paramètre `c`.
Par exemple, ladresse <http://exemple.com?c=hello> va exécuter le code
contenu dans le contrôleur `hello`.
Une notion qui na pas encore été évoquée est le système d'« actions ». Une
action est exécutée *sur* un contrôleur. Concrètement, un contrôleur va être
représenté par une classe et ses actions par des méthodes. Pour exécuter une
action, il est nécessaire dindiquer un paramètre `a` dans lURL.
Exemple de code :
```php
<?php
class FreshRSS_hello_Controller extends FreshRSS_ActionController {
public function indexAction() {
$this->view->a_variable = 'FooBar';
}
public function worldAction() {
$this->view->a_variable = 'Hello World!';
}
}
?>
```
Si lon charge ladresse <http://exemple.com?c=hello&a=world>, laction
`world` va donc être exécutée sur le contrôleur `hello`.
Note : si `c` ou `a` nest pas précisée, la valeur par défaut de chacune de
ces variables est `index`. Ainsi ladresse <http://exemple.com?c=hello> va
exécuter laction `index` du contrôleur `hello`.
Plus loin, sera utilisée la convention `hello/world` pour évoquer un couple
contrôleur/action.
### Vues
Chaque vue est associée à un contrôleur et à une action. La vue associée à
`hello/world` va être stockée dans un fichier bien spécifique :
`views/hello/world.phtml`. Cette convention est imposée par Minz.
Comme expliqué plus haut, les vues sont du code HTML mixé à du PHP. Exemple
de code :
```html
<p>
Phrase passée en paramètre : <?= $this->a_variable ?>
</p>
```
La variable `$this->a_variable` a été passée précédemment par le contrôleur (voir exemple précédent). La différence est que dans le contrôleur il est nécessaire de passer par `$this->view` et que dans la vue `$this` suffit.
### Accéder aux paramètres GET / POST
Il est souvent nécessaire de profiter des paramètres passés par GET ou par
POST. Dans Minz, ces paramètres sont accessibles de façon indistincts à
laide de la classe `Minz_Request`. Exemple de code :
```php
<?php
$default_value = 'foo';
$param = Minz_Request::param('bar', $default_value);
// Affichera la valeur du paramètre `bar` (passé via GET ou POST)
// ou "foo" si le paramètre nexiste pas.
echo $param;
// Force la valeur du paramètre `bar`
Minz_Request::_param('bar', 'baz');
// Affichera forcément "baz" puisque nous venons de forcer sa valeur.
// Notez que le second paramètre (valeur par défaut) est facultatif.
echo Minz_Request::param('bar');
?>
```
La méthode `Minz_Request::isPost()` peut être utile pour nexécuter un
morceau de code que sil sagit dune requête POST.
Note : il est préférable de nutiliser `Minz_Request` que dans les
contrôleurs. Il est probable que vous rencontriez cette méthode dans les
vues de FreshRSS, voire dans les modèles, mais sachez quil ne sagit
**pas** dune bonne pratique.
### Accéder aux paramètres de session
Laccès aux paramètres de session est étrangement similaire aux paramètres
GET / POST mais passe par la classe `Minz_Session` cette fois-ci ! Il ny a
pas dexemple ici car vous pouvez reprendre le précédent en changeant tous
les `Minz_Request` par des `Minz_Session`.
### Gestion des URL
Pour profiter pleinement du système de routage de Minz, il est fortement
déconseillé décrire les URL en dur dans votre code. Par exemple, la vue
suivante doit être évitée :
```html
<p>
Accéder à la page <a href="http://exemple.com?c=hello&amp;a=world">Hello world</a>!
</p>
```
Si un jour il est décidé dutiliser un système d'« url rewriting » pour
avoir des adresses au format <http://exemple.com/controller/action>, toutes
les adresses précédentes deviendraient ineffectives !
Préférez donc lutilisation de la classe `Minz_Url` et de sa méthode
`display()`. `Minz_Url::display()` prend en paramètre un tableau de la forme
suivante :
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
'params' => [
'foo' => 'bar',
],
];
// Affichera quelque chose comme .?c=hello&amp;a=world&amp;foo=bar
echo Minz_Url::display($url_array);
?>
```
Comme cela peut devenir un peu pénible à utiliser à la longue, surtout dans
les vues, il est préférable dutiliser le raccourci `_url()` :
```php
<?php
// Affichera la même chose que précédemment
echo _url('hello', 'world', 'foo', 'bar');
?>
```
Note : en règle générale, la forme raccourcie (`_url()`) doit être utilisée
dans les vues tandis que la forme longue (`Minz_Url::display()`) doit être
utilisée dans les contrôleurs.
### Redirections
Il est souvent nécessaire de rediriger un utilisateur vers une autre
page. Pour cela, la classe `Minz_Request` dispose dune autre méthode utile
: `forward()`. Cette méthode prend en argument le même format dURL que
celui vu juste avant.
Exemple de code :
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
];
// Indique à Minz de rediriger lutilisateur vers la page hello/world.
// Notez quil sagit dune redirection au sens Minz du terme, pas dune redirection que le navigateur va avoir à gérer (code HTTP 301 ou 302)
// Le code qui suit forward() va ainsi être exécuté !
Minz_Request::forward($url_array);
// Pour effectuer une redirection type 302, ajoutez "true".
// Le code qui suivra ne sera alors jamais exécuté.
Minz_Request::forward($url_array, true);
?>
```
Il est très fréquent de vouloir effectuer une redirection tout en affichant
un message à lutilisateur pour lui indiquer comment sest déroulée laction
effectuée juste avant (validation dun formulaire par exemple). Un tel
message est passé par une variable de session `notification` (note : nous
parlerons plutôt de « feedback » désormais pour éviter la confusion avec une
notification qui peut survenir à tout moment). Pour faciliter ce genre
daction très fréquente, il existe deux raccourcis qui effectuent tout deux
une redirection type 302 en affectant un message de feedback :
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
];
$feedback_good = 'Tout sest bien passé !';
$feedback_bad = 'Oups, quelque chose na pas marché.';
Minz_Request::good($feedback_good, $url_array);
// ou
Minz_Request::bad($feedback_bad, $url_array);
?>
```
### Gestion de la traduction
Il est fréquent (et cest un euphémisme) de vouloir afficher des phrases à
lutilisateur. Dans lexemple précédent par exemple, nous affichions un
feedback à lutilisateur en fonction du résultat dune validation de
formulaire. Le problème est que FreshRSS possède des utilisateurs de
différentes nationalités. Il est donc nécessaire de pouvoir gérer
différentes langues pour ne pas rester cantonné à lAnglais ou au Français.
La solution consiste à utiliser la classe `Minz_Translate` qui permet de
traduire dynamiquement FreshRSS (ou toute application basée sur Minz). Avant
dutiliser ce module, il est nécessaire de savoir où trouver les chaînes de
caractères à traduire. Chaque langue possède son propre sous-répertoire dans
un répertoire parent nommé `i18n`. Par exemple, les fichiers de langue en
Français sont situés dans `i18n/fr/`. Il existe sept fichiers différents :
* `admin.php` pour tout ce qui est relatif à ladministration de FreshRSS ;
* `conf.php` pour laspect configuration ;
* `feedback.php` contient les traductions des messages de feedback ;
* `gen.php` stocke ce qui est global à FreshRSS (gen pour « general ») ;
* `index.php` pour la page principale qui liste les flux et la page « À propos » ;
* `install.php` contient les phrases relatives à linstallation de FreshRSS ;
* `sub.php` pour laspect gestion des abonnements (sub pour « subscription »).
Cette organisation permet de ne pas avoir un unique énorme fichier de
traduction.
Les fichiers de traduction sont assez simples : il sagit seulement de
retourner un tableau PHP contenant les traductions. Extrait du fichier
`app/i18n/fr/gen.php` :
```php
<?php
return array(
'action' => [
'actualize' => 'Actualiser',
'back_to_rss_feeds' => '← Retour à vos flux RSS',
'cancel' => 'Annuler',
'create' => 'Créer',
'disable' => 'Désactiver',
),
'freshrss' => array(
'_' => 'FreshRSS',
'about' => 'À propos de FreshRSS',
),
];
?>
```
Pour accéder à ces traductions, `Minz_Translate` va nous aider à laide de
sa méthode `Minz_Translate::t()`. Comme cela peut être un peu long à taper,
il a été introduit un raccourci qui **doit** être utilisé en toutes
circonstances : `_t()`. Exemple de code :
```html
<p>
<a href="<?= _url('index', 'index') ?>">
<?= _t('gen.action.back_to_rss_feeds') ?>
</a>
</p>
```
La chaîne à passer à la fonction `_t()` consiste en une série didentifiants
séparés par des points. Le premier identifiant indique de quel fichier on
veut extraire la traduction (dans notre cas présent, de `gen.php`), tandis
que les suivantes indiquent des entrées de tableaux. Ainsi `action` est une
entrée du tableau principal et `back_to_rss_feeds` est une entrée du tableau
`action`. Cela permet dorganiser encore un peu plus nos fichiers de
traduction.
Il existe un petit cas particulier qui permet parfois de se simplifier la
vie : le cas de lidentifiant `_`. Celui-ci doit nécessairement être présent
en bout de chaîne et permet de donner une valeur à lidentifiant de niveau
supérieur. Cest assez dur à expliquer mais très simple à comprendre. Dans
lexemple donné plus haut, un `_` est associé à la valeur `FreshRSS` : cela
signifie quil ny a pas besoin décrire `_t('gen.freshrss._')` mais
`_t('gen.freshrss')` suffit.
### Gestion de la configuration
see [Minz documentation](/docs/fr/developers/Minz/index.md)
## Écrire une extension pour FreshRSS

View File

@@ -0,0 +1,249 @@
# Minz
Cette fiche technique devrait renvoyer vers la documentation officielle de
FreshRSS et de Minz (le framework PHP sur lequel repose
FreshRSS). Malheureusement cette documentation nexiste pas encore. Voici
donc en quelques mots les principaux éléments à connaître. Il nest pas
nécessaire de lire lensemble des chapitres de cette section si vous navez
pas à utiliser une fonctionnalité dans votre extension (si vous navez pas
besoin de traduire votre extension, pas besoin den savoir plus sur le
module `Minz_Translate` par exemple).
## Architecture MVC
Minz repose et impose une architecture MVC pour les projets lutilisant. On
distingue dans cette architecture trois composants principaux :
* Le Modèle : cest lobjet de base que lon va manipuler. Dans FreshRSS,
les catégories, les flux et les articles sont des modèles. La partie du
code qui permet de les manipuler en base de données fait aussi partie du
modèle mais est séparée du modèle de base : on parle de DAO (pour « Data
Access Object »). Les modèles sont stockés dans un répertoire `Models`.
* La Vue : cest ce qui représente ce que verra lutilisateur. La vue est
donc simplement du code HTML que lon mixe avec du PHP pour afficher les
informations dynamiques. Les vues sont stockées dans un répertoire
`views`.
* Le Contrôleur : cest ce qui permet de lier modèles et vues entre
eux. Typiquement, un contrôleur va charger des modèles à partir de la base
de données (une liste darticles par exemple) pour les « passer » à une
vue afin quelle les affiche. Les contrôleurs sont stockés dans un
répertoire `Controllers`.
## Routage
Afin de lier une URL à un contrôleur, on doit passer par une phase dite de «
routage ». Dans FreshRSS, cela est particulièrement simple car il suffit
dindiquer le nom du contrôleur à charger dans lURL à laide dun paramètre `c`.
Par exemple, ladresse <http://exemple.com?c=hello> va exécuter le code
contenu dans le contrôleur `hello`.
Une notion qui na pas encore été évoquée est le système d'« actions ». Une
action est exécutée *sur* un contrôleur. Concrètement, un contrôleur va être
représenté par une classe et ses actions par des méthodes. Pour exécuter une
action, il est nécessaire dindiquer un paramètre `a` dans lURL.
Exemple de code :
```php
<?php
class FreshRSS_hello_Controller extends FreshRSS_ActionController {
public function indexAction() {
$this->view->a_variable = 'FooBar';
}
public function worldAction() {
$this->view->a_variable = 'Hello World!';
}
}
?>
```
Si lon charge ladresse <http://exemple.com?c=hello&a=world>, laction
`world` va donc être exécutée sur le contrôleur `hello`.
Note : si `c` ou `a` nest pas précisée, la valeur par défaut de chacune de
ces variables est `index`. Ainsi ladresse <http://exemple.com?c=hello> va
exécuter laction `index` du contrôleur `hello`.
Plus loin, sera utilisée la convention `hello/world` pour évoquer un couple
contrôleur/action.
## Vues
Chaque vue est associée à un contrôleur et à une action. La vue associée à
`hello/world` va être stockée dans un fichier bien spécifique :
`views/hello/world.phtml`. Cette convention est imposée par Minz.
Comme expliqué plus haut, les vues sont du code HTML mixé à du PHP. Exemple
de code :
```html
<p>
Phrase passée en paramètre : <?= $this->a_variable ?>
</p>
```
La variable `$this->a_variable` a été passée précédemment par le contrôleur (voir exemple précédent). La différence est que dans le contrôleur il est nécessaire de passer par `$this->view` et que dans la vue `$this` suffit.
## Accéder aux paramètres GET / POST
Il est souvent nécessaire de profiter des paramètres passés par GET ou par
POST. Dans Minz, ces paramètres sont accessibles de façon indistincts à
laide de la classe `Minz_Request`. Exemple de code :
```php
<?php
$default_value = 'foo';
$param = Minz_Request::param('bar', $default_value);
// Affichera la valeur du paramètre `bar` (passé via GET ou POST)
// ou "foo" si le paramètre nexiste pas.
echo $param;
// Force la valeur du paramètre `bar`
Minz_Request::_param('bar', 'baz');
// Affichera forcément "baz" puisque nous venons de forcer sa valeur.
// Notez que le second paramètre (valeur par défaut) est facultatif.
echo Minz_Request::param('bar');
?>
```
La méthode `Minz_Request::isPost()` peut être utile pour nexécuter un
morceau de code que sil sagit dune requête POST.
Note : il est préférable de nutiliser `Minz_Request` que dans les
contrôleurs. Il est probable que vous rencontriez cette méthode dans les
vues de FreshRSS, voire dans les modèles, mais sachez quil ne sagit
**pas** dune bonne pratique.
## Accéder aux paramètres de session
Laccès aux paramètres de session est étrangement similaire aux paramètres
GET / POST mais passe par la classe `Minz_Session` cette fois-ci ! Il ny a
pas dexemple ici car vous pouvez reprendre le précédent en changeant tous
les `Minz_Request` par des `Minz_Session`.
## Gestion des URL
Pour profiter pleinement du système de routage de Minz, il est fortement
déconseillé décrire les URL en dur dans votre code. Par exemple, la vue
suivante doit être évitée :
```html
<p>
Accéder à la page <a href="http://exemple.com?c=hello&amp;a=world">Hello world</a>!
</p>
```
Si un jour il est décidé dutiliser un système d'« url rewriting » pour
avoir des adresses au format <http://exemple.com/controller/action>, toutes
les adresses précédentes deviendraient ineffectives !
Préférez donc lutilisation de la classe `Minz_Url` et de sa méthode
`display()`. `Minz_Url::display()` prend en paramètre un tableau de la forme
suivante :
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
'params' => [
'foo' => 'bar',
],
];
// Affichera quelque chose comme .?c=hello&amp;a=world&amp;foo=bar
echo Minz_Url::display($url_array);
?>
```
Comme cela peut devenir un peu pénible à utiliser à la longue, surtout dans
les vues, il est préférable dutiliser le raccourci `_url()` :
```php
<?php
// Affichera la même chose que précédemment
echo _url('hello', 'world', 'foo', 'bar');
?>
```
Note : en règle générale, la forme raccourcie (`_url()`) doit être utilisée
dans les vues tandis que la forme longue (`Minz_Url::display()`) doit être
utilisée dans les contrôleurs.
## Redirections
Il est souvent nécessaire de rediriger un utilisateur vers une autre
page. Pour cela, la classe `Minz_Request` dispose dune autre méthode utile
: `forward()`. Cette méthode prend en argument le même format dURL que
celui vu juste avant.
Exemple de code :
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
];
// Indique à Minz de rediriger lutilisateur vers la page hello/world.
// Notez quil sagit dune redirection au sens Minz du terme, pas dune redirection que le navigateur va avoir à gérer (code HTTP 301 ou 302)
// Le code qui suit forward() va ainsi être exécuté !
Minz_Request::forward($url_array);
// Pour effectuer une redirection type 302, ajoutez "true".
// Le code qui suivra ne sera alors jamais exécuté.
Minz_Request::forward($url_array, true);
?>
```
Il est très fréquent de vouloir effectuer une redirection tout en affichant
un message à lutilisateur pour lui indiquer comment sest déroulée laction
effectuée juste avant (validation dun formulaire par exemple). Un tel
message est passé par une variable de session `notification` (note : nous
parlerons plutôt de « feedback » désormais pour éviter la confusion avec une
notification qui peut survenir à tout moment). Pour faciliter ce genre
daction très fréquente, il existe deux raccourcis qui effectuent tout deux
une redirection type 302 en affectant un message de feedback :
```php
<?php
$url_array = [
'c' => 'hello',
'a' => 'world',
];
$feedback_good = 'Tout sest bien passé !';
$feedback_bad = 'Oups, quelque chose na pas marché.';
Minz_Request::good($feedback_good, $url_array);
// ou
Minz_Request::bad($feedback_bad, $url_array);
?>
```
## Gestion de la traduction
Cette partie est [expliquée dans la page dédiée](/docs/fr/internationalization.md).
## Migration
Existing documentation includes:
* [How to manage migrations](migrations.md)

View File

@@ -0,0 +1,3 @@
# Migration
see [English documentation](/docs/en/developers/Minz/migrations.md)

View File

@@ -0,0 +1,79 @@
# Gestion de la traduction
Il est fréquent (et cest un euphémisme) de vouloir afficher des phrases à
lutilisateur. Dans lexemple précédent par exemple, nous affichions un
feedback à lutilisateur en fonction du résultat dune validation de
formulaire. Le problème est que FreshRSS possède des utilisateurs de
différentes nationalités. Il est donc nécessaire de pouvoir gérer
différentes langues pour ne pas rester cantonné à lAnglais ou au Français.
La solution consiste à utiliser la classe `Minz_Translate` qui permet de
traduire dynamiquement FreshRSS (ou toute application basée sur Minz). Avant
dutiliser ce module, il est nécessaire de savoir où trouver les chaînes de
caractères à traduire. Chaque langue possède son propre sous-répertoire dans
un répertoire parent nommé `i18n`. Par exemple, les fichiers de langue en
Français sont situés dans `i18n/fr/`. Il existe sept fichiers différents :
* `admin.php` pour tout ce qui est relatif à ladministration de FreshRSS ;
* `conf.php` pour laspect configuration ;
* `feedback.php` contient les traductions des messages de feedback ;
* `gen.php` stocke ce qui est global à FreshRSS (gen pour « general ») ;
* `index.php` pour la page principale qui liste les flux et la page « À propos » ;
* `install.php` contient les phrases relatives à linstallation de FreshRSS ;
* `sub.php` pour laspect gestion des abonnements (sub pour « subscription »).
Cette organisation permet de ne pas avoir un unique énorme fichier de
traduction.
Les fichiers de traduction sont assez simples : il sagit seulement de
retourner un tableau PHP contenant les traductions. Extrait du fichier
`app/i18n/fr/gen.php` :
```php
<?php
return array(
'action' => [
'actualize' => 'Actualiser',
'back_to_rss_feeds' => '← Retour à vos flux RSS',
'cancel' => 'Annuler',
'create' => 'Créer',
'disable' => 'Désactiver',
),
'freshrss' => array(
'_' => 'FreshRSS',
'about' => 'À propos de FreshRSS',
),
];
?>
```
Pour accéder à ces traductions, `Minz_Translate` va nous aider à laide de
sa méthode `Minz_Translate::t()`. Comme cela peut être un peu long à taper,
il a été introduit un raccourci qui **doit** être utilisé en toutes
circonstances : `_t()`. Exemple de code :
```html
<p>
<a href="<?= _url('index', 'index') ?>">
<?= _t('gen.action.back_to_rss_feeds') ?>
</a>
</p>
```
La chaîne à passer à la fonction `_t()` consiste en une série didentifiants
séparés par des points. Le premier identifiant indique de quel fichier on
veut extraire la traduction (dans notre cas présent, de `gen.php`), tandis
que les suivantes indiquent des entrées de tableaux. Ainsi `action` est une
entrée du tableau principal et `back_to_rss_feeds` est une entrée du tableau
`action`. Cela permet dorganiser encore un peu plus nos fichiers de
traduction.
Il existe un petit cas particulier qui permet parfois de se simplifier la
vie : le cas de lidentifiant `_`. Celui-ci doit nécessairement être présent
en bout de chaîne et permet de donner une valeur à lidentifiant de niveau
supérieur. Cest assez dur à expliquer mais très simple à comprendre. Dans
lexemple donné plus haut, un `_` est associé à la valeur `FreshRSS` : cela
signifie quil ny a pas besoin décrire `_t('gen.freshrss._')` mais
`_t('gen.freshrss')` suffit.