feat(Production): Complete production deployment infrastructure

- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
This commit is contained in:
2025-10-25 19:18:37 +02:00
parent caa85db796
commit fc3d7e6357
83016 changed files with 378904 additions and 20919 deletions

View File

@@ -6,8 +6,11 @@ namespace App\Framework\View\Processors;
use App\Framework\Config\AppConfig;
use App\Framework\DI\Container;
use App\Framework\LiveComponents\ComponentRegistry;
use App\Framework\LiveComponents\Contracts\LiveComponentContract;
use App\Framework\Template\Processing\StringProcessor;
use App\Framework\View\Functions\ImageSlotFunction;
use App\Framework\View\Functions\LazyComponentFunction;
use App\Framework\View\Functions\UrlFunction;
use App\Framework\View\RawHtml;
use App\Framework\View\RenderContext;
@@ -19,6 +22,7 @@ final class PlaceholderReplacer implements StringProcessor
{
public function __construct(
private readonly Container $container,
private readonly ComponentRegistry $componentRegistry
) {
}
@@ -37,9 +41,22 @@ final class PlaceholderReplacer implements StringProcessor
// Template-Funktionen: {{ date('Y-m-d') }}, {{ format_currency(100) }}
$html = $this->replaceTemplateFunctions($html, $context);
// Standard Variablen und Methoden: {{ item.getRelativeFile() }}
// Triple curly braces for raw/unescaped HTML: {{{ $content }}} or {{{ content }}}
// Supports both old and new syntax for backwards compatibility
$html = preg_replace_callback(
'/{{{\\s*\\$?([\\w.]+)\\s*}}}/',
function ($matches) use ($context) {
$expression = $matches[1];
return $this->resolveRaw($context->data, $expression);
},
$html
);
// Standard Variablen und Methoden: {{ $item.getRelativeFile() }} or {{ item.getRelativeFile() }}
// Supports both old and new syntax for backwards compatibility
return preg_replace_callback(
'/{{\\s*([\\w.]+)(?:\\(\\s*([^)]*)\\s*\\))?\\s*}}/',
'/{{\\s*\\$?([\\w.]+)(?:\\(\\s*([^)]*)\\s*\\))?\\s*}}/',
function ($matches) use ($context) {
$expression = $matches[1];
$params = isset($matches[2]) ? trim($matches[2]) : null;
@@ -62,7 +79,7 @@ final class PlaceholderReplacer implements StringProcessor
$functionName = $matches[1];
$params = trim($matches[2]);
$functions = new TemplateFunctions($this->container, ImageSlotFunction::class, UrlFunction::class);
$functions = new TemplateFunctions($this->container, ImageSlotFunction::class, LazyComponentFunction::class, UrlFunction::class);
if ($functions->has($functionName)) {
$function = $functions->get($functionName);
$args = $this->parseParams($params, $context->data);
@@ -166,6 +183,46 @@ final class PlaceholderReplacer implements StringProcessor
}
}
private function resolveRaw(array $data, string $expr): string
{
$value = $this->resolveValue($data, $expr);
if ($value === null) {
// Bleibt als Platzhalter stehen
return '{{{ ' . $expr . ' }}}';
}
// LiveComponentContract - automatisch rendern mit Wrapper
if ($value instanceof LiveComponentContract) {
return $this->componentRegistry->renderWithWrapper($value);
}
// RawHtml-Objekte - direkt ausgeben
if ($value instanceof RawHtml) {
return $value->content;
}
// HtmlElement-Objekte - direkt ausgeben
if ($value instanceof \App\Framework\View\ValueObjects\HtmlElement) {
return (string) $value;
}
// Strings direkt ausgeben (KEIN escaping!)
if (is_string($value)) {
return $value;
}
// Arrays und komplexe Objekte können nicht direkt als String dargestellt werden
if (is_array($value)) {
return $this->handleArrayValue($expr, $value);
}
if (is_object($value) && ! method_exists($value, '__toString')) {
return $this->handleObjectValue($expr, $value);
}
return (string)$value;
}
private function resolveEscaped(array $data, string $expr, int $flags): string
{
$value = $this->resolveValue($data, $expr);
@@ -174,6 +231,14 @@ final class PlaceholderReplacer implements StringProcessor
return '{{ ' . $expr . ' }}';
}
// LiveComponentContract - automatisch rendern mit Wrapper
// WICHTIG: Wrapper-HTML ist bereits escaped, also NICHT nochmal escapen!
if ($value instanceof LiveComponentContract) {
$wrapperHtml = $this->componentRegistry->renderWithWrapper($value);
// Wrap in RawHtml to prevent double-escaping by code below (line 271)
return $wrapperHtml;
}
// RawHtml-Objekte nicht escapen
if ($value instanceof RawHtml) {
return $value->content;