Files
erp_naurua/includes/db.php
Mathias Gläser d52b6953ed Add OTC sales UI with direct sales support
- Create OTC UI form at public/otc/index.php
- Add API endpoint public/api/otc-order.php
- Extract shared DB connection to includes/db.php
- Add migration for OTC products (0006_phase1_otc_products.sql)
- Support order_source='direct' with automatic DIR- reference generation
- Include billing address capture with default values
- Add payment methods cash and paypal for direct sales
- Implement stock allocation and inventory management
2026-04-06 19:55:24 +02:00

151 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
function parse_env_file(string $path): array
{
if (!is_file($path)) {
return [];
}
$result = [];
$lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($lines === false) {
return [];
}
foreach ($lines as $line) {
$trimmed = trim($line);
if ($trimmed === '' || str_starts_with($trimmed, '#')) {
continue;
}
$pos = strpos($trimmed, '=');
if ($pos === false) {
continue;
}
$key = trim(substr($trimmed, 0, $pos));
$value = trim(substr($trimmed, $pos + 1));
if ($key === '') {
continue;
}
if (strlen($value) >= 2) {
$first = $value[0];
$last = $value[strlen($value) - 1];
if (($first === '"' && $last === '"') || ($first === "'" && $last === "'")) {
$value = substr($value, 1, -1);
}
}
$result[$key] = $value;
}
return $result;
}
function expand_env_values(array $env): array
{
$expanded = $env;
$pattern = '/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/';
foreach ($expanded as $key => $value) {
$expanded[$key] = preg_replace_callback(
$pattern,
static function (array $matches) use (&$expanded): string {
$lookup = $matches[1];
return (string) ($expanded[$lookup] ?? getenv($lookup) ?: '');
},
(string) $value
) ?? (string) $value;
}
return $expanded;
}
function env_value(string $key, array $localEnv, string $default = ''): string
{
$runtime = getenv($key);
if ($runtime !== false && $runtime !== '') {
return $runtime;
}
if (isset($localEnv[$key]) && $localEnv[$key] !== '') {
return (string) $localEnv[$key];
}
return $default;
}
function connect_database(): PDO
{
$env = parse_env_file(__DIR__ . '/../.env');
$env = expand_env_values($env);
$databaseUrl = env_value('DATABASE_URL', $env);
if ($databaseUrl !== '') {
$parts = parse_url($databaseUrl);
if ($parts !== false && ($parts['scheme'] ?? '') === 'postgresql') {
$host = (string) ($parts['host'] ?? '');
$port = (string) ($parts['port'] ?? '5432');
$dbName = ltrim((string) ($parts['path'] ?? ''), '/');
$user = (string) ($parts['user'] ?? '');
$pass = (string) ($parts['pass'] ?? '');
if ($host !== '' && $dbName !== '' && $user !== '') {
$dsn = "pgsql:host={$host};port={$port};dbname={$dbName}";
return new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
}
}
$host = env_value('DB_HOST', $env);
$port = env_value('DB_PORT', $env, '5432');
$dbName = env_value('DB_NAME', $env);
$user = env_value('DB_USER', $env);
$pass = env_value('DB_PASSWORD', $env);
if ($host === '' || $dbName === '' || $user === '') {
throw new RuntimeException('Missing DB configuration');
}
$dsn = "pgsql:host={$host};port={$port};dbname={$dbName}";
return new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
function parse_number(mixed $value): ?float
{
if ($value === null || $value === '') {
return null;
}
if (is_int($value) || is_float($value)) {
return (float) $value;
}
if (!is_string($value)) {
return null;
}
$normalized = str_replace(["\u{00A0}", ' '], '', trim($value));
$normalized = str_replace(',', '.', $normalized);
if (!is_numeric($normalized)) {
return null;
}
return (float) $normalized;
}
function json_response(int $status, array $payload): void
{
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}