Système de billetterie avec PHP et MySQL





 Dans ce didacticiel, nous allons développer un système de billetterie avec PHP et MySQL. Un système de billetterie est un outil de service client que les entreprises peuvent utiliser pour gérer les demandes d'assistance sur leur site Web.

La structure du système de billetterie consistera en une page de navigation des billets, une page de création de billets et une page de visualisation des billets. Tous les billets seront stockés dans une base de données MySQL, que nous pourrons ensuite récupérer et remplir sur notre page Web avec HTML et PHP.

Le package Advanced comprend des fonctionnalités supplémentaires et un lien de téléchargement vers le code source.


1. Mise en route

Avant de commencer à programmer notre système de billetterie, nous devons nous assurer que nous avons un serveur Web entièrement fonctionnel avec PHP et MySQL installés.

1.1. Exigences

  • Je vous recommande de télécharger et d'installer XAMPP sur votre environnement de développement. Je vous suggère fortement de ne pas utiliser XAMPP sur votre environnement de production car il n'est pas adapté à cette fin.
  • Assurez-vous que votre serveur Web exécute PHP 5.4+. La dernière version de XAMPP sera pré-construite avec la dernière version de PHP, et vous ne devriez donc pas rencontrer de problèmes.
  • Téléchargez et installez un éditeur de code. Vous pouvez utiliser le Bloc-notes pour modifier les fichiers, mais je ne le recommande pas. Utilisez plutôt l'un des éléments suivants : Notepad++ , Visual Studio Code ou Atom .

1.2. Ce que vous apprendrez dans ce tutoriel

  • Afficher les enregistrements MySQL — Récupérez les tickets de la base de données et remplissez-les avec HTML5 et CSS3.
  • Conception de formulaire — Concevez un formulaire de création de ticket avec HTML5 et CSS3.
  • Gestion de la base de données - Exécutez des requêtes MySQL à l'aide de l'interface PDO (mise à jour des tickets, création de tickets, etc.).
  • Requêtes SQL préparées — Sécurisez vos requêtes et empêchez l'injection SQL avec des instructions préparées.
  • Modèle de base — Créez un système de modèle de base à l'aide des fonctions PHP (en-tête et pied de page).

1.3. Structure et configuration des fichiers

Nous devons démarrer notre serveur Web et créer les répertoires et les fichiers que nous allons utiliser pour notre système de billetterie. Si vous avez installé XAMPP, suivez les instructions ci-dessous.

  • Ouvrez le panneau de configuration XAMPP
  • À côté du module Apache, cliquez sur Démarrer
  • À côté du module MySQL, cliquez sur Démarrer
  • Accédez au répertoire d'installation de XAMPP ( C:\xampp )
  • Ouvrez le répertoire htdocs
  • Créez les répertoires et fichiers suivants :

Structure du fichier

\-- ticketsystem
    |-- style.css
    |-- index.php
    |-- create.php
    |-- view.php
    |-- functions.php

Chaque fichier contiendra les éléments suivants :

  • style.css — La feuille de style (CSS3) de notre système de billetterie, qui est utilisée pour formater notre contenu structuré (HTML).
  • index.php — Récupère tous les tickets de la base de données MySQL, itère les résultats et les affiche en conséquence.
  • create.php — Formulaire HTML qui sera utilisé pour créer des tickets et les insérer dans la base de données MySQL.
  • view.php — La page d'affichage contiendra toutes les informations relatives au ticket et consistera en des boutons qui mettront à jour le statut du ticket (fermer, résoudre, etc.) et les commentaires soumis par l'utilisateur.
  • functions.php — Ce fichier contiendra la fonction de connexion à la base de données MySQL et les fonctions d'en-tête et de pied de page.

2. Création de la base de données et configuration des tables

Nous devons créer la base de données MySQL et créer la table des tickets. Nous pouvons le faire avec phpMyAdmin (inclus avec XAMPP).

