commit
This commit is contained in:
@@ -3,60 +3,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace App;
|
||||
|
||||
final class Config
|
||||
class Config
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $env,
|
||||
public readonly string $prefix,
|
||||
public readonly string $primaryDomain,
|
||||
public readonly string $primaryUrl,
|
||||
public readonly string $apiBase,
|
||||
public readonly string $assetVersion,
|
||||
public readonly bool $dbEnabled,
|
||||
public readonly array $db,
|
||||
) {}
|
||||
|
||||
public static function fromPhpConstants(string $configDir): self
|
||||
{
|
||||
// config.php defines these constants.
|
||||
$env = defined('APP_ENV') ? (string) APP_ENV : 'prod';
|
||||
$prefix = defined('APP_PREFIX') ? (string) APP_PREFIX : 'app';
|
||||
$primaryDom = defined('APP_DOMAIN_PRIMARY') ? (string) APP_DOMAIN_PRIMARY : 'example.test';
|
||||
$primaryUrl = defined('APP_URL_PRIMARY') ? (string) APP_URL_PRIMARY : 'https://example.test';
|
||||
$apiBase = defined('APP_API_BASE') ? (string) APP_API_BASE : ($primaryUrl . '/api');
|
||||
$assetVersion = defined('ASSET_VERSION') ? (string) ASSET_VERSION : '';
|
||||
|
||||
$dbEnabled = defined('APP_DB_ENABLED') ? (bool) APP_DB_ENABLED : false;
|
||||
|
||||
$dbFileRoot = rtrim($configDir, '/\\') . DIRECTORY_SEPARATOR . 'db.php';
|
||||
$dbFileEnv = rtrim($configDir, '/\\') . DIRECTORY_SEPARATOR . $env . DIRECTORY_SEPARATOR . 'db.php';
|
||||
$dbFile = file_exists($dbFileRoot) ? $dbFileRoot : (file_exists($dbFileEnv) ? $dbFileEnv : null);
|
||||
$db = $dbFile ? (array) require $dbFile : [];
|
||||
|
||||
return new self(
|
||||
env: $env,
|
||||
prefix: $prefix,
|
||||
primaryDomain: $primaryDom,
|
||||
primaryUrl: rtrim($primaryUrl, '/'),
|
||||
apiBase: rtrim($apiBase, '/'),
|
||||
assetVersion: $assetVersion,
|
||||
dbEnabled: $dbEnabled,
|
||||
db: $db
|
||||
);
|
||||
public array $db,
|
||||
public bool $dbEnabled = true
|
||||
) {
|
||||
}
|
||||
|
||||
public function cookiePrefix(): string
|
||||
{
|
||||
// Example: add suffix for staging
|
||||
if ($this->env === 'staging') {
|
||||
return $this->prefix . '_stg_';
|
||||
}
|
||||
return $this->prefix . '_';
|
||||
}
|
||||
|
||||
public function cookieDomain(): string
|
||||
{
|
||||
// Leading dot for subdomain-wide cookies
|
||||
return '.' . ltrim($this->primaryDomain, '.');
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/App/functions.php
Normal file
28
src/App/functions.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Lädt ein Template-Partial.
|
||||
*
|
||||
* @param string $name Dateiname ohne .php
|
||||
* @param string $folder Unterordner in /public/partials/
|
||||
* @param array $data Daten, die im Template verfügbar sein sollen
|
||||
*/
|
||||
function tpl(string $name, string $folder = 'landing', array $data = []): void
|
||||
{
|
||||
$path = __DIR__ . '/../../public/partials/' . $folder . '/' . $name . '.php';
|
||||
if (file_exists($path)) {
|
||||
extract($data);
|
||||
require $path;
|
||||
} else {
|
||||
echo "<!-- Template not found: {$folder}/{$name} -->";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML Escaping Helper.
|
||||
*/
|
||||
function e(?string $string): string
|
||||
{
|
||||
return htmlspecialchars($string ?? '', ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
104
src/Repository/KeaHostRepository.php
Normal file
104
src/Repository/KeaHostRepository.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* Repository für das KEA DHCP Host-Management.
|
||||
* Interagiert direkt mit der 'hosts' Tabelle in der PostgreSQL-Datenbank.
|
||||
*/
|
||||
final class KeaHostRepository
|
||||
{
|
||||
public function __construct(private PDO $pdo) {}
|
||||
|
||||
/**
|
||||
* Ruft eine Liste aller Host-Reservierungen ab (Geräte-Inventar).
|
||||
*/
|
||||
public function findAll(int $limit = 50): array
|
||||
{
|
||||
// 'dhcp_identifier' ist in KEA i.d.R. die MAC-Adresse (bei type=1)
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT host_id, dhcp_identifier, ipv4_address, hostname, user_context
|
||||
FROM hosts
|
||||
ORDER BY host_id DESC
|
||||
LIMIT :limit'
|
||||
);
|
||||
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sucht einen Host anhand der MAC-Adresse (dhcp_identifier).
|
||||
*/
|
||||
public function findByMac(string $mac): ?array
|
||||
{
|
||||
// Hinweis: KEA speichert MACs in PostgreSQL oft als BYTEA.
|
||||
// Je nach Treiber-Konfiguration muss $mac hier ggf. als Hex-String (z.B. '\x...')
|
||||
// formatiert übergeben werden.
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT host_id, dhcp_identifier, ipv4_address, hostname, user_context
|
||||
FROM hosts
|
||||
WHERE dhcp_identifier = :mac
|
||||
LIMIT 1'
|
||||
);
|
||||
$stmt->execute(['mac' => $mac]);
|
||||
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
return $row ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt eine neue Host-Reservierung inkl. Metadaten.
|
||||
*
|
||||
* @param string $mac MAC-Adresse
|
||||
* @param string $ip IPv4-Adresse
|
||||
* @param int $subnetId Die ID des Subnets (dhcp4_subnet_id), in dem die IP liegt
|
||||
* @param string|null $hostname Optionaler Hostname
|
||||
* @param array $metadata Zusätzliche Infos (Standort, Verantwortlicher etc.) für 'user_context'
|
||||
*/
|
||||
public function create(string $mac, string $ip, int $subnetId, ?string $hostname = null, array $metadata = []): int
|
||||
{
|
||||
// Metadaten werden im KEA-Standardfeld 'user_context' als JSON gespeichert
|
||||
$userContextJson = json_encode($metadata, JSON_THROW_ON_ERROR);
|
||||
|
||||
// dhcp_identifier_type 1 = HW_ADDRESS (Ethernet)
|
||||
$stmt = $this->pdo->prepare(
|
||||
'INSERT INTO hosts (dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, ipv4_address, hostname, user_context)
|
||||
VALUES (:mac, 1, :subnetId, :ip, :hostname, :user_context)'
|
||||
);
|
||||
|
||||
$stmt->execute([
|
||||
'mac' => $mac,
|
||||
'subnetId' => $subnetId,
|
||||
'ip' => $ip,
|
||||
'hostname' => $hostname,
|
||||
'user_context' => $userContextJson,
|
||||
]);
|
||||
|
||||
return $this->lastInsertIdSafe();
|
||||
}
|
||||
|
||||
private function driver(): string
|
||||
{
|
||||
return (string)$this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||
}
|
||||
|
||||
private function lastInsertIdSafe(): int
|
||||
{
|
||||
$driver = $this->driver();
|
||||
|
||||
if ($driver === 'pgsql') {
|
||||
// KEA Standard-Sequenz für die hosts Tabelle
|
||||
$id = $this->pdo->lastInsertId('hosts_host_id_seq');
|
||||
if ($id !== '') {
|
||||
return (int)$id;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)$this->pdo->lastInsertId();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user