render($_component); } return $out; } try { $this->pushContext($component); $renderer = $this->getRendererFor($component); $out = $renderer->render($component, $root); } finally { $this->popContext(); } return $out; } /** * @inheritdoc */ public function renderAsync($component, ?Renderer $root = null) { $root = $root ?? $this; $out = ''; if (is_array($component)) { foreach ($component as $_component) { $out .= $root->renderAsync($_component); } } else { $out = $this->render($component, $root) . $this->java_script_binding->getOnLoadCodeAsync(); } return $out; } /** * Get a renderer for a certain Component class. * * Either initializes a new renderer or uses a cached one initialized * before. * * @throws LogicException if no renderer could be found for component. */ protected function getRendererFor(Component $component): ComponentRenderer { return $this->component_renderer_loader->getRendererFor($component, $this->getContexts()); } /** * Returns the current context stack, where most recently added components are last. * E.g. ["FirstComponent", "SecondComponent", "ThirdComponent", ...]; * * @return Component[] */ protected function getContexts(): array { return $this->contexts; } /** * Adds a component to the current context stack. This mainly serves for testability. */ protected function pushContext(Component $component): void { $this->contexts[] = $component; } /** * Removes the most recently added component from the current context stack. * This mainly serves for testability. */ protected function popContext(): void { array_pop($this->contexts); } }