Initial commit

This commit is contained in:
2025-11-01 21:47:32 +01:00
commit a32bed95dc
16 changed files with 514 additions and 0 deletions

9
Dockerfile Normal file
View File

@@ -0,0 +1,9 @@
FROM php:8.2-apache
LABEL authors="youyou"
COPY . /var/www/html
WORKDIR /var/www/html
RUN docker-php-ext-install pdo pdo_mysql
EXPOSE 80

52
README.md Normal file
View File

@@ -0,0 +1,52 @@
# Projet CMS Simplifié
### Technologies utilisées
Ce projet a été construit avec les technologies suivantes :
![HTML5](https://img.shields.io/badge/HTML5-E34F26?style=for-the-badge&logo=html5&logoColor=white)
![CSS3](https://img.shields.io/badge/CSS3-1572B6?style=for-the-badge&logo=css3&logoColor=white)
![PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white)
![MySQL](https://img.shields.io/badge/MySQL-4479A1?style=for-the-badge&logo=mysql&logoColor=white)
## Lancement des dockers MySql et Php
### Création d'un réseau pour que les services docker puissent communiquer
```bash
docker network create -d bridge CMS-bridge
```
### Build BDD
Builder la BDD MySql avec le Dockerfile présent dans le répertoire bdd
```bash
docker build -t cms_mysql .
```
Lancer l'image créée en le connectant au réseau précédemment créé
```bash
docker run -d --name CMS_mysql -p 3306:3306 --network=CMS-bridge cms_mysql:latest
```
### Build PHP-Apache
Builder PHP Apache avec le Dockerfile présent à la racine du projet
```bash
docker build -t cms_php .
```
Lancer l'image créée en le connectant au réseau précédemment créé
```bash
docker run -d --name CMS_php -p 8080:80 --network=CMS-bridge cms_php:latest
```
Pour éviter de lancer les commandes à chaque fois, un script launch-dockers.sh a executer en 'sudo' est disponible.

47
admin/add.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
require '../include/db.php';
require '../include/authenticator.php';
requireLogin();
$errors = [];
$titre = '';
$contenu = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$titre = trim($_POST['titre'] ?? '');
$contenu = trim($_POST['contenu'] ?? '');
if ($titre === '' || $contenu === '') {
$errors[] = 'Tous les champs sont obligatoires.';
} else {
$stmt = $pdo->prepare('INSERT INTO articles (titre, contenu, date_creation) VALUES (:titre, :contenu, :date)');
$stmt->execute([
':titre' => $titre,
':contenu' => $contenu,
':date' => date('Y-m-d H:i:s'),
]);
header('Location:board.php');
exit;
}
}
?>
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Ajouter un article</title>
<link rel="stylesheet" href="/assets/style.css">
</head>
<body>
<h1>Ajouter un article</h1>
<?php foreach ($errors as $e): ?>
<p class="error"><?= htmlspecialchars($e) ?></p>
<?php endforeach; ?>
<form method="post">
<label>Titre<br><input type="text" name="titre" value="<?= htmlspecialchars($titre) ?>" required></label><br>
<label>Contenu<br><textarea name="contenu" rows="10" required><?= htmlspecialchars($contenu) ?></textarea></label><br>
<button type="submit">Publier</button>
<a href="board.php">Annuler</a>
</form>
</body>
</html>

28
admin/board.php Normal file
View File

@@ -0,0 +1,28 @@
<?php
require '../include/db.php';
require '../include/authenticator.php';
requireLogin();
$stmt = $pdo->query('SELECT * FROM articles ORDER BY date_creation DESC');
$articles = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="fr">
<head><meta charset="UTF-8"><title>Admin - Tableau de bord</title></head>
<body>
<h1>Tableau de bord</h1>
<a href="add.php">Ajouter un article</a> | <a href="logout.php">Se déconnecter</a>
<table border="1">
<tr><th>ID</th><th>Titre</th><th>Actions</th></tr>
<?php foreach ($articles as $a): ?>
<tr>
<td><?= $a['id'] ?></td>
<td><?= htmlspecialchars($a['titre']) ?></td>
<td>
<a href="modif.php?id=<?= $a['id'] ?>">Modifier</a> |
<a href="delete.php?id=<?= $a['id'] ?>">Supprimer</a>
</td>
</tr>
<?php endforeach; ?>
</table>
</body>
</html>

44
admin/delete.php Normal file
View File

@@ -0,0 +1,44 @@
<?php
require '../include/db.php';
require '../include/authenticator.php';
requireLogin();
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id <= 0) {
header('Location:board.php');
exit;
}
$stmt = $pdo->prepare('SELECT id, titre FROM articles WHERE id = :id');
$stmt->execute([':id' => $id]);
$article = $stmt->fetch();
if (!$article) {
header('Location: board.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['confirm']) && $_POST['confirm'] === 'yes') {
$d = $pdo->prepare('DELETE FROM articles WHERE id = :id');
$d->execute([':id' => $id]);
}
header('Location: board.php');
exit;
}
?>
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Supprimer l'article</title>
<link rel="stylesheet" href="/assets/style.css">
</head>
<body>
<h1>Supprimer l'article</h1>
<p>Êtes-vous sûr de vouloir supprimer : <strong><?= htmlspecialchars($article['titre']) ?></strong> ?</p>
<form method="post">
<button type="submit" name="confirm" value="yes">Oui, supprimer</button>
<a href="board.php">Annuler</a>
</form>
</body>
</html>

36
admin/login.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
<?php
require '../include/db.php';
require '../include/authenticator.php';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (checkLogin($pdo, $_POST['login'], $_POST['password'])) {
header('Location: board.php');
exit;
} else {
$error = 'Identifiants incorrects';
}
}
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Connexion</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<nav>
<a href="../index.php">Accueil</a>
</nav>
<h1>Connexion</h1>
<form method="post">
<input type="text" name="login" placeholder="Login" required><br>
<input type="password" name="password" placeholder="Mot de passe" required><br>
<button type="submit">Se connecter</button>
</form>
<p class="error"><?= $error ?></p>
</body>
</html>

