1111
1212use Nette ;
1313use Nette \DI \ServiceCreationException ;
14+ use Nette \Utils \Strings ;
1415
1516
1617/**
@@ -24,6 +25,8 @@ final class ServiceDefinition extends Definition
2425{
2526 use Nette \SmartObject;
2627
28+ public ?bool $ lazy = null ;
29+
2730 private Statement $ creator ;
2831
2932 /** @var Statement[] */
@@ -181,18 +184,33 @@ private function prependSelf(Statement $setup): Statement
181184
182185 public function generateCode (Nette \DI \PhpGenerator $ generator ): string
183186 {
184- $ code = $ this -> creator -> generateCode ( $ generator ) . " ; \n" ;
185- if (! $ this ->setup ) {
186- return ' return ' . $ code ;
187+ $ lines = [] ;
188+ foreach ([ $ this ->creator , ... $ this -> setup ] as $ stmt ) {
189+ $ lines [] = $ stmt -> generateCode ( $ generator ) . " ; \n" ;
187190 }
188191
189- $ code = '$service = ' . $ code ;
190- foreach ($ this ->setup as $ setup ) {
191- $ code .= $ setup ->generateCode ($ generator ) . "; \n" ;
192+ $ class = $ this ->creator ->getEntity ();
193+ $ lazy = PHP_VERSION_ID >= 80400
194+ && $ this ->lazy
195+ && is_string ($ class )
196+ && ($ ancestor = ($ tmp = class_parents ($ class )) ? array_pop ($ tmp ) : $ class )
197+ && !(new \ReflectionClass ($ ancestor ))->isInternal ()
198+ && !preg_grep ('#(?:func_get_arg|func_num_args)#i ' , $ lines ); // latteFactory workaround
199+
200+ if ($ lazy ) {
201+ $ lines [0 ] = (new \ReflectionClass ($ class ))->hasMethod ('__construct ' )
202+ ? $ generator ->formatPhp ("\$service->__construct(...?:); \n" , [$ this ->creator ->arguments ])
203+ : '' ;
204+ return "return new ReflectionClass( $ class::class)->newLazyGhost(function ( \$service) { \n"
205+ . Strings::indent (implode ('' , $ lines ))
206+ . '}); ' ;
207+
208+ } elseif (count ($ lines ) === 1 ) {
209+ return 'return ' . $ lines [0 ];
210+
211+ } else {
212+ return '$service = ' . implode ('' , $ lines ) . 'return $service; ' ;
192213 }
193-
194- $ code .= 'return $service; ' ;
195- return $ code ;
196214 }
197215
198216
0 commit comments