Accédez à phpMyAdmin (par exemple http://localhost/phpmyadmin/) dans votre navigateur et suivez les instructions ci-dessous.

  • Cliquez sur l' onglet Bases de données en haut
  • Sous Créer une base de données , tapez phpticket dans la zone de texte
  • Sélectionnez utf8_general_ci comme classement (UTF-8 est l'encodage par défaut dans HTML5)
  • Cliquez sur Créer

Lorsque la base de données est sélectionnée, cliquez sur l'onglet SQL et exécutez l'instruction suivante :

SQLCopie

CREATE TABLE IF NOT EXISTS `tickets` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `title` varchar(255) NOT NULL,
        `msg` text NOT NULL,
        `email` varchar(255) NOT NULL,
        `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
        `status` enum('open','closed','resolved') NOT NULL DEFAULT 'open',
        PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
 
INSERT INTO `tickets` (`id`, `title`, `msg`, `email`, `created`, `status`) VALUES (1, 'Test Ticket', 'This is your first ticket.', 'support@codeshack.io', '2020-06-10 13:06:17', 'open');
 
CREATE TABLE IF NOT EXISTS `tickets_comments` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `ticket_id` int(11) NOT NULL,
        `msg` text NOT NULL,
        `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
 
INSERT INTO `tickets_comments` (`id`, `ticket_id`, `msg`, `created`) VALUES (1, 1, 'This is a test comment.', '2020-06-10 16:23:39');

Les données que nous insérons dans les tables tickets et tickets_comments seront à des fins de test.

Le code SQL ci-dessus créera les tickets et la table tickets_comments . Voir la définition de chaque colonne ci-dessous.

des billets:

  • id — L'identifiant unique du ticket.
  • title — Le titre du ticket.
  • msg — Le message du ticket.
  • créé — La date à laquelle le ticket a été soumis.
  • status — Le statut du ticket, qui peut être défini comme ouvert, fermé ou résolu.

tickets_commentaires :

  • id — L'identifiant unique du ticket.
  • ticket_id — L'ID du ticket, qui sera utilisé pour associer les deux tables et créer une relation.
  • msg — Le message de commentaire.
  • créé — La date à laquelle le commentaire a été soumis.

Sur phpMyAdmin, la structure de la table des tickets devrait ressembler à ceci :

http://localhost/phpmyadmin




Et la table tickets_comments devrait ressembler à ceci :

http://localhost/phpmyadmin/





3. Conception du système de billetterie avec CSS3

La feuille de style formatera la mise en page de notre système de billetterie. Avec CSS (Cascading Style Sheets), nous pouvons modifier la police, le jeu de couleurs, les tailles, etc.

Modifiez le fichier style.css et ajoutez :

CSSCopie

* {
    box-sizing: border-box;
    font-family: -apple-system, BlinkMacSystemFont, "segoe ui", roboto, oxygen, ubuntu, cantarell, "fira sans", "droid sans", "helvetica neue", Arial, sans-serif;
    font-size: 16px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
body {
    background-color: #FFFFFF;
    margin: 0;
}
.navtop {
    background-color: #3f69a8;
    height: 60px;
    width: 100%;
    border: 0;
}
.navtop div {
    display: flex;
    margin: 0 auto;
    width: 1000px;
    height: 100%;
}
.navtop div h1, .navtop div a {
    display: inline-flex;
    align-items: center;
}
.navtop div h1 {
    flex: 1;
    font-size: 24px;
    padding: 0;
    margin: 0;
    color: #ecf0f6;
    font-weight: normal;
}
.navtop div a {
    padding: 0 20px;
    text-decoration: none;
    color: #c5d2e5;
    font-weight: bold;
}
.navtop div a i {
    padding: 2px 8px 0 0;
}
.navtop div a:hover {
    color: #ecf0f6;
}
.content {
    width: 1000px;
    margin: 0 auto;
}
.content h2 {
    margin: 0;
    padding: 25px 0;
    font-size: 22px;
    border-bottom: 1px solid #ebebeb;
    color: #666666;
}
.btns {
    display: flex;
}
.btns .btn {
    display: inline-block;
    text-decoration: none;
    background-color: #38b673;
    font-weight: bold;
    font-size: 14px;
    border-radius: 5px;
    color: #FFFFFF;
    padding: 10px 15px;
    margin: 15px 10px 15px 0;
}
.btns .btn:hover {
    background-color: #32a367;
}
.btns .btn.red {
    background-color: #b63838;
}
.btns .btn.red:hover {
    background-color: #a33232;
}
.home .tickets-list {
    display: flex;
    flex-flow: column;
}
.home .tickets-list .ticket {
    padding: 15px 0;
    width: 100%;
    border-bottom: 1px solid #ebebeb;
    display: flex;
    text-decoration: none;
}
.home .tickets-list .ticket .con {
    display: flex;
    justify-content: center;
    flex-flow: column;
}
.home .tickets-list .ticket i {
    text-align: center;
    width: 80px;
    color: #b3b3b3;
}
.home .tickets-list .ticket .title {
    font-weight: 600;
    color: #666666;
}
.home .tickets-list .ticket .msg {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    max-width: 400px;
    color: #999999;
    font-size: 14px;
}
.home .tickets-list .ticket .created {
    flex-grow: 1;
    align-items: flex-end;
    color: #999999;
    font-size: 14px;
}
.home .tickets-list .ticket:last-child {
    border-bottom: 0;
}
.home .tickets-list .ticket:hover {
    background-color: #fcfcfc;
}
.view h2 .open, .view h2 .resolved {
    color: #38b673;
}
.view h2 .closed {
    color: #b63838;
}
.view .ticket {
    padding: 20px 0;
}
.view .ticket .created {
    color: gray;
}
.view .comments {
    margin-top: 15px;
    border-top: 1px solid #ebebeb;
    padding: 25px 0;
}
.view .comments .comment {
    display: flex;
    padding-bottom: 5px;
}
.view .comments .comment div {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    width: 70px;
    color: #e6e6e6;
    transform: scaleX(-1);
}
.view .comments .comment p {
    margin: 0 0 20px 0;
}
.view .comments .comment p span {
    display: flex;
    font-size: 14px;
    padding-bottom: 5px;
    color: gray;
}
.create form, .view form {
    padding: 15px 0;
    display: flex;
    flex-flow: column;
    width: 400px;
}
.create form label, .view form label {
    display: inline-flex;
    width: 100%;
    padding: 10px 0;
    margin-right: 25px;
}
.create form input, .create form textarea, .view form input, .view form textarea {
    padding: 10px;
    width: 100%;
    margin-right: 25px;
    margin-bottom: 15px;
    border: 1px solid #cccccc;
}
.create form textarea, .view form textarea {
    height: 200px;
}
.create form input[type="submit"], .view form input[type="submit"] {
    display: block;
    background-color: #38b673;
    border: 0;
    font-weight: bold;
    font-size: 14px;
    color: #FFFFFF;
    cursor: pointer;
    width: 200px;
    margin-top: 15px;
    border-radius: 5px;
}
.create form input[type="submit"]:hover, .view form input[type="submit"]:hover {
    background-color: #32a367;
}

C'est essentiellement tout ce que nous devons ajouter à notre feuille de style. N'hésitez pas à le personnaliser à votre guise.

4. Création du fichier de fonctions

Le fichier de fonctions contiendra toutes les fonctions que nous allons utiliser dans notre système de billetterie, notamment la fonction de connexion à la base de données PDO, la fonction d'en-tête de modèle et la fonction de pied de page de modèle.

Editez le fichier functions.php et ajoutez :

PHPCopie

<?php
function pdo_connect_mysql() {
    // Update the details below with your MySQL details
    $DATABASE_HOST = 'localhost';
    $DATABASE_USER = 'root';
    $DATABASE_PASS = '';
    $DATABASE_NAME = 'phpticket';
    try {
        return new PDO('mysql:host=' . $DATABASE_HOST . ';dbname=' . $DATABASE_NAME . ';charset=utf8', $DATABASE_USER, $DATABASE_PASS);
    } catch (PDOException $exception) {
        // If there is an error with the connection, stop the script and display the error.
        exit('Failed to connect to database!');
    }
}

La fonction ci-dessus que nous utiliserons pour nous connecter à notre base de données MySQL en utilisant l'interface PDO. Les variables de base de données doivent refléter vos identifiants de base de données MySQL.

Ajouter après :

PHPCopie

// Template header, feel free to customize this
function template_header($title) {
echo <<<EOT
<!DOCTYPE html>
<html>
        <head>
                <meta charset="utf-8">
                <title>$title</title>
                <link href="style.css" rel="stylesheet" type="text/css">
                <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
        </head>
        <body>
    <nav class="navtop">
        <div>
                <h1>Ticketing System</h1>
            <a href="index.php"><i class="fas fa-ticket-alt"></i>Tickets</a>
        </div>
    </nav>
EOT;
}

Ceci est notre fonction d'en-tête de modèle. Au lieu de répéter le même code dans chaque fichier, nous pouvons simplement exécuter la fonction ci-dessus.

Ajouter après :

PHPCopie

// Template footer
function template_footer() {
echo <<<EOT
    </body>
</html>
EOT;
}
?>

Semblable à la fonction d'en-tête de modèle, mais à la place, la fonction de pied de page de modèle ajoutera les balises de fermeture à notre modèle. Le code du modèle que nous ajoutons dans tous nos fichiers sera placé entre ces deux fonctions.

5. Création de la page d'accueil

La page d'accueil sera composée de la liste peuplée de tickets avec des liens qui redirigeront l'utilisateur vers la page du ticket. Le "bouton créer un ticket" sera également inclus sur cette page. Tous les tickets sont extraits de la base de données MySQL.

Modifiez index.php et ajoutez :

PHPCopie

<?php
include 'functions.php';
// Connect to MySQL using the below function
$pdo = pdo_connect_mysql();
// MySQL query that retrieves  all the tickets from the databse
$stmt = $pdo->prepare('SELECT * FROM tickets ORDER BY created DESC');
$stmt->execute();
$tickets = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>

La première chose que nous devons faire est d'inclure le fichier de fonctions car nous utiliserons toutes les fonctions de ce fichier, puis d'exécuter une requête SQL qui récupère tous les tickets de notre table de tickets - classés par date de création du ticket ( descendant).

Les résultats sont ensuite stockés dans un tableau que nous pouvons utiliser ultérieurement pour remplir avec HTML.

Ajouter après :

PHPCopie

<?=template_header('Tickets')?>
 
<div class="content home">
 
        <h2>Tickets</h2>
 
        <p>Welcome to the index page. You can view the list of tickets below.</p>
 
        <div class="btns">
                <a href="create.php" class="btn">Create Ticket</a>
        </div>
 
        <div class="tickets-list">
                <?php foreach ($tickets as $ticket): ?>
                <a href="view.php?id=<?=$ticket['id']?>" class="ticket">
                       <span class="con">
                               <?php if ($ticket['status'] == 'open'): ?>
                               <i class="far fa-clock fa-2x"></i>
                               <?php elseif ($ticket['status'] == 'resolved'): ?>
                               <i class="fas fa-check fa-2x"></i>
                               <?php elseif ($ticket['status'] == 'closed'): ?>
                               <i class="fas fa-times fa-2x"></i>
                               <?php endif; ?>
                       </span>
                       <span class="con">
                               <span class="title"><?=htmlspecialchars($ticket['title'], ENT_QUOTES)?></span>
                               <span class="msg"><?=htmlspecialchars($ticket['msg'], ENT_QUOTES)?></span>
                       </span>
                       <span class="con created"><?=date('F dS, G:ia', strtotime($ticket['created']))?></span>
                </a>
                <?php endforeach; ?>
        </div>
 
</div>
 
<?=template_footer()?>

Avec le code ci-dessus, nous exécutons les fonctions d'en-tête et de pied de page du modèle, et entre ces 2 fonctions, nous itérons les tickets à l'aide d'une boucle foreach et les remplissons en conséquence à l'aide de la balise de lien hypertexte HTML.

Nous utilisons la fonction htmlspecialchars pour empêcher les attaques XSS, qui convertiront les caractères spéciaux en entités HTML et donc toute attaque présentée sera convertie.

C'est tout ce que nous devons faire pour la page d'accueil. Si nous naviguons vers http://localhost/ticketsystem/index.php dans notre navigateur, nous devrions voir ce qui suit :

http://localhost/ticketsystem/index.php



6. Création de la page Créer un ticket

La page Créer un ticket contiendra un formulaire HTML que les visiteurs pourront utiliser pour soumettre des tickets.

Modifiez le fichier create.php et ajoutez :

PHPCopie

<?php
include 'functions.php';
$pdo = pdo_connect_mysql();
// Output message variable
$msg = '';
// Check if POST data exists (user submitted the form)
if (isset($_POST['title'], $_POST['email'], $_POST['msg'])) {
    // Validation checks... make sure the POST data is not empty
    if (empty($_POST['title']) || empty($_POST['email']) || empty($_POST['msg'])) {
        $msg = 'Please complete the form!';
    } else if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
        $msg = 'Please provide a valid email address!';
    } else {
        // Insert new record into the tickets table
        $stmt = $pdo->prepare('INSERT INTO tickets (title, email, msg) VALUES (?, ?, ?)');
        $stmt->execute([ $_POST['title'], $_POST['email'], $_POST['msg'] ]);
        // Redirect to the view ticket page, the user will see their created ticket on this page
        header('Location: view.php?id=' . $pdo->lastInsertId());
    }
}
?>

Lors de la soumission du formulaire, les données sont transférées à notre serveur en utilisant la méthode de requête POST. Comme vous pouvez le voir dans le code ci-dessus, nous utilisons le$_POSTtableau pour récupérer les données. Si les variables POST existent et ne sont pas vides, insérez les données dans la table des tickets MySQL.

La fonction d' en-tête redirigera l'utilisateur vers sa page de ticket lors de la soumission du formulaire.

Ajouter après :

PHPCopie

<?=template_header('Create Ticket')?>
 
<div class="content create">
        <h2>Create Ticket</h2>
    <form action="create.php" method="post">
        <label for="title">Title</label>
        <input type="text" name="title" placeholder="Title" id="title" required>
        <label for="email">Email</label>
        <input type="email" name="email" placeholder="johndoe@example.com" id="email" required>
        <label for="msg">Message</label>
        <textarea name="msg" placeholder="Enter your message here..." id="msg" required></textarea>
        <input type="submit" value="Create">
    </form>
    <?php if ($msg): ?>
    <p><?=$msg?></p>
    <?php endif; ?>
</div>
 
<?=template_footer()?>

Le code ci-dessus est le modèle de formulaire HTML qui se compose des éléments input, label et textarea. le$msg la variable affichera les erreurs de validation.

Si nous cliquons sur le bouton Créer un ticket sur la page d'accueil, nous devrions voir :

http://localhost/ticketsystem/create.php



7. Création de la page Afficher le ticket

Sur la page de visualisation du ticket, l'utilisateur pourra voir tous les détails associés à son ticket ainsi que les commentaires et les boutons permettant de modifier le statut du ticket (ouvert, fermé, résolu, etc.).

Modifiez le fichier view.php et ajoutez :

PHPCopie

<?php
include 'functions.php';
// Connect to MySQL using the below function
$pdo = pdo_connect_mysql();
// Check if the ID param in the URL exists
if (!isset($_GET['id'])) {
    exit('No ID specified!');
}
// MySQL query that selects the ticket by the ID column, using the ID GET request variable
$stmt = $pdo->prepare('SELECT * FROM tickets WHERE id = ?');
$stmt->execute([ $_GET['id'] ]);
$ticket = $stmt->fetch(PDO::FETCH_ASSOC);
// Check if ticket exists
if (!$ticket) {
    exit('Invalid ticket ID!');
}

Pour afficher cette page, le paramètre d'ID de ticket doit être inclus dans l'URL car nous utilisons une requête GET pour déterminer l'ID de ticket, et nous pouvons ensuite récupérer l'ID avec PHP en utilisant le $_GET['id'] variable.

L'instruction préparée empêchera l'injection SQL et récupérera le ticket à partir de la table des tickets MySQL. Si le ticket n'existe pas, le script se terminera et affichera l'erreur.

Ajouter après :

PHPCopie

// Update status
if (isset($_GET['status']) && in_array($_GET['status'], array('open', 'closed', 'resolved'))) {
    $stmt = $pdo->prepare('UPDATE tickets SET status = ? WHERE id = ?');
    $stmt->execute([ $_GET['status'], $_GET['id'] ]);
    header('Location: view.php?id=' . $_GET['id']);
    exit;
}

Le code ci-dessus mettra à jour le statut du ticket, mais uniquement si le paramètre GET existe et que la valeur est : ouvert, fermé ou résolu. Le code ne s'exécutera que lorsque l'utilisateur cliquera sur le bouton Fermer ou Résoudre .

Ajouter après :

PHPCopie

// Check if the comment form has been submitted
if (isset($_POST['msg']) && !empty($_POST['msg'])) {
    // Insert the new comment into the "tickets_comments" table
    $stmt = $pdo->prepare('INSERT INTO tickets_comments (ticket_id, msg) VALUES (?, ?)');
    $stmt->execute([ $_GET['id'], $_POST['msg'] ]);
    header('Location: view.php?id=' . $_GET['id']);
    exit;
}
$stmt = $pdo->prepare('SELECT * FROM tickets_comments WHERE ticket_id = ? ORDER BY created DESC');
$stmt->execute([ $_GET['id'] ]);
$comments = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>

Le code ci-dessus gérera les commentaires sur la page du ticket. Les utilisateurs peuvent utiliser la section des commentaires pour répondre aux tickets. Tous les commentaires sont récupérés à l'aide de l'ID du ticket et sont stockés dans letickets_commentairestableau.

Ajouter après :

PHPCopie

<?=template_header('Ticket')?>
 
<div class="content view">
 
        <h2><?=htmlspecialchars($ticket['title'], ENT_QUOTES)?> <span class="<?=$ticket['status']?>">(<?=$ticket['status']?>)</span></h2>
 
    <div class="ticket">
        <p class="created"><?=date('F dS, G:ia', strtotime($ticket['created']))?></p>
        <p class="msg"><?=nl2br(htmlspecialchars($ticket['msg'], ENT_QUOTES))?></p>
    </div>
 
    <div class="btns">
        <a href="view.php?id=<?=$_GET['id']?>&status=closed" class="btn red">Close</a>
        <a href="view.php?id=<?=$_GET['id']?>&status=resolved" class="btn">Resolve</a>
    </div>
 
    <div class="comments">
        <?php foreach($comments as $comment): ?>
        <div class="comment">
            <div>
                <i class="fas fa-comment fa-2x"></i>
            </div>
            <p>
                <span><?=date('F dS, G:ia', strtotime($comment['created']))?></span>
                <?=nl2br(htmlspecialchars($comment['msg'], ENT_QUOTES))?>
            </p>
        </div>
        <?php endforeach; ?>
        <form action="" method="post">
            <textarea name="msg" placeholder="Enter your comment..."></textarea>
            <input type="submit" value="Post Comment">
        </form>
    </div>
 
</div>
 
<?=template_footer()?>

Le code ci-dessus est le modèle de cette page.

Si nous revenons à la page Tickets et que nous cliquons sur Ticket test , nous devrions voir ce qui suit :

http://localhost/ticketsystem/view.php?id=1



Conclusion

Toutes nos félicitations! Vous avez créé avec succès un système de billetterie avec PHP et MySQL. Vous recherchez un système de billetterie plus avancé ? Envisagez d'acheter le package avancé, qui vous aidera à prendre en charge les futurs développements et didacticiels.

Et ensuite ? Envisagez d'implémenter des fonctionnalités plus robustes sur le système avec les techniques que vous avez apprises dans ce didacticiel.

Si vous avez apprécié cet article, pensez à le partager sur les réseaux sociaux en utilisant les boutons sociaux ci-dessous.

Si vous souhaitez nous soutenir, envisagez d'acheter le package avancé ci-dessous car cela nous aidera grandement à créer plus de tutoriels et à maintenir notre serveur opérationnel. Le package avancé comprend un code amélioré et des fonctionnalités plus robustes.

Enregistrer un commentaire

Post a Comment (0)

Plus récente Plus ancienne