{
"event": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "ssh root@prod.karlkratz.com \"cat \/var\/www\/prod.karlkratz.de\/src\/Helpers\/ConfigLoader.php\"",
"timeout": 30000,
"description": "Show ConfigLoader class"
}
}
{
"tool_response": {
"stdout": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Helpers;\n\nuse App\\Services\\Config;\n\n\/**\n * ConfigLoader - DB-based Configuration System\n *\n * Lädt dynamische Konfiguration aus tenant_config Tabelle.\n * Nutzt App\\Services\\Config für DB-Verbindung (Credentials aus \/var\/credentials\/).\n *\/\nclass ConfigLoader {\n private static $instance = null;\n private $config = [];\n private $initialized = false;\n private $environment;\n private static ?\\PDO $db = null;\n\n \/**\n * Private Konstruktor für das Singleton-Pattern\n *\/\n private function __construct() {\n \/\/ Environment aus Config (auto-detected)\n $this->environment = Config::environment();\n\n $this->loadConfig();\n }\n\n \/**\n * Singleton-Instanz erhalten\n *\/\n public static function getInstance(): ConfigLoader {\n if (self::$instance === null) {\n self::$instance = new self();\n }\n return self::$instance;\n }\n\n \/**\n * Statischer Hilfsmethode für einfachen Zugriff\n *\/\n public static function config($key = null, $default = null) {\n $instance = self::getInstance();\n \n if ($key === null) {\n return $instance->getAll();\n }\n \n return $instance->get($key, $default);\n }\n\n \/**\n * Lädt Konfiguration aus DB-System\n *\/\n private function loadConfig() {\n try {\n $this->initDatabase();\n $this->loadFromDatabase();\n $this->initialized = true;\n } catch (\\Exception $e) {\n error_log(\"ConfigLoader DB initialization failed: \" . $e->getMessage());\n \/\/ Fallback zu leerem Config-Array\n $this->config = [];\n $this->initialized = true;\n }\n }\n\n \/**\n * Initialisiert DB-Verbindung via Config (aus \/var\/credentials\/)\n *\/\n private function initDatabase(): void {\n \/\/ PDO direkt aus Config erstellen\n self::$db = Config::createPDO();\n }\n\n \/**\n * Lädt alle Configs aus tenant_config Tabelle\n *\/\n private function loadFromDatabase(): void {\n $sql = \"SELECT section, config_key, config_value FROM tenant_config\n WHERE environment IN ('all', :env1)\n ORDER BY section, config_key, FIELD(environment, :env2, 'all')\";\n\n $stmt = self::$db->prepare($sql);\n $stmt->execute(['env1' => $this->environment, 'env2' => $this->environment]);\n $results = $stmt->fetchAll();\n\n $this->config = [];\n foreach ($results as $row) {\n $section = $row['section'];\n $key = $row['config_key'];\n $value = json_decode($row['config_value'], true);\n\n if (!isset($this->config[$section])) {\n $this->config[$section] = [];\n }\n\n \/\/ Expand dot-notation keys into nested arrays\n \/\/ e.g., key='whitelist.ips' becomes ['whitelist']['ips']\n $this->setNestedValue($this->config[$section], $key, $value);\n }\n }\n\n \/**\n * Setzt einen Wert in einem verschachtelten Array über Dot-Notation\n *\/\n private function setNestedValue(array &$array, string $key, $value): void {\n $keys = explode('.', $key);\n $current = &$array;\n\n foreach ($keys as $i => $segment) {\n if ($i === count($keys) - 1) {\n \/\/ Letztes Segment - Wert setzen (nur wenn nicht bereits gesetzt)\n if (!isset($current[$segment])) {\n $current[$segment] = $value;\n }\n } else {\n \/\/ Zwischensegment - Array erstellen falls nötig\n if (!isset($current[$segment]) || !is_array($current[$segment])) {\n $current[$segment] = [];\n }\n $current = &$current[$segment];\n }\n }\n }\n\n \/**\n * Holt einen Konfigurationswert über einen Pfad (dot notation)\n *\/\n public function get(string $key, $default = null) {\n if (!$this->initialized) {\n $this->loadConfig();\n }\n \n \/\/ Verschachtelter Key mit Punkt-Notation (z.B. 'database.connection.host')\n $keys = explode('.', $key);\n $value = $this->config;\n \n foreach ($keys as $segment) {\n if (!is_array($value) || !array_key_exists($segment, $value)) {\n return $default;\n }\n $value = $value[$segment];\n }\n \n return $value;\n }\n\n \/**\n * Gibt alle Konfigurationswerte zurück\n *\/\n public function getAll(): array {\n if (!$this->initialized) {\n $this->loadConfig();\n }\n return $this->config;\n }\n\n \/**\n * Prüft, ob ein Konfigurationsschlüssel existiert\n *\/\n public function has(string $key): bool {\n if (!$this->initialized) {\n $this->loadConfig();\n }\n \n \/\/ Verschachtelter Key mit Punkt-Notation\n $keys = explode('.', $key);\n $value = $this->config;\n \n foreach ($keys as $segment) {\n if (!is_array($value) || !array_key_exists($segment, $value)) {\n return false;\n }\n $value = $value[$segment];\n }\n \n return true;\n }\n\n \/**\n * Gibt die aktuelle Umgebung zurück\n *\/\n public function getEnvironment(): string {\n return $this->environment;\n }\n\n \/**\n * Hilfsmethode für die Überprüfung, ob eine bestimmte Umgebung aktiv ist\n *\/\n public function isEnvironment(string $env): bool {\n if (($env === 'production' || $env === 'prod') && $this->environment === 'prod') {\n return true;\n }\n \n if (($env === 'development' || $env === 'dev') && $this->environment === 'dev') {\n return true;\n }\n \n return $this->environment === $env;\n }\n\n \/**\n * Lädt die Konfiguration neu\n *\/\n public function refresh() {\n $this->config = [];\n $this->initialized = false;\n self::$db = null;\n $this->loadConfig();\n }\n\n \/**\n * Lädt JSON-Config-Datei als Fallback (für Services wie CRM, Auth)\n *\/\n public function loadJsonConfig(string $configName): array {\n $configFile = __DIR__ . \"\/..\/Config\/{$configName}.json\";\n\n if (!file_exists($configFile)) {\n error_log(\"ConfigLoader: JSON config file not found: {$configFile}\");\n return [];\n }\n\n $content = file_get_contents($configFile);\n $config = json_decode($content, true);\n\n if (json_last_error() !== JSON_ERROR_NONE) {\n error_log(\"ConfigLoader: Invalid JSON in {$configFile}: \" . json_last_error_msg());\n return [];\n }\n\n return $config;\n }\n\n \/**\n * Statische Methode für JSON-Config-Zugriff\n *\/\n public static function getJsonConfig(string $configName): array {\n $instance = self::getInstance();\n return $instance->loadJsonConfig($configName);\n }\n\n \/\/ OLD JSON SYSTEM - AUSKOMMENTIERT\n \/*\n private $configDir;\n \n private function loadConfig() {\n \/\/ Basis-Konfigurationsdateien\n $configFiles = $this->getConfigFiles();\n \n foreach ($configFiles as $file) {\n $this->loadConfigFile($file);\n }\n \n $this->initialized = true;\n }\n\n private function getConfigFiles(): array {\n $baseFiles = glob($this->configDir . '*.json');\n $envFiles = glob($this->configDir . '*.' . $this->environment . '.json');\n \n sort($baseFiles);\n sort($envFiles);\n \n return array_merge($baseFiles, $envFiles);\n }\n\n private function loadConfigFile(string $file) {\n \/\/ JSON file loading logic...\n }\n\n private function mergeConfigs(array $base, array $override): array {\n \/\/ Config merging logic...\n }\n\n private function overrideWithEnv(string $configKey, array $configData): array {\n \/\/ ENV override logic...\n }\n \n private function setNestedValue(array &$array, string $path, $value): void {\n \/\/ Nested value setting...\n }\n *\/\n}",
"stderr": "",
"interrupted": false,
"isImage": false,
"noOutputExpected": false
}
}