18
admin/logout.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
require '../include/authenticator.php';
$_SESSION = [];
if (!function_exists('logout_user')) {
$_SESSION = [];
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params['path'], $params['domain'], $params['secure'], $params['httponly']);
}
session_destroy();
}
header('Location: ../index.php');
exit;
?>

57
admin/modif.php Normal file
View File

@@ -0,0 +1,57 @@
<?php
global $pdo;
require '../include/db.php';
require '../include/authenticator.php';
requireLogin();
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id <= 0) {
header('Location: board.php');
exit;
}
$stmt = $pdo->prepare('SELECT * FROM articles WHERE id = :id');
$stmt->execute([':id' => $id]);
$article = $stmt->fetch();
if (!$article) {
header('Location: board.php');
exit;
}
$errors = [];
$titre = $article['titre'];
$contenu = $article['contenu'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$titre = trim($_POST['titre'] ?? '');
$contenu = trim($_POST['contenu'] ?? '');
if ($titre === '' || $contenu === '') {
$errors[] = 'Tous les champs sont obligatoires.';
} else {
$u = $pdo->prepare('UPDATE articles SET titre = :titre, contenu = :contenu WHERE id = :id');
$u->execute([':titre' => $titre, ':contenu' => $contenu, ':id' => $id]);
header('Location: board.php');
exit;
}
}
?>
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Modifier l'article</title>
<link rel="stylesheet" href="/assets/style.css">
</head>
<body>
<h1>Modifier l'article</h1>
<?php foreach ($errors as $e): ?>
<p class="error"><?= htmlspecialchars($e) ?></p>
<?php endforeach; ?>
<form method="post">
<label>Titre<br><input type="text" name="titre" value="<?= htmlspecialchars($titre) ?>" required></label><br>
<label>Contenu<br><textarea name="contenu" rows="10" required><?= htmlspecialchars($contenu) ?></textarea></label><br>
<button type="submit">Enregistrer</button>
<a href="board.php">Annuler</a>
</form>
</body>
</html>

17
article.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
require 'include/db.php';
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
$stmt = $pdo->prepare('SELECT * FROM articles WHERE id = ?');
$stmt->execute([$id]);
$article = $stmt->fetch();
if (!$article) { http_response_code(404); die('<h1>404 - Article introuvable</h1>'); }
?>
<!DOCTYPE html>
<html lang="fr">
<head><meta charset="UTF-8"><title><?= htmlspecialchars($article['titre']) ?></title></head>
<body>
<h1><?= htmlspecialchars($article['titre']) ?></h1>
<p><?= nl2br(htmlspecialchars($article['contenu'])) ?></p>
<a href="index.php">Retour</a>
</body>
</html>

66
assets/style.css Normal file
View File

