835 lines
23 KiB
PHP
835 lines
23 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 || $_SESSION['is_admin'] === 1);
|
|
}
|
|
|
|
/**
|
|
* Richiede che l'utente sia loggato, altrimenti reindirizza al login
|
|
*/
|
|
function require_login() {
|
|
if (!is_logged_in()) {
|
|
$_SESSION['redirect_after_login'] = $_SERVER['REQUEST_URI'];
|
|
// Determina il percorso relativo al login basato sulla directory corrente
|
|
$login_path = (strpos($_SERVER['SCRIPT_NAME'], '/admin/') !== false || strpos($_SERVER['SCRIPT_NAME'], '/user/') !== false)
|
|
? '../login.php'
|
|
: 'login.php';
|
|
header('Location: ' . $login_path);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Richiede che l'utente sia amministratore, altrimenti reindirizza
|
|
*/
|
|
function require_admin() {
|
|
require_login();
|
|
|
|
if (!is_admin()) {
|
|
// Determina il percorso relativo all'index basato sulla directory corrente
|
|
$index_path = (strpos($_SERVER['SCRIPT_NAME'], '/admin/') !== false || strpos($_SERVER['SCRIPT_NAME'], '/user/') !== false)
|
|
? '../index.php'
|
|
: 'index.php';
|
|
header('Location: ' . $index_path);
|
|
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'] = (bool)$is_admin; // Converti esplicitamente a boolean
|
|
$_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) {
|
|
if (USE_SMTP) {
|
|
return send_smtp_email($to, $subject, $message);
|
|
} else {
|
|
// Fallback a mail() PHP nativo
|
|
$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 tramite script Python
|
|
*
|
|
* @param string $to Email destinatario
|
|
* @param string $subject Oggetto email
|
|
* @param string $message Corpo email (HTML)
|
|
* @return bool True se inviata, false altrimenti
|
|
*/
|
|
function send_smtp_email($to, $subject, $message) {
|
|
try {
|
|
// Prepara dati JSON per lo script Python
|
|
$data = json_encode([
|
|
'to' => $to,
|
|
'subject' => $subject,
|
|
'html' => $message
|
|
], JSON_UNESCAPED_UNICODE);
|
|
|
|
// Percorso dello script Python
|
|
$script_path = __DIR__ . '/../send_email.py';
|
|
|
|
// Verifica che lo script esista
|
|
if (!file_exists($script_path)) {
|
|
error_log("Email Error: Script send_email.py non trovato");
|
|
return false;
|
|
}
|
|
|
|
// Esegui script Python
|
|
$command = 'python3 ' . escapeshellarg($script_path) . ' ' . escapeshellarg($data) . ' 2>&1';
|
|
exec($command, $output, $return_code);
|
|
|
|
// Parse risposta JSON
|
|
$result = json_decode(implode("\n", $output), true);
|
|
|
|
if ($return_code === 0 && isset($result['success']) && $result['success']) {
|
|
return true;
|
|
} else {
|
|
$error_msg = isset($result['error']) ? $result['error'] : 'Errore sconosciuto';
|
|
error_log("Email Error: " . $error_msg);
|
|
return false;
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
error_log("Email Error: " . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Invia email tramite SMTP PHP nativo (deprecato - usa send_smtp_email)
|
|
*
|
|
* @param string $to Email destinatario
|
|
* @param string $subject Oggetto email
|
|
* @param string $message Corpo email (HTML)
|
|
* @return bool True se inviata, false altrimenti
|
|
*/
|
|
function send_smtp_email_legacy($to, $subject, $message) {
|
|
try {
|
|
// Connessione al server SMTP con supporto SSL/TLS
|
|
$context = stream_context_create([
|
|
'ssl' => [
|
|
'verify_peer' => false,
|
|
'verify_peer_name' => false,
|
|
'allow_self_signed' => true
|
|
]
|
|
]);
|
|
|
|
// Per SSL (porta 465) usa protocollo ssl://, per TLS (porta 587) connessione normale
|
|
$protocol = (SMTP_ENCRYPTION === 'ssl') ? 'ssl://' : '';
|
|
$smtp = stream_socket_client(
|
|
$protocol . SMTP_HOST . ':' . SMTP_PORT,
|
|
$errno,
|
|
$errstr,
|
|
30,
|
|
STREAM_CLIENT_CONNECT,
|
|
$context
|
|
);
|
|
|
|
if (!$smtp) {
|
|
error_log("SMTP Error: Impossibile connettersi a " . SMTP_HOST . ":" . SMTP_PORT . " - $errstr ($errno)");
|
|
return false;
|
|
}
|
|
|
|
// Funzione helper per leggere risposta
|
|
$read = function() use ($smtp) {
|
|
return fgets($smtp, 515);
|
|
};
|
|
|
|
// Funzione helper per inviare comando
|
|
$send = function($cmd) use ($smtp) {
|
|
fputs($smtp, $cmd . "\r\n");
|
|
};
|
|
|
|
// Leggi il banner di benvenuto
|
|
$read();
|
|
|
|
// Inizia handshake SMTP
|
|
$send("EHLO " . SMTP_HOST);
|
|
$read();
|
|
|
|
// Inizia TLS se richiesto
|
|
if (SMTP_ENCRYPTION === 'tls') {
|
|
$send("STARTTLS");
|
|
$response = $read();
|
|
|
|
// Verifica risposta 220
|
|
if (strpos($response, '220') !== 0) {
|
|
error_log("SMTP Error: STARTTLS fallito - " . $response);
|
|
fclose($smtp);
|
|
return false;
|
|
}
|
|
|
|
// Abilita TLS con metodo compatibile (fallback automatico tra TLSv1.2, TLSv1.1, TLSv1.0)
|
|
$crypto_methods = [
|
|
STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
|
|
STREAM_CRYPTO_METHOD_TLS_CLIENT,
|
|
STREAM_CRYPTO_METHOD_SSLv23_CLIENT
|
|
];
|
|
|
|
$tls_enabled = false;
|
|
foreach ($crypto_methods as $method) {
|
|
if (@stream_socket_enable_crypto($smtp, true, $method)) {
|
|
$tls_enabled = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$tls_enabled) {
|
|
error_log("SMTP Error: Impossibile avviare crittografia TLS con nessun metodo");
|
|
fclose($smtp);
|
|
return false;
|
|
}
|
|
|
|
$send("EHLO " . SMTP_HOST);
|
|
$read();
|
|
}
|
|
|
|
// Autenticazione
|
|
$send("AUTH LOGIN");
|
|
$read();
|
|
|
|
$send(base64_encode(SMTP_USERNAME));
|
|
$read();
|
|
|
|
$send(base64_encode(SMTP_PASSWORD));
|
|
$response = $read();
|
|
|
|
// Verifica autenticazione
|
|
if (strpos($response, '235') === false) {
|
|
error_log("SMTP Error: Autenticazione fallita - " . $response);
|
|
fclose($smtp);
|
|
return false;
|
|
}
|
|
|
|
// Imposta mittente
|
|
$send("MAIL FROM: <" . MAIL_FROM . ">");
|
|
$read();
|
|
|
|
// Imposta destinatario
|
|
$send("RCPT TO: <" . $to . ">");
|
|
$read();
|
|
|
|
// Inizia corpo messaggio
|
|
$send("DATA");
|
|
$read();
|
|
|
|
// Costruisci headers
|
|
$headers = "From: " . MAIL_FROM_NAME . " <" . MAIL_FROM . ">\r\n";
|
|
$headers .= "To: <" . $to . ">\r\n";
|
|
$headers .= "Subject: " . $subject . "\r\n";
|
|
$headers .= "MIME-Version: 1.0\r\n";
|
|
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
|
|
$headers .= "Date: " . date('r') . "\r\n";
|
|
|
|
// Invia email
|
|
$send($headers . "\r\n" . $message . "\r\n.");
|
|
$read();
|
|
|
|
// Chiudi connessione
|
|
$send("QUIT");
|
|
$read();
|
|
fclose($smtp);
|
|
|
|
return true;
|
|
|
|
} catch (Exception $e) {
|
|
error_log("SMTP Error: " . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
// Gestisci null o valori non numerici
|
|
if ($price === null || $price === '') {
|
|
$price = 0;
|
|
}
|
|
return '€ ' . number_format((float)$price, 2, ',', '.');
|
|
}
|
|
|
|
/**
|
|
* Redirect a un'altra pagina
|
|
*
|
|
* @param string $url URL di destinazione
|
|
*/
|
|
function redirect($url) {
|
|
header("Location: $url");
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Estrae la durata di un video in minuti
|
|
*
|
|
* @param string $file_path Percorso del file video
|
|
* @return int|null Durata in minuti o null se non rilevabile
|
|
*/
|
|
function get_video_duration($file_path) {
|
|
// Metodo 1: Usa getID3 se disponibile
|
|
if (file_exists(__DIR__ . '/../vendor/getid3/getid3/getid3.php')) {
|
|
require_once __DIR__ . '/../vendor/getid3/getid3/getid3.php';
|
|
|
|
try {
|
|
$getID3 = new getID3();
|
|
$file_info = $getID3->analyze($file_path);
|
|
|
|
if (isset($file_info['playtime_seconds'])) {
|
|
return (int) ceil($file_info['playtime_seconds'] / 60);
|
|
}
|
|
} catch (Exception $e) {
|
|
// Continua con altri metodi
|
|
}
|
|
}
|
|
|
|
// Metodo 2: Usa ffprobe se disponibile
|
|
if (function_exists('shell_exec') && !in_array('shell_exec', explode(',', ini_get('disable_functions')))) {
|
|
$ffprobe_commands = [
|
|
'ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 ' . escapeshellarg($file_path),
|
|
'/usr/bin/ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 ' . escapeshellarg($file_path),
|
|
'/usr/local/bin/ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 ' . escapeshellarg($file_path)
|
|
];
|
|
|
|
foreach ($ffprobe_commands as $cmd) {
|
|
$output = @shell_exec($cmd . ' 2>&1');
|
|
if ($output && is_numeric(trim($output))) {
|
|
$seconds = (float) trim($output);
|
|
return (int) ceil($seconds / 60);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Metodo 3: Usa ffmpeg se disponibile
|
|
if (function_exists('shell_exec') && !in_array('shell_exec', explode(',', ini_get('disable_functions')))) {
|
|
$ffmpeg_commands = [
|
|
'ffmpeg -i ' . escapeshellarg($file_path) . ' 2>&1',
|
|
'/usr/bin/ffmpeg -i ' . escapeshellarg($file_path) . ' 2>&1',
|
|
'/usr/local/bin/ffmpeg -i ' . escapeshellarg($file_path) . ' 2>&1'
|
|
];
|
|
|
|
foreach ($ffmpeg_commands as $cmd) {
|
|
$output = @shell_exec($cmd);
|
|
if ($output && preg_match('/Duration: (\d{2}):(\d{2}):(\d{2})/', $output, $matches)) {
|
|
$hours = (int) $matches[1];
|
|
$minutes = (int) $matches[2];
|
|
$seconds = (int) $matches[3];
|
|
return $hours * 60 + $minutes + (int) ceil($seconds / 60);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Nessun metodo funzionante
|
|
return null;
|
|
}
|
|
|
|
?>
|