nis2-agile/application/config/database.php
Cristiano Benassati ae78a2f7f4 [CORE] Initial project scaffold - NIS2 Agile Compliance Platform
Complete MVP implementation including:
- PHP 8.4 backend with Front Controller pattern (80+ API endpoints)
- Multi-tenant architecture with organization_id isolation
- JWT authentication (HS256, 2h access + 7d refresh tokens)
- 14 controllers: Auth, Organization, Assessment, Dashboard, Risk,
  Incident, Policy, SupplyChain, Training, Asset, Audit, Admin
- AI Service integration (Anthropic Claude API) for gap analysis,
  risk suggestions, policy generation, incident classification
- NIS2 gap analysis questionnaire (~80 questions, 10 categories)
- MySQL schema (20 tables) with NIS2 Art. 21 compliance controls
- NIS2 Art. 23 incident reporting workflow (24h/72h/30d)
- Frontend: login, register, dashboard, assessment wizard, org setup
- Docker configuration (PHP-FPM + Nginx + MySQL)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:50:18 +01:00

169 lines
4.5 KiB
PHP

<?php
/**
* NIS2 Agile - Configurazione Database
*
* Database dedicato: nis2_agile_db
* Utente dedicato: nis2_user
* COMPLETAMENTE ISOLATO dagli altri applicativi
*/
require_once __DIR__ . '/env.php';
define('DB_HOST', Env::get('DB_HOST', 'localhost'));
define('DB_PORT', Env::get('DB_PORT', '3306'));
define('DB_NAME', Env::get('DB_NAME', 'nis2_agile_db'));
define('DB_USER', Env::get('DB_USER', 'nis2_user'));
define('DB_PASS', Env::getRequired('DB_PASS'));
define('DB_CHARSET', 'utf8mb4');
class Database
{
private static ?PDO $instance = null;
/**
* Ottiene l'istanza PDO (singleton)
*/
public static function getInstance(): PDO
{
if (self::$instance === null) {
$dsn = sprintf(
'mysql:host=%s;port=%s;dbname=%s;charset=%s',
DB_HOST,
DB_PORT,
DB_NAME,
DB_CHARSET
);
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci",
];
try {
self::$instance = new PDO($dsn, DB_USER, DB_PASS, $options);
} catch (PDOException $e) {
if (defined('APP_DEBUG') && APP_DEBUG) {
throw new Exception('Database connection failed: ' . $e->getMessage());
} else {
throw new Exception('Database connection failed');
}
}
}
return self::$instance;
}
/**
* Esegue una query con parametri
*/
public static function query(string $sql, array $params = []): PDOStatement
{
$stmt = self::getInstance()->prepare($sql);
$stmt->execute($params);
return $stmt;
}
/**
* Ottiene una singola riga
*/
public static function fetchOne(string $sql, array $params = []): ?array
{
$result = self::query($sql, $params)->fetch();
return $result ?: null;
}
/**
* Ottiene tutte le righe
*/
public static function fetchAll(string $sql, array $params = []): array
{
return self::query($sql, $params)->fetchAll();
}
/**
* Inserisce e restituisce l'ID
*/
public static function insert(string $table, array $data): int
{
$columns = implode(', ', array_keys($data));
$placeholders = implode(', ', array_fill(0, count($data), '?'));
$sql = "INSERT INTO {$table} ({$columns}) VALUES ({$placeholders})";
self::query($sql, array_values($data));
return (int) self::getInstance()->lastInsertId();
}
/**
* Aggiorna righe
*/
public static function update(string $table, array $data, string $where, array $whereParams = []): int
{
$setParts = [];
foreach (array_keys($data) as $column) {
$setParts[] = "{$column} = ?";
}
$setClause = implode(', ', $setParts);
$sql = "UPDATE {$table} SET {$setClause} WHERE {$where}";
$params = array_merge(array_values($data), $whereParams);
return self::query($sql, $params)->rowCount();
}
/**
* Elimina righe
*/
public static function delete(string $table, string $where, array $params = []): int
{
$sql = "DELETE FROM {$table} WHERE {$where}";
return self::query($sql, $params)->rowCount();
}
/**
* Conta righe
*/
public static function count(string $table, string $where = '1=1', array $params = []): int
{
$sql = "SELECT COUNT(*) as cnt FROM {$table} WHERE {$where}";
$result = self::fetchOne($sql, $params);
return (int) ($result['cnt'] ?? 0);
}
/**
* Inizia una transazione
*/
public static function beginTransaction(): bool
{
return self::getInstance()->beginTransaction();
}
/**
* Commit transazione
*/
public static function commit(): bool
{
return self::getInstance()->commit();
}
/**
* Rollback transazione
*/
public static function rollback(): bool
{
return self::getInstance()->rollBack();
}
/**
* Restituisce l'ultimo ID inserito
*/
public static function lastInsertId(): int
{
return (int) self::getInstance()->lastInsertId();
}
private function __clone() {}
}