@@ -0,0 +1,66 @@
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
background-color: #f4f4f4;
color: #333;
}
header {
background: #333;
color: #fff;
padding: 10px 0;
text-align: center;
margin-bottom: 20px;
}
h1 {
color: #444;
border-bottom: 2px solid #ccc;
padding-bottom: 10px;
margin-top: 0;
}
article {
background: #fff;
padding: 15px;
margin-bottom: 15px;
border: 1px solid #ddd;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
article h2 a {
color: #007BFF;
text-decoration: none;
}
article h2 a:hover {
text-decoration: underline;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table th, table td {
padding: 10px;
border: 1px solid #ccc;
text-align: left;
}
table th {
background-color: #e2e2e2;
}
.error {
color: red;
font-weight: bold;
border: 1px solid red;
padding: 10px;
background: #ffe6e6;
border-radius: 5px;
}

8
bdd/Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
FROM mysql
LABEL authors="youyou"
ENV MYSQL_ROOT_PASSWORD='passwordRoot'
COPY ./init.sql /docker-entrypoint-initdb.d/
EXPOSE 3306

20
bdd/init.sql Normal file
View File

@@ -0,0 +1,20 @@
CREATE DATABASE IF NOT EXISTS cms_simpli CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE cms_simpli;
CREATE TABLE utilisateur (
id INT AUTO_INCREMENT PRIMARY KEY,
login VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL
);
CREATE TABLE articles (
id INT AUTO_INCREMENT PRIMARY KEY,
titre VARCHAR(255) NOT NULL,
contenu TEXT NOT NULL,
date_creation DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO utilisateur (login, password) VALUES ('admin', '$2y$10$OVqu798zF7FF36HER0nZ9uOJ5tuuTR.kwPK2GTiqlPPYzR2szGzB6');

32
include/authenticator.php Normal file
View File

@@ -0,0 +1,32 @@
<?php
session_start();
function isLogged(): bool
{
return isset($_SESSION['user']);
}
function checkLogin(PDO $pdo, $login, $password): bool
{
$stmt = $pdo->prepare('SELECT * FROM utilisateur WHERE login = ?');
$stmt->execute([$login]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user'] = $user['login'];
return true;
}
return false;
}
function requireLogin() {
if (!isLogged()) {
header('Location: login.php');
exit;
}
}
?>

13
include/db.php Normal file
View File

@@ -0,0 +1,13 @@
<?php
$host = 'CMS_mysql'; // nom du conteneur MySQL (dans le réseau Docker)
$dbname = 'cms_simpli';
$user = 'root';
$pass = 'passwordRoot';
$charset = 'utf8mb4';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die('Erreur de connexion : ' . $e->getMessage());
}

42
index.php Normal file
View File

@@ -0,0 +1,42 @@
<?php
require 'include/db.php';
$stmt = $pdo->query('SELECT * FROM articles ORDER BY date_creation DESC LIMIT 10');
$articles = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Accueil - CMS</title>
<link rel="stylesheet" href="assets/style.css">
</head>
<body>
<header>
<nav>
<a href="index.php">Accueil</a> |
<a href="admin/login.php">Administratreur</a>
</nav>
</header>
<main>
<h1>Articles</h1>
<?php if (empty($articles)): ?>
<p>CHEF ATTEND JE TROUVE L'INSPI POUR la SUITE</p>
<?php endif; ?>
<?php foreach ($articles as $a): ?>
<article>
<h2><a href="article.php?id=<?= $a['id'] ?>"><?= htmlspecialchars($a['titre']) ?></a></h2>
<small>Publié le <?= date('d/m/Y', strtotime($a['date_creation'])) ?></small>
<p><?= substr(htmlspecialchars($a['contenu']), 0, 200) ?>...</p>
<p><a href="article.php?id=<?= $a['id'] ?>">Lire la suite...</a></p>
</article>
<?php endforeach; ?>
</main>
<footer>
<p>&copy; <?= date('Y') ?> CMS. Tous droits réservés PAR MOI.</p>
</footer>
</body>
</html>

25
launch-dockers.sh Normal file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
docker stop CMS_mysql
docker stop CMS_php
docker rm CMS_mysql
docker rm CMS_php
docker network rm CMS-bridge
docker network create -d bridge CMS-bridge
cd bdd
docker build -t cms_mysql .
docker run -d --name CMS_mysql -p 3306:3306 --network=CMS-bridge cms_mysql:latest
cd ..
docker build -t cms_php .
docker run -d --name CMS_php -p 8080:80 --network=CMS-bridge cms_php:latest