diff --git a/src/Bridges/ApplicationDI/ApplicationExtension.php b/src/Bridges/ApplicationDI/ApplicationExtension.php index cdb09ecec..c74089010 100644 --- a/src/Bridges/ApplicationDI/ApplicationExtension.php +++ b/src/Bridges/ApplicationDI/ApplicationExtension.php @@ -28,6 +28,9 @@ final class ApplicationExtension extends Nette\DI\CompilerExtension /** @var array */ private $scanDirs; + /** @var Nette\Loaders\RobotLoader|null */ + private $robotLoader; + /** @var int */ private $invalidLinkMode; @@ -35,11 +38,12 @@ final class ApplicationExtension extends Nette\DI\CompilerExtension private $tempDir; - public function __construct(bool $debugMode = false, array $scanDirs = null, string $tempDir = null) + public function __construct(bool $debugMode = false, array $scanDirs = null, string $tempDir = null, Nette\Loaders\RobotLoader $robotLoader = null) { $this->debugMode = $debugMode; $this->scanDirs = (array) $scanDirs; $this->tempDir = $tempDir; + $this->robotLoader = $robotLoader; } @@ -78,7 +82,7 @@ public function loadConfiguration() } $this->compiler->addExportedType(Nette\Application\Application::class); - $touch = $this->debugMode && $config->scanDirs && $this->tempDir ? $this->tempDir . '/touch' : null; + $touch = $this->debugMode && ($config->scanDirs || $this->robotLoader) && $this->tempDir ? $this->tempDir . '/touch' : null; $presenterFactory = $builder->addDefinition($this->prefix('presenterFactory')) ->setType(Nette\Application\IPresenterFactory::class) ->setFactory(Nette\Application\PresenterFactory::class, [new Definitions\Statement( @@ -133,9 +137,15 @@ public function beforeCompile() private function findPresenters(): array { $config = $this->getConfig(); - $classes = []; - if ($config->scanDirs) { + if ($this->robotLoader) { + if ($config->scanDirs && $config->scanDirs !== $this->scanDirs) { + trigger_error("Option 'scanDir' has no effect, global RobotLoader is used.", E_USER_DEPRECATED); + } + $robot = $this->robotLoader; + $robot->refresh(); + + } elseif ($config->scanDirs) { if (!class_exists(Nette\Loaders\RobotLoader::class)) { throw new Nette\NotSupportedException("RobotLoader is required to find presenters, install package `nette/robot-loader` or disable option {$this->prefix('scanDirs')}: false"); } @@ -148,6 +158,10 @@ private function findPresenters(): array } else { $robot->rebuild(); } + } + + $classes = []; + if (isset($robot)) { $classes = array_keys($robot->getIndexedClasses()); $this->getContainerBuilder()->addDependency($this->tempDir . '/touch'); } diff --git a/tests/Bridges.DI/ApplicationExtension.scan.phpt b/tests/Bridges.DI/ApplicationExtension.scan.phpt index 84e1209cb..59723a575 100644 --- a/tests/Bridges.DI/ApplicationExtension.scan.phpt +++ b/tests/Bridges.DI/ApplicationExtension.scan.phpt @@ -78,3 +78,25 @@ test(function () { $name = $container->findByType(Presenter1::class)[0]; Assert::same('test', $container->createService($name)->getView()); }); + + +test(function () { + $robot = new Nette\Loaders\RobotLoader; + $robot->addDirectory(__DIR__ . '/files'); + $robot->setTempDirectory(getTempDir()); + + $compiler = new DI\Compiler; + $compiler->addExtension('application', new ApplicationExtension(false, null, null, $robot)); + + $builder = $compiler->getContainerBuilder(); + $builder->addDefinition('myRouter')->setFactory(Nette\Application\Routers\SimpleRouter::class); + $builder->addDefinition('myHttpRequest')->setFactory(Nette\Http\Request::class, [new DI\Statement(Nette\Http\UrlScript::class)]); + $builder->addDefinition('myHttpResponse')->setFactory(Nette\Http\Response::class); + $code = $compiler->setClassName('Container4')->compile(); + eval($code); + + $container = new Container2; + Assert::count(3, $container->findByType(BasePresenter::class)); + Assert::count(1, $container->findByType(Presenter1::class)); + Assert::count(1, $container->findByType(Presenter2::class)); +}); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 600348824..4d8c52cf9 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -22,6 +22,27 @@ }, ob_get_level()); +function getTempDir(): string +{ + $dir = __DIR__ . '/tmp/' . getmypid(); + + if (empty($GLOBALS['\\lock'])) { + // garbage collector + $GLOBALS['\\lock'] = $lock = fopen(__DIR__ . '/lock', 'w'); + if (rand(0, 100)) { + flock($lock, LOCK_SH); + @mkdir(dirname($dir)); + } elseif (flock($lock, LOCK_EX)) { + Tester\Helpers::purge(dirname($dir)); + } + + @mkdir($dir); + } + + return $dir; +} + + function test(\Closure $function): void { $function();