diff --git a/src/TwigComponent/src/BlockStack.php b/src/TwigComponent/src/BlockStack.php index f6a249e3d3..1d4cb90ba7 100644 --- a/src/TwigComponent/src/BlockStack.php +++ b/src/TwigComponent/src/BlockStack.php @@ -28,9 +28,15 @@ final class BlockStack */ private array $stack; + /** + * @var array + */ + private static array $templateIndexStack = []; + public function convert(array $blocks, int $targetEmbeddedTemplateIndex): array { $newBlocks = []; + $hostEmbeddedTemplateIndex = null; foreach ($blocks as $blockName => $block) { // Keep already converted outer blocks untouched if (str_starts_with($blockName, self::OUTER_BLOCK_PREFIX)) { @@ -41,7 +47,7 @@ public function convert(array $blocks, int $targetEmbeddedTemplateIndex): array // Determine the location of the block where it is defined in the host Template. // Each component has its own embedded template. That template's index uniquely // identifies the block definition. - $hostEmbeddedTemplateIndex = $this->findHostEmbeddedTemplateIndex(); + $hostEmbeddedTemplateIndex ??= $this->findHostEmbeddedTemplateIndex(); // Change the name of outer blocks to something unique so blocks of nested components aren't overridden, // which otherwise might cause a recursion loop when nesting components. @@ -69,12 +75,10 @@ private function findHostEmbeddedTemplateIndex(): int { $backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS | \DEBUG_BACKTRACE_PROVIDE_OBJECT); - $componentTemplateClassName = null; - foreach ($backtrace as $trace) { if (isset($trace['object']) && $trace['object'] instanceof Template) { $classname = $trace['object']::class; - $templateIndex = $this->getTemplateIndexFromTemplateClassname($classname); + $templateIndex = self::getTemplateIndexFromTemplateClassname($classname); if ($templateIndex) { // If there's no template index, then we're in a component template // and we need to go up until we find the embedded template @@ -93,7 +97,7 @@ private function findCallingEmbeddedTemplateIndex(): int foreach ($backtrace as $trace) { if (isset($trace['object']) && $trace['object'] instanceof Template) { - return $this->getTemplateIndexFromTemplateClassname($trace['object']::class); + return self::getTemplateIndexFromTemplateClassname($trace['object']::class); } } } @@ -108,7 +112,7 @@ private function findHostEmbeddedTemplateIndexFromCaller(): int foreach ($backtrace as $trace) { if (isset($trace['object']) && $trace['object'] instanceof Template) { $classname = $trace['object']::class; - $templateIndex = $this->getTemplateIndexFromTemplateClassname($classname); + $templateIndex = self::getTemplateIndexFromTemplateClassname($classname); if (null === $renderer) { if ($templateIndex) { // This class is an embedded template. @@ -139,8 +143,8 @@ private function findHostEmbeddedTemplateIndexFromCaller(): int return 0; } - private function getTemplateIndexFromTemplateClassname(string $classname): int + private static function getTemplateIndexFromTemplateClassname(string $classname): int { - return (int) substr($classname, strrpos($classname, '___') + 3); + return self::$templateIndexStack[$classname] ??= (int) substr($classname, strrpos($classname, '___') + 3); } }