1111
1212use Nette ;
1313use Nette \DI \ServiceCreationException ;
14+ use Nette \Utils \Strings ;
1415
1516
1617/**
@@ -24,6 +25,7 @@ final class ServiceDefinition extends Definition
2425{
2526 use Nette \SmartObject;
2627
28+ public ?bool $ lazy = null ;
2729 private Statement $ creator ;
2830
2931 /** @var Statement[] */
@@ -181,19 +183,36 @@ private function prependSelf(Statement $setup): Statement
181183
182184 public function generateMethod (Nette \PhpGenerator \Method $ method , Nette \DI \PhpGenerator $ generator ): void
183185 {
184- $ code = $ generator ->formatStatement ($ this ->creator ) . "; \n" ;
185- if (!$ this ->setup ) {
186- $ method ->setBody ('return ' . $ code );
187- return ;
186+ $ lines = [];
187+ foreach ([$ this ->creator , ...$ this ->setup ] as $ stmt ) {
188+ $ lines [] = $ generator ->formatStatement ($ stmt ) . "; \n" ;
188189 }
189190
190- $ code = '$service = ' . $ code ;
191- foreach ($ this ->setup as $ setup ) {
192- $ code .= $ generator ->formatStatement ($ setup ) . "; \n" ;
191+ if ($ this ->canBeLazy () && !preg_grep ('#(?:func_get_arg|func_num_args)#i ' , $ lines )) { // latteFactory workaround
192+ $ class = $ this ->creator ->getEntity ();
193+ $ lines [0 ] = (new \ReflectionClass ($ class ))->hasMethod ('__construct ' )
194+ ? $ generator ->formatPhp ("\$service->__construct(...?:); \n" , [$ this ->creator ->arguments ])
195+ : '' ;
196+ $ method ->setBody ("return new ReflectionClass( $ class::class)->newLazyGhost(function ( \$service) { \n"
197+ . Strings::indent (implode ('' , $ lines ))
198+ . '}); ' );
199+
200+ } elseif (count ($ lines ) === 1 ) {
201+ $ method ->setBody ('return ' . implode ('' , $ lines ));
202+
203+ } else {
204+ $ method ->setBody ('$service = ' . implode ('' , $ lines ) . 'return $service; ' );
193205 }
206+ }
194207
195- $ code .= 'return $service; ' ;
196- $ method ->setBody ($ code );
208+
209+ private function canBeLazy (): bool
210+ {
211+ return $ this ->lazy
212+ && is_string ($ class = $ this ->creator ->getEntity ())
213+ && ($ this ->creator ->arguments || $ this ->setup )
214+ && ($ ancestor = ($ tmp = class_parents ($ class )) ? array_pop ($ tmp ) : $ class )
215+ && !(new \ReflectionClass ($ ancestor ))->isInternal ();
197216 }
198217
199218
0 commit comments