'...']
public ?string $layout = null, // Optionales Layout
public array $slots = [], // Benannte Slots wie ['main' => '
...
']
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|\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 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;
}
}