Files
api/services/nginx/app/classes/db.php
T

234 lines
6.7 KiB
PHP

<?php
namespace classes;
use Exception;
use mysqli;
use objects\orders_o;
class db
{
public mysqli $conn;
private string $host;
private string $user;
private string $password;
private string $database;
private int $port = 3306;
private string $ssl_mode = 'DISABLED'; // mysqldump SSL mode (e.g., DISABLED, PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY)
public function __construct(array $config)
{
$this->host = $config['host'];
$this->user = $config['user'];
$this->password = $config['password'];
$this->database = $config['database'];
if (isset($config['port']) && is_numeric($config['port'])) {
$this->port = (int)$config['port'];
}
if (isset($config['ssl_mode']) && is_string($config['ssl_mode']) && $config['ssl_mode'] !== '') {
$this->ssl_mode = $config['ssl_mode'];
}
}
public static function getPDO(): \PDO
{
global $CONFIG_DB;
$port = $CONFIG_DB['port'] ?? 3306;
$dsn = "mysql:host={$CONFIG_DB['host']};port={$port};dbname={$CONFIG_DB['database']};charset=utf8mb4";
return new \PDO($dsn, $CONFIG_DB['user'], $CONFIG_DB['password'], [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_EMULATE_PREPARES => false,
]);
}
public function testConnection(): bool
{
try {
$conn = new mysqli($this->host, $this->user, $this->password, $this->database, $this->port);
if ($conn->connect_error) {
return false;
}
$this->conn = $conn;
return true;
} catch (Exception) {
return false;
}
}
public function connect(): void
{
global $response;
try {
// Enable error reporting for mysqli to catch connection issues via exceptions
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$this->conn = new mysqli($this->host, $this->user, $this->password, $this->database, $this->port);
if ($this->conn->connect_error) {
throw new Exception($this->conn->connect_error);
}
} catch (Exception $e) {
if ($response) {
$response->internal_server_error("Database connection failed: " . $e->getMessage());
} else {
throw $e;
}
}
}
public function escape_string(string $string): string
{
return $this->conn->real_escape_string($string);
}
public function close(): void
{
$this->conn->close();
}
public function get(string $table, int $id)
{
$sql = "SELECT * FROM $table WHERE id = $id";
$result = $this->query($sql);
return $this->fetch_assoc($result);
}
public function query(string $sql): \mysqli_result|bool
{
// If the connection is not established, connect
return $this->conn->query($sql);
}
public function fetch_assoc($result)
{
return $result->fetch_assoc();
}
public function list_objects(string $table): array
{
$sql = "SELECT * FROM $table";
$result = $this->query($sql);
return $this->fetch_all($result);
}
public function fetch_all($result)
{
return $result->fetch_all(MYSQLI_ASSOC);
}
public function list_objects_paginated(string $table, int $page, int $limit): array
{
$offset = ($page - 1) * $limit;
$sql = "SELECT * FROM $table LIMIT $limit OFFSET $offset";
$result = $this->query($sql);
return $this->fetch_all($result);
}
public function count_objects(string $table): int
{
$sql = "SELECT COUNT(*) FROM $table";
$result = $this->query($sql);
return $result->fetch_row()[0];
}
public function insert_id(): int
{
return $this->conn->insert_id;
}
public function conn(): mysqli
{
return $this->conn;
}
public function prepare(string $sql): false|\mysqli_stmt
{
return $this->conn->prepare($sql);
}
public function num_rows(\mysqli_result|bool $result): int|string
{
return $result->num_rows;
}
public function getUsername()
{
return $this->user;
}
public function getPassword()
{
return $this->password;
}
public function getHost()
{
return $this->host;
}
public function getDatabase()
{
return $this->database;
}
public function backupDatabase(string $path): bool
{
// Save the database to the path
// Build a safe mysqldump command with configurable SSL (MariaDB-compatible flags)
$mode = strtoupper(trim($this->ssl_mode));
// Map ssl_mode to MariaDB client flags
// DISABLED => --skip-ssl (no TLS)
// PREFERRED => (no flag; client decides)
// REQUIRED/VERIFY_* => --ssl (enable TLS without strict verification unless CA materials provided)
$sslFlag = '';
switch ($mode) {
case 'DISABLED':
$sslFlag = '--skip-ssl';
break;
case 'PREFERRED':
$sslFlag = '';
break;
case 'REQUIRED':
case 'VERIFY_CA':
case 'VERIFY_IDENTITY':
default:
$sslFlag = '--ssl';
break;
}
$host = escapeshellarg($this->host);
$user = escapeshellarg($this->user);
$pass = escapeshellarg($this->password);
$db = escapeshellarg($this->database);
$port = (int)$this->port;
$outfile = escapeshellarg($path);
$sslPart = $sslFlag !== '' ? ($sslFlag . ' ') : '';
$command = "mysqldump {$sslPart}-h $host -P $port -u $user --password=$pass $db > $outfile 2>&1";
exec($command, $output, $return);
// Check if the command was successful
return $return === 0;
}
public function getView(string $view): array
{
$sql = "SELECT * FROM $view";
$result = $this->query($sql);
return $this->fetch_all($result);
}
/**
* Generate a fake ID for a table.
* Fake ids are not stored in the database, they are generated on every request starting from -1.
* This is useful for testing purposes.
* @see orders_o::simulateOrderFromXLVask()
* @param string $table
* @return int
*/
public function getNextFakeId(string $table): int
{
// This is a static variable that will be shared across all instances of the class
static $fakeId = 0; // Start from 0 and decrement on each call
$fakeId--;
return $fakeId;
}
}