|
|
@@ -136,32 +136,43 @@ class RegisterCprController
|
|
|
throw new \RuntimeException('genial-cli returned empty output');
|
|
|
}
|
|
|
|
|
|
+ $decoded = json_decode($clean, true);
|
|
|
+ if (json_last_error() === JSON_ERROR_NONE) {
|
|
|
+ return $decoded;
|
|
|
+ }
|
|
|
+
|
|
|
+ $normalized = $this->normalizeCliOutput($clean);
|
|
|
+ $decoded = json_decode($normalized, true);
|
|
|
+ if (json_last_error() !== JSON_ERROR_NONE) {
|
|
|
+ throw new \RuntimeException('Failed to decode genial-cli output: ' . json_last_error_msg());
|
|
|
+ }
|
|
|
+
|
|
|
+ return $decoded;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function normalizeCliOutput(string $content): string
|
|
|
+ {
|
|
|
// Strip ANSI escape codes, just in case
|
|
|
- $clean = preg_replace('/\e\[[\d;]*m/', '', $clean);
|
|
|
+ $normalized = preg_replace('/\e\[[\d;]*m/', '', $content);
|
|
|
|
|
|
// Convert single-quoted strings to JSON-compatible double-quoted ones
|
|
|
- $clean = preg_replace_callback(
|
|
|
- "/'([^'\\]*(?:\\.[^'\\]*)*)'/",
|
|
|
+ $normalized = preg_replace_callback(
|
|
|
+ "/'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)'/",
|
|
|
static function (array $matches): string {
|
|
|
$inner = str_replace(['\\', '"'], ['\\\\', '\\"'], $matches[1]);
|
|
|
return '"' . $inner . '"';
|
|
|
},
|
|
|
- $clean
|
|
|
+ $normalized
|
|
|
);
|
|
|
|
|
|
// Quote object keys so json_decode can understand them
|
|
|
- $clean = preg_replace(
|
|
|
- '/([\\{\\[,,]\s*|\n\s*)([A-Za-z_][A-Za-z0-9_]*)\s*:/',
|
|
|
- '$1"$2":',
|
|
|
- $clean
|
|
|
+ $normalized = preg_replace(
|
|
|
+ '/(?<=\{|\[|,|\n)\s*([A-Za-z_][A-Za-z0-9_]*)\s*:/',
|
|
|
+ '"$1":',
|
|
|
+ $normalized
|
|
|
);
|
|
|
|
|
|
- $decoded = json_decode($clean, true);
|
|
|
- if (json_last_error() !== JSON_ERROR_NONE) {
|
|
|
- throw new \RuntimeException('Failed to decode genial-cli output: ' . json_last_error_msg());
|
|
|
- }
|
|
|
-
|
|
|
- return $decoded;
|
|
|
+ return $normalized;
|
|
|
}
|
|
|
|
|
|
private function logCliResult(array $result, string $context): void
|