feat: stockage articles en fichiers Markdown, SSO intégré, URLs propres
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
Options -Indexes
|
||||
DirectoryIndex index.php
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
# Fichiers et répertoires réels servis directement
|
||||
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -d
|
||||
RewriteRule ^ - [L]
|
||||
|
||||
# URL propre pour les articles : /post/<slug>
|
||||
RewriteRule ^post/([a-z0-9][a-z0-9-]*)/?$ /index.php?action=view&slug=$1 [L,QSA]
|
||||
|
||||
# Ajoute .php si le fichier correspondant existe
|
||||
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
|
||||
RewriteRule ^(.+?)/?$ /$1.php [L,QSA]
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
define('BASE_PATH', realpath(__DIR__ . '/../'));
|
||||
|
||||
$uuid = $_GET['uuid'] ?? '';
|
||||
$name = $_GET['name'] ?? '';
|
||||
|
||||
// Valide le format UUID v4
|
||||
if (!preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $uuid)) {
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Sécurise le nom de fichier (pas de traversal)
|
||||
$name = basename($name);
|
||||
if ($name === '' || $name[0] === '.') {
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$path = BASE_PATH . '/data/' . $uuid . '/files/' . $name;
|
||||
|
||||
if (!is_file($path)) {
|
||||
http_response_code(404);
|
||||
exit;
|
||||
}
|
||||
|
||||
$mime = mime_content_type($path) ?: 'application/octet-stream';
|
||||
header('Content-Type: ' . $mime);
|
||||
header('Content-Length: ' . filesize($path));
|
||||
header('Cache-Control: public, max-age=31536000, immutable');
|
||||
readfile($path);
|
||||
exit;
|
||||
+152
-6
@@ -1,16 +1,162 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
define('BASE_PATH', realpath(__DIR__ . '/../'));
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
$isHttps = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
|
||||
session_set_cookie_params(['lifetime' => 0, 'path' => '/', 'secure' => $isHttps, 'httponly' => true, 'samesite' => 'Lax']);
|
||||
session_start();
|
||||
}
|
||||
|
||||
require_once BASE_PATH . '/src/helpers.php';
|
||||
require_once BASE_PATH . '/src/auth.php';
|
||||
require_once BASE_PATH . '/config/config.php';
|
||||
require_once BASE_PATH . '/src/db.php';
|
||||
require_once BASE_PATH . '/src/PostManager.php';
|
||||
require_once BASE_PATH . '/src/ArticleManager.php';
|
||||
|
||||
$postManager = new PostManager($db);
|
||||
$articles = new ArticleManager(BASE_PATH . '/data');
|
||||
|
||||
ob_start();
|
||||
$action = $_GET['action'] ?? 'list';
|
||||
$uuid = $_GET['uuid'] ?? '';
|
||||
$slug = $_GET['slug'] ?? '';
|
||||
|
||||
$posts = $postManager->getAll();
|
||||
require_once BASE_PATH . '/templates/post_list.php';
|
||||
switch ($action) {
|
||||
|
||||
case 'create':
|
||||
requireAuth();
|
||||
|
||||
$title = $_POST['title'] ?? '';
|
||||
$content = $_POST['content'] ?? '';
|
||||
$postSlug = $_POST['slug'] ?? '';
|
||||
$published = isset($_POST['published']);
|
||||
$published_at = str_replace('T', ' ', $_POST['published_at'] ?? date('Y-m-d H:i:s'));
|
||||
$errors = [];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (trim($title) === '') {
|
||||
$errors[] = 'Le titre est obligatoire.';
|
||||
}
|
||||
if (empty($errors)) {
|
||||
$newUuid = $articles->create($title, $content, $published, $postSlug, $published_at);
|
||||
|
||||
foreach ($_FILES['files']['tmp_name'] ?? [] as $i => $tmpName) {
|
||||
if ($_FILES['files']['error'][$i] === UPLOAD_ERR_OK) {
|
||||
$articles->addFile($newUuid, [
|
||||
'name' => $_FILES['files']['name'][$i],
|
||||
'tmp_name' => $tmpName,
|
||||
'error' => $_FILES['files']['error'][$i],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
header('Location: /');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$formAction = '/?action=create';
|
||||
$action = 'create';
|
||||
include BASE_PATH . '/templates/post_form.php';
|
||||
break;
|
||||
|
||||
case 'view':
|
||||
$article = $slug !== '' ? $articles->getBySlug($slug) : null;
|
||||
if (!$article) {
|
||||
http_response_code(404);
|
||||
echo 'Article introuvable.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$files = $articles->getFiles($article['uuid']);
|
||||
|
||||
// Résout les chemins de fichiers relatifs dans le contenu
|
||||
$rawContent = $articles->resolveFileUrls($article['uuid'], $article['content']);
|
||||
|
||||
include BASE_PATH . '/templates/post_view.php';
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
requireAuth();
|
||||
|
||||
$article = $articles->getByUuid($uuid);
|
||||
if (!$article) {
|
||||
http_response_code(404);
|
||||
echo 'Article introuvable.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$title = $_POST['title'] ?? $article['title'];
|
||||
$content = $_POST['content'] ?? $article['content'];
|
||||
$postSlug = $_POST['slug'] ?? $article['slug'];
|
||||
$published = isset($_POST['published']) ? true : $article['published'];
|
||||
$published_at = $_POST['published_at']
|
||||
?? date('Y-m-d\TH:i', strtotime((string)($article['published_at'] ?? 'now')));
|
||||
$errors = [];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (trim($title) === '') {
|
||||
$errors[] = 'Le titre est obligatoire.';
|
||||
}
|
||||
if (empty($errors)) {
|
||||
$articles->update(
|
||||
$uuid,
|
||||
$title,
|
||||
$content,
|
||||
$published,
|
||||
$_POST['slug'] ?? '',
|
||||
str_replace('T', ' ', $_POST['published_at'] ?? '')
|
||||
);
|
||||
|
||||
foreach ($_FILES['files']['tmp_name'] ?? [] as $i => $tmpName) {
|
||||
if ($_FILES['files']['error'][$i] === UPLOAD_ERR_OK) {
|
||||
$articles->addFile($uuid, [
|
||||
'name' => $_FILES['files']['name'][$i],
|
||||
'tmp_name' => $tmpName,
|
||||
'error' => $_FILES['files']['error'][$i],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$updated = $articles->getByUuid($uuid);
|
||||
header('Location: /post/' . rawurlencode($updated['slug'] ?? $uuid));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$formAction = '/?action=edit&uuid=' . rawurlencode($uuid);
|
||||
$action = 'edit';
|
||||
$existingFiles = $articles->getFiles($uuid);
|
||||
include BASE_PATH . '/templates/post_form.php';
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
requireAuth();
|
||||
if ($uuid !== '') {
|
||||
$articles->delete($uuid);
|
||||
}
|
||||
header('Location: /');
|
||||
exit;
|
||||
|
||||
case 'about':
|
||||
include BASE_PATH . '/templates/about.php';
|
||||
break;
|
||||
|
||||
case 'legal':
|
||||
include BASE_PATH . '/templates/legal.php';
|
||||
break;
|
||||
|
||||
case 'contact':
|
||||
include BASE_PATH . '/templates/contact.php';
|
||||
break;
|
||||
|
||||
case 'licenses':
|
||||
include BASE_PATH . '/templates/licenses.php';
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
default:
|
||||
$posts = $articles->getAll();
|
||||
include BASE_PATH . '/templates/post_list.php';
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ if (!function_exists('url')) {
|
||||
}
|
||||
|
||||
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||
require_once dirname(__DIR__, 2) . '/app/bootstrap.php';
|
||||
require_once dirname(__DIR__, 2) . '/bootstrap.php';
|
||||
require_once dirname(__DIR__, 2) . '/config/config.php';
|
||||
|
||||
// Paramètres (env)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||
require_once dirname(__DIR__, 2) . '/app/bootstrap.php';
|
||||
require_once dirname(__DIR__, 2) . '/bootstrap.php';
|
||||
require_once dirname(__DIR__, 2) . '/config/config.php';
|
||||
|
||||
// si tu as un service pour ouvrir une session
|
||||
@@ -58,16 +58,11 @@ try {
|
||||
$pdo->prepare('UPDATE auth_magic_links SET consumed_at = NOW() WHERE id = :id')->execute([':id' => $row['id']]);
|
||||
$pdo->commit();
|
||||
|
||||
// ouvre une session applicative « anonyme authentifiée par email »
|
||||
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
session_start();
|
||||
}
|
||||
$_SESSION['auth'] = [
|
||||
'method' => 'magic',
|
||||
'email' => (string)$row['email'],
|
||||
'ts' => time(),
|
||||
];
|
||||
// Aucun create user ici, conforme à la demande
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['user_email'] = strtolower(trim((string)$row['email']));
|
||||
|
||||
$dest = $row['return_to'] ?? '/';
|
||||
// sécurité: ne renvoyer que des chemins relatifs
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
define('BASE_PATH', realpath(__DIR__ . '/../'));
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
require_once BASE_PATH . '/src/auth.php';
|
||||
require_once BASE_PATH . '/config/config.php';
|
||||
|
||||
$logoutUrl = ssoLogoutUrl();
|
||||
|
||||
$_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: ' . $logoutUrl, true, 303);
|
||||
exit;
|
||||
+36
-67
@@ -2,14 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Infrastructure\Database;
|
||||
|
||||
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||
require_once dirname(__DIR__, 2) . '/app/bootstrap.php';
|
||||
require_once dirname(__DIR__, 2) . '/bootstrap.php';
|
||||
require_once dirname(__DIR__, 2) . '/config/config.php';
|
||||
|
||||
if (!function_exists('env')) {
|
||||
@@ -25,13 +23,13 @@ if (!function_exists('env')) {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
$debug = (env('APP_DEBUG', '0') === '1');
|
||||
|
||||
// --- OIDC config ---
|
||||
$OIDC_ISSUER = rtrim((string)env('OIDC_ISSUER', ''), '/');
|
||||
$OIDC_CLIENT_ID = (string)env('OIDC_CLIENT_ID', '');
|
||||
$OIDC_CLIENT_SECRET = (string)env('OIDC_CLIENT_SECRET', '');
|
||||
$OIDC_REDIRECT_URI = (string)(env('OIDC_REDIRECT_URI') ?: url('oidc/callback'));
|
||||
$OIDC_ISSUER = rtrim((string)(env('OIDC_ISSUER') ?? ''), '/');
|
||||
$OIDC_CLIENT_ID = (string)(env('OIDC_CLIENT_ID') ?? '');
|
||||
$OIDC_CLIENT_SECRET = (string)(env('OIDC_CLIENT_SECRET') ?? '');
|
||||
$OIDC_REDIRECT_URI = (string)(env('OIDC_REDIRECT_URI') ?: url('oidc/callback.php'));
|
||||
|
||||
if (!$OIDC_ISSUER || !$OIDC_CLIENT_ID || !$OIDC_REDIRECT_URI) {
|
||||
http_response_code(500);
|
||||
@@ -42,7 +40,6 @@ if (!$OIDC_ISSUER || !$OIDC_CLIENT_ID || !$OIDC_REDIRECT_URI) {
|
||||
$tokenEndpoint = $OIDC_ISSUER . '/protocol/openid-connect/token';
|
||||
$userInfoEndpoint = $OIDC_ISSUER . '/protocol/openid-connect/userinfo';
|
||||
|
||||
// --- Checks retour ---
|
||||
if (!isset($_GET['state'], $_SESSION['oidc_state']) || !hash_equals((string)$_SESSION['oidc_state'], (string)$_GET['state'])) {
|
||||
http_response_code(400);
|
||||
echo $debug ? 'State invalide.' : 'Requête invalide.';
|
||||
@@ -58,9 +55,7 @@ if (empty($_GET['code'])) {
|
||||
$code = (string)$_GET['code'];
|
||||
|
||||
$codeVerifier = $_SESSION['oidc_code_verifier'] ?? null;
|
||||
unset($_SESSION['oidc_code_verifier']); // anti-replay
|
||||
$expectedNonce = $_SESSION['oidc_nonce'] ?? null;
|
||||
unset($_SESSION['oidc_nonce']); // anti-replay
|
||||
unset($_SESSION['oidc_code_verifier'], $_SESSION['oidc_nonce']);
|
||||
|
||||
if (!$codeVerifier) {
|
||||
http_response_code(400);
|
||||
@@ -68,7 +63,7 @@ if (!$codeVerifier) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- Échange code -> tokens ---
|
||||
// Échange code → tokens
|
||||
$post = [
|
||||
'grant_type' => 'authorization_code',
|
||||
'code' => $code,
|
||||
@@ -86,15 +81,17 @@ curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query($post, '', '&', PHP_QUERY_RFC3986),
|
||||
CURLOPT_TIMEOUT => 15,
|
||||
CURLOPT_SSL_VERIFYPEER => true,
|
||||
CURLOPT_SSL_VERIFYHOST => 2,
|
||||
]);
|
||||
$tokenResponse = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$err = curl_error($ch);
|
||||
$curlErr = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($tokenResponse === false || $httpCode !== 200) {
|
||||
http_response_code(500);
|
||||
echo $debug ? 'Échec échange token: ' . htmlspecialchars($err ?: (string)$tokenResponse) : 'Erreur d’authentification.';
|
||||
echo $debug ? 'Échec échange token : ' . htmlspecialchars($curlErr ?: (string)$tokenResponse) : 'Erreur d\'authentification.';
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -104,16 +101,18 @@ $idToken = $tokens['id_token'] ?? null;
|
||||
|
||||
if (!$accessToken) {
|
||||
http_response_code(500);
|
||||
echo $debug ? 'Access token manquant.' : 'Erreur d’authentification.';
|
||||
echo $debug ? 'Access token manquant.' : 'Erreur d\'authentification.';
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- UserInfo ---
|
||||
// UserInfo
|
||||
$ch = curl_init($userInfoEndpoint);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $accessToken],
|
||||
CURLOPT_TIMEOUT => 10,
|
||||
CURLOPT_SSL_VERIFYPEER => true,
|
||||
CURLOPT_SSL_VERIFYHOST => 2,
|
||||
]);
|
||||
$userInfoResponse = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
@@ -121,22 +120,17 @@ curl_close($ch);
|
||||
|
||||
if ($userInfoResponse === false || $httpCode !== 200) {
|
||||
http_response_code(500);
|
||||
echo $debug ? 'Échec UserInfo: ' . htmlspecialchars((string)$userInfoResponse) : 'Erreur d’authentification.';
|
||||
echo $debug ? 'Échec UserInfo.' : 'Erreur d\'authentification.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$claims = json_decode((string)$userInfoResponse, true) ?: [];
|
||||
$email = $claims['email'] ?? null;
|
||||
|
||||
// --- Récup info utiles ---
|
||||
$email = $claims['email'] ?? null;
|
||||
$username = $claims['preferred_username'] ?? ($email ?: null);
|
||||
$firstname = $claims['given_name'] ?? null;
|
||||
$lastname = $claims['family_name'] ?? null;
|
||||
|
||||
// Fallback : lire l'email depuis le payload du id_token
|
||||
if (!$email && $idToken && substr_count($idToken, '.') === 2) {
|
||||
[, $p, ] = explode('.', $idToken, 3);
|
||||
$payloadJson = base64_decode(strtr($p, '-_', '+/'), true);
|
||||
$payload = $payloadJson ? json_decode($payloadJson, true) : null;
|
||||
$payload = json_decode((string)base64_decode(strtr($p, '-_', '+/'), true), true);
|
||||
if (is_array($payload) && !empty($payload['email'])) {
|
||||
$email = $payload['email'];
|
||||
}
|
||||
@@ -144,50 +138,25 @@ if (!$email && $idToken && substr_count($idToken, '.') === 2) {
|
||||
|
||||
if (!$email) {
|
||||
http_response_code(400);
|
||||
echo $debug ? 'Email non fourni par IdP.' : 'Impossible de récupérer votre email.';
|
||||
echo $debug ? 'Email non fourni par l\'IdP.' : 'Impossible de récupérer votre email.';
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- Si l'utilisateur existe déjà -> connecter et redirect ---
|
||||
$flow = $_SESSION['oidc_flow'] ?? 'login';
|
||||
|
||||
// Vérifie existence en base
|
||||
/** @var \PDO $pdo */
|
||||
$pdo = Database::get();
|
||||
$stmt = $pdo->prepare('SELECT id FROM users WHERE email = :email LIMIT 1');
|
||||
$stmt->execute([':email' => $email]);
|
||||
$existingId = $stmt->fetchColumn();
|
||||
|
||||
// Si flow=login ET utilisateur existe → connexion directe
|
||||
if ($flow === 'login' && $existingId) {
|
||||
$_SESSION['user_id'] = (int)$existingId;
|
||||
$_SESSION['user_email'] = $email;
|
||||
$_SESSION['oidc'] = [
|
||||
'issuer' => $OIDC_ISSUER,
|
||||
'sub' => $claims['sub'] ?? null,
|
||||
'access_token' => $accessToken,
|
||||
'id_token' => $idToken,
|
||||
'expires_at' => time() + (int)($tokens['expires_in'] ?? 3600),
|
||||
];
|
||||
$target = $_SESSION['oidc_return_to'] ?? '/';
|
||||
unset($_SESSION['oidc_return_to'], $_SESSION['oidc_flow']);
|
||||
if (!is_string($target) || $target === '' || $target[0] !== '/') {
|
||||
$target = '/';
|
||||
}
|
||||
header('Location: ' . $target, true, 303);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Sinon : go formulaire d’inscription (pré-rempli)
|
||||
$_SESSION['pending_oidc'] = [
|
||||
'issuer' => $OIDC_ISSUER,
|
||||
'sub' => $claims['sub'] ?? null,
|
||||
'email' => $email,
|
||||
'username' => $claims['preferred_username'] ?? ($email ?: null),
|
||||
'firstname' => $claims['given_name'] ?? null,
|
||||
'lastname' => $claims['family_name'] ?? null,
|
||||
// Ouvre la session authentifiée
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['user_email'] = strtolower(trim($email));
|
||||
$_SESSION['oidc'] = [
|
||||
'issuer' => $OIDC_ISSUER,
|
||||
'sub' => $claims['sub'] ?? null,
|
||||
'access_token' => $accessToken,
|
||||
'id_token' => $idToken,
|
||||
'expires_at' => time() + (int)($tokens['expires_in'] ?? 3600),
|
||||
];
|
||||
unset($_SESSION['oidc_flow']);
|
||||
|
||||
header('Location: ' . url('register/from-oidc'), true, 303);
|
||||
$target = $_SESSION['oidc_return_to'] ?? '/';
|
||||
unset($_SESSION['oidc_return_to'], $_SESSION['oidc_flow']);
|
||||
if (!is_string($target) || $target === '' || $target[0] !== '/') {
|
||||
$target = '/';
|
||||
}
|
||||
header('Location: ' . $target, true, 303);
|
||||
exit;
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
}
|
||||
|
||||
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||
require_once dirname(__DIR__, 2) . '/app/bootstrap.php';
|
||||
require_once dirname(__DIR__, 2) . '/bootstrap.php';
|
||||
require_once dirname(__DIR__, 2) . '/config/config.php';
|
||||
|
||||
function maskToken(?string $t): string
|
||||
|
||||
@@ -7,7 +7,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
}
|
||||
|
||||
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||
require_once dirname(__DIR__, 2) . '/app/bootstrap.php';
|
||||
require_once dirname(__DIR__, 2) . '/bootstrap.php';
|
||||
require_once dirname(__DIR__, 2) . '/config/config.php';
|
||||
|
||||
if (!function_exists('env')) {
|
||||
|
||||
+4
-157
@@ -1,160 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
define('BASE_PATH', realpath(__DIR__ . '/../'));
|
||||
|
||||
require_once BASE_PATH . '/src/db.php';
|
||||
require_once BASE_PATH . '/src/PostManager.php';
|
||||
require_once BASE_PATH . '/src/FileManager.php';
|
||||
|
||||
$action = $_GET['action'] ?? 'list';
|
||||
$id = isset($_GET['id']) ? (int) $_GET['id'] : null;
|
||||
|
||||
$postManager = new PostManager($db);
|
||||
$fileManager = new FileManager($db, __DIR__ . '/assets/uploads');
|
||||
|
||||
|
||||
// Gérer les accès
|
||||
// les fonctions create, delete, edit doit être autorisée aux personnes dont les roles leur permette
|
||||
|
||||
|
||||
|
||||
// Afficher la bonne page
|
||||
switch ($action) {
|
||||
case 'create':
|
||||
$title = $_POST['title'] ?? '';
|
||||
$content = $_POST['content'] ?? '';
|
||||
$published_at = $_POST['published_at'] ?? date('Y-m-d H:i:s');
|
||||
$published_at = str_replace('T', ' ', $published_at); // conversion HTML -> SQL
|
||||
$errors = [];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (trim($title) === '') {
|
||||
$errors[] = 'Le titre est obligatoire.';
|
||||
}
|
||||
|
||||
if (empty($errors)) {
|
||||
$postId = $postManager->create($title, $content, $published_at);
|
||||
|
||||
if (!empty($_FILES['files']['name'][0])) {
|
||||
foreach ($_FILES['files']['tmp_name'] as $i => $tmpName) {
|
||||
if ($_FILES['files']['error'][$i] === UPLOAD_ERR_OK) {
|
||||
$file = [
|
||||
'name' => $_FILES['files']['name'][$i],
|
||||
'type' => $_FILES['files']['type'][$i],
|
||||
'tmp_name' => $_FILES['files']['tmp_name'][$i],
|
||||
'error' => $_FILES['files']['error'][$i],
|
||||
'size' => $_FILES['files']['size'][$i],
|
||||
];
|
||||
$fileManager->upload($postId, $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header('Location: route.php');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$formAction = 'route.php?action=create';
|
||||
$action = 'create';
|
||||
include BASE_PATH . '/templates/post_form.php';
|
||||
break;
|
||||
|
||||
case 'view':
|
||||
if (!$id) {
|
||||
echo 'ID manquant.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$post = $postManager->get($id);
|
||||
if (!$post) {
|
||||
echo 'Post introuvable.';
|
||||
exit;
|
||||
}
|
||||
|
||||
include __DIR__ . '/../templates/post_view.php';
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if ($id) {
|
||||
$postManager->delete($id);
|
||||
}
|
||||
header('Location: route.php');
|
||||
exit;
|
||||
|
||||
case 'edit':
|
||||
if (!$id) {
|
||||
echo 'ID manquant.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$post = $postManager->get($id);
|
||||
if (!$post) {
|
||||
echo 'Post introuvable.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$title = $_POST['title'] ?? $post['title'];
|
||||
$content = $_POST['content'] ?? $post['content'];
|
||||
$published_at = $_POST['published_at'] ?? date('Y-m-d\TH:i', strtotime($post['created_at']));
|
||||
$published = isset($_POST['published']) ? true : $post['is_published'];
|
||||
$errors = [];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (trim($title) === '') {
|
||||
$errors[] = 'Le titre est obligatoire.';
|
||||
}
|
||||
|
||||
if (empty($errors)) {
|
||||
$published_at_sql = str_replace('T', ' ', $_POST['published_at']);
|
||||
$postManager->update($id, $title, $content, $published_at_sql, $published);
|
||||
|
||||
if (!empty($_FILES['files']['name'][0])) {
|
||||
foreach ($_FILES['files']['tmp_name'] as $i => $tmpName) {
|
||||
if ($_FILES['files']['error'][$i] === UPLOAD_ERR_OK) {
|
||||
$file = [
|
||||
'name' => $_FILES['files']['name'][$i],
|
||||
'type' => $_FILES['files']['type'][$i],
|
||||
'tmp_name' => $_FILES['files']['tmp_name'][$i],
|
||||
'error' => $_FILES['files']['error'][$i],
|
||||
'size' => $_FILES['files']['size'][$i],
|
||||
];
|
||||
$fileManager->upload($id, $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header("Location: route.php?action=view&id=$id");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$formAction = "route.php?action=edit&id=$id";
|
||||
$action = 'edit';
|
||||
include BASE_PATH . '/templates/post_form.php';
|
||||
break;
|
||||
|
||||
case 'about':
|
||||
include BASE_PATH . '/templates/about.php';
|
||||
break;
|
||||
|
||||
case 'legal':
|
||||
include BASE_PATH . '/templates/legal.php';
|
||||
break;
|
||||
|
||||
case 'contact':
|
||||
include BASE_PATH . '/templates/contact.php';
|
||||
break;
|
||||
|
||||
case 'licenses':
|
||||
include BASE_PATH . '/templates/licenses.php';
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
default:
|
||||
$posts = $postManager->getAll();
|
||||
include BASE_PATH . '/templates/post_list.php';
|
||||
break;
|
||||
}
|
||||
// Ce fichier est conservé pour compatibilité ascendante.
|
||||
// Toute la logique est désormais dans index.php.
|
||||
header('Location: /' . ($_SERVER['QUERY_STRING'] ? '?' . $_SERVER['QUERY_STRING'] : ''), true, 301);
|
||||
exit;
|
||||
|
||||
Reference in New Issue
Block a user