11
11
12
12
use Nette ;
13
13
use Nette \DI \ServiceCreationException ;
14
+ use Nette \Utils \Strings ;
14
15
15
16
16
17
/**
@@ -24,6 +25,7 @@ final class ServiceDefinition extends Definition
24
25
{
25
26
use Nette \SmartObject;
26
27
28
+ public ?bool $ lazy = null ;
27
29
private Statement $ creator ;
28
30
29
31
/** @var Statement[] */
@@ -181,19 +183,36 @@ private function prependSelf(Statement $setup): Statement
181
183
182
184
public function generateMethod (Nette \PhpGenerator \Method $ method , Nette \DI \PhpGenerator $ generator ): void
183
185
{
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" ;
188
189
}
189
190
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; ' );
193
205
}
206
+ }
194
207
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 ();
197
216
}
198
217
199
218
0 commit comments