Some checks failed
Deploy Application / deploy (push) Has been cancelled
103 lines
3.7 KiB
PHP
103 lines
3.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\View;
|
|
|
|
use App\Framework\Meta\MetaData;
|
|
use App\Framework\Template\TemplateContext;
|
|
use App\Framework\View\ValueObjects\ScopeStack;
|
|
|
|
final readonly class RenderContext implements TemplateContext
|
|
{
|
|
public readonly ScopeStack $scopes;
|
|
|
|
public function __construct(
|
|
public string $template, // Dateiname oder Template-Key
|
|
public MetaData $metaData,
|
|
public array $data = [], // Variablen wie ['title' => '...']
|
|
public ?string $layout = null, // Optionales Layout
|
|
public array $slots = [], // Benannte Slots wie ['main' => '<p>...</p>']
|
|
public ?string $controllerClass = null,
|
|
public ?string $route = null, // Route name for form ID generation
|
|
public ProcessingMode $processingMode = ProcessingMode::FULL,
|
|
public bool $isPartial = false, // Deprecated: Use processingMode instead
|
|
?ScopeStack $scopes = null, // Stack von Scopes für verschachtelte Loops
|
|
) {
|
|
// Initialize empty ScopeStack if not provided
|
|
$this->scopes = $scopes ?? ScopeStack::empty();
|
|
}
|
|
|
|
/**
|
|
* Erstellt einen neuen RenderContext mit zusätzlichem Scope
|
|
*
|
|
* Der neue Scope wird am Anfang des Scope-Stacks eingefügt (höchste Priorität).
|
|
* Dies ermöglicht verschachtelte Loops, bei denen innere Loop-Variablen
|
|
* äußere Variablen überschreiben können.
|
|
*
|
|
* @param array<string, mixed>|\App\Framework\View\ValueObjects\TemplateScope $variables
|
|
* Variablen für den neuen Scope (z.B. ['item' => $item]) oder TemplateScope
|
|
* @return self Neuer RenderContext mit erweitertem Scope-Stack
|
|
*/
|
|
public function withScope(array|\App\Framework\View\ValueObjects\TemplateScope $variables): self
|
|
{
|
|
return new self(
|
|
template: $this->template,
|
|
metaData: $this->metaData,
|
|
data: $this->data,
|
|
layout: $this->layout,
|
|
slots: $this->slots,
|
|
controllerClass: $this->controllerClass,
|
|
route: $this->route,
|
|
processingMode: $this->processingMode,
|
|
isPartial: $this->isPartial,
|
|
scopes: $this->scopes->push($variables),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Löst eine Variable aus allen verfügbaren Scopes auf
|
|
*
|
|
* Sucht die Variable zuerst in den Scopes (von innen nach außen),
|
|
* dann in den globalen Daten.
|
|
*
|
|
* @param string $name Variablenname (ohne $)
|
|
* @return mixed Wert der Variable oder null wenn nicht gefunden
|
|
*/
|
|
public function resolveVariable(string $name): mixed
|
|
{
|
|
// Suche in Scopes (von innen nach außen)
|
|
$value = $this->scopes->resolve($name);
|
|
if ($value !== null) {
|
|
return $value;
|
|
}
|
|
|
|
// Fallback zu globalen Daten
|
|
if (array_key_exists($name, $this->data)) {
|
|
return $this->data[$name];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Gibt alle verfügbaren Variablen zurück (alle Scopes + globale Daten)
|
|
*
|
|
* Die Variablen werden gemerged, wobei innerste Scopes Priorität haben.
|
|
* Dies ist nützlich für ExpressionEvaluator, der einen flachen Array erwartet.
|
|
*
|
|
* @return array<string, mixed> Alle Variablen mit Scope-Priorität (innerste Scope überschreibt äußere)
|
|
*/
|
|
public function getAllVariables(): array
|
|
{
|
|
// Beginne mit globalen Daten
|
|
$allVariables = $this->data;
|
|
|
|
// Merge Scopes (ScopeStack handles priority: inner scopes override outer)
|
|
$scopeVariables = $this->scopes->getAllVariables();
|
|
$allVariables = array_merge($allVariables, $scopeVariables);
|
|
|
|
return $allVariables;
|
|
}
|
|
}
|