From 69a7c7be7980dbb156da4cfc26d442df2c2f6c6b Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 10:47:09 +0100 Subject: [PATCH 01/43] Add registry --- .../src/Commands/DiscoveryGenerateCommand.php | 4 +- packages/core/src/FrameworkKernel.php | 39 ++++++++++++++++--- packages/core/src/Kernel/LoadConfig.php | 10 +++-- .../core/src/Kernel/LoadDiscoveryClasses.php | 23 +++++------ .../src/Kernel/LoadDiscoveryLocations.php | 15 +++---- .../src/DiscoveryDiscovery.php | 9 ++--- packages/discovery/src/Registry.php | 12 ++++++ 7 files changed, 78 insertions(+), 34 deletions(-) rename packages/{core => discovery}/src/DiscoveryDiscovery.php (73%) create mode 100644 packages/discovery/src/Registry.php diff --git a/packages/core/src/Commands/DiscoveryGenerateCommand.php b/packages/core/src/Commands/DiscoveryGenerateCommand.php index ca286ddfa6..d4df32f2a4 100644 --- a/packages/core/src/Commands/DiscoveryGenerateCommand.php +++ b/packages/core/src/Commands/DiscoveryGenerateCommand.php @@ -15,6 +15,7 @@ use Tempest\Core\FrameworkKernel; use Tempest\Core\Kernel; use Tempest\Core\Kernel\LoadDiscoveryClasses; +use Tempest\Discovery\Registry; if (class_exists(\Tempest\Console\ConsoleCommand::class)) { final readonly class DiscoveryGenerateCommand @@ -59,9 +60,10 @@ public function generateDiscoveryCache(DiscoveryCacheStrategy $strategy, Closure $kernel = $this->resolveKernel(); $loadDiscoveryClasses = new LoadDiscoveryClasses( - container: $kernel->container, + registry: $kernel->container->get(Registry::class), discoveryConfig: $kernel->container->get(DiscoveryConfig::class), discoveryCache: $this->discoveryCache, + container: $kernel->container, ); $discoveries = $loadDiscoveryClasses->build(); diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index 9fb47ddfeb..66d492a0f9 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -14,6 +14,7 @@ use Tempest\Core\Kernel\LoadDiscoveryClasses; use Tempest\Core\Kernel\LoadDiscoveryLocations; use Tempest\Core\Kernel\RegisterEmergencyExceptionHandler; +use Tempest\Discovery\Registry; use Tempest\EventBus\EventBus; use Tempest\Process\GenericProcessExecutor; use Tempest\Support\Filesystem; @@ -65,6 +66,7 @@ public static function boot( ->registerInternalStorage() ->registerKernel() ->loadComposer() + ->setupRegistry() ->loadDiscoveryLocations() ->loadConfig() ->loadDiscovery() @@ -156,9 +158,22 @@ public function registerShutdownFunction(): self return $this; } + public function setupRegistry(): self + { + $this->container->singleton(Registry::class, fn () => new Registry()); + + return $this; + } + public function loadDiscoveryLocations(): self { - $this->container->invoke(LoadDiscoveryLocations::class); + $loadDiscoveryLocations = new LoadDiscoveryLocations( + rootPath: $this->root, + registry: $this->container->get(Registry::class), + composer: $this->container->get(Composer::class), + ); + + $loadDiscoveryLocations(); return $this; } @@ -166,7 +181,15 @@ public function loadDiscoveryLocations(): self public function loadDiscovery(): self { $this->container->addInitializer(DiscoveryCacheInitializer::class); - $this->container->invoke(LoadDiscoveryClasses::class, discoveryLocations: $this->discoveryLocations); + + $loadDiscoveryClasses = new LoadDiscoveryClasses( + registry: $this->container->get(Registry::class), + discoveryConfig: $this->container->get(DiscoveryConfig::class), + discoveryCache: $this->container->get(DiscoveryCache::class), + container: $this->container, + ); + + $loadDiscoveryClasses(); return $this; } @@ -175,7 +198,13 @@ public function loadConfig(): self { $this->container->addInitializer(ConfigCacheInitializer::class); - $loadConfig = $this->container->get(LoadConfig::class, environment: Environment::guessFromEnvironment()); + $loadConfig = new LoadConfig( + registry: $this->container->get(Registry::class), + container: $this->container, + cache: $this->container->get(ConfigCache::class), + environment: Environment::guessFromEnvironment(), + ); + $loadConfig(); return $this; @@ -183,7 +212,7 @@ public function loadConfig(): self public function registerInternalStorage(): self { - $path = isset($this->internalStorage) ? $this->internalStorage : $this->root . '/.tempest'; + $path = $this->internalStorage ?? $this->root . '/.tempest'; if (! is_dir($path)) { if (file_exists($path)) { @@ -256,7 +285,7 @@ public function registerExceptionHandler(): self )); return true; - }, error_levels: E_ALL); + }); return $this; } diff --git a/packages/core/src/Kernel/LoadConfig.php b/packages/core/src/Kernel/LoadConfig.php index 6c916f1664..edeebfb898 100644 --- a/packages/core/src/Kernel/LoadConfig.php +++ b/packages/core/src/Kernel/LoadConfig.php @@ -4,9 +4,10 @@ namespace Tempest\Core\Kernel; +use Tempest\Container\Container; use Tempest\Core\ConfigCache; use Tempest\Core\Environment; -use Tempest\Core\Kernel; +use Tempest\Discovery\Registry; use Tempest\Support\Arr\MutableArray; use Tempest\Support\Filesystem; use Tempest\Support\Path; @@ -18,7 +19,8 @@ final readonly class LoadConfig { public function __construct( - private Kernel $kernel, + private Registry $registry, + private Container $container, private ConfigCache $cache, private Environment $environment, ) {} @@ -30,7 +32,7 @@ public function __invoke(): void foreach ($configPaths as $path) { $configFile = require $path; - $this->kernel->container->config($configFile); + $this->container->config($configFile); } } @@ -42,7 +44,7 @@ public function find(): array $configPaths = new MutableArray(); // Scan for config files in all discovery locations - foreach ($this->kernel->discoveryLocations as $discoveryLocation) { + foreach ($this->registry->locations as $discoveryLocation) { $this->scan($discoveryLocation->path, $configPaths); } diff --git a/packages/core/src/Kernel/LoadDiscoveryClasses.php b/packages/core/src/Kernel/LoadDiscoveryClasses.php index f6ae0b8cf6..88461bd3d1 100644 --- a/packages/core/src/Kernel/LoadDiscoveryClasses.php +++ b/packages/core/src/Kernel/LoadDiscoveryClasses.php @@ -9,12 +9,12 @@ use Tempest\Core\DiscoveryCache; use Tempest\Core\DiscoveryCacheStrategy; use Tempest\Core\DiscoveryConfig; -use Tempest\Core\DiscoveryDiscovery; -use Tempest\Core\Kernel; use Tempest\Discovery\DiscoversPath; use Tempest\Discovery\Discovery; +use Tempest\Discovery\DiscoveryDiscovery; use Tempest\Discovery\DiscoveryItems; use Tempest\Discovery\DiscoveryLocation; +use Tempest\Discovery\Registry; use Tempest\Discovery\SkipDiscovery; use Tempest\Reflection\ClassReflector; use Tempest\Support\Filesystem; @@ -27,9 +27,10 @@ final class LoadDiscoveryClasses private array $shouldSkipForClass = []; public function __construct( - private readonly Container $container, + private readonly Registry $registry, private readonly DiscoveryConfig $discoveryConfig, private readonly DiscoveryCache $discoveryCache, + private readonly ?Container $container = null, ) {} /** @@ -56,9 +57,7 @@ public function build( ?array $discoveryClasses = null, ?array $discoveryLocations = null, ): array { - $kernel = $this->container->get(Kernel::class); - - $discoveryLocations ??= $kernel->discoveryLocations; + $discoveryLocations ??= $this->registry->locations; if ($discoveryClasses === null) { // DiscoveryDiscovery needs to be applied before we can build all other discoveries @@ -73,7 +72,7 @@ public function build( // Resolve all other discoveries from the container, optionally loading their cache $discoveries = array_map( fn (string $discoveryClass) => $this->resolveDiscovery($discoveryClass), - $kernel->discoveryClasses, + $this->registry->classes, ); // The second pass over all directories to apply all other discovery classes @@ -190,11 +189,8 @@ private function discoverPath(string $input, DiscoveryLocation $location, array $pathInfo = pathinfo($input); $extension = $pathInfo['extension'] ?? null; $fileName = $pathInfo['filename'] ?: null; - $className = null; // If this is a PHP file starting with an uppercase letter, we assume it's a class. - // TODO: Figure out if we can refactor this to checking composer's autoload map (it might not always be available) - // An other idea is to check whether composer has a check to verify whether a file is a class? if ($extension === 'php' && ucfirst($fileName) === $fileName) { $className = $location->toClassName($input); @@ -265,11 +261,16 @@ private function discoverPath(string $input, DiscoveryLocation $location, array /** * Create a discovery instance from a class name. * Optionally set the cached discovery items whenever caching is enabled. + * @param class-string $discoveryClass */ private function resolveDiscovery(string $discoveryClass): Discovery { /** @var Discovery $discovery */ - $discovery = $this->container->get($discoveryClass); + if (! $this->container) { + $discovery = new $discoveryClass(); + } else { + $discovery = $this->container->get($discoveryClass); + } $discovery->setItems(new DiscoveryItems()); diff --git a/packages/core/src/Kernel/LoadDiscoveryLocations.php b/packages/core/src/Kernel/LoadDiscoveryLocations.php index 76364d0f74..6e00683862 100644 --- a/packages/core/src/Kernel/LoadDiscoveryLocations.php +++ b/packages/core/src/Kernel/LoadDiscoveryLocations.php @@ -5,9 +5,9 @@ namespace Tempest\Core\Kernel; use Tempest\Core\Composer; -use Tempest\Core\Kernel; use Tempest\Discovery\DiscoveryLocation; use Tempest\Discovery\DiscoveryLocationCouldNotBeLoaded; +use Tempest\Discovery\Registry; use Tempest\Support\Filesystem; use function Tempest\Support\Path\normalize; @@ -16,17 +16,18 @@ final readonly class LoadDiscoveryLocations { public function __construct( - private Kernel $kernel, + private string $rootPath, + private Registry $registry, private Composer $composer, ) {} public function __invoke(): void { - $this->kernel->discoveryLocations = [ + $this->registry->locations = [ ...$this->discoverCorePackages(), ...$this->discoverVendorPackages(), ...$this->discoverAppNamespaces(), - ...$this->kernel->discoveryLocations, + ...$this->registry->locations, ]; } @@ -35,7 +36,7 @@ public function __invoke(): void */ private function discoverCorePackages(): array { - $composerPath = normalize($this->kernel->root, 'vendor/composer'); + $composerPath = normalize($this->rootPath, 'vendor/composer'); $installed = $this->loadJsonFile(normalize($composerPath, 'installed.json')); $packages = $installed['packages'] ?? []; @@ -69,7 +70,7 @@ private function discoverAppNamespaces(): array $discoveredLocations = []; foreach ($this->composer->namespaces as $namespace) { - $path = normalize($this->kernel->root, $namespace->path); + $path = normalize($this->rootPath, $namespace->path); $discoveredLocations[] = new DiscoveryLocation($namespace->namespace, $path); } @@ -82,7 +83,7 @@ private function discoverAppNamespaces(): array */ private function discoverVendorPackages(): array { - $composerPath = normalize($this->kernel->root, 'vendor/composer'); + $composerPath = normalize($this->rootPath, 'vendor/composer'); $installed = $this->loadJsonFile(normalize($composerPath, 'installed.json')); $packages = $installed['packages'] ?? []; diff --git a/packages/core/src/DiscoveryDiscovery.php b/packages/discovery/src/DiscoveryDiscovery.php similarity index 73% rename from packages/core/src/DiscoveryDiscovery.php rename to packages/discovery/src/DiscoveryDiscovery.php index 07a3f66d5f..ed77138bf6 100644 --- a/packages/core/src/DiscoveryDiscovery.php +++ b/packages/discovery/src/DiscoveryDiscovery.php @@ -2,11 +2,8 @@ declare(strict_types=1); -namespace Tempest\Core; +namespace Tempest\Discovery; -use Tempest\Discovery\Discovery; -use Tempest\Discovery\DiscoveryLocation; -use Tempest\Discovery\IsDiscovery; use Tempest\Reflection\ClassReflector; final class DiscoveryDiscovery implements Discovery @@ -14,7 +11,7 @@ final class DiscoveryDiscovery implements Discovery use IsDiscovery; public function __construct( - private readonly Kernel $kernel, + private readonly Registry $registry, ) {} public function discover(DiscoveryLocation $location, ClassReflector $class): void @@ -33,7 +30,7 @@ public function discover(DiscoveryLocation $location, ClassReflector $class): vo public function apply(): void { foreach ($this->discoveryItems as $className) { - $this->kernel->discoveryClasses[] = $className; + $this->registry->classes[] = $className; } } } diff --git a/packages/discovery/src/Registry.php b/packages/discovery/src/Registry.php new file mode 100644 index 0000000000..1e58b4e848 --- /dev/null +++ b/packages/discovery/src/Registry.php @@ -0,0 +1,12 @@ +> */ + public array $classes = []; +} \ No newline at end of file From 086545f3f9cb16b2cbf84060b3b25abfafad5577 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 11:07:39 +0100 Subject: [PATCH 02/43] Move things around, decouple things, make Aidan happy. --- .../src/Commands/DiscoveryGenerateCommand.php | 5 ++- .../src/Commands/DiscoveryStatusCommand.php | 11 +++--- packages/core/src/FrameworkKernel.php | 39 ++++++++++++------- packages/core/src/Kernel.php | 10 ----- packages/core/src/PublishesFiles.php | 2 +- packages/core/src/functions.php | 4 +- packages/{core => discovery}/src/Composer.php | 5 +-- .../src/ComposerJsonCouldNotBeLocated.php | 2 +- .../src}/LoadDiscoveryClasses.php | 9 +---- .../src}/LoadDiscoveryLocations.php | 7 +--- .../TempestViewCompilerInitializer.php | 3 +- .../Framework/Testing/InstallerTester.php | 3 +- .../Framework/Testing/IntegrationTest.php | 2 +- .../Discovery/DiscoveryScanBench.php | 2 +- tests/Integration/Core/ComposerTest.php | 4 +- tests/Integration/Core/FunctionsTest.php | 3 +- .../Core/LoadDiscoveryClassesTest.php | 2 +- tests/Integration/Core/PublishesFilesTest.php | 3 +- .../View/TempestViewRendererTest.php | 6 +-- .../Vite/DevelopmentTagsResolverTest.php | 2 +- 20 files changed, 56 insertions(+), 68 deletions(-) rename packages/{core => discovery}/src/Composer.php (98%) rename packages/{core => discovery}/src/ComposerJsonCouldNotBeLocated.php (79%) rename packages/{core/src/Kernel => discovery/src}/LoadDiscoveryClasses.php (97%) rename packages/{core/src/Kernel => discovery/src}/LoadDiscoveryLocations.php (94%) diff --git a/packages/core/src/Commands/DiscoveryGenerateCommand.php b/packages/core/src/Commands/DiscoveryGenerateCommand.php index d4df32f2a4..44c3a76a4c 100644 --- a/packages/core/src/Commands/DiscoveryGenerateCommand.php +++ b/packages/core/src/Commands/DiscoveryGenerateCommand.php @@ -14,7 +14,7 @@ use Tempest\Core\DiscoveryConfig; use Tempest\Core\FrameworkKernel; use Tempest\Core\Kernel; -use Tempest\Core\Kernel\LoadDiscoveryClasses; +use Tempest\Discovery\LoadDiscoveryClasses; use Tempest\Discovery\Registry; if (class_exists(\Tempest\Console\ConsoleCommand::class)) { @@ -23,7 +23,8 @@ use HasConsole; public function __construct( - private Kernel $kernel, + private Registry $registry, + private FrameworkKernel $kernel, private DiscoveryCache $discoveryCache, ) {} diff --git a/packages/core/src/Commands/DiscoveryStatusCommand.php b/packages/core/src/Commands/DiscoveryStatusCommand.php index 1f037ff114..9ce4db4d49 100644 --- a/packages/core/src/Commands/DiscoveryStatusCommand.php +++ b/packages/core/src/Commands/DiscoveryStatusCommand.php @@ -10,6 +10,7 @@ use Tempest\Core\DiscoveryCache; use Tempest\Core\DiscoveryCacheStrategy; use Tempest\Core\Kernel; +use Tempest\Discovery\Registry; use Tempest\Support\Filesystem; use function Tempest\root_path; @@ -20,7 +21,7 @@ { public function __construct( private Console $console, - private Kernel $kernel, + private Registry $registry, private DiscoveryCache $discoveryCache, ) {} @@ -32,8 +33,8 @@ public function __invoke( bool $showLocations = false, ): void { $this->console->header('Discovery status'); - $this->console->keyValue('Registered locations', (string) count($this->kernel->discoveryLocations)); - $this->console->keyValue('Loaded discovery classes', (string) count($this->kernel->discoveryClasses)); + $this->console->keyValue('Registered locations', (string) count($this->registry->locations)); + $this->console->keyValue('Loaded discovery classes', (string) count($this->registry->classes)); $this->console->keyValue('Cache', match ($this->discoveryCache->enabled) { true => 'ENABLED', false => 'DISABLED', @@ -53,7 +54,7 @@ public function __invoke( $this->console->header('Discovery classes', subheader: 'These classes are used by Tempest to determine which classes to discover and how to handle them.'); $this->console->writeln(); - foreach ($this->kernel->discoveryClasses as $discoveryClass) { + foreach ($this->registry->classes as $discoveryClass) { $this->console->keyValue("{$discoveryClass}"); } } @@ -62,7 +63,7 @@ public function __invoke( $this->console->header('Discovery locations', subheader: 'These locations are used by Tempest to discover classes.'); $this->console->writeln(); - foreach ($this->kernel->discoveryLocations as $discoveryLocation) { + foreach ($this->registry->locations as $discoveryLocation) { $path = str(Filesystem\normalize_path($discoveryLocation->path)) ->replaceStart(root_path(), '.') ->toString(); diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index 66d492a0f9..555f700796 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -11,9 +11,10 @@ use Tempest\Container\GenericContainer; use Tempest\Core\Kernel\FinishDeferredTasks; use Tempest\Core\Kernel\LoadConfig; -use Tempest\Core\Kernel\LoadDiscoveryClasses; -use Tempest\Core\Kernel\LoadDiscoveryLocations; use Tempest\Core\Kernel\RegisterEmergencyExceptionHandler; +use Tempest\Discovery\Composer; +use Tempest\Discovery\LoadDiscoveryClasses; +use Tempest\Discovery\LoadDiscoveryLocations; use Tempest\Discovery\Registry; use Tempest\EventBus\EventBus; use Tempest\Process\GenericProcessExecutor; @@ -25,18 +26,30 @@ final class FrameworkKernel implements Kernel public bool $discoveryCache; - public array $discoveryClasses = []; + public array $discoveryClasses { + get => $this->registry->classes; + set => $this->registry->classes = $value; + } + + public array $discoveryLocations { + get => $this->registry->locations; + set => $this->registry->locations = $value; + } public string $internalStorage; + private Registry $registry; + public function __construct( public string $root, /** @var \Tempest\Discovery\DiscoveryLocation[] $discoveryLocations */ - public array $discoveryLocations = [], + array $discoveryLocations = [], ?Container $container = null, ?string $internalStorage = null, ) { $this->container = $container ?? $this->createContainer(); + $this->registry = new Registry(); + $this->discoveryLocations = $discoveryLocations; if ($internalStorage !== null) { $this->internalStorage = $internalStorage; @@ -59,14 +72,14 @@ public static function boot( container: $container, internalStorage: $internalStorage, ) + ->registerRegistry() + ->registerKernel() ->validateRoot() ->loadEnv() ->registerEmergencyExceptionHandler() ->registerShutdownFunction() ->registerInternalStorage() - ->registerKernel() ->loadComposer() - ->setupRegistry() ->loadDiscoveryLocations() ->loadConfig() ->loadDiscovery() @@ -132,6 +145,13 @@ public function loadEnv(): self return $this; } + public function registerRegistry(): self + { + $this->container->singleton(Registry::class, fn () => $this->registry); + + return $this; + } + public function registerKernel(): self { $this->container->singleton(Kernel::class, $this); @@ -158,13 +178,6 @@ public function registerShutdownFunction(): self return $this; } - public function setupRegistry(): self - { - $this->container->singleton(Registry::class, fn () => new Registry()); - - return $this; - } - public function loadDiscoveryLocations(): self { $loadDiscoveryLocations = new LoadDiscoveryLocations( diff --git a/packages/core/src/Kernel.php b/packages/core/src/Kernel.php index 65f45fb96d..416ff00afc 100644 --- a/packages/core/src/Kernel.php +++ b/packages/core/src/Kernel.php @@ -18,16 +18,6 @@ interface Kernel get; } - public array $discoveryLocations { - get; - set; - } - - public array $discoveryClasses { - get; - set; - } - public Container $container { get; } diff --git a/packages/core/src/PublishesFiles.php b/packages/core/src/PublishesFiles.php index 410d5d156b..6b8c5d7c18 100644 --- a/packages/core/src/PublishesFiles.php +++ b/packages/core/src/PublishesFiles.php @@ -9,6 +9,7 @@ use Tempest\Console\Exceptions\ConsoleException; use Tempest\Console\HasConsole; use Tempest\Container\Inject; +use Tempest\Discovery\Composer; use Tempest\Discovery\SkipDiscovery; use Tempest\Generation\Php\ClassManipulator; use Tempest\Generation\Php\DataObjects\StubFile; @@ -23,7 +24,6 @@ use Tempest\Validation\Rules\EndsWith; use Tempest\Validation\Rules\IsNotEmptyString; use Throwable; - use function strlen; use function Tempest\root_path; use function Tempest\src_path; diff --git a/packages/core/src/functions.php b/packages/core/src/functions.php index 3e93e0267e..65aa452325 100644 --- a/packages/core/src/functions.php +++ b/packages/core/src/functions.php @@ -6,16 +6,14 @@ use Closure; use Stringable; -use Tempest\Container; -use Tempest\Core\Composer; use Tempest\Core\DeferredTasks; use Tempest\Core\EnvironmentVariableValidationFailed; use Tempest\Core\Kernel; +use Tempest\Discovery\Composer; use Tempest\Intl\Translator; use Tempest\Support\Namespace\PathCouldNotBeMappedToNamespace; use Tempest\Validation\Rule; use Tempest\Validation\Validator; - use function Tempest\Support\Namespace\to_psr4_namespace; use function Tempest\Support\Path\to_absolute_path; diff --git a/packages/core/src/Composer.php b/packages/discovery/src/Composer.php similarity index 98% rename from packages/core/src/Composer.php rename to packages/discovery/src/Composer.php index e3c6917b9a..4c4949a0fc 100644 --- a/packages/core/src/Composer.php +++ b/packages/discovery/src/Composer.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Tempest\Core; +namespace Tempest\Discovery; use Tempest\Process\ProcessExecutor; use Tempest\Support\Arr; @@ -10,7 +10,6 @@ use Tempest\Support\Namespace\Psr4Namespace; use Tempest\Support\Path; use Tempest\Support\Str; - use function Tempest\Support\arr; final class Composer @@ -105,7 +104,7 @@ public function addNamespace(string $namespace, string $path): self public function save(): self { - Filesystem\write_json($this->composerPath, $this->composer, pretty: true); + Filesystem\write_json($this->composerPath, $this->composer); return $this; } diff --git a/packages/core/src/ComposerJsonCouldNotBeLocated.php b/packages/discovery/src/ComposerJsonCouldNotBeLocated.php similarity index 79% rename from packages/core/src/ComposerJsonCouldNotBeLocated.php rename to packages/discovery/src/ComposerJsonCouldNotBeLocated.php index 10bf4b2c7d..09f1e8de1e 100644 --- a/packages/core/src/ComposerJsonCouldNotBeLocated.php +++ b/packages/discovery/src/ComposerJsonCouldNotBeLocated.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Tempest\Core; +namespace Tempest\Discovery; use Exception; diff --git a/packages/core/src/Kernel/LoadDiscoveryClasses.php b/packages/discovery/src/LoadDiscoveryClasses.php similarity index 97% rename from packages/core/src/Kernel/LoadDiscoveryClasses.php rename to packages/discovery/src/LoadDiscoveryClasses.php index 88461bd3d1..001fd4991c 100644 --- a/packages/core/src/Kernel/LoadDiscoveryClasses.php +++ b/packages/discovery/src/LoadDiscoveryClasses.php @@ -2,20 +2,13 @@ declare(strict_types=1); -namespace Tempest\Core\Kernel; +namespace Tempest\Discovery; use AssertionError; use Tempest\Container\Container; use Tempest\Core\DiscoveryCache; use Tempest\Core\DiscoveryCacheStrategy; use Tempest\Core\DiscoveryConfig; -use Tempest\Discovery\DiscoversPath; -use Tempest\Discovery\Discovery; -use Tempest\Discovery\DiscoveryDiscovery; -use Tempest\Discovery\DiscoveryItems; -use Tempest\Discovery\DiscoveryLocation; -use Tempest\Discovery\Registry; -use Tempest\Discovery\SkipDiscovery; use Tempest\Reflection\ClassReflector; use Tempest\Support\Filesystem; use Throwable; diff --git a/packages/core/src/Kernel/LoadDiscoveryLocations.php b/packages/discovery/src/LoadDiscoveryLocations.php similarity index 94% rename from packages/core/src/Kernel/LoadDiscoveryLocations.php rename to packages/discovery/src/LoadDiscoveryLocations.php index 6e00683862..a507b14095 100644 --- a/packages/core/src/Kernel/LoadDiscoveryLocations.php +++ b/packages/discovery/src/LoadDiscoveryLocations.php @@ -2,14 +2,9 @@ declare(strict_types=1); -namespace Tempest\Core\Kernel; +namespace Tempest\Discovery; -use Tempest\Core\Composer; -use Tempest\Discovery\DiscoveryLocation; -use Tempest\Discovery\DiscoveryLocationCouldNotBeLoaded; -use Tempest\Discovery\Registry; use Tempest\Support\Filesystem; - use function Tempest\Support\Path\normalize; /** @internal */ diff --git a/packages/view/src/Initializers/TempestViewCompilerInitializer.php b/packages/view/src/Initializers/TempestViewCompilerInitializer.php index 34036052ec..f9bb54dc41 100644 --- a/packages/view/src/Initializers/TempestViewCompilerInitializer.php +++ b/packages/view/src/Initializers/TempestViewCompilerInitializer.php @@ -6,6 +6,7 @@ use Tempest\Container\Initializer; use Tempest\Container\Singleton; use Tempest\Core\Kernel; +use Tempest\Discovery\Registry; use Tempest\View\Attributes\AttributeFactory; use Tempest\View\Elements\ElementFactory; use Tempest\View\Parser\TempestViewCompiler; @@ -18,7 +19,7 @@ public function initialize(Container $container): TempestViewCompiler return new TempestViewCompiler( elementFactory: $container->get(ElementFactory::class), attributeFactory: $container->get(AttributeFactory::class), - discoveryLocations: $container->get(Kernel::class)->discoveryLocations, + discoveryLocations: $container->get(Registry::class)->locations, ); } } diff --git a/src/Tempest/Framework/Testing/InstallerTester.php b/src/Tempest/Framework/Testing/InstallerTester.php index de4c57027d..1c7bf81334 100644 --- a/src/Tempest/Framework/Testing/InstallerTester.php +++ b/src/Tempest/Framework/Testing/InstallerTester.php @@ -6,13 +6,12 @@ use PHPUnit\Framework\Assert; use Tempest\Container\Container; -use Tempest\Core\Composer; use Tempest\Core\FrameworkKernel; +use Tempest\Discovery\Composer; use Tempest\Process\Testing\ProcessTester; use Tempest\Support\Arr; use Tempest\Support\Filesystem; use Tempest\Support\Namespace\Psr4Namespace; - use function Tempest\Support\Path\to_absolute_path; final class InstallerTester diff --git a/src/Tempest/Framework/Testing/IntegrationTest.php b/src/Tempest/Framework/Testing/IntegrationTest.php index 7c600b78ba..77b4161f45 100644 --- a/src/Tempest/Framework/Testing/IntegrationTest.php +++ b/src/Tempest/Framework/Testing/IntegrationTest.php @@ -50,7 +50,7 @@ abstract class IntegrationTest extends TestCase /** @var \Tempest\Discovery\DiscoveryLocation[] */ protected array $discoveryLocations = []; - protected Kernel $kernel; + protected FrameworkKernel $kernel; protected GenericContainer $container; diff --git a/tests/Benchmark/Discovery/DiscoveryScanBench.php b/tests/Benchmark/Discovery/DiscoveryScanBench.php index 8376dbdf67..543abdeb04 100644 --- a/tests/Benchmark/Discovery/DiscoveryScanBench.php +++ b/tests/Benchmark/Discovery/DiscoveryScanBench.php @@ -14,9 +14,9 @@ use Tempest\Core\DiscoveryCacheStrategy; use Tempest\Core\DiscoveryConfig; use Tempest\Core\FrameworkKernel; -use Tempest\Core\Kernel\LoadDiscoveryClasses; use Tempest\Discovery\Discovery; use Tempest\Discovery\DiscoveryLocation; +use Tempest\Discovery\LoadDiscoveryClasses; final class DiscoveryScanBench { diff --git a/tests/Integration/Core/ComposerTest.php b/tests/Integration/Core/ComposerTest.php index d173e3d8e1..feb5dca5c8 100644 --- a/tests/Integration/Core/ComposerTest.php +++ b/tests/Integration/Core/ComposerTest.php @@ -5,8 +5,8 @@ namespace Tests\Tempest\Integration\Core; use PHPUnit\Framework\Attributes\Test; -use Tempest\Core\Composer; -use Tempest\Core\ComposerJsonCouldNotBeLocated; +use Tempest\Discovery\Composer; +use Tempest\Discovery\ComposerJsonCouldNotBeLocated; use Tempest\Process\ProcessExecutor; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; diff --git a/tests/Integration/Core/FunctionsTest.php b/tests/Integration/Core/FunctionsTest.php index c7a1b17e94..32059a6efe 100644 --- a/tests/Integration/Core/FunctionsTest.php +++ b/tests/Integration/Core/FunctionsTest.php @@ -5,12 +5,11 @@ namespace Tests\Tempest\Integration\Core; use PHPUnit\Framework\Attributes\TestWith; -use Tempest\Core\Composer; use Tempest\Core\FrameworkKernel; +use Tempest\Discovery\Composer; use Tempest\Support\Namespace\PathCouldNotBeMappedToNamespace; use Tempest\Support\Namespace\Psr4Namespace; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; - use function Tempest\internal_storage_path; use function Tempest\registered_namespace; use function Tempest\root_path; diff --git a/tests/Integration/Core/LoadDiscoveryClassesTest.php b/tests/Integration/Core/LoadDiscoveryClassesTest.php index 29a21db43b..724a11c866 100644 --- a/tests/Integration/Core/LoadDiscoveryClassesTest.php +++ b/tests/Integration/Core/LoadDiscoveryClassesTest.php @@ -5,10 +5,10 @@ namespace Tests\Tempest\Integration\Core; use PHPUnit\Framework\Attributes\Test; -use Tempest\Core\Kernel\LoadDiscoveryClasses; use Tempest\Database\MigratesUp; use Tempest\Database\Migrations\RunnableMigrations; use Tempest\Discovery\DiscoveryLocation; +use Tempest\Discovery\LoadDiscoveryClasses; use Tempest\Support\Arr; use Tests\Tempest\Fixtures\Discovery\HiddenDatabaseMigration; use Tests\Tempest\Fixtures\Discovery\HiddenMigratableDatabaseMigration; diff --git a/tests/Integration/Core/PublishesFilesTest.php b/tests/Integration/Core/PublishesFilesTest.php index d1611ed346..650af8eced 100644 --- a/tests/Integration/Core/PublishesFilesTest.php +++ b/tests/Integration/Core/PublishesFilesTest.php @@ -6,11 +6,10 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; -use Tempest\Core\Composer; +use Tempest\Discovery\Composer; use Tempest\Support\Namespace\Psr4Namespace; use Tests\Tempest\Fixtures\Core\PublishesFilesConcreteClass; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; - use function Tempest\Support\Path\normalize; /** diff --git a/tests/Integration/View/TempestViewRendererTest.php b/tests/Integration/View/TempestViewRendererTest.php index cbd9aaf583..3956b2d673 100644 --- a/tests/Integration/View/TempestViewRendererTest.php +++ b/tests/Integration/View/TempestViewRendererTest.php @@ -6,6 +6,7 @@ use Tempest\Core\Kernel; use Tempest\Discovery\DiscoveryLocation; +use Tempest\Discovery\Registry; use Tempest\Support\Html\HtmlString; use Tempest\View\Exceptions\ElementWasInvalid; use Tempest\View\Exceptions\XmlDeclarationCouldNotBeParsed; @@ -947,10 +948,9 @@ public function test_zero_in_attribute(): void public function test_discovery_locations_are_passed_to_compiler(): void { - /** @var \Tempest\Core\Kernel $kernel */ - $kernel = $this->get(Kernel::class); + $registry = $this->get(Registry::class); - $kernel->discoveryLocations[] = new DiscoveryLocation( + $registry->locations[] = new DiscoveryLocation( 'Tests\Tempest\Integration\View\Fixtures', __DIR__ . '/Fixtures', ); diff --git a/tests/Integration/Vite/DevelopmentTagsResolverTest.php b/tests/Integration/Vite/DevelopmentTagsResolverTest.php index 20fa380083..510fb08a77 100644 --- a/tests/Integration/Vite/DevelopmentTagsResolverTest.php +++ b/tests/Integration/Vite/DevelopmentTagsResolverTest.php @@ -4,7 +4,7 @@ namespace Tests\Tempest\Integration\Vite; -use Tempest\Core\Composer; +use Tempest\Discovery\Composer; use Tempest\Support\Namespace\Psr4Namespace; use Tempest\Vite\Exceptions\FileSystemEntrypointWasNotFoundException; use Tempest\Vite\TagCompiler\TagCompiler; From e1c00bf1fb801572ec0b8d642b0aee12adfc9138 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 11:10:28 +0100 Subject: [PATCH 03/43] QA --- packages/core/src/Commands/DiscoveryStatusCommand.php | 1 - packages/core/src/PublishesFiles.php | 1 + packages/core/src/functions.php | 1 + packages/discovery/src/Composer.php | 1 + packages/discovery/src/LoadDiscoveryLocations.php | 1 + packages/discovery/src/Registry.php | 2 +- .../view/src/Initializers/TempestViewCompilerInitializer.php | 1 - src/Tempest/Framework/Testing/InstallerTester.php | 1 + src/Tempest/Framework/Testing/IntegrationTest.php | 1 - tests/Integration/Core/FunctionsTest.php | 1 + tests/Integration/Core/PublishesFilesTest.php | 1 + tests/Integration/View/TempestViewRendererTest.php | 1 - 12 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/core/src/Commands/DiscoveryStatusCommand.php b/packages/core/src/Commands/DiscoveryStatusCommand.php index 9ce4db4d49..3fb2ac8e80 100644 --- a/packages/core/src/Commands/DiscoveryStatusCommand.php +++ b/packages/core/src/Commands/DiscoveryStatusCommand.php @@ -9,7 +9,6 @@ use Tempest\Console\ConsoleCommand; use Tempest\Core\DiscoveryCache; use Tempest\Core\DiscoveryCacheStrategy; -use Tempest\Core\Kernel; use Tempest\Discovery\Registry; use Tempest\Support\Filesystem; diff --git a/packages/core/src/PublishesFiles.php b/packages/core/src/PublishesFiles.php index 6b8c5d7c18..c4f10a4c6b 100644 --- a/packages/core/src/PublishesFiles.php +++ b/packages/core/src/PublishesFiles.php @@ -24,6 +24,7 @@ use Tempest\Validation\Rules\EndsWith; use Tempest\Validation\Rules\IsNotEmptyString; use Throwable; + use function strlen; use function Tempest\root_path; use function Tempest\src_path; diff --git a/packages/core/src/functions.php b/packages/core/src/functions.php index 65aa452325..30845336c4 100644 --- a/packages/core/src/functions.php +++ b/packages/core/src/functions.php @@ -14,6 +14,7 @@ use Tempest\Support\Namespace\PathCouldNotBeMappedToNamespace; use Tempest\Validation\Rule; use Tempest\Validation\Validator; + use function Tempest\Support\Namespace\to_psr4_namespace; use function Tempest\Support\Path\to_absolute_path; diff --git a/packages/discovery/src/Composer.php b/packages/discovery/src/Composer.php index 4c4949a0fc..477c04b758 100644 --- a/packages/discovery/src/Composer.php +++ b/packages/discovery/src/Composer.php @@ -10,6 +10,7 @@ use Tempest\Support\Namespace\Psr4Namespace; use Tempest\Support\Path; use Tempest\Support\Str; + use function Tempest\Support\arr; final class Composer diff --git a/packages/discovery/src/LoadDiscoveryLocations.php b/packages/discovery/src/LoadDiscoveryLocations.php index a507b14095..13b87eadac 100644 --- a/packages/discovery/src/LoadDiscoveryLocations.php +++ b/packages/discovery/src/LoadDiscoveryLocations.php @@ -5,6 +5,7 @@ namespace Tempest\Discovery; use Tempest\Support\Filesystem; + use function Tempest\Support\Path\normalize; /** @internal */ diff --git a/packages/discovery/src/Registry.php b/packages/discovery/src/Registry.php index 1e58b4e848..1cf68c07b8 100644 --- a/packages/discovery/src/Registry.php +++ b/packages/discovery/src/Registry.php @@ -9,4 +9,4 @@ final class Registry /** @var array> */ public array $classes = []; -} \ No newline at end of file +} diff --git a/packages/view/src/Initializers/TempestViewCompilerInitializer.php b/packages/view/src/Initializers/TempestViewCompilerInitializer.php index f9bb54dc41..2e9374fc6f 100644 --- a/packages/view/src/Initializers/TempestViewCompilerInitializer.php +++ b/packages/view/src/Initializers/TempestViewCompilerInitializer.php @@ -5,7 +5,6 @@ use Tempest\Container\Container; use Tempest\Container\Initializer; use Tempest\Container\Singleton; -use Tempest\Core\Kernel; use Tempest\Discovery\Registry; use Tempest\View\Attributes\AttributeFactory; use Tempest\View\Elements\ElementFactory; diff --git a/src/Tempest/Framework/Testing/InstallerTester.php b/src/Tempest/Framework/Testing/InstallerTester.php index 1c7bf81334..1032853ab6 100644 --- a/src/Tempest/Framework/Testing/InstallerTester.php +++ b/src/Tempest/Framework/Testing/InstallerTester.php @@ -12,6 +12,7 @@ use Tempest\Support\Arr; use Tempest\Support\Filesystem; use Tempest\Support\Namespace\Psr4Namespace; + use function Tempest\Support\Path\to_absolute_path; final class InstallerTester diff --git a/src/Tempest/Framework/Testing/IntegrationTest.php b/src/Tempest/Framework/Testing/IntegrationTest.php index 77b4161f45..4bccdfa35f 100644 --- a/src/Tempest/Framework/Testing/IntegrationTest.php +++ b/src/Tempest/Framework/Testing/IntegrationTest.php @@ -18,7 +18,6 @@ use Tempest\Container\GenericContainer; use Tempest\Core\Exceptions\ExceptionTester; use Tempest\Core\FrameworkKernel; -use Tempest\Core\Kernel; use Tempest\Database\Testing\DatabaseTester; use Tempest\DateTime\DateTimeInterface; use Tempest\Discovery\DiscoveryLocation; diff --git a/tests/Integration/Core/FunctionsTest.php b/tests/Integration/Core/FunctionsTest.php index 32059a6efe..132a98489b 100644 --- a/tests/Integration/Core/FunctionsTest.php +++ b/tests/Integration/Core/FunctionsTest.php @@ -10,6 +10,7 @@ use Tempest\Support\Namespace\PathCouldNotBeMappedToNamespace; use Tempest\Support\Namespace\Psr4Namespace; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; + use function Tempest\internal_storage_path; use function Tempest\registered_namespace; use function Tempest\root_path; diff --git a/tests/Integration/Core/PublishesFilesTest.php b/tests/Integration/Core/PublishesFilesTest.php index 650af8eced..1ee6b178ab 100644 --- a/tests/Integration/Core/PublishesFilesTest.php +++ b/tests/Integration/Core/PublishesFilesTest.php @@ -10,6 +10,7 @@ use Tempest\Support\Namespace\Psr4Namespace; use Tests\Tempest\Fixtures\Core\PublishesFilesConcreteClass; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; + use function Tempest\Support\Path\normalize; /** diff --git a/tests/Integration/View/TempestViewRendererTest.php b/tests/Integration/View/TempestViewRendererTest.php index 3956b2d673..a42db545fd 100644 --- a/tests/Integration/View/TempestViewRendererTest.php +++ b/tests/Integration/View/TempestViewRendererTest.php @@ -4,7 +4,6 @@ namespace Tests\Tempest\Integration\View; -use Tempest\Core\Kernel; use Tempest\Discovery\DiscoveryLocation; use Tempest\Discovery\Registry; use Tempest\Support\Html\HtmlString; From ad30d43154a3de259530e443b8d54a8b854638d8 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 11:12:26 +0100 Subject: [PATCH 04/43] QA --- tests/Integration/Database/Builder/IsDatabaseModelTest.php | 1 + tests/PHPStan/QueryFunctionDynamicReturnTypeExtension.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Integration/Database/Builder/IsDatabaseModelTest.php b/tests/Integration/Database/Builder/IsDatabaseModelTest.php index 1a312bad0f..f3a60efe7f 100644 --- a/tests/Integration/Database/Builder/IsDatabaseModelTest.php +++ b/tests/Integration/Database/Builder/IsDatabaseModelTest.php @@ -771,6 +771,7 @@ public function test_on_database_does_not_mutate_original(): void // Original still works against default database $foo->update(bar: 'updated'); + $refreshed = Foo::get($foo->id); $this->assertSame('updated', $refreshed->bar); diff --git a/tests/PHPStan/QueryFunctionDynamicReturnTypeExtension.php b/tests/PHPStan/QueryFunctionDynamicReturnTypeExtension.php index 1675a5872c..686ce5e4a8 100644 --- a/tests/PHPStan/QueryFunctionDynamicReturnTypeExtension.php +++ b/tests/PHPStan/QueryFunctionDynamicReturnTypeExtension.php @@ -22,7 +22,7 @@ public function __construct( public function isFunctionSupported(FunctionReflection $functionReflection): bool { - return $functionReflection->getName() === 'Tempest\\Database\\query'; + return $functionReflection->getName() === \Tempest\Database\query::class; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type From e17108b7eb44ffd5511415f987c61bac123eb9b1 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 11:39:23 +0100 Subject: [PATCH 05/43] Moving classes a-round, oh yeah, a-round. --- packages/cache/src/Commands/CacheClearCommand.php | 3 +-- packages/cache/src/Commands/CacheStatusCommand.php | 3 +-- packages/cache/src/InternalCacheInsightsProvider.php | 4 ++-- packages/console/src/Middleware/OverviewMiddleware.php | 3 +-- packages/core/src/Commands/DiscoveryClearCommand.php | 2 +- packages/core/src/Commands/DiscoveryGenerateCommand.php | 6 +++--- packages/core/src/Commands/DiscoveryStatusCommand.php | 5 ++--- packages/core/src/FrameworkKernel.php | 3 +++ .../{core => discovery}/src/Config/discovery.config.php | 2 +- packages/{core => discovery}/src/DiscoveryCache.php | 7 ++----- .../{core => discovery}/src/DiscoveryCacheInitializer.php | 2 +- .../{core => discovery}/src/DiscoveryCacheStrategy.php | 3 ++- .../src/DiscoveryCachingStrategyWasChanged.php | 2 +- packages/{core => discovery}/src/DiscoveryConfig.php | 2 +- packages/discovery/src/LoadDiscoveryClasses.php | 3 --- tests/Benchmark/Discovery/DiscoveryScanBench.php | 6 +++--- tests/Fixtures/Config/discovery.config.php | 2 +- tests/Integration/Cache/CacheStatusCommandTest.php | 2 +- tests/Integration/Core/DiscoveryCacheTest.php | 5 ++--- 19 files changed, 29 insertions(+), 36 deletions(-) rename packages/{core => discovery}/src/Config/discovery.config.php (62%) rename packages/{core => discovery}/src/DiscoveryCache.php (94%) rename packages/{core => discovery}/src/DiscoveryCacheInitializer.php (98%) rename packages/{core => discovery}/src/DiscoveryCacheStrategy.php (96%) rename packages/{core => discovery}/src/DiscoveryCachingStrategyWasChanged.php (93%) rename packages/{core => discovery}/src/DiscoveryConfig.php (96%) diff --git a/packages/cache/src/Commands/CacheClearCommand.php b/packages/cache/src/Commands/CacheClearCommand.php index fb1c7b13cb..61c30c8df8 100644 --- a/packages/cache/src/Commands/CacheClearCommand.php +++ b/packages/cache/src/Commands/CacheClearCommand.php @@ -14,11 +14,10 @@ use Tempest\Container\Container; use Tempest\Container\GenericContainer; use Tempest\Core\ConfigCache; -use Tempest\Core\DiscoveryCache; +use Tempest\Discovery\DiscoveryCache; use Tempest\Icon\IconCache; use Tempest\Support\Str; use Tempest\View\ViewCache; - use function Tempest\Support\arr; if (class_exists(\Tempest\Console\ConsoleCommand::class)) { diff --git a/packages/cache/src/Commands/CacheStatusCommand.php b/packages/cache/src/Commands/CacheStatusCommand.php index 766eda0d27..1fb76e42eb 100644 --- a/packages/cache/src/Commands/CacheStatusCommand.php +++ b/packages/cache/src/Commands/CacheStatusCommand.php @@ -13,13 +13,12 @@ use Tempest\Container\Container; use Tempest\Container\GenericContainer; use Tempest\Core\ConfigCache; -use Tempest\Core\DiscoveryCache; use Tempest\Core\Environment; +use Tempest\Discovery\DiscoveryCache; use Tempest\Icon\IconCache; use Tempest\Support\Str; use Tempest\View\ViewCache; use UnitEnum; - use function Tempest\Support\arr; if (class_exists(ConsoleCommand::class)) { diff --git a/packages/cache/src/InternalCacheInsightsProvider.php b/packages/cache/src/InternalCacheInsightsProvider.php index b1b0d039c9..754d5f8470 100644 --- a/packages/cache/src/InternalCacheInsightsProvider.php +++ b/packages/cache/src/InternalCacheInsightsProvider.php @@ -3,11 +3,11 @@ namespace Tempest\Cache; use Tempest\Core\ConfigCache; -use Tempest\Core\DiscoveryCache; -use Tempest\Core\DiscoveryCacheStrategy; use Tempest\Core\Insight; use Tempest\Core\InsightsProvider; use Tempest\Core\InsightType; +use Tempest\Discovery\DiscoveryCache; +use Tempest\Discovery\DiscoveryCacheStrategy; use Tempest\Icon\IconCache; use Tempest\View\ViewCache; diff --git a/packages/console/src/Middleware/OverviewMiddleware.php b/packages/console/src/Middleware/OverviewMiddleware.php index f68ce82273..21de5a4c8a 100644 --- a/packages/console/src/Middleware/OverviewMiddleware.php +++ b/packages/console/src/Middleware/OverviewMiddleware.php @@ -13,9 +13,8 @@ use Tempest\Console\ExitCode; use Tempest\Console\Initializers\Invocation; use Tempest\Core\AppConfig; -use Tempest\Core\DiscoveryCache; use Tempest\Core\Priority; - +use Tempest\Discovery\DiscoveryCache; use function Tempest\Support\arr; use function Tempest\Support\str; diff --git a/packages/core/src/Commands/DiscoveryClearCommand.php b/packages/core/src/Commands/DiscoveryClearCommand.php index b31776e113..2eb5acc6f7 100644 --- a/packages/core/src/Commands/DiscoveryClearCommand.php +++ b/packages/core/src/Commands/DiscoveryClearCommand.php @@ -6,7 +6,7 @@ use Tempest\Console\Console; use Tempest\Console\ConsoleCommand; -use Tempest\Core\DiscoveryCache; +use Tempest\Discovery\DiscoveryCache; if (class_exists(\Tempest\Console\ConsoleCommand::class)) { final readonly class DiscoveryClearCommand diff --git a/packages/core/src/Commands/DiscoveryGenerateCommand.php b/packages/core/src/Commands/DiscoveryGenerateCommand.php index 44c3a76a4c..c1ef5cf245 100644 --- a/packages/core/src/Commands/DiscoveryGenerateCommand.php +++ b/packages/core/src/Commands/DiscoveryGenerateCommand.php @@ -9,11 +9,11 @@ use Tempest\Console\HasConsole; use Tempest\Container\Container; use Tempest\Container\GenericContainer; -use Tempest\Core\DiscoveryCache; -use Tempest\Core\DiscoveryCacheStrategy; -use Tempest\Core\DiscoveryConfig; use Tempest\Core\FrameworkKernel; use Tempest\Core\Kernel; +use Tempest\Discovery\DiscoveryCache; +use Tempest\Discovery\DiscoveryCacheStrategy; +use Tempest\Discovery\DiscoveryConfig; use Tempest\Discovery\LoadDiscoveryClasses; use Tempest\Discovery\Registry; diff --git a/packages/core/src/Commands/DiscoveryStatusCommand.php b/packages/core/src/Commands/DiscoveryStatusCommand.php index 3fb2ac8e80..4da78b4417 100644 --- a/packages/core/src/Commands/DiscoveryStatusCommand.php +++ b/packages/core/src/Commands/DiscoveryStatusCommand.php @@ -7,11 +7,10 @@ use Tempest\Console\Console; use Tempest\Console\ConsoleArgument; use Tempest\Console\ConsoleCommand; -use Tempest\Core\DiscoveryCache; -use Tempest\Core\DiscoveryCacheStrategy; +use Tempest\Discovery\DiscoveryCache; +use Tempest\Discovery\DiscoveryCacheStrategy; use Tempest\Discovery\Registry; use Tempest\Support\Filesystem; - use function Tempest\root_path; use function Tempest\Support\str; diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index 555f700796..56d0231284 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -13,6 +13,9 @@ use Tempest\Core\Kernel\LoadConfig; use Tempest\Core\Kernel\RegisterEmergencyExceptionHandler; use Tempest\Discovery\Composer; +use Tempest\Discovery\DiscoveryCache; +use Tempest\Discovery\DiscoveryCacheInitializer; +use Tempest\Discovery\DiscoveryConfig; use Tempest\Discovery\LoadDiscoveryClasses; use Tempest\Discovery\LoadDiscoveryLocations; use Tempest\Discovery\Registry; diff --git a/packages/core/src/Config/discovery.config.php b/packages/discovery/src/Config/discovery.config.php similarity index 62% rename from packages/core/src/Config/discovery.config.php rename to packages/discovery/src/Config/discovery.config.php index 447b2d232e..0ab1f56186 100644 --- a/packages/core/src/Config/discovery.config.php +++ b/packages/discovery/src/Config/discovery.config.php @@ -2,6 +2,6 @@ declare(strict_types=1); -use Tempest\Core\DiscoveryConfig; +use Tempest\Discovery\DiscoveryConfig; return new DiscoveryConfig(); diff --git a/packages/core/src/DiscoveryCache.php b/packages/discovery/src/DiscoveryCache.php similarity index 94% rename from packages/core/src/DiscoveryCache.php rename to packages/discovery/src/DiscoveryCache.php index be6c20a6e3..75b00ddb0f 100644 --- a/packages/core/src/DiscoveryCache.php +++ b/packages/discovery/src/DiscoveryCache.php @@ -2,17 +2,14 @@ declare(strict_types=1); -namespace Tempest\Core; +namespace Tempest\Discovery; use Psr\Cache\CacheItemPoolInterface; use RuntimeException; use Symfony\Component\Cache\Adapter\PhpFilesAdapter; -use Tempest\Discovery\Discovery; -use Tempest\Discovery\DiscoveryItems; -use Tempest\Discovery\DiscoveryLocation; +use Tempest\Core\CouldNotStoreDiscoveryCache; use Tempest\Support\Filesystem; use Throwable; - use function Tempest\internal_storage_path; final class DiscoveryCache diff --git a/packages/core/src/DiscoveryCacheInitializer.php b/packages/discovery/src/DiscoveryCacheInitializer.php similarity index 98% rename from packages/core/src/DiscoveryCacheInitializer.php rename to packages/discovery/src/DiscoveryCacheInitializer.php index 0370519a66..4ccde362af 100644 --- a/packages/core/src/DiscoveryCacheInitializer.php +++ b/packages/discovery/src/DiscoveryCacheInitializer.php @@ -1,6 +1,6 @@ Date: Wed, 11 Mar 2026 11:49:58 +0100 Subject: [PATCH 06/43] Aidan's gonna love reading these commit messages --- packages/discovery/composer.json | 3 ++- packages/discovery/src/DiscoveryCache.php | 11 ++++++++++- packages/discovery/src/LoadDiscoveryClasses.php | 2 +- packages/discovery/src/Registry.php | 10 ++++++---- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/discovery/composer.json b/packages/discovery/composer.json index 4c668e62a2..a51ed164ad 100644 --- a/packages/discovery/composer.json +++ b/packages/discovery/composer.json @@ -6,7 +6,8 @@ "require": { "php": "^8.5", "tempest/reflection": "3.x-dev", - "tempest/support": "3.x-dev" + "tempest/support": "3.x-dev", + "symfony/cache": "^7.3" }, "autoload": { "psr-4": { diff --git a/packages/discovery/src/DiscoveryCache.php b/packages/discovery/src/DiscoveryCache.php index 75b00ddb0f..198991ca48 100644 --- a/packages/discovery/src/DiscoveryCache.php +++ b/packages/discovery/src/DiscoveryCache.php @@ -27,7 +27,7 @@ public function __construct( private ?CacheItemPoolInterface $pool = null, ) { $this->pool = $pool ?? new PhpFilesAdapter( - directory: internal_storage_path('cache/discovery'), + directory: self::getCachePath(), ); } @@ -98,4 +98,13 @@ public static function getCurrentDiscoverStrategyCachePath(): string return __DIR__ . '/current_discovery_strategy'; } } + + private static function getCachePath(): string + { + try { + return internal_storage_path('cache/views'); + } catch (Throwable) { + return __DIR__ . '/../.tempest/cache'; + } + } } diff --git a/packages/discovery/src/LoadDiscoveryClasses.php b/packages/discovery/src/LoadDiscoveryClasses.php index 07ad8f5d5d..13598d721c 100644 --- a/packages/discovery/src/LoadDiscoveryClasses.php +++ b/packages/discovery/src/LoadDiscoveryClasses.php @@ -20,7 +20,7 @@ public function __construct( private readonly Registry $registry, private readonly DiscoveryConfig $discoveryConfig, private readonly DiscoveryCache $discoveryCache, - private readonly ?Container $container = null, + private readonly Container $container, ) {} /** diff --git a/packages/discovery/src/Registry.php b/packages/discovery/src/Registry.php index 1cf68c07b8..e5c4db17a4 100644 --- a/packages/discovery/src/Registry.php +++ b/packages/discovery/src/Registry.php @@ -4,9 +4,11 @@ final class Registry { - /** @var \Tempest\Discovery\DiscoveryLocation[] */ - public array $locations = []; + public function __construct( + /** @var \Tempest\Discovery\DiscoveryLocation[] */ + public array $locations = [], - /** @var array> */ - public array $classes = []; + /** @var array> */ + public array $classes = [], + ) {} } From 8162e91502657e1bb752c058ef3c1734e8748cfc Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 13:08:52 +0100 Subject: [PATCH 07/43] Making my code uglier, to make Aidan's code work. --- composer.json | 3 ++- packages/discovery/composer.json | 2 ++ packages/discovery/src/LoadDiscoveryClasses.php | 15 +++++++++------ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index ce22082b6f..2f75288f30 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,8 @@ "symfony/yaml": "^7.3", "tempest/highlight": "^2.11.4", "vlucas/phpdotenv": "^5.6.1", - "voku/portable-ascii": "^2.0.3" + "voku/portable-ascii": "^2.0.3", + "psr/container": "^2.0" }, "require-dev": { "adam-paterson/oauth2-slack": "^1.1", diff --git a/packages/discovery/composer.json b/packages/discovery/composer.json index a51ed164ad..f5a0a3d6a7 100644 --- a/packages/discovery/composer.json +++ b/packages/discovery/composer.json @@ -5,8 +5,10 @@ "minimum-stability": "dev", "require": { "php": "^8.5", + "tempest/container": "3.x-dev", "tempest/reflection": "3.x-dev", "tempest/support": "3.x-dev", + "psr/container": "^2.0", "symfony/cache": "^7.3" }, "autoload": { diff --git a/packages/discovery/src/LoadDiscoveryClasses.php b/packages/discovery/src/LoadDiscoveryClasses.php index 13598d721c..87b9a71816 100644 --- a/packages/discovery/src/LoadDiscoveryClasses.php +++ b/packages/discovery/src/LoadDiscoveryClasses.php @@ -5,6 +5,7 @@ namespace Tempest\Discovery; use AssertionError; +use Psr\Container\ContainerInterface; use Tempest\Container\Container; use Tempest\Reflection\ClassReflector; use Tempest\Support\Filesystem; @@ -20,7 +21,7 @@ public function __construct( private readonly Registry $registry, private readonly DiscoveryConfig $discoveryConfig, private readonly DiscoveryCache $discoveryCache, - private readonly Container $container, + private readonly Container|ContainerInterface $container, ) {} /** @@ -30,7 +31,8 @@ public function __construct( public function __invoke( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): void { + ): void + { $discoveries = $this->build($discoveryClasses, $discoveryLocations); foreach ($discoveries as $discovery) { @@ -46,7 +48,8 @@ public function __invoke( public function build( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): array { + ): array + { $discoveryLocations ??= $this->registry->locations; if ($discoveryClasses === null) { @@ -256,10 +259,10 @@ private function discoverPath(string $input, DiscoveryLocation $location, array private function resolveDiscovery(string $discoveryClass): Discovery { /** @var Discovery $discovery */ - if (! $this->container) { - $discovery = new $discoveryClass(); - } else { + if ($this->container instanceof ContainerInterface || $this->container instanceof Container) { $discovery = $this->container->get($discoveryClass); + } else { + $discovery = new $discoveryClass(); } $discovery->setItems(new DiscoveryItems()); From 1eb5cff359b38654d6d5d7f4a3f45cbf5d161df8 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 13:10:46 +0100 Subject: [PATCH 08/43] The atrocity is real --- packages/container/src/GenericContainer.php | 3 ++- packages/discovery/src/LoadDiscoveryClasses.php | 11 ++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/container/src/GenericContainer.php b/packages/container/src/GenericContainer.php index 2483f0640b..6491f65d6b 100644 --- a/packages/container/src/GenericContainer.php +++ b/packages/container/src/GenericContainer.php @@ -6,6 +6,7 @@ use ArrayIterator; use Closure; +use Psr\Container\ContainerInterface; use ReflectionFunction; use Tempest\Container\Exceptions\DecoratorDidNotImplementInterface; use Tempest\Container\Exceptions\DependencyCouldNotBeAutowired; @@ -20,7 +21,7 @@ use Throwable; use UnitEnum; -final class GenericContainer implements Container +final class GenericContainer implements Container, ContainerInterface { use HasInstance; diff --git a/packages/discovery/src/LoadDiscoveryClasses.php b/packages/discovery/src/LoadDiscoveryClasses.php index 87b9a71816..2286bc484d 100644 --- a/packages/discovery/src/LoadDiscoveryClasses.php +++ b/packages/discovery/src/LoadDiscoveryClasses.php @@ -6,7 +6,6 @@ use AssertionError; use Psr\Container\ContainerInterface; -use Tempest\Container\Container; use Tempest\Reflection\ClassReflector; use Tempest\Support\Filesystem; use Throwable; @@ -21,7 +20,7 @@ public function __construct( private readonly Registry $registry, private readonly DiscoveryConfig $discoveryConfig, private readonly DiscoveryCache $discoveryCache, - private readonly Container|ContainerInterface $container, + private readonly ContainerInterface $container, ) {} /** @@ -31,8 +30,7 @@ public function __construct( public function __invoke( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): void - { + ): void { $discoveries = $this->build($discoveryClasses, $discoveryLocations); foreach ($discoveries as $discovery) { @@ -48,8 +46,7 @@ public function __invoke( public function build( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): array - { + ): array { $discoveryLocations ??= $this->registry->locations; if ($discoveryClasses === null) { @@ -259,7 +256,7 @@ private function discoverPath(string $input, DiscoveryLocation $location, array private function resolveDiscovery(string $discoveryClass): Discovery { /** @var Discovery $discovery */ - if ($this->container instanceof ContainerInterface || $this->container instanceof Container) { + if ($this->container instanceof ContainerInterface) { $discovery = $this->container->get($discoveryClass); } else { $discovery = new $discoveryClass(); From 2e1ca4c9ed091f48eda8709b16cd4263b9e60500 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 13:10:57 +0100 Subject: [PATCH 09/43] =?UTF-8?q?Even=20cleanup=20can't=20save=20us?= =?UTF-8?q?=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 4 ++-- packages/cache/src/Commands/CacheClearCommand.php | 1 + packages/cache/src/Commands/CacheStatusCommand.php | 1 + packages/console/src/Middleware/OverviewMiddleware.php | 1 + packages/core/src/Commands/DiscoveryStatusCommand.php | 1 + packages/discovery/src/DiscoveryCache.php | 1 + packages/discovery/src/DiscoveryCacheStrategy.php | 1 + tests/Integration/Core/DiscoveryCacheTest.php | 1 + 8 files changed, 9 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 2f75288f30..501c32b42a 100644 --- a/composer.json +++ b/composer.json @@ -30,6 +30,7 @@ "psr-discovery/http-factory-implementations": "^1.2", "psr/cache": "^3.0", "psr/clock": "^1.0.0", + "psr/container": "^2.0", "psr/http-client": "^1.0.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0|^2.0", @@ -45,8 +46,7 @@ "symfony/yaml": "^7.3", "tempest/highlight": "^2.11.4", "vlucas/phpdotenv": "^5.6.1", - "voku/portable-ascii": "^2.0.3", - "psr/container": "^2.0" + "voku/portable-ascii": "^2.0.3" }, "require-dev": { "adam-paterson/oauth2-slack": "^1.1", diff --git a/packages/cache/src/Commands/CacheClearCommand.php b/packages/cache/src/Commands/CacheClearCommand.php index 61c30c8df8..84036ab77b 100644 --- a/packages/cache/src/Commands/CacheClearCommand.php +++ b/packages/cache/src/Commands/CacheClearCommand.php @@ -18,6 +18,7 @@ use Tempest\Icon\IconCache; use Tempest\Support\Str; use Tempest\View\ViewCache; + use function Tempest\Support\arr; if (class_exists(\Tempest\Console\ConsoleCommand::class)) { diff --git a/packages/cache/src/Commands/CacheStatusCommand.php b/packages/cache/src/Commands/CacheStatusCommand.php index 1fb76e42eb..7c2c70e189 100644 --- a/packages/cache/src/Commands/CacheStatusCommand.php +++ b/packages/cache/src/Commands/CacheStatusCommand.php @@ -19,6 +19,7 @@ use Tempest\Support\Str; use Tempest\View\ViewCache; use UnitEnum; + use function Tempest\Support\arr; if (class_exists(ConsoleCommand::class)) { diff --git a/packages/console/src/Middleware/OverviewMiddleware.php b/packages/console/src/Middleware/OverviewMiddleware.php index 21de5a4c8a..739ca7d45a 100644 --- a/packages/console/src/Middleware/OverviewMiddleware.php +++ b/packages/console/src/Middleware/OverviewMiddleware.php @@ -15,6 +15,7 @@ use Tempest\Core\AppConfig; use Tempest\Core\Priority; use Tempest\Discovery\DiscoveryCache; + use function Tempest\Support\arr; use function Tempest\Support\str; diff --git a/packages/core/src/Commands/DiscoveryStatusCommand.php b/packages/core/src/Commands/DiscoveryStatusCommand.php index 4da78b4417..cbca03f8c5 100644 --- a/packages/core/src/Commands/DiscoveryStatusCommand.php +++ b/packages/core/src/Commands/DiscoveryStatusCommand.php @@ -11,6 +11,7 @@ use Tempest\Discovery\DiscoveryCacheStrategy; use Tempest\Discovery\Registry; use Tempest\Support\Filesystem; + use function Tempest\root_path; use function Tempest\Support\str; diff --git a/packages/discovery/src/DiscoveryCache.php b/packages/discovery/src/DiscoveryCache.php index 198991ca48..406ca6bcdd 100644 --- a/packages/discovery/src/DiscoveryCache.php +++ b/packages/discovery/src/DiscoveryCache.php @@ -10,6 +10,7 @@ use Tempest\Core\CouldNotStoreDiscoveryCache; use Tempest\Support\Filesystem; use Throwable; + use function Tempest\internal_storage_path; final class DiscoveryCache diff --git a/packages/discovery/src/DiscoveryCacheStrategy.php b/packages/discovery/src/DiscoveryCacheStrategy.php index 8fb7d02c2d..2c6e976f18 100644 --- a/packages/discovery/src/DiscoveryCacheStrategy.php +++ b/packages/discovery/src/DiscoveryCacheStrategy.php @@ -5,6 +5,7 @@ namespace Tempest\Discovery; use Tempest\Core\Environment; + use function Tempest\env; enum DiscoveryCacheStrategy: string diff --git a/tests/Integration/Core/DiscoveryCacheTest.php b/tests/Integration/Core/DiscoveryCacheTest.php index efb0b33e7f..28c9b5be5e 100644 --- a/tests/Integration/Core/DiscoveryCacheTest.php +++ b/tests/Integration/Core/DiscoveryCacheTest.php @@ -10,6 +10,7 @@ use Tempest\Discovery\DiscoveryLocation; use Tests\Tempest\Integration\Core\Fixtures\TestDiscovery; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; + use function Tempest\Reflection\reflect; final class DiscoveryCacheTest extends FrameworkIntegrationTestCase From c76c35f08abf1ebee487cdcf8ebc72f9fa281194 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 13:57:25 +0100 Subject: [PATCH 10/43] =?UTF-8?q?The=20horror=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/1-essentials/05-discovery.md | 50 +++++++++++++++++++ packages/core/src/FrameworkKernel.php | 33 +++++------- ...DiscoveryClasses.php => BootDiscovery.php} | 23 +++++---- packages/discovery/src/Composer.php | 2 +- ...coveryLocations.php => CreateRegistry.php} | 25 +++++++--- .../Discovery/DiscoveryScanBench.php | 1 + 6 files changed, 96 insertions(+), 38 deletions(-) rename packages/discovery/src/{LoadDiscoveryClasses.php => BootDiscovery.php} (96%) rename packages/discovery/src/{LoadDiscoveryLocations.php => CreateRegistry.php} (87%) diff --git a/docs/1-essentials/05-discovery.md b/docs/1-essentials/05-discovery.md index d6a4bc3e1e..31ebd17028 100644 --- a/docs/1-essentials/05-discovery.md +++ b/docs/1-essentials/05-discovery.md @@ -218,3 +218,53 @@ Most of Tempest's features are built on top of discovery. The following is a non - {b`Tempest\Vite\ViteDiscovery`} discovers `*.entrypoint.{ts,js,css}` files and register them as [entrypoints](../2-features/02-asset-bundling.md#entrypoints). - {b`Tempest\Auth\AccessControl\PolicyDiscovery`} discovers methods annotated with the {b`#[Tempest\Auth\AccessControl\Policy]`} attribute and registers them as [access control policies](../2-features/04-authentication.md#access-control). - {b`Tempest\Core\InsightsProviderDiscovery`} discovers classes that implement {b`Tempest\Core\InsightsProvider`} and registers them as insights providers, which power the `tempest about` command. + +## Discovery as a standalone package + +`tempest/discovery` can be used as a standalone package in any application. All it needs is a PSR-11 compliant container. + +Start by requiring `tempest/discovery`: + +```console +composer require tempest/discovery +``` + +Next, you must create a {b`Tempest\Discovery\Registry`}, this object will keep track of all discovery locations. It's important that you add this registry to whatever container you're using: + +```php +use Tempest\Discovery\CreateRegistry; + +// The $container is provided by your project + +$registry = new CreateRegistry(rootPath: __DIR__)(); +$container->singleton(Registry::class, $registry); +// Or use another method, depending on what your container implementation requires: +// $container->set(Registry::class, $registry); +``` + +With this registry, you can boot discovery: + +```php +use Tempest\Discovery\BootDiscovery; + +new BootDiscovery( + container: $container, + registry: $registry, +)(); +``` + +### Custom registry + +{b`Tempest\Discovery\CreateRegistry`} will scan a given root path for discovery locations. It does so by analyzing your composer.json file. If you prefer another way of defining locations to scan, you can manually build a registry like so: + +```php +use Tempest\Discovery\Registry; +use Tempest\Discovery\DiscoveryLocation; + +$registry = new Registry(locations: [ + new DiscoveryLocation('App\\', 'src/') +]); + +// Don't forget to register the registry in the container of your choice. +$container->singleton(Registry::class, $registry); +``` \ No newline at end of file diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index 56d0231284..b892d953e4 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -12,12 +12,12 @@ use Tempest\Core\Kernel\FinishDeferredTasks; use Tempest\Core\Kernel\LoadConfig; use Tempest\Core\Kernel\RegisterEmergencyExceptionHandler; +use Tempest\Discovery\BootDiscovery; use Tempest\Discovery\Composer; use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheInitializer; use Tempest\Discovery\DiscoveryConfig; -use Tempest\Discovery\LoadDiscoveryClasses; -use Tempest\Discovery\LoadDiscoveryLocations; +use Tempest\Discovery\CreateRegistry; use Tempest\Discovery\Registry; use Tempest\EventBus\EventBus; use Tempest\Process\GenericProcessExecutor; @@ -75,7 +75,6 @@ public static function boot( container: $container, internalStorage: $internalStorage, ) - ->registerRegistry() ->registerKernel() ->validateRoot() ->loadEnv() @@ -83,7 +82,7 @@ public static function boot( ->registerShutdownFunction() ->registerInternalStorage() ->loadComposer() - ->loadDiscoveryLocations() + ->createRegistry() ->loadConfig() ->loadDiscovery() ->registerExceptionHandler() @@ -148,13 +147,6 @@ public function loadEnv(): self return $this; } - public function registerRegistry(): self - { - $this->container->singleton(Registry::class, fn () => $this->registry); - - return $this; - } - public function registerKernel(): self { $this->container->singleton(Kernel::class, $this); @@ -181,15 +173,16 @@ public function registerShutdownFunction(): self return $this; } - public function loadDiscoveryLocations(): self + public function createRegistry(): self { - $loadDiscoveryLocations = new LoadDiscoveryLocations( + $createRegistry = new CreateRegistry( rootPath: $this->root, - registry: $this->container->get(Registry::class), composer: $this->container->get(Composer::class), ); - $loadDiscoveryLocations(); + $registry = $createRegistry(); + + $this->container->singleton(Registry::class, $registry); return $this; } @@ -198,14 +191,14 @@ public function loadDiscovery(): self { $this->container->addInitializer(DiscoveryCacheInitializer::class); - $loadDiscoveryClasses = new LoadDiscoveryClasses( - registry: $this->container->get(Registry::class), - discoveryConfig: $this->container->get(DiscoveryConfig::class), - discoveryCache: $this->container->get(DiscoveryCache::class), + $bootDiscovery = new BootDiscovery( container: $this->container, + registry: $this->container->get(Registry::class), + config: $this->container->get(DiscoveryConfig::class), + cache: $this->container->get(DiscoveryCache::class), ); - $loadDiscoveryClasses(); + $bootDiscovery(); return $this; } diff --git a/packages/discovery/src/LoadDiscoveryClasses.php b/packages/discovery/src/BootDiscovery.php similarity index 96% rename from packages/discovery/src/LoadDiscoveryClasses.php rename to packages/discovery/src/BootDiscovery.php index 2286bc484d..1e31702384 100644 --- a/packages/discovery/src/LoadDiscoveryClasses.php +++ b/packages/discovery/src/BootDiscovery.php @@ -10,17 +10,16 @@ use Tempest\Support\Filesystem; use Throwable; -/** @internal */ -final class LoadDiscoveryClasses +final class BootDiscovery { private array $appliedDiscovery = []; private array $shouldSkipForClass = []; public function __construct( - private readonly Registry $registry, - private readonly DiscoveryConfig $discoveryConfig, - private readonly DiscoveryCache $discoveryCache, private readonly ContainerInterface $container, + private readonly Registry $registry, + private readonly DiscoveryConfig $config = new DiscoveryConfig(), + private readonly DiscoveryCache $cache = new DiscoveryCache(DiscoveryCacheStrategy::NONE), ) {} /** @@ -30,7 +29,8 @@ public function __construct( public function __invoke( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): void { + ): void + { $discoveries = $this->build($discoveryClasses, $discoveryLocations); foreach ($discoveries as $discovery) { @@ -46,7 +46,8 @@ public function __invoke( public function build( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): array { + ): array + { $discoveryLocations ??= $this->registry->locations; if ($discoveryClasses === null) { @@ -104,7 +105,7 @@ private function restoreFromCache(array $discoveries, DiscoveryLocation $locatio return false; } - $cachedForLocation = $this->discoveryCache->restore($location); + $cachedForLocation = $this->cache->restore($location); if (! $this->isCachedLocationUsable($discoveries, $cachedForLocation)) { return false; @@ -290,7 +291,7 @@ private function shouldSkipBasedOnConfig(ClassReflector|string $input): bool $input = $input->getName(); } - return $this->discoveryConfig->shouldSkip($input); + return $this->config->shouldSkip($input); } /** @@ -298,11 +299,11 @@ private function shouldSkipBasedOnConfig(ClassReflector|string $input): bool */ private function isLocationCached(DiscoveryLocation $location): bool { - if (! $this->discoveryCache->enabled) { + if (! $this->cache->enabled) { return false; } - return match ($this->discoveryCache->strategy) { + return match ($this->cache->strategy) { // If discovery cache is disabled, no locations should be skipped, all should always be discovered DiscoveryCacheStrategy::NONE, DiscoveryCacheStrategy::INVALID => false, // If discover cache is enabled, all locations cache should be skipped diff --git a/packages/discovery/src/Composer.php b/packages/discovery/src/Composer.php index 477c04b758..128ba12bc8 100644 --- a/packages/discovery/src/Composer.php +++ b/packages/discovery/src/Composer.php @@ -124,7 +124,7 @@ public function executeUpdate(): self private function loadComposerFile(string $path): array { if (! Filesystem\is_file($path)) { - throw new ComposerJsonCouldNotBeLocated('Could not locate composer.json.'); + throw new ComposerJsonCouldNotBeLocated("Could not locate {$path}"); } return Filesystem\read_json($path); diff --git a/packages/discovery/src/LoadDiscoveryLocations.php b/packages/discovery/src/CreateRegistry.php similarity index 87% rename from packages/discovery/src/LoadDiscoveryLocations.php rename to packages/discovery/src/CreateRegistry.php index 13b87eadac..529be2ffcc 100644 --- a/packages/discovery/src/LoadDiscoveryLocations.php +++ b/packages/discovery/src/CreateRegistry.php @@ -8,16 +8,27 @@ use function Tempest\Support\Path\normalize; -/** @internal */ -final readonly class LoadDiscoveryLocations +final readonly class CreateRegistry { + private Composer $composer; + private Registry $registry; + public function __construct( private string $rootPath, - private Registry $registry, - private Composer $composer, - ) {} + ?Registry $registry = null, + ?Composer $composer = null, + ) { + $this->registry = $registry ?? new Registry(); + + if (!$composer) { + $composer = new Composer($rootPath); + $composer->load(); + } - public function __invoke(): void + $this->composer = $composer; + } + + public function __invoke(): Registry { $this->registry->locations = [ ...$this->discoverCorePackages(), @@ -25,6 +36,8 @@ public function __invoke(): void ...$this->discoverAppNamespaces(), ...$this->registry->locations, ]; + + return $this->registry; } /** diff --git a/tests/Benchmark/Discovery/DiscoveryScanBench.php b/tests/Benchmark/Discovery/DiscoveryScanBench.php index 68f4970b3f..8b54162455 100644 --- a/tests/Benchmark/Discovery/DiscoveryScanBench.php +++ b/tests/Benchmark/Discovery/DiscoveryScanBench.php @@ -42,6 +42,7 @@ public function __construct() private function createLoader(): LoadDiscoveryClasses { return new LoadDiscoveryClasses( + container: $this->container, discoveryConfig: new DiscoveryConfig(), discoveryCache: new DiscoveryCache(DiscoveryCacheStrategy::NONE), From d50348e5bf3230a560b8b32d1fc993a3e2d6e935 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 13:59:49 +0100 Subject: [PATCH 11/43] Cleaning up, as far as possible --- packages/core/src/FrameworkKernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index b892d953e4..c8647c93ab 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -51,8 +51,7 @@ public function __construct( ?string $internalStorage = null, ) { $this->container = $container ?? $this->createContainer(); - $this->registry = new Registry(); - $this->discoveryLocations = $discoveryLocations; + $this->registry = new Registry(locations: $discoveryLocations); if ($internalStorage !== null) { $this->internalStorage = $internalStorage; @@ -177,6 +176,7 @@ public function createRegistry(): self { $createRegistry = new CreateRegistry( rootPath: $this->root, + registry: $this->registry, composer: $this->container->get(Composer::class), ); From 57b2c2a828612329ff88be8f55e2172f6fa43fab Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 14:14:46 +0100 Subject: [PATCH 12/43] Wip. Yes, it's wip --- docs/1-essentials/05-discovery.md | 6 +++--- packages/core/src/FrameworkKernel.php | 16 ++++++++-------- packages/discovery/composer.json | 1 - .../src/{CreateRegistry.php => LoadRegistry.php} | 2 +- tests/Benchmark/Discovery/DiscoveryScanBench.php | 16 ++++++++++------ .../QueryFunctionDynamicReturnTypeExtension.php | 2 +- 6 files changed, 23 insertions(+), 20 deletions(-) rename packages/discovery/src/{CreateRegistry.php => LoadRegistry.php} (99%) diff --git a/docs/1-essentials/05-discovery.md b/docs/1-essentials/05-discovery.md index 31ebd17028..6a192e304e 100644 --- a/docs/1-essentials/05-discovery.md +++ b/docs/1-essentials/05-discovery.md @@ -232,11 +232,11 @@ composer require tempest/discovery Next, you must create a {b`Tempest\Discovery\Registry`}, this object will keep track of all discovery locations. It's important that you add this registry to whatever container you're using: ```php -use Tempest\Discovery\CreateRegistry; +use Tempest\Discovery\LoadRegistry; // The $container is provided by your project -$registry = new CreateRegistry(rootPath: __DIR__)(); +$registry = new LoadRegistry(rootPath: __DIR__)(); $container->singleton(Registry::class, $registry); // Or use another method, depending on what your container implementation requires: // $container->set(Registry::class, $registry); @@ -255,7 +255,7 @@ new BootDiscovery( ### Custom registry -{b`Tempest\Discovery\CreateRegistry`} will scan a given root path for discovery locations. It does so by analyzing your composer.json file. If you prefer another way of defining locations to scan, you can manually build a registry like so: +{b`Tempest\Discovery\LoadRegistry`} will scan a given root path for discovery locations. It does so by analyzing your composer.json file. If you prefer another way of defining locations to scan, you can manually build a registry like so: ```php use Tempest\Discovery\Registry; diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index c8647c93ab..a3998958b1 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -17,7 +17,7 @@ use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheInitializer; use Tempest\Discovery\DiscoveryConfig; -use Tempest\Discovery\CreateRegistry; +use Tempest\Discovery\LoadRegistry; use Tempest\Discovery\Registry; use Tempest\EventBus\EventBus; use Tempest\Process\GenericProcessExecutor; @@ -41,7 +41,7 @@ final class FrameworkKernel implements Kernel public string $internalStorage; - private Registry $registry; + public Registry $registry; public function __construct( public string $root, @@ -81,9 +81,9 @@ public static function boot( ->registerShutdownFunction() ->registerInternalStorage() ->loadComposer() - ->createRegistry() + ->loadRegistry() ->loadConfig() - ->loadDiscovery() + ->bootDiscovery() ->registerExceptionHandler() ->event(KernelEvent::BOOTED); } @@ -172,22 +172,22 @@ public function registerShutdownFunction(): self return $this; } - public function createRegistry(): self + public function loadRegistry(): self { - $createRegistry = new CreateRegistry( + $loadRegistry = new LoadRegistry( rootPath: $this->root, registry: $this->registry, composer: $this->container->get(Composer::class), ); - $registry = $createRegistry(); + $registry = $loadRegistry(); $this->container->singleton(Registry::class, $registry); return $this; } - public function loadDiscovery(): self + public function bootDiscovery(): self { $this->container->addInitializer(DiscoveryCacheInitializer::class); diff --git a/packages/discovery/composer.json b/packages/discovery/composer.json index f5a0a3d6a7..3d3e68e2ae 100644 --- a/packages/discovery/composer.json +++ b/packages/discovery/composer.json @@ -5,7 +5,6 @@ "minimum-stability": "dev", "require": { "php": "^8.5", - "tempest/container": "3.x-dev", "tempest/reflection": "3.x-dev", "tempest/support": "3.x-dev", "psr/container": "^2.0", diff --git a/packages/discovery/src/CreateRegistry.php b/packages/discovery/src/LoadRegistry.php similarity index 99% rename from packages/discovery/src/CreateRegistry.php rename to packages/discovery/src/LoadRegistry.php index 529be2ffcc..9a29198a54 100644 --- a/packages/discovery/src/CreateRegistry.php +++ b/packages/discovery/src/LoadRegistry.php @@ -8,7 +8,7 @@ use function Tempest\Support\Path\normalize; -final readonly class CreateRegistry +final readonly class LoadRegistry { private Composer $composer; private Registry $registry; diff --git a/tests/Benchmark/Discovery/DiscoveryScanBench.php b/tests/Benchmark/Discovery/DiscoveryScanBench.php index 8b54162455..f41caafa5d 100644 --- a/tests/Benchmark/Discovery/DiscoveryScanBench.php +++ b/tests/Benchmark/Discovery/DiscoveryScanBench.php @@ -11,12 +11,13 @@ use PhpBench\Attributes\Warmup; use Tempest\Container\Container; use Tempest\Core\FrameworkKernel; +use Tempest\Discovery\BootDiscovery; use Tempest\Discovery\Discovery; use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheStrategy; use Tempest\Discovery\DiscoveryConfig; use Tempest\Discovery\DiscoveryLocation; -use Tempest\Discovery\LoadDiscoveryClasses; +use Tempest\Discovery\Registry; final class DiscoveryScanBench { @@ -30,22 +31,25 @@ final class DiscoveryScanBench private string $root; + private Registry $registry; + public function __construct() { $this->root = dirname(__DIR__, 3); $kernel = FrameworkKernel::boot(root: $this->root); $this->container = $kernel->container; + $this->registry = $kernel->registry; $this->discoveryLocations = $kernel->discoveryLocations; $this->discoveryClasses = $kernel->discoveryClasses; } - private function createLoader(): LoadDiscoveryClasses + private function createLoader(): BootDiscovery { - return new LoadDiscoveryClasses( - + return new BootDiscovery( container: $this->container, - discoveryConfig: new DiscoveryConfig(), - discoveryCache: new DiscoveryCache(DiscoveryCacheStrategy::NONE), + registry: $this->registry, + config: new DiscoveryConfig(), + cache: new DiscoveryCache(DiscoveryCacheStrategy::NONE), ); } diff --git a/tests/PHPStan/QueryFunctionDynamicReturnTypeExtension.php b/tests/PHPStan/QueryFunctionDynamicReturnTypeExtension.php index 686ce5e4a8..1675a5872c 100644 --- a/tests/PHPStan/QueryFunctionDynamicReturnTypeExtension.php +++ b/tests/PHPStan/QueryFunctionDynamicReturnTypeExtension.php @@ -22,7 +22,7 @@ public function __construct( public function isFunctionSupported(FunctionReflection $functionReflection): bool { - return $functionReflection->getName() === \Tempest\Database\query::class; + return $functionReflection->getName() === 'Tempest\\Database\\query'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type From e5e319b1495aca5f838984e36acb7bfc603bdae6 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 19:41:26 +0100 Subject: [PATCH 13/43] =?UTF-8?q?Moarrr=20WIP=20=E2=80=94=20but=20actually?= =?UTF-8?q?=20getting=20somewhere.=20Aidan's=20gonna=20be=20so=20happy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/container/src/Container.php | 3 ++- packages/container/src/GenericContainer.php | 2 +- .../core/src/Commands/DiscoveryGenerateCommand.php | 14 ++++++++------ .../core/src/Commands/DiscoveryStatusCommand.php | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/container/src/Container.php b/packages/container/src/Container.php index 8eec70c4f6..cacfe160bc 100644 --- a/packages/container/src/Container.php +++ b/packages/container/src/Container.php @@ -4,12 +4,13 @@ namespace Tempest\Container; +use Psr\Container\ContainerInterface; use Tempest\Reflection\ClassReflector; use Tempest\Reflection\FunctionReflector; use Tempest\Reflection\MethodReflector; use UnitEnum; -interface Container +interface Container extends ContainerInterface { public function register(string $className, callable $definition): self; diff --git a/packages/container/src/GenericContainer.php b/packages/container/src/GenericContainer.php index 6491f65d6b..1cd0f3f936 100644 --- a/packages/container/src/GenericContainer.php +++ b/packages/container/src/GenericContainer.php @@ -21,7 +21,7 @@ use Throwable; use UnitEnum; -final class GenericContainer implements Container, ContainerInterface +final class GenericContainer implements Container { use HasInstance; diff --git a/packages/core/src/Commands/DiscoveryGenerateCommand.php b/packages/core/src/Commands/DiscoveryGenerateCommand.php index c1ef5cf245..bc7f472415 100644 --- a/packages/core/src/Commands/DiscoveryGenerateCommand.php +++ b/packages/core/src/Commands/DiscoveryGenerateCommand.php @@ -11,6 +11,7 @@ use Tempest\Container\GenericContainer; use Tempest\Core\FrameworkKernel; use Tempest\Core\Kernel; +use Tempest\Discovery\BootDiscovery; use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheStrategy; use Tempest\Discovery\DiscoveryConfig; @@ -60,16 +61,16 @@ public function generateDiscoveryCache(DiscoveryCacheStrategy $strategy, Closure { $kernel = $this->resolveKernel(); - $loadDiscoveryClasses = new LoadDiscoveryClasses( - registry: $kernel->container->get(Registry::class), - discoveryConfig: $kernel->container->get(DiscoveryConfig::class), - discoveryCache: $this->discoveryCache, + $bootDiscovery = new BootDiscovery( container: $kernel->container, + registry: $kernel->container->get(Registry::class), + config: $kernel->container->get(DiscoveryConfig::class), + cache: $this->discoveryCache, ); - $discoveries = $loadDiscoveryClasses->build(); + $discoveries = $bootDiscovery->build(); - foreach ($this->kernel->discoveryLocations as $location) { + foreach ($this->registry->locations as $location) { $this->discoveryCache->store($location, $discoveries); $log($location->path); } @@ -81,6 +82,7 @@ public function resolveKernel(): Kernel { $container = new GenericContainer(); $container->singleton(Container::class, $container); + $container->singleton(Registry::class, $this->registry); return new FrameworkKernel( root: $this->kernel->root, diff --git a/packages/core/src/Commands/DiscoveryStatusCommand.php b/packages/core/src/Commands/DiscoveryStatusCommand.php index cbca03f8c5..4e5c67096e 100644 --- a/packages/core/src/Commands/DiscoveryStatusCommand.php +++ b/packages/core/src/Commands/DiscoveryStatusCommand.php @@ -24,7 +24,7 @@ public function __construct( private DiscoveryCache $discoveryCache, ) {} - #[ConsoleCommand(name: 'discovery:status', description: 'Lists all discovery locations and discovery classes')] + #[ConsoleCommand(name: 'discovery:status', description: 'Lists all discovery locations and discovery classes', aliases: ['d:s'])] public function __invoke( #[ConsoleArgument(description: 'Prints discovery classes', aliases: ['c'])] bool $showClasses = false, From 66c4a77b7a2ae1958c23b01f03c357326fac2462 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 19:41:49 +0100 Subject: [PATCH 14/43] Forgot to ran QA. Always a good idea --- packages/container/src/GenericContainer.php | 1 - packages/core/src/Commands/DiscoveryGenerateCommand.php | 1 - packages/discovery/src/BootDiscovery.php | 6 ++---- packages/discovery/src/LoadRegistry.php | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/container/src/GenericContainer.php b/packages/container/src/GenericContainer.php index 1cd0f3f936..2483f0640b 100644 --- a/packages/container/src/GenericContainer.php +++ b/packages/container/src/GenericContainer.php @@ -6,7 +6,6 @@ use ArrayIterator; use Closure; -use Psr\Container\ContainerInterface; use ReflectionFunction; use Tempest\Container\Exceptions\DecoratorDidNotImplementInterface; use Tempest\Container\Exceptions\DependencyCouldNotBeAutowired; diff --git a/packages/core/src/Commands/DiscoveryGenerateCommand.php b/packages/core/src/Commands/DiscoveryGenerateCommand.php index bc7f472415..958c238704 100644 --- a/packages/core/src/Commands/DiscoveryGenerateCommand.php +++ b/packages/core/src/Commands/DiscoveryGenerateCommand.php @@ -15,7 +15,6 @@ use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheStrategy; use Tempest\Discovery\DiscoveryConfig; -use Tempest\Discovery\LoadDiscoveryClasses; use Tempest\Discovery\Registry; if (class_exists(\Tempest\Console\ConsoleCommand::class)) { diff --git a/packages/discovery/src/BootDiscovery.php b/packages/discovery/src/BootDiscovery.php index 1e31702384..93f11d22e9 100644 --- a/packages/discovery/src/BootDiscovery.php +++ b/packages/discovery/src/BootDiscovery.php @@ -29,8 +29,7 @@ public function __construct( public function __invoke( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): void - { + ): void { $discoveries = $this->build($discoveryClasses, $discoveryLocations); foreach ($discoveries as $discovery) { @@ -46,8 +45,7 @@ public function __invoke( public function build( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): array - { + ): array { $discoveryLocations ??= $this->registry->locations; if ($discoveryClasses === null) { diff --git a/packages/discovery/src/LoadRegistry.php b/packages/discovery/src/LoadRegistry.php index 9a29198a54..f988460a8f 100644 --- a/packages/discovery/src/LoadRegistry.php +++ b/packages/discovery/src/LoadRegistry.php @@ -20,7 +20,7 @@ public function __construct( ) { $this->registry = $registry ?? new Registry(); - if (!$composer) { + if (! $composer) { $composer = new Composer($rootPath); $composer->load(); } From 8ae0a812d40dfbad44a18b3bcb585f90326e001e Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 19:46:32 +0100 Subject: [PATCH 15/43] =?UTF-8?q?Did=20we=20actually=E2=80=A6=20make=20it?= =?UTF-8?q?=20green=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/FrameworkKernel.php | 5 ++++- tests/Integration/Core/LoadDiscoveryClassesTest.php | 10 +++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index a3998958b1..f47fb28b02 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -6,6 +6,7 @@ use Dotenv\Dotenv; use ErrorException; +use Psr\Container\ContainerInterface; use RuntimeException; use Tempest\Container\Container; use Tempest\Container\GenericContainer; @@ -115,7 +116,9 @@ public function createContainer(): Container GenericContainer::setInstance($container); - $container->singleton(Container::class, fn () => $container); + $container->singleton(Container::class, $container); + $container->singleton(ContainerInterface::class, $container); + $container->singleton(GenericContainer::class, $container); return $container; } diff --git a/tests/Integration/Core/LoadDiscoveryClassesTest.php b/tests/Integration/Core/LoadDiscoveryClassesTest.php index 724a11c866..91081a9ad7 100644 --- a/tests/Integration/Core/LoadDiscoveryClassesTest.php +++ b/tests/Integration/Core/LoadDiscoveryClassesTest.php @@ -7,8 +7,8 @@ use PHPUnit\Framework\Attributes\Test; use Tempest\Database\MigratesUp; use Tempest\Database\Migrations\RunnableMigrations; +use Tempest\Discovery\BootDiscovery; use Tempest\Discovery\DiscoveryLocation; -use Tempest\Discovery\LoadDiscoveryClasses; use Tempest\Support\Arr; use Tests\Tempest\Fixtures\Discovery\HiddenDatabaseMigration; use Tests\Tempest\Fixtures\Discovery\HiddenMigratableDatabaseMigration; @@ -63,14 +63,14 @@ public function only_load_specific_discovery_classes(): void $dependency = $this->container->get(ManualTestDiscoveryDependency::class); $dependency->discovered = false; - /** @var LoadDiscoveryClasses $loadDiscoveryClasses */ - $loadDiscoveryClasses = $this->container->get(LoadDiscoveryClasses::class); + /** @var \Tempest\Discovery\BootDiscovery $bootDiscovery */ + $bootDiscovery = $this->container->get(BootDiscovery::class); - $loadDiscoveryClasses(discoveryClasses: [], discoveryLocations: []); + $bootDiscovery(discoveryClasses: [], discoveryLocations: []); $this->assertFalse($dependency->discovered); - $loadDiscoveryClasses( + $bootDiscovery( discoveryClasses: [ ManualTestDiscovery::class, ], From 6410671c4fb4a41e6d596cae41923382dd9043c0 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 19:48:56 +0100 Subject: [PATCH 16/43] RectOOOOOOOOOOOOOAAAAAArrr --- rector.php | 1 + 1 file changed, 1 insertion(+) diff --git a/rector.php b/rector.php index b511c8c6c9..5f13cad104 100644 --- a/rector.php +++ b/rector.php @@ -29,6 +29,7 @@ __DIR__ . '/src', __DIR__ . '/tests', ]) + ->withSkipPath(__DIR__ . '/tests/PHPStan/QueryFunctionDynamicReturnTypeExtension.php') ->withConfiguredRule(AddSensitiveParameterAttributeRector::class, [ 'sensitive_parameters' => [ 'password', From 78529365785eec2e535d9999280961203c22e008 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 19:50:16 +0100 Subject: [PATCH 17/43] We did not make it green :( --- packages/container/composer.json | 3 ++- packages/generation/composer.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/container/composer.json b/packages/container/composer.json index 561630f19b..0d0473a7c7 100644 --- a/packages/container/composer.json +++ b/packages/container/composer.json @@ -5,7 +5,8 @@ "minimum-stability": "dev", "require": { "php": "^8.5", - "tempest/reflection": "3.x-dev" + "tempest/reflection": "3.x-dev", + "psr/container": "^2.0" }, "autoload": { "files": [ diff --git a/packages/generation/composer.json b/packages/generation/composer.json index d25bd45cac..d7e402984d 100644 --- a/packages/generation/composer.json +++ b/packages/generation/composer.json @@ -8,7 +8,8 @@ "nette/php-generator": "4.2.1", "nette/schema": "^1.3.4", "nikic/php-parser": "^5.3", - "tempest/support": "3.x-dev" + "tempest/support": "3.x-dev", + "psr/container": "^2.0" }, "autoload": { "psr-4": { From dda118397565c4dc7d9c892172c3245552db1f58 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 19:56:22 +0100 Subject: [PATCH 18/43] Ok now it'll be green! --- packages/container/src/GenericContainer.php | 3 +++ .../core/src/Commands/DiscoveryGenerateCommand.php | 2 +- packages/core/src/FrameworkKernel.php | 10 ---------- packages/discovery/src/BootDiscovery.php | 12 +++++------- phpstan-baseline.neon | 2 +- tests/Benchmark/Discovery/DiscoveryScanBench.php | 4 ++-- tests/Integration/Core/Config/LoadConfigTest.php | 2 +- tests/Integration/Core/KernelTest.php | 2 +- .../Commands/DiscoveryStatusCommandTest.php | 4 ++-- .../Http/Exceptions/ExceptionRendererTest.php | 4 ++-- .../Http/Exceptions/HttpExceptionHandlerTest.php | 4 ++-- 11 files changed, 20 insertions(+), 29 deletions(-) diff --git a/packages/container/src/GenericContainer.php b/packages/container/src/GenericContainer.php index 2483f0640b..79c3177028 100644 --- a/packages/container/src/GenericContainer.php +++ b/packages/container/src/GenericContainer.php @@ -7,6 +7,7 @@ use ArrayIterator; use Closure; use ReflectionFunction; +use Tempest\Container\Exceptions\CircularDependencyEncountered; use Tempest\Container\Exceptions\DecoratorDidNotImplementInterface; use Tempest\Container\Exceptions\DependencyCouldNotBeAutowired; use Tempest\Container\Exceptions\DependencyCouldNotBeInstantiated; @@ -172,6 +173,8 @@ public function config(object $config): self * @template TClassName of object * @param class-string $className * @return TClassName + * @throws CircularDependencyEncountered + * @throws TaggedDependencyCouldNotBeResolved */ public function get(string $className, null|string|UnitEnum $tag = null, mixed ...$params): object { diff --git a/packages/core/src/Commands/DiscoveryGenerateCommand.php b/packages/core/src/Commands/DiscoveryGenerateCommand.php index 958c238704..228846fdbc 100644 --- a/packages/core/src/Commands/DiscoveryGenerateCommand.php +++ b/packages/core/src/Commands/DiscoveryGenerateCommand.php @@ -85,7 +85,7 @@ public function resolveKernel(): Kernel return new FrameworkKernel( root: $this->kernel->root, - discoveryLocations: $this->kernel->discoveryLocations, + discoveryLocations: $this->kernel->registry->locations, container: $container, ) ->registerKernel() diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index f47fb28b02..ff6fbdd8c6 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -30,16 +30,6 @@ final class FrameworkKernel implements Kernel public bool $discoveryCache; - public array $discoveryClasses { - get => $this->registry->classes; - set => $this->registry->classes = $value; - } - - public array $discoveryLocations { - get => $this->registry->locations; - set => $this->registry->locations = $value; - } - public string $internalStorage; public Registry $registry; diff --git a/packages/discovery/src/BootDiscovery.php b/packages/discovery/src/BootDiscovery.php index 93f11d22e9..38966b04e4 100644 --- a/packages/discovery/src/BootDiscovery.php +++ b/packages/discovery/src/BootDiscovery.php @@ -29,7 +29,8 @@ public function __construct( public function __invoke( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): void { + ): void + { $discoveries = $this->build($discoveryClasses, $discoveryLocations); foreach ($discoveries as $discovery) { @@ -45,7 +46,8 @@ public function __invoke( public function build( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): array { + ): array + { $discoveryLocations ??= $this->registry->locations; if ($discoveryClasses === null) { @@ -255,11 +257,7 @@ private function discoverPath(string $input, DiscoveryLocation $location, array private function resolveDiscovery(string $discoveryClass): Discovery { /** @var Discovery $discovery */ - if ($this->container instanceof ContainerInterface) { - $discovery = $this->container->get($discoveryClass); - } else { - $discovery = new $discoveryClass(); - } + $discovery = $this->container->get($discoveryClass); $discovery->setItems(new DiscoveryItems()); diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 2d624b923b..7d2fa08689 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -72,7 +72,7 @@ parameters: # Intentional: dd() delegates to ld() and dump() delegates to lw() - identifier: disallowed.function - path: packages/core/src/Composer.php + path: packages/discovery/src/Composer.php count: 1 # Intentional: exec() is required for running composer commands - diff --git a/tests/Benchmark/Discovery/DiscoveryScanBench.php b/tests/Benchmark/Discovery/DiscoveryScanBench.php index f41caafa5d..9794b768c3 100644 --- a/tests/Benchmark/Discovery/DiscoveryScanBench.php +++ b/tests/Benchmark/Discovery/DiscoveryScanBench.php @@ -39,8 +39,8 @@ public function __construct() $kernel = FrameworkKernel::boot(root: $this->root); $this->container = $kernel->container; $this->registry = $kernel->registry; - $this->discoveryLocations = $kernel->discoveryLocations; - $this->discoveryClasses = $kernel->discoveryClasses; + $this->discoveryLocations = $kernel->registry->locations; + $this->discoveryClasses = $kernel->registry->classes; } private function createLoader(): BootDiscovery diff --git a/tests/Integration/Core/Config/LoadConfigTest.php b/tests/Integration/Core/Config/LoadConfigTest.php index 365fff006f..0a469b5583 100644 --- a/tests/Integration/Core/Config/LoadConfigTest.php +++ b/tests/Integration/Core/Config/LoadConfigTest.php @@ -25,7 +25,7 @@ protected function setUp(): void Filesystem\ensure_directory_empty(__DIR__ . '/Fixtures'); $this->container->get(ConfigCache::class)->clear(); - $this->kernel->discoveryLocations = [ + $this->kernel->registry->locations = [ new DiscoveryLocation('App', __DIR__ . '/Fixtures'), ]; } diff --git a/tests/Integration/Core/KernelTest.php b/tests/Integration/Core/KernelTest.php index 2b810aea54..657d715061 100644 --- a/tests/Integration/Core/KernelTest.php +++ b/tests/Integration/Core/KernelTest.php @@ -27,7 +27,7 @@ public function test_discovery_boot(): void $this->assertInstanceOf(Container::class, $kernel->container); - $this->assertNotEmpty($kernel->discoveryClasses); + $this->assertNotEmpty($kernel->registry->classes); $test = $kernel->container->get(TestDependency::class); diff --git a/tests/Integration/Framework/Commands/DiscoveryStatusCommandTest.php b/tests/Integration/Framework/Commands/DiscoveryStatusCommandTest.php index b87f9c1875..b185a153cf 100644 --- a/tests/Integration/Framework/Commands/DiscoveryStatusCommandTest.php +++ b/tests/Integration/Framework/Commands/DiscoveryStatusCommandTest.php @@ -17,11 +17,11 @@ public function test_discovery_status_command(): void { $output = $this->console->call('discovery:status -cl'); - foreach ($this->kernel->discoveryClasses as $discoveryClass) { + foreach ($this->kernel->registry->classes as $discoveryClass) { $output->assertContains(basename(str_replace('\\', '/', $discoveryClass))); } - foreach ($this->kernel->discoveryLocations as $discoveryLocation) { + foreach ($this->kernel->registry->locations as $discoveryLocation) { // @TODO(aidan-casey): remove the src/ directory. $output->assertContains(str(realpath($discoveryLocation->path))->afterLast(['src/', 'packages/', 'vendor/', 'tests/'])->toString()); } diff --git a/tests/Integration/Http/Exceptions/ExceptionRendererTest.php b/tests/Integration/Http/Exceptions/ExceptionRendererTest.php index 653695a589..f6bfc22222 100644 --- a/tests/Integration/Http/Exceptions/ExceptionRendererTest.php +++ b/tests/Integration/Http/Exceptions/ExceptionRendererTest.php @@ -52,8 +52,8 @@ public function __construct(FrameworkKernel $kernel) { $this->root = $kernel->root; $this->internalStorage = $kernel->internalStorage; - $this->discoveryLocations = $kernel->discoveryLocations; - $this->discoveryClasses = $kernel->discoveryClasses; + $this->discoveryLocations = $kernel->registry->locations; + $this->discoveryClasses = $kernel->registry->classes; $this->container = $kernel->container; } diff --git a/tests/Integration/Http/Exceptions/HttpExceptionHandlerTest.php b/tests/Integration/Http/Exceptions/HttpExceptionHandlerTest.php index 370c7d9e1f..2be6dfa8b3 100644 --- a/tests/Integration/Http/Exceptions/HttpExceptionHandlerTest.php +++ b/tests/Integration/Http/Exceptions/HttpExceptionHandlerTest.php @@ -48,8 +48,8 @@ public function __construct(FrameworkKernel $kernel) { $this->root = $kernel->root; $this->internalStorage = $kernel->internalStorage; - $this->discoveryLocations = $kernel->discoveryLocations; - $this->discoveryClasses = $kernel->discoveryClasses; + $this->discoveryLocations = $kernel->registry->locations; + $this->discoveryClasses = $kernel->registry->classes; $this->container = $kernel->container; } From f616bdc33ae996e34f295353761997882bb7a39c Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 11 Mar 2026 19:57:34 +0100 Subject: [PATCH 19/43] No but now for real --- packages/discovery/src/BootDiscovery.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/discovery/src/BootDiscovery.php b/packages/discovery/src/BootDiscovery.php index 38966b04e4..d4ec619c61 100644 --- a/packages/discovery/src/BootDiscovery.php +++ b/packages/discovery/src/BootDiscovery.php @@ -29,8 +29,7 @@ public function __construct( public function __invoke( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): void - { + ): void { $discoveries = $this->build($discoveryClasses, $discoveryLocations); foreach ($discoveries as $discovery) { @@ -46,8 +45,7 @@ public function __invoke( public function build( ?array $discoveryClasses = null, ?array $discoveryLocations = null, - ): array - { + ): array { $discoveryLocations ??= $this->registry->locations; if ($discoveryClasses === null) { From 1d62fc65af1b884763501bf66a32c3adc8a12c21 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 08:17:00 +0100 Subject: [PATCH 20/43] Improvement, yes? --- packages/discovery/src/Registry.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/discovery/src/Registry.php b/packages/discovery/src/Registry.php index e5c4db17a4..059307b895 100644 --- a/packages/discovery/src/Registry.php +++ b/packages/discovery/src/Registry.php @@ -11,4 +11,9 @@ public function __construct( /** @var array> */ public array $classes = [], ) {} + + public static function autoload(string $path): self + { + return (new LoadRegistry($path))(); + } } From 45b46b3fc18811adc95f8c4896dba522e45317f7 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 08:25:29 +0100 Subject: [PATCH 21/43] Update docs --- docs/1-essentials/05-discovery.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/1-essentials/05-discovery.md b/docs/1-essentials/05-discovery.md index 6a192e304e..153330c82c 100644 --- a/docs/1-essentials/05-discovery.md +++ b/docs/1-essentials/05-discovery.md @@ -232,11 +232,11 @@ composer require tempest/discovery Next, you must create a {b`Tempest\Discovery\Registry`}, this object will keep track of all discovery locations. It's important that you add this registry to whatever container you're using: ```php -use Tempest\Discovery\LoadRegistry; +use Tempest\Discovery\Registry; -// The $container is provided by your project +$registry = Registry::autoload(__DIR__); -$registry = new LoadRegistry(rootPath: __DIR__)(); +// The $container is provided by your project $container->singleton(Registry::class, $registry); // Or use another method, depending on what your container implementation requires: // $container->set(Registry::class, $registry); @@ -253,16 +253,19 @@ new BootDiscovery( )(); ``` +Whenever this action is run, discovery will find all discovery classes, and run them against all registry locations. + ### Custom registry -{b`Tempest\Discovery\LoadRegistry`} will scan a given root path for discovery locations. It does so by analyzing your composer.json file. If you prefer another way of defining locations to scan, you can manually build a registry like so: +`Registry::autoload()` will scan a given root path and autmatically determine discovery locations by analyzing your composer.json file. If you prefer another way of defining locations to scan, you can manually build a registry like so: ```php use Tempest\Discovery\Registry; use Tempest\Discovery\DiscoveryLocation; $registry = new Registry(locations: [ - new DiscoveryLocation('App\\', 'src/') + new DiscoveryLocation('App\\', 'src/'), + // … ]); // Don't forget to register the registry in the container of your choice. From 5876ebba589b87a83ffbab5ce44617be92bab3d8 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 08:33:31 +0100 Subject: [PATCH 22/43] Remove container dependency from support --- packages/support/composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/support/composer.json b/packages/support/composer.json index 0f4ea97577..c2b69a31b4 100644 --- a/packages/support/composer.json +++ b/packages/support/composer.json @@ -5,7 +5,6 @@ "minimum-stability": "dev", "require": { "php": "^8.5", - "tempest/container": "3.x-dev", "voku/portable-ascii": "^2.0.3", "symfony/uid": "^7.1" }, From 029fdf19888286b456ef781a21381e33dc6eb09b Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 08:36:21 +0100 Subject: [PATCH 23/43] Update docs --- docs/1-essentials/05-discovery.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/1-essentials/05-discovery.md b/docs/1-essentials/05-discovery.md index 153330c82c..510d04561f 100644 --- a/docs/1-essentials/05-discovery.md +++ b/docs/1-essentials/05-discovery.md @@ -270,4 +270,18 @@ $registry = new Registry(locations: [ // Don't forget to register the registry in the container of your choice. $container->singleton(Registry::class, $registry); -``` \ No newline at end of file +``` + +### Using `tempest/container` + +If you're using `tempest/container` with discovery, you'll have to make sure that the container itself is also registered as a singleton: + +```php +use Tempest\Container\Container; +use Tempest\Container\GenericContainer; + +$container = new GenericContainer(); +$container->singleton(Container::class, $container); +``` + +This is because `tempest/container` comes with a handful of discovery classes itself, and they rely on the container being a singleton to configure it. \ No newline at end of file From 00b9ca9849c1966aaed04d180032a23afb2f7006 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 08:39:40 +0100 Subject: [PATCH 24/43] Fix deps --- packages/generation/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/generation/composer.json b/packages/generation/composer.json index d7e402984d..ac4da40e6e 100644 --- a/packages/generation/composer.json +++ b/packages/generation/composer.json @@ -8,6 +8,7 @@ "nette/php-generator": "4.2.1", "nette/schema": "^1.3.4", "nikic/php-parser": "^5.3", + "tempest/container": "3.x-dev", "tempest/support": "3.x-dev", "psr/container": "^2.0" }, From a7ab796308ea5cf88f70246633d1424f2a32c40b Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 08:53:39 +0100 Subject: [PATCH 25/43] Making it faster, better, stronger --- docs/1-essentials/05-discovery.md | 41 +++---------------- packages/container/src/GenericContainer.php | 8 +++- packages/core/src/FrameworkKernel.php | 16 +------- packages/discovery/src/BootDiscovery.php | 5 ++- packages/discovery/src/DiscoveryDiscovery.php | 15 +++++-- packages/discovery/src/RegistryWasNotSet.php | 13 ++++++ 6 files changed, 43 insertions(+), 55 deletions(-) create mode 100644 packages/discovery/src/RegistryWasNotSet.php diff --git a/docs/1-essentials/05-discovery.md b/docs/1-essentials/05-discovery.md index 510d04561f..ee4b3babcb 100644 --- a/docs/1-essentials/05-discovery.md +++ b/docs/1-essentials/05-discovery.md @@ -229,35 +229,23 @@ Start by requiring `tempest/discovery`: composer require tempest/discovery ``` -Next, you must create a {b`Tempest\Discovery\Registry`}, this object will keep track of all discovery locations. It's important that you add this registry to whatever container you're using: - -```php -use Tempest\Discovery\Registry; - -$registry = Registry::autoload(__DIR__); - -// The $container is provided by your project -$container->singleton(Registry::class, $registry); -// Or use another method, depending on what your container implementation requires: -// $container->set(Registry::class, $registry); -``` - -With this registry, you can boot discovery: +Next, you can boot discovery: ```php use Tempest\Discovery\BootDiscovery; +use Tempest\Discovery\Registry; new BootDiscovery( container: $container, - registry: $registry, + registry: Registry::autoload(__DIR__), )(); ``` -Whenever this action is run, discovery will find all discovery classes, and run them against all registry locations. +Whenever this action is run, discovery will find all discovery classes, and run them against all registry locations. ### Custom registry -`Registry::autoload()` will scan a given root path and autmatically determine discovery locations by analyzing your composer.json file. If you prefer another way of defining locations to scan, you can manually build a registry like so: +`Registry::autoload()` will scan a given root path and autmatically determine discovery locations by analyzing the composer.json file in that path. If you prefer another way of defining locations to scan, you can manually build a registry like so: ```php use Tempest\Discovery\Registry; @@ -267,21 +255,4 @@ $registry = new Registry(locations: [ new DiscoveryLocation('App\\', 'src/'), // … ]); - -// Don't forget to register the registry in the container of your choice. -$container->singleton(Registry::class, $registry); -``` - -### Using `tempest/container` - -If you're using `tempest/container` with discovery, you'll have to make sure that the container itself is also registered as a singleton: - -```php -use Tempest\Container\Container; -use Tempest\Container\GenericContainer; - -$container = new GenericContainer(); -$container->singleton(Container::class, $container); -``` - -This is because `tempest/container` comes with a handful of discovery classes itself, and they rely on the container being a singleton to configure it. \ No newline at end of file +``` \ No newline at end of file diff --git a/packages/container/src/GenericContainer.php b/packages/container/src/GenericContainer.php index 79c3177028..82e280ef0d 100644 --- a/packages/container/src/GenericContainer.php +++ b/packages/container/src/GenericContainer.php @@ -6,6 +6,7 @@ use ArrayIterator; use Closure; +use Psr\Container\ContainerInterface; use ReflectionFunction; use Tempest\Container\Exceptions\CircularDependencyEncountered; use Tempest\Container\Exceptions\DecoratorDidNotImplementInterface; @@ -41,7 +42,12 @@ public function __construct( /** @var ArrayIterator $decorators */ private(set) ArrayIterator $decorators = new ArrayIterator(), private(set) ?DependencyChain $chain = null, - ) {} + ) { + GenericContainer::setInstance($this); + $this->singleton(Container::class, $this); + $this->singleton(ContainerInterface::class, $this); + $this->singleton(GenericContainer::class, $this); + } public function setDefinitions(array $definitions): self { diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index ff6fbdd8c6..88daa8e2fe 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -6,7 +6,6 @@ use Dotenv\Dotenv; use ErrorException; -use Psr\Container\ContainerInterface; use RuntimeException; use Tempest\Container\Container; use Tempest\Container\GenericContainer; @@ -41,7 +40,7 @@ public function __construct( ?Container $container = null, ?string $internalStorage = null, ) { - $this->container = $container ?? $this->createContainer(); + $this->container = $container ?? new GenericContainer(); $this->registry = new Registry(locations: $discoveryLocations); if ($internalStorage !== null) { @@ -100,19 +99,6 @@ public function shutdown(int|string $status = ''): never exit($status); } - public function createContainer(): Container - { - $container = new GenericContainer(); - - GenericContainer::setInstance($container); - - $container->singleton(Container::class, $container); - $container->singleton(ContainerInterface::class, $container); - $container->singleton(GenericContainer::class, $container); - - return $container; - } - public function loadComposer(): self { if (class_exists(GenericProcessExecutor::class)) { diff --git a/packages/discovery/src/BootDiscovery.php b/packages/discovery/src/BootDiscovery.php index d4ec619c61..1b3a36fac2 100644 --- a/packages/discovery/src/BootDiscovery.php +++ b/packages/discovery/src/BootDiscovery.php @@ -51,6 +51,7 @@ public function build( if ($discoveryClasses === null) { // DiscoveryDiscovery needs to be applied before we can build all other discoveries $discoveryDiscovery = $this->resolveDiscovery(DiscoveryDiscovery::class); + $discoveryDiscovery->setRegistry($this->registry); // The first pass over all directories to find all discovery classes $this->discover([$discoveryDiscovery], $discoveryLocations); @@ -250,7 +251,9 @@ private function discoverPath(string $input, DiscoveryLocation $location, array /** * Create a discovery instance from a class name. * Optionally set the cached discovery items whenever caching is enabled. - * @param class-string $discoveryClass + * @template T of Discovery + * @param class-string $discoveryClass + * @return T */ private function resolveDiscovery(string $discoveryClass): Discovery { diff --git a/packages/discovery/src/DiscoveryDiscovery.php b/packages/discovery/src/DiscoveryDiscovery.php index ed77138bf6..1b4772bf6a 100644 --- a/packages/discovery/src/DiscoveryDiscovery.php +++ b/packages/discovery/src/DiscoveryDiscovery.php @@ -10,9 +10,14 @@ final class DiscoveryDiscovery implements Discovery { use IsDiscovery; - public function __construct( - private readonly Registry $registry, - ) {} + private ?Registry $registry = null; + + public function setRegistry(Registry $registry): self + { + $this->registry = $registry; + + return $this; + } public function discover(DiscoveryLocation $location, ClassReflector $class): void { @@ -29,6 +34,10 @@ public function discover(DiscoveryLocation $location, ClassReflector $class): vo public function apply(): void { + if ($this->registry === null) { + throw new RegistryWasNotSet(); + } + foreach ($this->discoveryItems as $className) { $this->registry->classes[] = $className; } diff --git a/packages/discovery/src/RegistryWasNotSet.php b/packages/discovery/src/RegistryWasNotSet.php new file mode 100644 index 0000000000..e35c4e0e55 --- /dev/null +++ b/packages/discovery/src/RegistryWasNotSet.php @@ -0,0 +1,13 @@ + Date: Thu, 12 Mar 2026 08:55:00 +0100 Subject: [PATCH 26/43] Docs --- docs/1-essentials/05-discovery.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/1-essentials/05-discovery.md b/docs/1-essentials/05-discovery.md index ee4b3babcb..2bdf3eb085 100644 --- a/docs/1-essentials/05-discovery.md +++ b/docs/1-essentials/05-discovery.md @@ -235,6 +235,8 @@ Next, you can boot discovery: use Tempest\Discovery\BootDiscovery; use Tempest\Discovery\Registry; +// $container is any PSR-11 compliant container, already available in your app + new BootDiscovery( container: $container, registry: Registry::autoload(__DIR__), From ba946734bba036cd3709f954e78f35f2ecec99ac Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 08:59:16 +0100 Subject: [PATCH 27/43] Docs, of course --- docs/1-essentials/05-discovery.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/1-essentials/05-discovery.md b/docs/1-essentials/05-discovery.md index 2bdf3eb085..af0668ed35 100644 --- a/docs/1-essentials/05-discovery.md +++ b/docs/1-essentials/05-discovery.md @@ -257,4 +257,35 @@ $registry = new Registry(locations: [ new DiscoveryLocation('App\\', 'src/'), // … ]); +``` + +### Config and caching + +You can pass optional config and cache parameters into the `BootDiscovery` action, with these you can exclude files and classes from discovery, as well as config caching behavior: + +```php +use Tempest\Discovery\BootDiscovery; +use Tempest\Discovery\DiscoveryCache; +use Tempest\Discovery\DiscoveryCacheStrategy; +use Tempest\Discovery\DiscoveryConfig; +use Tempest\Discovery\Registry; + +new BootDiscovery( + container: $container, + registry: Registry::autoload(__DIR__), + config: new DiscoveryConfig() + ->skipClasses( + \App\Foo::class, + \Tempest\Container\AutowireDiscovery::class + ) + ->skipPaths( + __DIR__ . '/../vendor/tempest/support' + ), + cache: new DiscoveryCache( + strategy: DiscoveryCacheStrategy::PARTIAL, + pool: new PhpFilesAdapter( + directory: __DIR__ . '/.cache/discovery' + ) + ), +)(); ``` \ No newline at end of file From d991965e317ece40908cce2e6006f58edea1b02d Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 09:00:43 +0100 Subject: [PATCH 28/43] QA, of course --- packages/discovery/src/RegistryWasNotSet.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/discovery/src/RegistryWasNotSet.php b/packages/discovery/src/RegistryWasNotSet.php index e35c4e0e55..b7714dd866 100644 --- a/packages/discovery/src/RegistryWasNotSet.php +++ b/packages/discovery/src/RegistryWasNotSet.php @@ -8,6 +8,6 @@ final class RegistryWasNotSet extends Exception { public function __construct() { - parent::__construct("No registry was set, did you forget to call `DiscoveryDiscovery::setRegistry()`?"); + parent::__construct('No registry was set, did you forget to call `DiscoveryDiscovery::setRegistry()`?'); } -} \ No newline at end of file +} From a606c0fc998e68e4c1cb8b7ba2657a54533b1c72 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 09:18:48 +0100 Subject: [PATCH 29/43] Testing --- composer.json | 2 + .../src/Commands/DiscoveryGenerateCommand.php | 9 +-- packages/discovery/composer.json | 9 +++ packages/discovery/src/BootDiscovery.php | 4 +- packages/discovery/src/DiscoveryDiscovery.php | 15 +---- packages/discovery/src/RegistryWasNotSet.php | 13 ----- packages/discovery/tests/DiscoveryTest.php | 57 +++++++++++++++++++ .../tests/Fixtures/DiscoveredItem.php | 10 ++++ .../tests/Fixtures/MyDiscoveryClass.php | 30 ++++++++++ 9 files changed, 118 insertions(+), 31 deletions(-) delete mode 100644 packages/discovery/src/RegistryWasNotSet.php create mode 100644 packages/discovery/tests/DiscoveryTest.php create mode 100644 packages/discovery/tests/Fixtures/DiscoveredItem.php create mode 100644 packages/discovery/tests/Fixtures/MyDiscoveryClass.php diff --git a/composer.json b/composer.json index 501c32b42a..796dc8debb 100644 --- a/composer.json +++ b/composer.json @@ -74,6 +74,7 @@ "nesbot/carbon": "^3.8", "nyholm/psr7": "^1.8", "patrickbussmann/oauth2-apple": "^0.3", + "php-di/php-di": "^7.0", "phpat/phpat": "^0.11.0", "phpbench/phpbench": "^1.4", "phpstan/phpstan": "2.1.40", @@ -218,6 +219,7 @@ "Tempest\\Database\\Tests\\": "packages/database/tests", "Tempest\\DateTime\\Tests\\": "packages/datetime/tests", "Tempest\\Debug\\Tests\\": "packages/debug/tests", + "Tempest\\Discovery\\Tests\\": "packages/discovery/tests", "Tempest\\EventBus\\Tests\\": "packages/event-bus/tests", "Tempest\\Generation\\Tests\\": "packages/generation/tests", "Tempest\\HttpClient\\Tests\\": "packages/http-client/tests", diff --git a/packages/core/src/Commands/DiscoveryGenerateCommand.php b/packages/core/src/Commands/DiscoveryGenerateCommand.php index 228846fdbc..5bd21f20b5 100644 --- a/packages/core/src/Commands/DiscoveryGenerateCommand.php +++ b/packages/core/src/Commands/DiscoveryGenerateCommand.php @@ -45,10 +45,11 @@ public function __invoke(): void $this->clearDiscoveryCache(); - $this->console->task( - label: "Generating discovery cache using the `{$strategy->value}` strategy", - handler: fn (Closure $log) => $this->generateDiscoveryCache($strategy, $log), - ); + $this->generateDiscoveryCache($strategy, fn () => null); +// $this->console->task( +// label: "Generating discovery cache using the `{$strategy->value}` strategy", +// handler: fn (Closure $log) => $this->generateDiscoveryCache($strategy, $log), +// ); } public function clearDiscoveryCache(): void diff --git a/packages/discovery/composer.json b/packages/discovery/composer.json index 3d3e68e2ae..56b38e3938 100644 --- a/packages/discovery/composer.json +++ b/packages/discovery/composer.json @@ -10,9 +10,18 @@ "psr/container": "^2.0", "symfony/cache": "^7.3" }, + "require-dev": { + "tempest/container": "3.x-dev", + "php-di/php-di": "^7.0" + }, "autoload": { "psr-4": { "Tempest\\Discovery\\": "src" } + }, + "autoload-dev": { + "psr-4": { + "Tempest\\Discovery\\Tests": "tests" + } } } diff --git a/packages/discovery/src/BootDiscovery.php b/packages/discovery/src/BootDiscovery.php index 1b3a36fac2..775f433a61 100644 --- a/packages/discovery/src/BootDiscovery.php +++ b/packages/discovery/src/BootDiscovery.php @@ -50,8 +50,8 @@ public function build( if ($discoveryClasses === null) { // DiscoveryDiscovery needs to be applied before we can build all other discoveries - $discoveryDiscovery = $this->resolveDiscovery(DiscoveryDiscovery::class); - $discoveryDiscovery->setRegistry($this->registry); + $discoveryDiscovery = new DiscoveryDiscovery($this->registry); + $discoveryDiscovery->setItems(new DiscoveryItems()); // The first pass over all directories to find all discovery classes $this->discover([$discoveryDiscovery], $discoveryLocations); diff --git a/packages/discovery/src/DiscoveryDiscovery.php b/packages/discovery/src/DiscoveryDiscovery.php index 1b4772bf6a..ed77138bf6 100644 --- a/packages/discovery/src/DiscoveryDiscovery.php +++ b/packages/discovery/src/DiscoveryDiscovery.php @@ -10,14 +10,9 @@ final class DiscoveryDiscovery implements Discovery { use IsDiscovery; - private ?Registry $registry = null; - - public function setRegistry(Registry $registry): self - { - $this->registry = $registry; - - return $this; - } + public function __construct( + private readonly Registry $registry, + ) {} public function discover(DiscoveryLocation $location, ClassReflector $class): void { @@ -34,10 +29,6 @@ public function discover(DiscoveryLocation $location, ClassReflector $class): vo public function apply(): void { - if ($this->registry === null) { - throw new RegistryWasNotSet(); - } - foreach ($this->discoveryItems as $className) { $this->registry->classes[] = $className; } diff --git a/packages/discovery/src/RegistryWasNotSet.php b/packages/discovery/src/RegistryWasNotSet.php deleted file mode 100644 index b7714dd866..0000000000 --- a/packages/discovery/src/RegistryWasNotSet.php +++ /dev/null @@ -1,13 +0,0 @@ -assertSame('check', MyDiscoveryClass::$discoveredItem->name); + } + + public function test_discovery_with_other_container(): void + { + $container = new Container(); + + new BootDiscovery( + container: $container, + registry: new Registry(locations: [ + new DiscoveryLocation( + namespace: 'Tempest\Discovery\Tests\Fixtures', + path: __DIR__ . '/Fixtures', + ), + ]), + )(); + + self::assertNotNull(MyDiscoveryClass::$discoveredItem); + $this->assertSame('check', MyDiscoveryClass::$discoveredItem->name); + } +} \ No newline at end of file diff --git a/packages/discovery/tests/Fixtures/DiscoveredItem.php b/packages/discovery/tests/Fixtures/DiscoveredItem.php new file mode 100644 index 0000000000..336bfc3be3 --- /dev/null +++ b/packages/discovery/tests/Fixtures/DiscoveredItem.php @@ -0,0 +1,10 @@ +is(DiscoveredItem::class)) { + $this->discoveryItems->add($location, $class); + } + } + + public function apply(): void + { + /** @var ClassReflector $class */ + foreach ($this->discoveryItems as $class) { + self::$discoveredItem = $class->newInstanceArgs(['name' => 'check']); + } + } +} \ No newline at end of file From 1b7b3d385ddaba3df8bc9ddaf452f8e2a294d655 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 09:24:21 +0100 Subject: [PATCH 30/43] Fixing testing --- packages/container/src/GenericContainer.php | 1 - .../core/src/Commands/DiscoveryGenerateCommand.php | 9 ++++----- packages/core/src/FrameworkKernel.php | 11 ++++++++++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/container/src/GenericContainer.php b/packages/container/src/GenericContainer.php index 82e280ef0d..7e57aa8ac7 100644 --- a/packages/container/src/GenericContainer.php +++ b/packages/container/src/GenericContainer.php @@ -43,7 +43,6 @@ public function __construct( private(set) ArrayIterator $decorators = new ArrayIterator(), private(set) ?DependencyChain $chain = null, ) { - GenericContainer::setInstance($this); $this->singleton(Container::class, $this); $this->singleton(ContainerInterface::class, $this); $this->singleton(GenericContainer::class, $this); diff --git a/packages/core/src/Commands/DiscoveryGenerateCommand.php b/packages/core/src/Commands/DiscoveryGenerateCommand.php index 5bd21f20b5..228846fdbc 100644 --- a/packages/core/src/Commands/DiscoveryGenerateCommand.php +++ b/packages/core/src/Commands/DiscoveryGenerateCommand.php @@ -45,11 +45,10 @@ public function __invoke(): void $this->clearDiscoveryCache(); - $this->generateDiscoveryCache($strategy, fn () => null); -// $this->console->task( -// label: "Generating discovery cache using the `{$strategy->value}` strategy", -// handler: fn (Closure $log) => $this->generateDiscoveryCache($strategy, $log), -// ); + $this->console->task( + label: "Generating discovery cache using the `{$strategy->value}` strategy", + handler: fn (Closure $log) => $this->generateDiscoveryCache($strategy, $log), + ); } public function clearDiscoveryCache(): void diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index 88daa8e2fe..9c0a5021ff 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -40,7 +40,7 @@ public function __construct( ?Container $container = null, ?string $internalStorage = null, ) { - $this->container = $container ?? new GenericContainer(); + $this->container = $container ?? $this->createContainer(); $this->registry = new Registry(locations: $discoveryLocations); if ($internalStorage !== null) { @@ -78,6 +78,15 @@ public static function boot( ->event(KernelEvent::BOOTED); } + public function createContainer(): GenericContainer + { + $container = new GenericContainer(); + + GenericContainer::setInstance($container); + + return $container; + } + public function validateRoot(): self { $root = Filesystem\normalize_path($this->root); From d1f28b101feff147cace3059c063b286ce3325cb Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 09:49:00 +0100 Subject: [PATCH 31/43] Fixing testing --- packages/discovery/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/discovery/composer.json b/packages/discovery/composer.json index 56b38e3938..b1232690a7 100644 --- a/packages/discovery/composer.json +++ b/packages/discovery/composer.json @@ -21,7 +21,7 @@ }, "autoload-dev": { "psr-4": { - "Tempest\\Discovery\\Tests": "tests" + "Tempest\\Discovery\\Tests\\": "tests" } } } From 5ff8c029e2605fed6da1419a85362545b3533664 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 09:49:12 +0100 Subject: [PATCH 32/43] QA --- packages/discovery/tests/DiscoveryTest.php | 10 +++++----- packages/discovery/tests/Fixtures/DiscoveredItem.php | 2 +- packages/discovery/tests/Fixtures/MyDiscoveryClass.php | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/discovery/tests/DiscoveryTest.php b/packages/discovery/tests/DiscoveryTest.php index f7429fe97b..decea683c3 100644 --- a/packages/discovery/tests/DiscoveryTest.php +++ b/packages/discovery/tests/DiscoveryTest.php @@ -23,7 +23,7 @@ public function test_standalone_discovery(): void { $container = new GenericContainer(); - new BootDiscovery( + (new BootDiscovery( container: $container, registry: new Registry(locations: [ new DiscoveryLocation( @@ -31,7 +31,7 @@ public function test_standalone_discovery(): void path: __DIR__ . '/Fixtures', ), ]), - )(); + ))(); self::assertNotNull(MyDiscoveryClass::$discoveredItem); $this->assertSame('check', MyDiscoveryClass::$discoveredItem->name); @@ -41,7 +41,7 @@ public function test_discovery_with_other_container(): void { $container = new Container(); - new BootDiscovery( + (new BootDiscovery( container: $container, registry: new Registry(locations: [ new DiscoveryLocation( @@ -49,9 +49,9 @@ public function test_discovery_with_other_container(): void path: __DIR__ . '/Fixtures', ), ]), - )(); + ))(); self::assertNotNull(MyDiscoveryClass::$discoveredItem); $this->assertSame('check', MyDiscoveryClass::$discoveredItem->name); } -} \ No newline at end of file +} diff --git a/packages/discovery/tests/Fixtures/DiscoveredItem.php b/packages/discovery/tests/Fixtures/DiscoveredItem.php index 336bfc3be3..779b8676b0 100644 --- a/packages/discovery/tests/Fixtures/DiscoveredItem.php +++ b/packages/discovery/tests/Fixtures/DiscoveredItem.php @@ -7,4 +7,4 @@ final class DiscoveredItem public function __construct( public string $name, ) {} -} \ No newline at end of file +} diff --git a/packages/discovery/tests/Fixtures/MyDiscoveryClass.php b/packages/discovery/tests/Fixtures/MyDiscoveryClass.php index 36ad2f456e..8cfe11aa2f 100644 --- a/packages/discovery/tests/Fixtures/MyDiscoveryClass.php +++ b/packages/discovery/tests/Fixtures/MyDiscoveryClass.php @@ -27,4 +27,4 @@ public function apply(): void self::$discoveredItem = $class->newInstanceArgs(['name' => 'check']); } } -} \ No newline at end of file +} From 1880b21ea0982516cf9377701beb895591debd53 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 09:52:08 +0100 Subject: [PATCH 33/43] QA --- packages/discovery/tests/DiscoveryTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/discovery/tests/DiscoveryTest.php b/packages/discovery/tests/DiscoveryTest.php index decea683c3..96b032ed4b 100644 --- a/packages/discovery/tests/DiscoveryTest.php +++ b/packages/discovery/tests/DiscoveryTest.php @@ -33,7 +33,7 @@ public function test_standalone_discovery(): void ]), ))(); - self::assertNotNull(MyDiscoveryClass::$discoveredItem); + $this->assertNotNull(MyDiscoveryClass::$discoveredItem); $this->assertSame('check', MyDiscoveryClass::$discoveredItem->name); } @@ -51,7 +51,7 @@ public function test_discovery_with_other_container(): void ]), ))(); - self::assertNotNull(MyDiscoveryClass::$discoveredItem); + $this->assertNotNull(MyDiscoveryClass::$discoveredItem); $this->assertSame('check', MyDiscoveryClass::$discoveredItem->name); } } From c283ecf3b87b509ff74a430099b2d7f6f61b5d6c Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 11:01:21 +0100 Subject: [PATCH 34/43] Rector wip --- .../config/sets/level/up-to-tempest-34.php | 15 ++++ packages/upgrade/config/sets/tempest34.php | 13 ++++ .../upgrade/src/Set/TempestLevelSetList.php | 1 + packages/upgrade/src/Set/TempestSetList.php | 1 + .../UpdateDiscoveryImportsRector.php | 51 ++++++++++++++ ...CouldNotBeLocatedNamespaceChange.input.php | 11 +++ .../ComposerNamespaceChange.input.php | 10 +++ .../DiscoveryCacheNamespaceChange.input.php | 10 +++ ...veryCacheStrategyNamespaceChange.input.php | 11 +++ ...trategyWasChangedNamespaceChange.input.php | 11 +++ .../DiscoveryConfigNamespaceChange.input.php | 10 +++ .../FullyQualifiedDiscoveryCache.input.php | 8 +++ .../tests/Tempest34/Tempest34RectorTest.php | 69 +++++++++++++++++++ .../tests/Tempest34/tempest34_rector.php | 9 +++ 14 files changed, 230 insertions(+) create mode 100644 packages/upgrade/config/sets/level/up-to-tempest-34.php create mode 100644 packages/upgrade/config/sets/tempest34.php create mode 100644 packages/upgrade/src/Tempest34/UpdateDiscoveryImportsRector.php create mode 100644 packages/upgrade/tests/Tempest34/Fixtures/ComposerJsonCouldNotBeLocatedNamespaceChange.input.php create mode 100644 packages/upgrade/tests/Tempest34/Fixtures/ComposerNamespaceChange.input.php create mode 100644 packages/upgrade/tests/Tempest34/Fixtures/DiscoveryCacheNamespaceChange.input.php create mode 100644 packages/upgrade/tests/Tempest34/Fixtures/DiscoveryCacheStrategyNamespaceChange.input.php create mode 100644 packages/upgrade/tests/Tempest34/Fixtures/DiscoveryCachingStrategyWasChangedNamespaceChange.input.php create mode 100644 packages/upgrade/tests/Tempest34/Fixtures/DiscoveryConfigNamespaceChange.input.php create mode 100644 packages/upgrade/tests/Tempest34/Fixtures/FullyQualifiedDiscoveryCache.input.php create mode 100644 packages/upgrade/tests/Tempest34/Tempest34RectorTest.php create mode 100644 packages/upgrade/tests/Tempest34/tempest34_rector.php diff --git a/packages/upgrade/config/sets/level/up-to-tempest-34.php b/packages/upgrade/config/sets/level/up-to-tempest-34.php new file mode 100644 index 0000000000..4d52182503 --- /dev/null +++ b/packages/upgrade/config/sets/level/up-to-tempest-34.php @@ -0,0 +1,15 @@ +sets([ + TempestSetList::TEMPEST_20, + TempestSetList::TEMPEST_28, + TempestSetList::TEMPEST_30, + TempestSetList::TEMPEST_34, + ]); +}; diff --git a/packages/upgrade/config/sets/tempest34.php b/packages/upgrade/config/sets/tempest34.php new file mode 100644 index 0000000000..3e1a006856 --- /dev/null +++ b/packages/upgrade/config/sets/tempest34.php @@ -0,0 +1,13 @@ +rule(UpdateDiscoveryImportsRector::class); +}; diff --git a/packages/upgrade/src/Set/TempestLevelSetList.php b/packages/upgrade/src/Set/TempestLevelSetList.php index 859b32034c..93c6365044 100644 --- a/packages/upgrade/src/Set/TempestLevelSetList.php +++ b/packages/upgrade/src/Set/TempestLevelSetList.php @@ -9,4 +9,5 @@ final class TempestLevelSetList public const string UP_TO_TEMPEST_20 = __DIR__ . '/../../config/sets/level/up-to-tempest-20.php'; public const string UP_TO_TEMPEST_28 = __DIR__ . '/../../config/sets/level/up-to-tempest-28.php'; public const string UP_TO_TEMPEST_30 = __DIR__ . '/../../config/sets/level/up-to-tempest-30.php'; + public const string UP_TO_TEMPEST_34 = __DIR__ . '/../../config/sets/level/up-to-tempest-34.php'; } diff --git a/packages/upgrade/src/Set/TempestSetList.php b/packages/upgrade/src/Set/TempestSetList.php index 8c4bcaa293..c23d6f1736 100644 --- a/packages/upgrade/src/Set/TempestSetList.php +++ b/packages/upgrade/src/Set/TempestSetList.php @@ -9,4 +9,5 @@ final class TempestSetList public const string TEMPEST_20 = __DIR__ . '/../../config/sets/tempest20.php'; public const string TEMPEST_28 = __DIR__ . '/../../config/sets/tempest28.php'; public const string TEMPEST_30 = __DIR__ . '/../../config/sets/tempest30.php'; + public const string TEMPEST_34 = __DIR__ . '/../../config/sets/tempest34.php'; } diff --git a/packages/upgrade/src/Tempest34/UpdateDiscoveryImportsRector.php b/packages/upgrade/src/Tempest34/UpdateDiscoveryImportsRector.php new file mode 100644 index 0000000000..50e915195c --- /dev/null +++ b/packages/upgrade/src/Tempest34/UpdateDiscoveryImportsRector.php @@ -0,0 +1,51 @@ + 'Tempest\Discovery\DiscoveryCache', + 'Tempest\Core\DiscoveryCacheStrategy' => 'Tempest\Discovery\DiscoveryCacheStrategy', + 'Tempest\Core\Composer' => 'Tempest\Discovery\Composer', + 'Tempest\Core\ComposerJsonCouldNotBeLocated' => 'Tempest\Discovery\ComposerJsonCouldNotBeLocated', + 'Tempest\Core\DiscoveryCachingStrategyWasChanged' => 'Tempest\Discovery\DiscoveryCachingStrategyWasChanged', + 'Tempest\Core\DiscoveryConfig' => 'Tempest\Discovery\DiscoveryConfig', + ]; + + public function getNodeTypes(): array + { + return [ + Node\UseItem::class, + Node\Name\FullyQualified::class, + ]; + } + + public function refactor(Node $node): ?Node + { + if ($node instanceof Node\UseItem) { + $name = $node->name->toString(); + + if (isset(self::CLASS_RENAMES[$name])) { + $node->name = new Node\Name(self::CLASS_RENAMES[$name]); + + return $node; + } + + return null; + } + + if ($node instanceof Node\Name\FullyQualified) { + $name = $node->toString(); + + if (isset(self::CLASS_RENAMES[$name])) { + return new Node\Name\FullyQualified(self::CLASS_RENAMES[$name]); + } + } + + return null; + } +} diff --git a/packages/upgrade/tests/Tempest34/Fixtures/ComposerJsonCouldNotBeLocatedNamespaceChange.input.php b/packages/upgrade/tests/Tempest34/Fixtures/ComposerJsonCouldNotBeLocatedNamespaceChange.input.php new file mode 100644 index 0000000000..fb2ffeee8d --- /dev/null +++ b/packages/upgrade/tests/Tempest34/Fixtures/ComposerJsonCouldNotBeLocatedNamespaceChange.input.php @@ -0,0 +1,11 @@ + new RectorTester(__DIR__ . '/tempest34_rector.php'); + } + + public function test_discovery_cache_namespace_change(): void + { + $this->rector + ->runFixture(__DIR__ . '/Fixtures/DiscoveryCacheNamespaceChange.input.php') + ->assertContains('use Tempest\Discovery\DiscoveryCache;') + ->assertNotContains('use Tempest\Core\DiscoveryCache;'); + } + + public function test_discovery_cache_strategy_namespace_change(): void + { + $this->rector + ->runFixture(__DIR__ . '/Fixtures/DiscoveryCacheStrategyNamespaceChange.input.php') + ->assertContains('use Tempest\Discovery\DiscoveryCacheStrategy;') + ->assertNotContains('use Tempest\Core\DiscoveryCacheStrategy;'); + } + + public function test_composer_namespace_change(): void + { + $this->rector + ->runFixture(__DIR__ . '/Fixtures/ComposerNamespaceChange.input.php') + ->assertContains('use Tempest\Discovery\Composer;') + ->assertNotContains('use Tempest\Core\Composer;'); + } + + public function test_composer_json_could_not_be_located_namespace_change(): void + { + $this->rector + ->runFixture(__DIR__ . '/Fixtures/ComposerJsonCouldNotBeLocatedNamespaceChange.input.php') + ->assertContains('use Tempest\Discovery\ComposerJsonCouldNotBeLocated;') + ->assertNotContains('use Tempest\Core\ComposerJsonCouldNotBeLocated;'); + } + + public function test_discovery_caching_strategy_was_changed_namespace_change(): void + { + $this->rector + ->runFixture(__DIR__ . '/Fixtures/DiscoveryCachingStrategyWasChangedNamespaceChange.input.php') + ->assertContains('use Tempest\Discovery\DiscoveryCachingStrategyWasChanged;') + ->assertNotContains('use Tempest\Core\DiscoveryCachingStrategyWasChanged;'); + } + + public function test_discovery_config_namespace_change(): void + { + $this->rector + ->runFixture(__DIR__ . '/Fixtures/DiscoveryConfigNamespaceChange.input.php') + ->assertContains('use Tempest\Discovery\DiscoveryConfig;') + ->assertNotContains('use Tempest\Core\DiscoveryConfig;'); + } + + public function test_fully_qualified_discovery_cache(): void + { + $this->rector + ->runFixture(__DIR__ . '/Fixtures/FullyQualifiedDiscoveryCache.input.php') + ->assertContains('Tempest\Discovery\DiscoveryCache') + ->assertNotContains('Tempest\Core\DiscoveryCache'); + } +} diff --git a/packages/upgrade/tests/Tempest34/tempest34_rector.php b/packages/upgrade/tests/Tempest34/tempest34_rector.php new file mode 100644 index 0000000000..bdd47e5fe3 --- /dev/null +++ b/packages/upgrade/tests/Tempest34/tempest34_rector.php @@ -0,0 +1,9 @@ +withSets([TempestSetList::TEMPEST_34]); From d49074cd0d94f900563bf6d2a7a0dd73f0156d00 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 11:04:23 +0100 Subject: [PATCH 35/43] Rector wip --- packages/upgrade/config/sets/tempest34.php | 2 + .../UpdateKernelDiscoveryPropertiesRector.php | 63 +++++++++++++++++++ .../Fixtures/KernelDiscoveryClasses.input.php | 15 +++++ .../KernelDiscoveryLocations.input.php | 15 +++++ .../tests/Tempest34/Tempest34RectorTest.php | 16 +++++ 5 files changed, 111 insertions(+) create mode 100644 packages/upgrade/src/Tempest34/UpdateKernelDiscoveryPropertiesRector.php create mode 100644 packages/upgrade/tests/Tempest34/Fixtures/KernelDiscoveryClasses.input.php create mode 100644 packages/upgrade/tests/Tempest34/Fixtures/KernelDiscoveryLocations.input.php diff --git a/packages/upgrade/config/sets/tempest34.php b/packages/upgrade/config/sets/tempest34.php index 3e1a006856..41d2aa0b0d 100644 --- a/packages/upgrade/config/sets/tempest34.php +++ b/packages/upgrade/config/sets/tempest34.php @@ -4,10 +4,12 @@ use Rector\Configuration\Option; use Rector\Configuration\Parameter\SimpleParameterProvider; use Tempest\Upgrade\Tempest34\UpdateDiscoveryImportsRector; +use Tempest\Upgrade\Tempest34\UpdateKernelDiscoveryPropertiesRector; return static function (RectorConfig $config): void { SimpleParameterProvider::setParameter(Option::AUTO_IMPORT_NAMES, value: true); SimpleParameterProvider::setParameter(Option::IMPORT_SHORT_CLASSES, value: true); $config->rule(UpdateDiscoveryImportsRector::class); + $config->rule(UpdateKernelDiscoveryPropertiesRector::class); }; diff --git a/packages/upgrade/src/Tempest34/UpdateKernelDiscoveryPropertiesRector.php b/packages/upgrade/src/Tempest34/UpdateKernelDiscoveryPropertiesRector.php new file mode 100644 index 0000000000..bbae2e5811 --- /dev/null +++ b/packages/upgrade/src/Tempest34/UpdateKernelDiscoveryPropertiesRector.php @@ -0,0 +1,63 @@ + 'locations', + 'discoveryClasses' => 'classes', + ]; + + public function getNodeTypes(): array + { + return [ + PropertyFetch::class, + ]; + } + + public function refactor(Node $node): ?Node + { + if (! $node instanceof PropertyFetch) { + return null; + } + + if (! $node->name instanceof Identifier) { + return null; + } + + $propertyName = $node->name->toString(); + + if (! isset(self::PROPERTY_RENAMES[$propertyName])) { + return null; + } + + if (! $this->isKernelType($node->var)) { + return null; + } + + // Transform $kernel->discoveryLocations to $kernel->registry->locations + return new PropertyFetch( + new PropertyFetch($node->var, 'registry'), + self::PROPERTY_RENAMES[$propertyName], + ); + } + + private function isKernelType(Node\Expr $expr): bool + { + $type = $this->nodeTypeResolver->getType($expr); + + foreach ($type->getObjectClassNames() as $className) { + if ($className === 'Tempest\Core\Kernel' || is_subclass_of($className, 'Tempest\Core\Kernel')) { + return true; + } + } + + return false; + } +} diff --git a/packages/upgrade/tests/Tempest34/Fixtures/KernelDiscoveryClasses.input.php b/packages/upgrade/tests/Tempest34/Fixtures/KernelDiscoveryClasses.input.php new file mode 100644 index 0000000000..3947e599ca --- /dev/null +++ b/packages/upgrade/tests/Tempest34/Fixtures/KernelDiscoveryClasses.input.php @@ -0,0 +1,15 @@ +kernel->discoveryClasses; + } +} diff --git a/packages/upgrade/tests/Tempest34/Fixtures/KernelDiscoveryLocations.input.php b/packages/upgrade/tests/Tempest34/Fixtures/KernelDiscoveryLocations.input.php new file mode 100644 index 0000000000..cbf480ccec --- /dev/null +++ b/packages/upgrade/tests/Tempest34/Fixtures/KernelDiscoveryLocations.input.php @@ -0,0 +1,15 @@ +kernel->discoveryLocations; + } +} diff --git a/packages/upgrade/tests/Tempest34/Tempest34RectorTest.php b/packages/upgrade/tests/Tempest34/Tempest34RectorTest.php index 64abd92adc..e061d567f1 100644 --- a/packages/upgrade/tests/Tempest34/Tempest34RectorTest.php +++ b/packages/upgrade/tests/Tempest34/Tempest34RectorTest.php @@ -66,4 +66,20 @@ public function test_fully_qualified_discovery_cache(): void ->assertContains('Tempest\Discovery\DiscoveryCache') ->assertNotContains('Tempest\Core\DiscoveryCache'); } + + public function test_kernel_discovery_locations_refactored(): void + { + $this->rector + ->runFixture(__DIR__ . '/Fixtures/KernelDiscoveryLocations.input.php') + ->assertContains('$this->kernel->registry->locations') + ->assertNotContains('$this->kernel->discoveryLocations'); + } + + public function test_kernel_discovery_classes_refactored(): void + { + $this->rector + ->runFixture(__DIR__ . '/Fixtures/KernelDiscoveryClasses.input.php') + ->assertContains('$this->kernel->registry->classes') + ->assertNotContains('$this->kernel->discoveryClasses'); + } } From 47c0b6e78dd4c92f6234845932a2c23a80a352dd Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 11:28:57 +0100 Subject: [PATCH 36/43] Fix cache path --- packages/discovery/src/DiscoveryCache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/discovery/src/DiscoveryCache.php b/packages/discovery/src/DiscoveryCache.php index 406ca6bcdd..01ebe5bd09 100644 --- a/packages/discovery/src/DiscoveryCache.php +++ b/packages/discovery/src/DiscoveryCache.php @@ -103,7 +103,7 @@ public static function getCurrentDiscoverStrategyCachePath(): string private static function getCachePath(): string { try { - return internal_storage_path('cache/views'); + return internal_storage_path('cache/discovery'); } catch (Throwable) { return __DIR__ . '/../.tempest/cache'; } From 317215bbad733d199e5972ae3225be1b45f3ca97 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 12:29:24 +0100 Subject: [PATCH 37/43] wip --- .../src/CouldNotStoreDiscoveryCache.php | 3 +-- packages/discovery/src/DiscoveryCache.php | 1 - packages/discovery/src/DiscoveryCacheStrategy.php | 4 ++++ ...trategyCouldNotBeDeterminedWithEnvironment.php | 15 +++++++++++++++ .../Tempest34/UpdateDiscoveryImportsRector.php | 1 + ...otStoreDiscoveryCacheNamespaceChange.input.php | 13 +++++++++++++ .../tests/Tempest34/Tempest34RectorTest.php | 8 ++++++++ tests/Integration/Core/DiscoveryCacheTest.php | 2 +- 8 files changed, 43 insertions(+), 4 deletions(-) rename packages/{core => discovery}/src/CouldNotStoreDiscoveryCache.php (86%) create mode 100644 packages/discovery/src/DiscoveryCacheStrategyCouldNotBeDeterminedWithEnvironment.php create mode 100644 packages/upgrade/tests/Tempest34/Fixtures/CouldNotStoreDiscoveryCacheNamespaceChange.input.php diff --git a/packages/core/src/CouldNotStoreDiscoveryCache.php b/packages/discovery/src/CouldNotStoreDiscoveryCache.php similarity index 86% rename from packages/core/src/CouldNotStoreDiscoveryCache.php rename to packages/discovery/src/CouldNotStoreDiscoveryCache.php index 0fdd882457..0c93a63e1d 100644 --- a/packages/core/src/CouldNotStoreDiscoveryCache.php +++ b/packages/discovery/src/CouldNotStoreDiscoveryCache.php @@ -1,9 +1,8 @@ 'Tempest\Discovery\ComposerJsonCouldNotBeLocated', 'Tempest\Core\DiscoveryCachingStrategyWasChanged' => 'Tempest\Discovery\DiscoveryCachingStrategyWasChanged', 'Tempest\Core\DiscoveryConfig' => 'Tempest\Discovery\DiscoveryConfig', + 'Tempest\Core\CouldNotStoreDiscoveryCache' => 'Tempest\Discovery\CouldNotStoreDiscoveryCache', ]; public function getNodeTypes(): array diff --git a/packages/upgrade/tests/Tempest34/Fixtures/CouldNotStoreDiscoveryCacheNamespaceChange.input.php b/packages/upgrade/tests/Tempest34/Fixtures/CouldNotStoreDiscoveryCacheNamespaceChange.input.php new file mode 100644 index 0000000000..b42d72dee2 --- /dev/null +++ b/packages/upgrade/tests/Tempest34/Fixtures/CouldNotStoreDiscoveryCacheNamespaceChange.input.php @@ -0,0 +1,13 @@ +assertNotContains('use Tempest\Core\ComposerJsonCouldNotBeLocated;'); } + public function test_could_not_store_discovery_cache_namespace_change(): void + { + $this->rector + ->runFixture(__DIR__ . '/Fixtures/CouldNotStoreDiscoveryCacheNamespaceChange.input.php') + ->assertContains('use Tempest\Discovery\CouldNotStoreDiscoveryCache;') + ->assertNotContains('use Tempest\Core\CouldNotStoreDiscoveryCache;'); + } + public function test_discovery_caching_strategy_was_changed_namespace_change(): void { $this->rector diff --git a/tests/Integration/Core/DiscoveryCacheTest.php b/tests/Integration/Core/DiscoveryCacheTest.php index 28c9b5be5e..1b51bf1ddd 100644 --- a/tests/Integration/Core/DiscoveryCacheTest.php +++ b/tests/Integration/Core/DiscoveryCacheTest.php @@ -4,7 +4,7 @@ use PHPUnit\Framework\Attributes\PostCondition; use PHPUnit\Framework\Attributes\Test; -use Tempest\Core\CouldNotStoreDiscoveryCache; +use Tempest\Discovery\CouldNotStoreDiscoveryCache; use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheStrategy; use Tempest\Discovery\DiscoveryLocation; From 7a3a7b9ea6350484afc9ae53a4964b32c5fcdd35 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 12:31:20 +0100 Subject: [PATCH 38/43] Fix namespace --- packages/discovery/tests/DiscoveryTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/discovery/tests/DiscoveryTest.php b/packages/discovery/tests/DiscoveryTest.php index 96b032ed4b..9e46738bdd 100644 --- a/packages/discovery/tests/DiscoveryTest.php +++ b/packages/discovery/tests/DiscoveryTest.php @@ -1,6 +1,6 @@ Date: Thu, 12 Mar 2026 13:33:46 +0100 Subject: [PATCH 39/43] Remove registry --- docs/1-essentials/05-discovery.md | 18 +++---- .../src/Commands/DiscoveryGenerateCommand.php | 10 ++-- .../src/Commands/DiscoveryStatusCommand.php | 12 ++--- packages/core/src/FrameworkKernel.php | 51 +++++++++---------- packages/core/src/Kernel/LoadConfig.php | 11 ++-- ...try.php => AutoloadDiscoveryLocations.php} | 15 ++---- packages/discovery/src/BootDiscovery.php | 9 ++-- packages/discovery/src/DiscoveryConfig.php | 15 ++++++ packages/discovery/src/DiscoveryDiscovery.php | 4 +- packages/discovery/src/Registry.php | 19 ------- packages/discovery/tests/DiscoveryTest.php | 6 +-- .../TempestViewCompilerInitializer.php | 4 +- .../Discovery/DiscoveryScanBench.php | 12 ++--- .../Core/Config/LoadConfigTest.php | 2 +- tests/Integration/Core/KernelTest.php | 2 +- .../Commands/DiscoveryStatusCommandTest.php | 4 +- .../Http/Exceptions/ExceptionRendererTest.php | 4 +- .../Exceptions/HttpExceptionHandlerTest.php | 4 +- .../View/TempestViewRendererTest.php | 6 +-- 19 files changed, 98 insertions(+), 110 deletions(-) rename packages/discovery/src/{LoadRegistry.php => AutoloadDiscoveryLocations.php} (91%) delete mode 100644 packages/discovery/src/Registry.php diff --git a/docs/1-essentials/05-discovery.md b/docs/1-essentials/05-discovery.md index af0668ed35..570d6bcb8e 100644 --- a/docs/1-essentials/05-discovery.md +++ b/docs/1-essentials/05-discovery.md @@ -233,27 +233,27 @@ Next, you can boot discovery: ```php use Tempest\Discovery\BootDiscovery; -use Tempest\Discovery\Registry; +use Tempest\Discovery\DiscoveryConfig; // $container is any PSR-11 compliant container, already available in your app new BootDiscovery( container: $container, - registry: Registry::autoload(__DIR__), + config: DiscoveryConfig::autoload(__DIR__), )(); ``` Whenever this action is run, discovery will find all discovery classes, and run them against all registry locations. -### Custom registry +### Manually specify discovery locations -`Registry::autoload()` will scan a given root path and autmatically determine discovery locations by analyzing the composer.json file in that path. If you prefer another way of defining locations to scan, you can manually build a registry like so: +`DiscoveryConfig::autoload()` will scan a given root path and autmatically determine discovery locations by analyzing the composer.json file in that path. If you prefer another way of defining locations to scan, you can manually build a registry like so: ```php -use Tempest\Discovery\Registry; +use Tempest\Discovery\DiscoveryConfig; use Tempest\Discovery\DiscoveryLocation; -$registry = new Registry(locations: [ +$config = new DiscoveryConfig(locations: [ new DiscoveryLocation('App\\', 'src/'), // … ]); @@ -261,19 +261,17 @@ $registry = new Registry(locations: [ ### Config and caching -You can pass optional config and cache parameters into the `BootDiscovery` action, with these you can exclude files and classes from discovery, as well as config caching behavior: +You can pass config and cache parameters into the `BootDiscovery` action, with these you can exclude files and classes from discovery, as well as config caching behavior: ```php use Tempest\Discovery\BootDiscovery; use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheStrategy; use Tempest\Discovery\DiscoveryConfig; -use Tempest\Discovery\Registry; new BootDiscovery( container: $container, - registry: Registry::autoload(__DIR__), - config: new DiscoveryConfig() + config: DiscoveryConfig::autoload(__DIR__) ->skipClasses( \App\Foo::class, \Tempest\Container\AutowireDiscovery::class diff --git a/packages/core/src/Commands/DiscoveryGenerateCommand.php b/packages/core/src/Commands/DiscoveryGenerateCommand.php index 228846fdbc..53f415f80b 100644 --- a/packages/core/src/Commands/DiscoveryGenerateCommand.php +++ b/packages/core/src/Commands/DiscoveryGenerateCommand.php @@ -15,7 +15,6 @@ use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheStrategy; use Tempest\Discovery\DiscoveryConfig; -use Tempest\Discovery\Registry; if (class_exists(\Tempest\Console\ConsoleCommand::class)) { final readonly class DiscoveryGenerateCommand @@ -23,7 +22,7 @@ use HasConsole; public function __construct( - private Registry $registry, + private DiscoveryConfig $discoveryConfig, private FrameworkKernel $kernel, private DiscoveryCache $discoveryCache, ) {} @@ -62,14 +61,13 @@ public function generateDiscoveryCache(DiscoveryCacheStrategy $strategy, Closure $bootDiscovery = new BootDiscovery( container: $kernel->container, - registry: $kernel->container->get(Registry::class), config: $kernel->container->get(DiscoveryConfig::class), cache: $this->discoveryCache, ); $discoveries = $bootDiscovery->build(); - foreach ($this->registry->locations as $location) { + foreach ($this->discoveryConfig->locations as $location) { $this->discoveryCache->store($location, $discoveries); $log($location->path); } @@ -81,11 +79,11 @@ public function resolveKernel(): Kernel { $container = new GenericContainer(); $container->singleton(Container::class, $container); - $container->singleton(Registry::class, $this->registry); + $container->singleton(DiscoveryConfig::class, $this->discoveryConfig); return new FrameworkKernel( root: $this->kernel->root, - discoveryLocations: $this->kernel->registry->locations, + discoveryLocations: $this->kernel->discoveryConfig->locations, container: $container, ) ->registerKernel() diff --git a/packages/core/src/Commands/DiscoveryStatusCommand.php b/packages/core/src/Commands/DiscoveryStatusCommand.php index 4e5c67096e..b8dadd7b53 100644 --- a/packages/core/src/Commands/DiscoveryStatusCommand.php +++ b/packages/core/src/Commands/DiscoveryStatusCommand.php @@ -9,7 +9,7 @@ use Tempest\Console\ConsoleCommand; use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheStrategy; -use Tempest\Discovery\Registry; +use Tempest\Discovery\DiscoveryConfig; use Tempest\Support\Filesystem; use function Tempest\root_path; @@ -20,7 +20,7 @@ { public function __construct( private Console $console, - private Registry $registry, + private DiscoveryConfig $discoveryConfig, private DiscoveryCache $discoveryCache, ) {} @@ -32,8 +32,8 @@ public function __invoke( bool $showLocations = false, ): void { $this->console->header('Discovery status'); - $this->console->keyValue('Registered locations', (string) count($this->registry->locations)); - $this->console->keyValue('Loaded discovery classes', (string) count($this->registry->classes)); + $this->console->keyValue('Registered locations', (string) count($this->discoveryConfig->locations)); + $this->console->keyValue('Loaded discovery classes', (string) count($this->discoveryConfig->classes)); $this->console->keyValue('Cache', match ($this->discoveryCache->enabled) { true => 'ENABLED', false => 'DISABLED', @@ -53,7 +53,7 @@ public function __invoke( $this->console->header('Discovery classes', subheader: 'These classes are used by Tempest to determine which classes to discover and how to handle them.'); $this->console->writeln(); - foreach ($this->registry->classes as $discoveryClass) { + foreach ($this->discoveryConfig->classes as $discoveryClass) { $this->console->keyValue("{$discoveryClass}"); } } @@ -62,7 +62,7 @@ public function __invoke( $this->console->header('Discovery locations', subheader: 'These locations are used by Tempest to discover classes.'); $this->console->writeln(); - foreach ($this->registry->locations as $discoveryLocation) { + foreach ($this->discoveryConfig->locations as $discoveryLocation) { $path = str(Filesystem\normalize_path($discoveryLocation->path)) ->replaceStart(root_path(), '.') ->toString(); diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index 9c0a5021ff..fbdb529efe 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -12,13 +12,12 @@ use Tempest\Core\Kernel\FinishDeferredTasks; use Tempest\Core\Kernel\LoadConfig; use Tempest\Core\Kernel\RegisterEmergencyExceptionHandler; +use Tempest\Discovery\AutoloadDiscoveryLocations; use Tempest\Discovery\BootDiscovery; use Tempest\Discovery\Composer; use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheInitializer; use Tempest\Discovery\DiscoveryConfig; -use Tempest\Discovery\LoadRegistry; -use Tempest\Discovery\Registry; use Tempest\EventBus\EventBus; use Tempest\Process\GenericProcessExecutor; use Tempest\Support\Filesystem; @@ -31,7 +30,7 @@ final class FrameworkKernel implements Kernel public string $internalStorage; - public Registry $registry; + public DiscoveryConfig $discoveryConfig; public function __construct( public string $root, @@ -41,7 +40,7 @@ public function __construct( ?string $internalStorage = null, ) { $this->container = $container ?? $this->createContainer(); - $this->registry = new Registry(locations: $discoveryLocations); + // $this->registry = new Registry(locations: $discoveryLocations); if ($internalStorage !== null) { $this->internalStorage = $internalStorage; @@ -71,7 +70,7 @@ public static function boot( ->registerShutdownFunction() ->registerInternalStorage() ->loadComposer() - ->loadRegistry() + ->loadDiscoveryConfig() ->loadConfig() ->bootDiscovery() ->registerExceptionHandler() @@ -160,49 +159,49 @@ public function registerShutdownFunction(): self return $this; } - public function loadRegistry(): self + public function loadDiscoveryConfig(): self { - $loadRegistry = new LoadRegistry( + /** @var DiscoveryConfig $discoveryConfig */ + $discoveryConfig = $this->container->get(DiscoveryConfig::class); + + $discoveryConfig->locations = (new AutoloadDiscoveryLocations( rootPath: $this->root, - registry: $this->registry, composer: $this->container->get(Composer::class), - ); + ))($discoveryConfig); - $registry = $loadRegistry(); - - $this->container->singleton(Registry::class, $registry); + $this->container->config($discoveryConfig); + $this->discoveryConfig = $discoveryConfig; return $this; } - public function bootDiscovery(): self + public function loadConfig(): self { - $this->container->addInitializer(DiscoveryCacheInitializer::class); + $this->container->addInitializer(ConfigCacheInitializer::class); - $bootDiscovery = new BootDiscovery( + $loadConfig = new LoadConfig( + discoveryConfig: $this->container->get(DiscoveryConfig::class), container: $this->container, - registry: $this->container->get(Registry::class), - config: $this->container->get(DiscoveryConfig::class), - cache: $this->container->get(DiscoveryCache::class), + cache: $this->container->get(ConfigCache::class), + environment: Environment::guessFromEnvironment(), ); - $bootDiscovery(); + $loadConfig(); return $this; } - public function loadConfig(): self + public function bootDiscovery(): self { - $this->container->addInitializer(ConfigCacheInitializer::class); + $this->container->addInitializer(DiscoveryCacheInitializer::class); - $loadConfig = new LoadConfig( - registry: $this->container->get(Registry::class), + $bootDiscovery = new BootDiscovery( container: $this->container, - cache: $this->container->get(ConfigCache::class), - environment: Environment::guessFromEnvironment(), + config: $this->container->get(DiscoveryConfig::class), + cache: $this->container->get(DiscoveryCache::class), ); - $loadConfig(); + $bootDiscovery(); return $this; } diff --git a/packages/core/src/Kernel/LoadConfig.php b/packages/core/src/Kernel/LoadConfig.php index edeebfb898..1492f6803c 100644 --- a/packages/core/src/Kernel/LoadConfig.php +++ b/packages/core/src/Kernel/LoadConfig.php @@ -7,7 +7,7 @@ use Tempest\Container\Container; use Tempest\Core\ConfigCache; use Tempest\Core\Environment; -use Tempest\Discovery\Registry; +use Tempest\Discovery\DiscoveryConfig; use Tempest\Support\Arr\MutableArray; use Tempest\Support\Filesystem; use Tempest\Support\Path; @@ -19,7 +19,7 @@ final readonly class LoadConfig { public function __construct( - private Registry $registry, + private DiscoveryConfig $discoveryConfig, private Container $container, private ConfigCache $cache, private Environment $environment, @@ -32,6 +32,11 @@ public function __invoke(): void foreach ($configPaths as $path) { $configFile = require $path; + if ($configFile instanceof DiscoveryConfig) { + $configFile->locations = [...$this->discoveryConfig->locations, ...$configFile->locations]; + $configFile->classes = [...$this->discoveryConfig->classes, ...$configFile->classes]; + } + $this->container->config($configFile); } } @@ -44,7 +49,7 @@ public function find(): array $configPaths = new MutableArray(); // Scan for config files in all discovery locations - foreach ($this->registry->locations as $discoveryLocation) { + foreach ($this->discoveryConfig->locations as $discoveryLocation) { $this->scan($discoveryLocation->path, $configPaths); } diff --git a/packages/discovery/src/LoadRegistry.php b/packages/discovery/src/AutoloadDiscoveryLocations.php similarity index 91% rename from packages/discovery/src/LoadRegistry.php rename to packages/discovery/src/AutoloadDiscoveryLocations.php index f988460a8f..f9ae96b3b4 100644 --- a/packages/discovery/src/LoadRegistry.php +++ b/packages/discovery/src/AutoloadDiscoveryLocations.php @@ -8,18 +8,14 @@ use function Tempest\Support\Path\normalize; -final readonly class LoadRegistry +final readonly class AutoloadDiscoveryLocations { private Composer $composer; - private Registry $registry; public function __construct( private string $rootPath, - ?Registry $registry = null, ?Composer $composer = null, ) { - $this->registry = $registry ?? new Registry(); - if (! $composer) { $composer = new Composer($rootPath); $composer->load(); @@ -28,16 +24,15 @@ public function __construct( $this->composer = $composer; } - public function __invoke(): Registry + /** @return \Tempest\Discovery\DiscoveryLocation[] */ + public function __invoke(?DiscoveryConfig $config = null): array { - $this->registry->locations = [ + return [ ...$this->discoverCorePackages(), ...$this->discoverVendorPackages(), ...$this->discoverAppNamespaces(), - ...$this->registry->locations, + ...($config->locations ?? []), ]; - - return $this->registry; } /** diff --git a/packages/discovery/src/BootDiscovery.php b/packages/discovery/src/BootDiscovery.php index 775f433a61..4e2c9d1ee0 100644 --- a/packages/discovery/src/BootDiscovery.php +++ b/packages/discovery/src/BootDiscovery.php @@ -17,8 +17,7 @@ final class BootDiscovery public function __construct( private readonly ContainerInterface $container, - private readonly Registry $registry, - private readonly DiscoveryConfig $config = new DiscoveryConfig(), + private readonly DiscoveryConfig $config, private readonly DiscoveryCache $cache = new DiscoveryCache(DiscoveryCacheStrategy::NONE), ) {} @@ -46,11 +45,11 @@ public function build( ?array $discoveryClasses = null, ?array $discoveryLocations = null, ): array { - $discoveryLocations ??= $this->registry->locations; + $discoveryLocations ??= $this->config->locations; if ($discoveryClasses === null) { // DiscoveryDiscovery needs to be applied before we can build all other discoveries - $discoveryDiscovery = new DiscoveryDiscovery($this->registry); + $discoveryDiscovery = new DiscoveryDiscovery($this->config); $discoveryDiscovery->setItems(new DiscoveryItems()); // The first pass over all directories to find all discovery classes @@ -62,7 +61,7 @@ public function build( // Resolve all other discoveries from the container, optionally loading their cache $discoveries = array_map( fn (string $discoveryClass) => $this->resolveDiscovery($discoveryClass), - $this->registry->classes, + $this->config->classes, ); // The second pass over all directories to apply all other discovery classes diff --git a/packages/discovery/src/DiscoveryConfig.php b/packages/discovery/src/DiscoveryConfig.php index b1fbb3ced5..7ffd77bc34 100644 --- a/packages/discovery/src/DiscoveryConfig.php +++ b/packages/discovery/src/DiscoveryConfig.php @@ -8,6 +8,21 @@ final class DiscoveryConfig { private array $skipDiscovery = []; + /** @var array> The loaded discovery classes that will be used during discovery */ + public array $classes = []; + + public function __construct( + /** @var \Tempest\Discovery\DiscoveryLocation[] Locations that should be scanned during discovery */ + public array $locations = [], + ) {} + + public static function autoload(string $path): self + { + return new self( + locations: (new AutoloadDiscoveryLocations($path))(), + ); + } + public function shouldSkip(string $input): bool { return $this->skipDiscovery[$input] ?? false; diff --git a/packages/discovery/src/DiscoveryDiscovery.php b/packages/discovery/src/DiscoveryDiscovery.php index ed77138bf6..0a60a238e5 100644 --- a/packages/discovery/src/DiscoveryDiscovery.php +++ b/packages/discovery/src/DiscoveryDiscovery.php @@ -11,7 +11,7 @@ final class DiscoveryDiscovery implements Discovery use IsDiscovery; public function __construct( - private readonly Registry $registry, + private readonly DiscoveryConfig $config, ) {} public function discover(DiscoveryLocation $location, ClassReflector $class): void @@ -30,7 +30,7 @@ public function discover(DiscoveryLocation $location, ClassReflector $class): vo public function apply(): void { foreach ($this->discoveryItems as $className) { - $this->registry->classes[] = $className; + $this->config->classes[] = $className; } } } diff --git a/packages/discovery/src/Registry.php b/packages/discovery/src/Registry.php deleted file mode 100644 index 059307b895..0000000000 --- a/packages/discovery/src/Registry.php +++ /dev/null @@ -1,19 +0,0 @@ -> */ - public array $classes = [], - ) {} - - public static function autoload(string $path): self - { - return (new LoadRegistry($path))(); - } -} diff --git a/packages/discovery/tests/DiscoveryTest.php b/packages/discovery/tests/DiscoveryTest.php index 9e46738bdd..1a424a6fbb 100644 --- a/packages/discovery/tests/DiscoveryTest.php +++ b/packages/discovery/tests/DiscoveryTest.php @@ -6,8 +6,8 @@ use PHPUnit\Framework\TestCase; use Tempest\Container\GenericContainer; use Tempest\Discovery\BootDiscovery; +use Tempest\Discovery\DiscoveryConfig; use Tempest\Discovery\DiscoveryLocation; -use Tempest\Discovery\Registry; use Tempest\Discovery\Tests\Fixtures\MyDiscoveryClass; final class DiscoveryTest extends TestCase @@ -25,7 +25,7 @@ public function test_standalone_discovery(): void (new BootDiscovery( container: $container, - registry: new Registry(locations: [ + config: new DiscoveryConfig(locations: [ new DiscoveryLocation( namespace: 'Tempest\Discovery\Tests\Fixtures', path: __DIR__ . '/Fixtures', @@ -43,7 +43,7 @@ public function test_discovery_with_other_container(): void (new BootDiscovery( container: $container, - registry: new Registry(locations: [ + config: new DiscoveryConfig(locations: [ new DiscoveryLocation( namespace: 'Tempest\Discovery\Tests\Fixtures', path: __DIR__ . '/Fixtures', diff --git a/packages/view/src/Initializers/TempestViewCompilerInitializer.php b/packages/view/src/Initializers/TempestViewCompilerInitializer.php index 2e9374fc6f..c43e6c65ff 100644 --- a/packages/view/src/Initializers/TempestViewCompilerInitializer.php +++ b/packages/view/src/Initializers/TempestViewCompilerInitializer.php @@ -5,7 +5,7 @@ use Tempest\Container\Container; use Tempest\Container\Initializer; use Tempest\Container\Singleton; -use Tempest\Discovery\Registry; +use Tempest\Discovery\DiscoveryConfig; use Tempest\View\Attributes\AttributeFactory; use Tempest\View\Elements\ElementFactory; use Tempest\View\Parser\TempestViewCompiler; @@ -18,7 +18,7 @@ public function initialize(Container $container): TempestViewCompiler return new TempestViewCompiler( elementFactory: $container->get(ElementFactory::class), attributeFactory: $container->get(AttributeFactory::class), - discoveryLocations: $container->get(Registry::class)->locations, + discoveryLocations: $container->get(DiscoveryConfig::class)->locations, ); } } diff --git a/tests/Benchmark/Discovery/DiscoveryScanBench.php b/tests/Benchmark/Discovery/DiscoveryScanBench.php index 9794b768c3..cc6b2102ee 100644 --- a/tests/Benchmark/Discovery/DiscoveryScanBench.php +++ b/tests/Benchmark/Discovery/DiscoveryScanBench.php @@ -17,7 +17,6 @@ use Tempest\Discovery\DiscoveryCacheStrategy; use Tempest\Discovery\DiscoveryConfig; use Tempest\Discovery\DiscoveryLocation; -use Tempest\Discovery\Registry; final class DiscoveryScanBench { @@ -31,24 +30,23 @@ final class DiscoveryScanBench private string $root; - private Registry $registry; + private DiscoveryConfig $discoveryConfig; public function __construct() { $this->root = dirname(__DIR__, 3); $kernel = FrameworkKernel::boot(root: $this->root); $this->container = $kernel->container; - $this->registry = $kernel->registry; - $this->discoveryLocations = $kernel->registry->locations; - $this->discoveryClasses = $kernel->registry->classes; + $this->discoveryConfig = $kernel->discoveryConfig; + $this->discoveryLocations = $kernel->discoveryConfig->locations; + $this->discoveryClasses = $kernel->discoveryConfig->classes; } private function createLoader(): BootDiscovery { return new BootDiscovery( container: $this->container, - registry: $this->registry, - config: new DiscoveryConfig(), + config: $this->discoveryConfig, cache: new DiscoveryCache(DiscoveryCacheStrategy::NONE), ); } diff --git a/tests/Integration/Core/Config/LoadConfigTest.php b/tests/Integration/Core/Config/LoadConfigTest.php index 0a469b5583..daab792768 100644 --- a/tests/Integration/Core/Config/LoadConfigTest.php +++ b/tests/Integration/Core/Config/LoadConfigTest.php @@ -25,7 +25,7 @@ protected function setUp(): void Filesystem\ensure_directory_empty(__DIR__ . '/Fixtures'); $this->container->get(ConfigCache::class)->clear(); - $this->kernel->registry->locations = [ + $this->kernel->discoveryConfig->locations = [ new DiscoveryLocation('App', __DIR__ . '/Fixtures'), ]; } diff --git a/tests/Integration/Core/KernelTest.php b/tests/Integration/Core/KernelTest.php index 657d715061..45680d2cfa 100644 --- a/tests/Integration/Core/KernelTest.php +++ b/tests/Integration/Core/KernelTest.php @@ -27,7 +27,7 @@ public function test_discovery_boot(): void $this->assertInstanceOf(Container::class, $kernel->container); - $this->assertNotEmpty($kernel->registry->classes); + $this->assertNotEmpty($kernel->discoveryConfig->classes); $test = $kernel->container->get(TestDependency::class); diff --git a/tests/Integration/Framework/Commands/DiscoveryStatusCommandTest.php b/tests/Integration/Framework/Commands/DiscoveryStatusCommandTest.php index b185a153cf..1db858feef 100644 --- a/tests/Integration/Framework/Commands/DiscoveryStatusCommandTest.php +++ b/tests/Integration/Framework/Commands/DiscoveryStatusCommandTest.php @@ -17,11 +17,11 @@ public function test_discovery_status_command(): void { $output = $this->console->call('discovery:status -cl'); - foreach ($this->kernel->registry->classes as $discoveryClass) { + foreach ($this->kernel->discoveryConfig->classes as $discoveryClass) { $output->assertContains(basename(str_replace('\\', '/', $discoveryClass))); } - foreach ($this->kernel->registry->locations as $discoveryLocation) { + foreach ($this->kernel->discoveryConfig->locations as $discoveryLocation) { // @TODO(aidan-casey): remove the src/ directory. $output->assertContains(str(realpath($discoveryLocation->path))->afterLast(['src/', 'packages/', 'vendor/', 'tests/'])->toString()); } diff --git a/tests/Integration/Http/Exceptions/ExceptionRendererTest.php b/tests/Integration/Http/Exceptions/ExceptionRendererTest.php index f6bfc22222..27b73b1f90 100644 --- a/tests/Integration/Http/Exceptions/ExceptionRendererTest.php +++ b/tests/Integration/Http/Exceptions/ExceptionRendererTest.php @@ -52,8 +52,8 @@ public function __construct(FrameworkKernel $kernel) { $this->root = $kernel->root; $this->internalStorage = $kernel->internalStorage; - $this->discoveryLocations = $kernel->registry->locations; - $this->discoveryClasses = $kernel->registry->classes; + $this->discoveryLocations = $kernel->discoveryConfig->locations; + $this->discoveryClasses = $kernel->discoveryConfig->classes; $this->container = $kernel->container; } diff --git a/tests/Integration/Http/Exceptions/HttpExceptionHandlerTest.php b/tests/Integration/Http/Exceptions/HttpExceptionHandlerTest.php index 2be6dfa8b3..7ad74cca00 100644 --- a/tests/Integration/Http/Exceptions/HttpExceptionHandlerTest.php +++ b/tests/Integration/Http/Exceptions/HttpExceptionHandlerTest.php @@ -48,8 +48,8 @@ public function __construct(FrameworkKernel $kernel) { $this->root = $kernel->root; $this->internalStorage = $kernel->internalStorage; - $this->discoveryLocations = $kernel->registry->locations; - $this->discoveryClasses = $kernel->registry->classes; + $this->discoveryLocations = $kernel->discoveryConfig->locations; + $this->discoveryClasses = $kernel->discoveryConfig->classes; $this->container = $kernel->container; } diff --git a/tests/Integration/View/TempestViewRendererTest.php b/tests/Integration/View/TempestViewRendererTest.php index a42db545fd..c0d5b6e5fb 100644 --- a/tests/Integration/View/TempestViewRendererTest.php +++ b/tests/Integration/View/TempestViewRendererTest.php @@ -4,8 +4,8 @@ namespace Tests\Tempest\Integration\View; +use Tempest\Discovery\DiscoveryConfig; use Tempest\Discovery\DiscoveryLocation; -use Tempest\Discovery\Registry; use Tempest\Support\Html\HtmlString; use Tempest\View\Exceptions\ElementWasInvalid; use Tempest\View\Exceptions\XmlDeclarationCouldNotBeParsed; @@ -947,9 +947,9 @@ public function test_zero_in_attribute(): void public function test_discovery_locations_are_passed_to_compiler(): void { - $registry = $this->get(Registry::class); + $discoveryConfig = $this->get(DiscoveryConfig::class); - $registry->locations[] = new DiscoveryLocation( + $discoveryConfig->locations[] = new DiscoveryLocation( 'Tests\Tempest\Integration\View\Fixtures', __DIR__ . '/Fixtures', ); From 16ffd0c2c96f07396c73cb5db714fdbc55d71108 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 13:36:49 +0100 Subject: [PATCH 40/43] WIP --- docs/1-essentials/05-discovery.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/1-essentials/05-discovery.md b/docs/1-essentials/05-discovery.md index 570d6bcb8e..77031b47a4 100644 --- a/docs/1-essentials/05-discovery.md +++ b/docs/1-essentials/05-discovery.md @@ -243,11 +243,11 @@ new BootDiscovery( )(); ``` -Whenever this action is run, discovery will find all discovery classes, and run them against all registry locations. +Whenever this action is run, discovery will find all discovery classes, and run them against all registered locations. ### Manually specify discovery locations -`DiscoveryConfig::autoload()` will scan a given root path and autmatically determine discovery locations by analyzing the composer.json file in that path. If you prefer another way of defining locations to scan, you can manually build a registry like so: +`DiscoveryConfig::autoload()` will scan a given root path and autmatically determine discovery locations by analyzing the composer.json file in that path. If you prefer another way of defining locations to scan, you can manually provide them via `DiscoveryConfig`: ```php use Tempest\Discovery\DiscoveryConfig; From 0bf1bfe1e1bb21094c43bed77246d322068caae6 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 13:41:51 +0100 Subject: [PATCH 41/43] WIP --- packages/core/src/FrameworkKernel.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index fbdb529efe..47e519bc1a 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -18,6 +18,7 @@ use Tempest\Discovery\DiscoveryCache; use Tempest\Discovery\DiscoveryCacheInitializer; use Tempest\Discovery\DiscoveryConfig; +use Tempest\Discovery\DiscoveryLocation; use Tempest\EventBus\EventBus; use Tempest\Process\GenericProcessExecutor; use Tempest\Support\Filesystem; @@ -32,6 +33,9 @@ final class FrameworkKernel implements Kernel public DiscoveryConfig $discoveryConfig; + /** @var DiscoveryLocation[] */ + private array $discoveryLocations; + public function __construct( public string $root, /** @var \Tempest\Discovery\DiscoveryLocation[] $discoveryLocations */ @@ -40,7 +44,7 @@ public function __construct( ?string $internalStorage = null, ) { $this->container = $container ?? $this->createContainer(); - // $this->registry = new Registry(locations: $discoveryLocations); + $this->discoveryLocations = $discoveryLocations; if ($internalStorage !== null) { $this->internalStorage = $internalStorage; @@ -164,10 +168,13 @@ public function loadDiscoveryConfig(): self /** @var DiscoveryConfig $discoveryConfig */ $discoveryConfig = $this->container->get(DiscoveryConfig::class); - $discoveryConfig->locations = (new AutoloadDiscoveryLocations( - rootPath: $this->root, - composer: $this->container->get(Composer::class), - ))($discoveryConfig); + $discoveryConfig->locations = [ + ...$this->discoveryLocations, + ...(new AutoloadDiscoveryLocations( + rootPath: $this->root, + composer: $this->container->get(Composer::class), + ))($discoveryConfig), + ]; $this->container->config($discoveryConfig); $this->discoveryConfig = $discoveryConfig; From 87f754f8bb3fa0209a584b658ad8392b90b16b5e Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 14:15:33 +0100 Subject: [PATCH 42/43] WIP --- packages/core/src/FrameworkKernel.php | 4 ++-- packages/discovery/src/AutoloadDiscoveryLocations.php | 3 +-- tests/Integration/Core/Config/LoadConfigTest.php | 5 +++-- tests/Integration/Core/KernelTest.php | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index 47e519bc1a..cf9df38eab 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -170,10 +170,10 @@ public function loadDiscoveryConfig(): self $discoveryConfig->locations = [ ...$this->discoveryLocations, - ...(new AutoloadDiscoveryLocations( + ...new AutoloadDiscoveryLocations( rootPath: $this->root, composer: $this->container->get(Composer::class), - ))($discoveryConfig), + )(), ]; $this->container->config($discoveryConfig); diff --git a/packages/discovery/src/AutoloadDiscoveryLocations.php b/packages/discovery/src/AutoloadDiscoveryLocations.php index f9ae96b3b4..711b71d483 100644 --- a/packages/discovery/src/AutoloadDiscoveryLocations.php +++ b/packages/discovery/src/AutoloadDiscoveryLocations.php @@ -25,13 +25,12 @@ public function __construct( } /** @return \Tempest\Discovery\DiscoveryLocation[] */ - public function __invoke(?DiscoveryConfig $config = null): array + public function __invoke(): array { return [ ...$this->discoverCorePackages(), ...$this->discoverVendorPackages(), ...$this->discoverAppNamespaces(), - ...($config->locations ?? []), ]; } diff --git a/tests/Integration/Core/Config/LoadConfigTest.php b/tests/Integration/Core/Config/LoadConfigTest.php index daab792768..8fadc32194 100644 --- a/tests/Integration/Core/Config/LoadConfigTest.php +++ b/tests/Integration/Core/Config/LoadConfigTest.php @@ -5,6 +5,7 @@ use Tempest\Core\ConfigCache; use Tempest\Core\Environment; use Tempest\Core\Kernel\LoadConfig; +use Tempest\Discovery\DiscoveryConfig; use Tempest\Discovery\DiscoveryLocation; use Tempest\Support\Filesystem; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; @@ -25,9 +26,9 @@ protected function setUp(): void Filesystem\ensure_directory_empty(__DIR__ . '/Fixtures'); $this->container->get(ConfigCache::class)->clear(); - $this->kernel->discoveryConfig->locations = [ + $this->container->singleton(DiscoveryConfig::class, new DiscoveryConfig(locations: [ new DiscoveryLocation('App', __DIR__ . '/Fixtures'), - ]; + ])); } public function test_config_loaded_in_order(): void diff --git a/tests/Integration/Core/KernelTest.php b/tests/Integration/Core/KernelTest.php index 45680d2cfa..4f67f39953 100644 --- a/tests/Integration/Core/KernelTest.php +++ b/tests/Integration/Core/KernelTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\TestCase; use Tempest\Container\Container; use Tempest\Core\FrameworkKernel; +use Tempest\Discovery\DiscoveryConfig; use Tempest\Discovery\DiscoveryLocation; use Tests\Tempest\Fixtures\TestDependency; @@ -25,9 +26,8 @@ public function test_discovery_boot(): void ], ); - $this->assertInstanceOf(Container::class, $kernel->container); - - $this->assertNotEmpty($kernel->discoveryConfig->classes); + $discoveryConfig = $kernel->container->get(DiscoveryConfig::class); + $this->assertNotEmpty($discoveryConfig->classes); $test = $kernel->container->get(TestDependency::class); From 72fe86ae3fd2bc699fc3b421510afac6c52327e0 Mon Sep 17 00:00:00 2001 From: brendt Date: Thu, 12 Mar 2026 14:18:15 +0100 Subject: [PATCH 43/43] wip --- packages/core/src/FrameworkKernel.php | 4 ++-- tests/Integration/Core/KernelTest.php | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index cf9df38eab..5f027a67a8 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -170,10 +170,10 @@ public function loadDiscoveryConfig(): self $discoveryConfig->locations = [ ...$this->discoveryLocations, - ...new AutoloadDiscoveryLocations( + ...(new AutoloadDiscoveryLocations( rootPath: $this->root, composer: $this->container->get(Composer::class), - )(), + ))(), ]; $this->container->config($discoveryConfig); diff --git a/tests/Integration/Core/KernelTest.php b/tests/Integration/Core/KernelTest.php index 4f67f39953..14ab1da4ef 100644 --- a/tests/Integration/Core/KernelTest.php +++ b/tests/Integration/Core/KernelTest.php @@ -5,7 +5,6 @@ namespace Tests\Tempest\Integration\Core; use PHPUnit\Framework\TestCase; -use Tempest\Container\Container; use Tempest\Core\FrameworkKernel; use Tempest\Discovery\DiscoveryConfig; use Tempest\Discovery\DiscoveryLocation;