565 lines
14 KiB
PHP
565 lines
14 KiB
PHP
<?php
|
|
/**
|
|
* Funzioni Comuni
|
|
*
|
|
* Raccolta di funzioni utilizzate in tutta la piattaforma
|
|
*/
|
|
|
|
// ============================================
|
|
// FUNZIONI AUTENTICAZIONE E SESSIONE
|
|
// ============================================
|
|
|
|
/**
|
|
* Verifica se l'utente è loggato
|
|
*
|
|
* @return bool True se loggato, false altrimenti
|
|
*/
|
|
function is_logged_in() {
|
|
return isset($_SESSION['user_id']) && !empty($_SESSION['user_id']);
|
|
}
|
|
|
|
/**
|
|
* Verifica se l'utente è un amministratore
|
|
*
|
|
* @return bool True se admin, false altrimenti
|
|
*/
|
|
function is_admin() {
|
|
return isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true;
|
|
}
|
|
|
|
/**
|
|
* Richiede che l'utente sia loggato, altrimenti reindirizza al login
|
|
*/
|
|
function require_login() {
|
|
if (!is_logged_in()) {
|
|
$_SESSION['redirect_after_login'] = $_SERVER['REQUEST_URI'];
|
|
header('Location: ' . SITE_URL . '/login.php');
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Richiede che l'utente sia amministratore, altrimenti reindirizza
|
|
*/
|
|
function require_admin() {
|
|
require_login();
|
|
|
|
if (!is_admin()) {
|
|
header('Location: ' . SITE_URL . '/index.php');
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Effettua il login dell'utente
|
|
*
|
|
* @param int $user_id ID dell'utente
|
|
* @param bool $is_admin Se l'utente è admin
|
|
*/
|
|
function login_user($user_id, $is_admin = false) {
|
|
// Rigenera l'ID di sessione per sicurezza
|
|
session_regenerate_id(true);
|
|
|
|
$_SESSION['user_id'] = $user_id;
|
|
$_SESSION['is_admin'] = $is_admin;
|
|
$_SESSION['last_activity'] = time();
|
|
}
|
|
|
|
/**
|
|
* Effettua il logout dell'utente
|
|
*/
|
|
function logout_user() {
|
|
// Cancella tutte le variabili di sessione
|
|
$_SESSION = array();
|
|
|
|
// Distruggi il cookie di sessione se esiste
|
|
if (isset($_COOKIE[session_name()])) {
|
|
setcookie(session_name(), '', time() - 3600, '/');
|
|
}
|
|
|
|
// Distruggi la sessione
|
|
session_destroy();
|
|
}
|
|
|
|
/**
|
|
* Verifica la validità della sessione (timeout)
|
|
*
|
|
* @return bool True se sessione valida, false se scaduta
|
|
*/
|
|
function check_session_timeout() {
|
|
if (isset($_SESSION['last_activity'])) {
|
|
$elapsed = time() - $_SESSION['last_activity'];
|
|
|
|
if ($elapsed > SESSION_LIFETIME) {
|
|
logout_user();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$_SESSION['last_activity'] = time();
|
|
return true;
|
|
}
|
|
|
|
// ============================================
|
|
// FUNZIONI SICUREZZA
|
|
// ============================================
|
|
|
|
/**
|
|
* Hash sicuro di una password
|
|
*
|
|
* @param string $password Password in chiaro
|
|
* @return string Password hashata
|
|
*/
|
|
function hash_password($password) {
|
|
return password_hash($password, PASSWORD_DEFAULT);
|
|
}
|
|
|
|
/**
|
|
* Verifica una password contro il suo hash
|
|
*
|
|
* @param string $password Password in chiaro
|
|
* @param string $hash Hash salvato nel database
|
|
* @return bool True se corrisponde, false altrimenti
|
|
*/
|
|
function verify_password($password, $hash) {
|
|
return password_verify($password, $hash);
|
|
}
|
|
|
|
/**
|
|
* Genera un token casuale sicuro
|
|
*
|
|
* @param int $length Lunghezza del token
|
|
* @return string Token generato
|
|
*/
|
|
function generate_token($length = 32) {
|
|
return bin2hex(random_bytes($length));
|
|
}
|
|
|
|
/**
|
|
* Sanitizza input utente per prevenire XSS
|
|
*
|
|
* @param string $data Dati da sanitizzare
|
|
* @return string Dati sanitizzati
|
|
*/
|
|
function sanitize_input($data) {
|
|
$data = trim($data);
|
|
$data = stripslashes($data);
|
|
$data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Valida un indirizzo email
|
|
*
|
|
* @param string $email Email da validare
|
|
* @return bool True se valida, false altrimenti
|
|
*/
|
|
function validate_email($email) {
|
|
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
|
|
}
|
|
|
|
// ============================================
|
|
// FUNZIONI DATABASE - UTENTI
|
|
// ============================================
|
|
|
|
/**
|
|
* Ottiene un utente dal database tramite email
|
|
*
|
|
* @param string $email Email dell'utente
|
|
* @return array|false Dati utente o false se non trovato
|
|
*/
|
|
function get_user_by_email($email) {
|
|
$pdo = get_db_connection();
|
|
|
|
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ? AND deleted_at IS NULL");
|
|
$stmt->execute([$email]);
|
|
|
|
return $stmt->fetch();
|
|
}
|
|
|
|
/**
|
|
* Ottiene un utente dal database tramite ID
|
|
*
|
|
* @param int $user_id ID dell'utente
|
|
* @return array|false Dati utente o false se non trovato
|
|
*/
|
|
function get_user_by_id($user_id) {
|
|
$pdo = get_db_connection();
|
|
|
|
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ? AND deleted_at IS NULL");
|
|
$stmt->execute([$user_id]);
|
|
|
|
return $stmt->fetch();
|
|
}
|
|
|
|
/**
|
|
* Crea un nuovo utente nel database
|
|
*
|
|
* @param string $email Email
|
|
* @param string $password Password in chiaro (verrà hashata)
|
|
* @param string $first_name Nome
|
|
* @param string $last_name Cognome
|
|
* @param bool $is_admin Se è amministratore
|
|
* @return int|false ID del nuovo utente o false in caso di errore
|
|
*/
|
|
function create_user($email, $password, $first_name, $last_name, $is_admin = false) {
|
|
$pdo = get_db_connection();
|
|
|
|
$hashed_password = hash_password($password);
|
|
|
|
try {
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO users (email, password, first_name, last_name, is_admin, created_at)
|
|
VALUES (?, ?, ?, ?, ?, NOW())
|
|
");
|
|
|
|
$stmt->execute([
|
|
$email,
|
|
$hashed_password,
|
|
$first_name,
|
|
$last_name,
|
|
$is_admin ? 1 : 0
|
|
]);
|
|
|
|
return $pdo->lastInsertId();
|
|
|
|
} catch (PDOException $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// FUNZIONI DATABASE - LEZIONI
|
|
// ============================================
|
|
|
|
/**
|
|
* Ottiene tutte le lezioni demo (gratuite)
|
|
*
|
|
* @return array Array di lezioni demo
|
|
*/
|
|
function get_demo_lessons() {
|
|
$pdo = get_db_connection();
|
|
|
|
$stmt = $pdo->query("
|
|
SELECT * FROM lessons
|
|
WHERE is_demo = 1 AND is_active = 1
|
|
ORDER BY created_at DESC
|
|
");
|
|
|
|
return $stmt->fetchAll();
|
|
}
|
|
|
|
/**
|
|
* Ottiene tutte le lezioni attive
|
|
*
|
|
* @param string $type Tipo di lezione: 'all', 'video', 'live'
|
|
* @return array Array di lezioni
|
|
*/
|
|
function get_all_lessons($type = 'all') {
|
|
$pdo = get_db_connection();
|
|
|
|
$sql = "SELECT * FROM lessons WHERE is_active = 1";
|
|
|
|
if ($type !== 'all') {
|
|
$sql .= " AND type = :type";
|
|
}
|
|
|
|
$sql .= " ORDER BY created_at DESC";
|
|
|
|
$stmt = $pdo->prepare($sql);
|
|
|
|
if ($type !== 'all') {
|
|
$stmt->execute(['type' => $type]);
|
|
} else {
|
|
$stmt->execute();
|
|
}
|
|
|
|
return $stmt->fetchAll();
|
|
}
|
|
|
|
/**
|
|
* Ottiene una lezione specifica tramite ID
|
|
*
|
|
* @param int $lesson_id ID della lezione
|
|
* @return array|false Dati lezione o false se non trovata
|
|
*/
|
|
function get_lesson_by_id($lesson_id) {
|
|
$pdo = get_db_connection();
|
|
|
|
$stmt = $pdo->prepare("SELECT * FROM lessons WHERE id = ?");
|
|
$stmt->execute([$lesson_id]);
|
|
|
|
return $stmt->fetch();
|
|
}
|
|
|
|
/**
|
|
* Verifica se un utente ha acquistato una lezione
|
|
*
|
|
* @param int $user_id ID utente
|
|
* @param int $lesson_id ID lezione
|
|
* @return bool True se acquistata, false altrimenti
|
|
*/
|
|
function user_owns_lesson($user_id, $lesson_id) {
|
|
$pdo = get_db_connection();
|
|
|
|
$stmt = $pdo->prepare("
|
|
SELECT COUNT(*) as count
|
|
FROM purchases
|
|
WHERE user_id = ? AND lesson_id = ? AND status = 'completed'
|
|
");
|
|
|
|
$stmt->execute([$user_id, $lesson_id]);
|
|
$result = $stmt->fetch();
|
|
|
|
return $result['count'] > 0;
|
|
}
|
|
|
|
/**
|
|
* Ottiene tutte le lezioni acquistate da un utente
|
|
*
|
|
* @param int $user_id ID utente
|
|
* @return array Array di lezioni acquistate
|
|
*/
|
|
function get_user_purchased_lessons($user_id) {
|
|
$pdo = get_db_connection();
|
|
|
|
$stmt = $pdo->prepare("
|
|
SELECT l.*, p.purchased_at, p.amount as paid_amount
|
|
FROM lessons l
|
|
INNER JOIN purchases p ON l.id = p.lesson_id
|
|
WHERE p.user_id = ? AND p.status = 'completed'
|
|
ORDER BY p.purchased_at DESC
|
|
");
|
|
|
|
$stmt->execute([$user_id]);
|
|
|
|
return $stmt->fetchAll();
|
|
}
|
|
|
|
// ============================================
|
|
// FUNZIONI RECUPERO PASSWORD
|
|
// ============================================
|
|
|
|
/**
|
|
* Crea un token per il recupero password
|
|
*
|
|
* @param int $user_id ID utente
|
|
* @return string Token generato
|
|
*/
|
|
function create_password_reset_token($user_id) {
|
|
$pdo = get_db_connection();
|
|
|
|
$token = generate_token(32);
|
|
$expires_at = date('Y-m-d H:i:s', time() + PASSWORD_RESET_TOKEN_LIFETIME);
|
|
|
|
// Cancella eventuali token precedenti per questo utente
|
|
$stmt = $pdo->prepare("DELETE FROM password_resets WHERE user_id = ?");
|
|
$stmt->execute([$user_id]);
|
|
|
|
// Crea nuovo token
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO password_resets (user_id, token, expires_at, created_at)
|
|
VALUES (?, ?, ?, NOW())
|
|
");
|
|
|
|
$stmt->execute([$user_id, $token, $expires_at]);
|
|
|
|
return $token;
|
|
}
|
|
|
|
/**
|
|
* Verifica la validità di un token di reset password
|
|
*
|
|
* @param string $token Token da verificare
|
|
* @return int|false User ID se valido, false altrimenti
|
|
*/
|
|
function verify_password_reset_token($token) {
|
|
$pdo = get_db_connection();
|
|
|
|
$stmt = $pdo->prepare("
|
|
SELECT user_id FROM password_resets
|
|
WHERE token = ? AND expires_at > NOW() AND used_at IS NULL
|
|
");
|
|
|
|
$stmt->execute([$token]);
|
|
$result = $stmt->fetch();
|
|
|
|
return $result ? $result['user_id'] : false;
|
|
}
|
|
|
|
/**
|
|
* Marca un token come utilizzato
|
|
*
|
|
* @param string $token Token da marcare
|
|
*/
|
|
function mark_token_as_used($token) {
|
|
$pdo = get_db_connection();
|
|
|
|
$stmt = $pdo->prepare("UPDATE password_resets SET used_at = NOW() WHERE token = ?");
|
|
$stmt->execute([$token]);
|
|
}
|
|
|
|
// ============================================
|
|
// FUNZIONI EMAIL
|
|
// ============================================
|
|
|
|
/**
|
|
* Invia un'email (funzione base con mail() PHP)
|
|
*
|
|
* @param string $to Destinatario
|
|
* @param string $subject Oggetto
|
|
* @param string $message Messaggio HTML
|
|
* @return bool True se inviata, false altrimenti
|
|
*/
|
|
function send_email($to, $subject, $message) {
|
|
$headers = "MIME-Version: 1.0" . "\r\n";
|
|
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
|
|
$headers .= "From: " . MAIL_FROM_NAME . " <" . MAIL_FROM . ">" . "\r\n";
|
|
|
|
return mail($to, $subject, $message, $headers);
|
|
}
|
|
|
|
/**
|
|
* Invia email di recupero password
|
|
*
|
|
* @param string $email Email destinatario
|
|
* @param string $token Token di reset
|
|
* @return bool True se inviata, false altrimenti
|
|
*/
|
|
function send_password_reset_email($email, $token) {
|
|
$reset_link = SITE_URL . "/reset_password.php?token=" . $token;
|
|
|
|
$subject = "Recupero Password - " . SITE_NAME;
|
|
|
|
$message = "
|
|
<html>
|
|
<head>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
|
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
|
.button {
|
|
display: inline-block;
|
|
padding: 12px 24px;
|
|
background: #4A90E2;
|
|
color: white;
|
|
text-decoration: none;
|
|
border-radius: 5px;
|
|
margin: 20px 0;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class='container'>
|
|
<h2>Recupero Password</h2>
|
|
<p>Hai richiesto il recupero della password per il tuo account su " . SITE_NAME . ".</p>
|
|
<p>Clicca sul pulsante qui sotto per reimpostare la tua password:</p>
|
|
<a href='{$reset_link}' class='button'>Reimposta Password</a>
|
|
<p>Oppure copia e incolla questo link nel tuo browser:</p>
|
|
<p>{$reset_link}</p>
|
|
<p>Questo link è valido per " . (PASSWORD_RESET_TOKEN_LIFETIME / 60) . " minuti.</p>
|
|
<p>Se non hai richiesto tu questo recupero, ignora questa email.</p>
|
|
<hr>
|
|
<p><small>Questa è un'email automatica, non rispondere a questo messaggio.</small></p>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
";
|
|
|
|
return send_email($email, $subject, $message);
|
|
}
|
|
|
|
// ============================================
|
|
// FUNZIONI MESSAGGI FLASH
|
|
// ============================================
|
|
|
|
/**
|
|
* Imposta un messaggio flash da visualizzare nella prossima pagina
|
|
*
|
|
* @param string $type Tipo: 'success', 'error', 'warning', 'info'
|
|
* @param string $message Messaggio da visualizzare
|
|
*/
|
|
function set_flash_message($type, $message) {
|
|
$_SESSION['flash_message'] = [
|
|
'type' => $type,
|
|
'message' => $message
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Ottiene e cancella il messaggio flash
|
|
*
|
|
* @return array|null Array con tipo e messaggio, o null se non presente
|
|
*/
|
|
function get_flash_message() {
|
|
if (isset($_SESSION['flash_message'])) {
|
|
$flash = $_SESSION['flash_message'];
|
|
unset($_SESSION['flash_message']);
|
|
return $flash;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Visualizza il messaggio flash HTML
|
|
*
|
|
* @return string HTML del messaggio o stringa vuota
|
|
*/
|
|
function display_flash_message() {
|
|
$flash = get_flash_message();
|
|
|
|
if ($flash) {
|
|
$type = htmlspecialchars($flash['type']);
|
|
$message = htmlspecialchars($flash['message']);
|
|
|
|
return "<div class='alert alert-{$type}'>{$message}</div>";
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
// ============================================
|
|
// FUNZIONI UTILITY
|
|
// ============================================
|
|
|
|
/**
|
|
* Formatta una data in formato italiano
|
|
*
|
|
* @param string $date Data in formato SQL
|
|
* @return string Data formattata
|
|
*/
|
|
function format_date($date) {
|
|
return date('d/m/Y', strtotime($date));
|
|
}
|
|
|
|
/**
|
|
* Formatta data e ora in formato italiano
|
|
*
|
|
* @param string $datetime Datetime in formato SQL
|
|
* @return string Datetime formattata
|
|
*/
|
|
function format_datetime($datetime) {
|
|
return date('d/m/Y H:i', strtotime($datetime));
|
|
}
|
|
|
|
/**
|
|
* Formatta un prezzo in euro
|
|
*
|
|
* @param float $price Prezzo
|
|
* @return string Prezzo formattato
|
|
*/
|
|
function format_price($price) {
|
|
return '€ ' . number_format($price, 2, ',', '.');
|
|
}
|
|
|
|
/**
|
|
* Redirect a un'altra pagina
|
|
*
|
|
* @param string $url URL di destinazione
|
|
*/
|
|
function redirect($url) {
|
|
header("Location: $url");
|
|
exit;
|
|
}
|
|
|
|
?>
|