From f13c6a929e0025878391e5de4fed90a9d279d2ca Mon Sep 17 00:00:00 2001 From: Charles Sprayberry Date: Sun, 16 Mar 2025 04:31:44 -0400 Subject: [PATCH 1/5] Initial skeleton for supporting configured listeners --- annotated-container.xsd | 6 ++++++ src/Bootstrap/Bootstrap.php | 6 +++++- src/Bootstrap/BootstrappingConfiguration.php | 6 ++++++ .../CacheAwareBootstrappingConfiguration.php | 4 ++++ src/Bootstrap/DefaultListenerFactory.php | 12 ++++++++++++ src/Bootstrap/ListenerFactory.php | 11 +++++++++++ .../XmlBootstrappingConfiguration.php | 11 ++++++++++- .../XmlBootstrappingConfigurationTest.php | 18 +++++++++++++++--- 8 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 src/Bootstrap/DefaultListenerFactory.php create mode 100644 src/Bootstrap/ListenerFactory.php diff --git a/annotated-container.xsd b/annotated-container.xsd index 38949d9b..fb71fdf1 100644 --- a/annotated-container.xsd +++ b/annotated-container.xsd @@ -32,6 +32,7 @@ + @@ -86,5 +87,10 @@ + + + + + \ No newline at end of file diff --git a/src/Bootstrap/Bootstrap.php b/src/Bootstrap/Bootstrap.php index beffab3b..986efe66 100644 --- a/src/Bootstrap/Bootstrap.php +++ b/src/Bootstrap/Bootstrap.php @@ -33,6 +33,7 @@ public static function fromAnnotatedContainerConventions( ContainerFactory $containerFactory, Emitter $emitter, ParameterStoreFactory $parameterStoreFactory = new DefaultParameterStoreFactory(), + ListenerFactory $listenerFactory = new DefaultListenerFactory(), DefinitionProviderFactory $definitionProviderFactory = new DefaultDefinitionProviderFactory(), BootstrappingDirectoryResolver $directoryResolver = new VendorPresenceBasedBootstrappingDirectoryResolver(), Filesystem $filesystem = new PhpFunctionsFilesystem() @@ -41,7 +42,8 @@ public static function fromAnnotatedContainerConventions( $filesystem, $directoryResolver->configurationPath('annotated-container.xml'), $parameterStoreFactory, - $definitionProviderFactory + $definitionProviderFactory, + $listenerFactory ); return self::fromCompleteSetup( @@ -75,6 +77,8 @@ public function bootstrapContainer( $this->stopwatch->start(); + // add listeners from bootstrapping configuration to emitter + $analysisOptions = $this->analysisOptions($this->bootstrappingConfiguration); $this->emitter->emitBeforeBootstrap($this->bootstrappingConfiguration); diff --git a/src/Bootstrap/BootstrappingConfiguration.php b/src/Bootstrap/BootstrappingConfiguration.php index d2bc6830..5ac44edb 100644 --- a/src/Bootstrap/BootstrappingConfiguration.php +++ b/src/Bootstrap/BootstrappingConfiguration.php @@ -4,6 +4,7 @@ use Cspray\AnnotatedContainer\ArchitecturalDecisionRecords\SingleEntrypointDefinitionProvider; use Cspray\AnnotatedContainer\Definition\Cache\ContainerDefinitionCache; +use Cspray\AnnotatedContainer\Event\Listener; use Cspray\AnnotatedContainer\StaticAnalysis\DefinitionProvider; use Cspray\AnnotatedContainer\ContainerFactory\ParameterStore; @@ -23,4 +24,9 @@ public function containerDefinitionProvider() : ?DefinitionProvider; * @return list */ public function parameterStores() : array; + + /** + * @return list + */ + public function listeners() : array; } diff --git a/src/Bootstrap/CacheAwareBootstrappingConfiguration.php b/src/Bootstrap/CacheAwareBootstrappingConfiguration.php index d1ba5a59..94424f94 100644 --- a/src/Bootstrap/CacheAwareBootstrappingConfiguration.php +++ b/src/Bootstrap/CacheAwareBootstrappingConfiguration.php @@ -30,4 +30,8 @@ public function containerDefinitionProvider() : ?DefinitionProvider { public function parameterStores() : array { return $this->configuration->parameterStores(); } + + public function listeners() : array { + // TODO: Implement listeners() method. + } } diff --git a/src/Bootstrap/DefaultListenerFactory.php b/src/Bootstrap/DefaultListenerFactory.php new file mode 100644 index 00000000..445cabe4 --- /dev/null +++ b/src/Bootstrap/DefaultListenerFactory.php @@ -0,0 +1,12 @@ +filesystem->isFile($this->xmlFile)) { throw InvalidBootstrapConfiguration::fromFileMissing($this->xmlFile); @@ -142,6 +144,13 @@ public function parameterStores() : array { return $this->parameterStores; } + /** + * @return list + */ + public function listeners() : array { + // TODO: Implement listeners() method. + } + public function cache() : ?ContainerDefinitionCache { return null; } diff --git a/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php b/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php index 965d62be..4754a57d 100644 --- a/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php +++ b/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php @@ -3,6 +3,7 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; use Cspray\AnnotatedContainer\Bootstrap\DefaultDefinitionProviderFactory; +use Cspray\AnnotatedContainer\Bootstrap\DefaultListenerFactory; use Cspray\AnnotatedContainer\Bootstrap\DefaultParameterStoreFactory; use Cspray\AnnotatedContainer\Bootstrap\DefinitionProviderFactory; use Cspray\AnnotatedContainer\Bootstrap\ParameterStoreFactory; @@ -64,6 +65,7 @@ public function testXmlDoesNotValidateSchemaThrowsError() : void { '/my/path/to/annotated-container.xml', new DefaultParameterStoreFactory(), new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() ); } @@ -91,6 +93,7 @@ public function testValidXmlReturnsScanDirectories() : void { '/path/to/annotated-container.xml', new DefaultParameterStoreFactory(), new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() ); self::assertSame( @@ -124,6 +127,7 @@ public function testValidXmlReturnsDefinitionProvider() : void { '/path/annotated-container.xml', new DefaultParameterStoreFactory(), new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() ); $provider = $configuration->containerDefinitionProvider(); self::assertInstanceOf( @@ -158,6 +162,7 @@ public function testDefinitionProviderEmptyIfNoneDefined() : void { 'annotated-container.xml', new DefaultParameterStoreFactory(), new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() ); self::assertNull($config->containerDefinitionProvider()); @@ -182,6 +187,7 @@ public function testCacheDirNotSpecifiedReturnsNull() : void { 'annotated-container.xml', new DefaultParameterStoreFactory(), new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() ); self::assertNull($config->cache()); } @@ -205,6 +211,7 @@ public function testCacheIsAlwaysNull() : void { 'annotated-container.xml', new DefaultParameterStoreFactory(), new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() ); self::assertNull($config->cache()); @@ -232,6 +239,7 @@ public function testParameterStoresReturned() : void { 'annotated-container.xml', new DefaultParameterStoreFactory(), new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() ); self::assertCount(1, $config->parameterStores()); @@ -271,6 +279,7 @@ public function createParameterStore(string $identifier) : ParameterStore { 'annotated-container.xml', $parameterStoreFactory, new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() ); self::assertCount(1, $config->parameterStores()); @@ -304,7 +313,8 @@ public function createProvider(string $identifier) : DefinitionProvider { $this->filesystem, 'annotated-container.xml', new DefaultParameterStoreFactory(), - $consumerFactory + $consumerFactory, + new DefaultListenerFactory() ); $provider = $config->containerDefinitionProvider(); @@ -347,7 +357,8 @@ public function testVendorScanDirectoriesIncludedInList() : void { $this->filesystem, 'annotated-container.xml', new DefaultParameterStoreFactory(), - new DefaultDefinitionProviderFactory() + new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() ); self::assertSame( @@ -369,7 +380,8 @@ public function testConfigurationFileNotPresentThrowsException() : void { $this->filesystem, 'annotated-container.xml', new DefaultParameterStoreFactory(), - new DefaultDefinitionProviderFactory() + new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() ); } } From f65a4e2eb4572cb1f525b553dc0bd0f25165a8ab Mon Sep 17 00:00:00 2001 From: Charles Sprayberry Date: Sun, 16 Mar 2025 04:44:37 -0400 Subject: [PATCH 2/5] Organize bootstrap code into better sub-namespaces --- docs/how-to/02-bootstrap-your-container.md | 9 ++------- src/Bootstrap/Bootstrap.php | 11 ++++++++++ .../BootstrappingConfiguration.php | 7 +++---- .../CacheAwareBootstrappingConfiguration.php | 2 +- ...sOptionsFromBootstrappingConfiguration.php | 3 ++- .../DefaultDefinitionProviderFactory.php | 2 +- .../DefaultListenerFactory.php | 2 +- .../DefaultParameterStoreFactory.php | 2 +- .../DefinitionProviderFactory.php | 2 +- .../DelegatedParameterStoreFactory.php | 2 +- .../{ => Configuration}/ListenerFactory.php | 2 +- .../ParameterStoreFactory.php | 2 +- .../XmlBootstrappingConfiguration.php | 16 +++++++-------- .../BootstrappingDirectoryResolver.php | 2 +- ...nScanningThirdPartyInitializerProvider.php | 5 ++++- ...irectoryBootstrappingDirectoryResolver.php | 2 +- ...nceBasedBootstrappingDirectoryResolver.php | 2 +- ...untimePackagesComposerJsonPathProvider.php | 2 +- .../PackagesComposerJsonPathProvider.php | 2 +- .../ThirdPartyInitializer.php | 2 +- .../ThirdPartyInitializerProvider.php | 4 ++-- .../ServiceFromServiceDefinition.php | 2 +- .../{ => Listener}/ServiceGatherer.php | 6 +++--- .../{ => Listener}/ServiceWiringListener.php | 6 +++--- src/Cli/AnnotatedContainerCliRunner.php | 20 +++++++++---------- src/Cli/Command/InitCommand.php | 4 ++-- src/Cli/Command/ValidateCommand.php | 6 +++--- src/Event/BootstrapEmitter.php | 2 +- src/Event/Emitter.php | 2 +- .../Listener/Bootstrap/AfterBootstrap.php | 2 +- .../Listener/Bootstrap/BeforeBootstrap.php | 2 +- .../InvalidThirdPartyInitializer.php | 3 +-- .../package/other_src/ThirdInitializer.php | 2 +- .../cspray/package/src/FirstInitializer.php | 2 +- .../cspray/package/src/SecondInitializer.php | 2 +- test/Unit/Bootstrap/BootstrapTest.php | 18 ++++++++--------- ...cheAwareBootstrappingConfigurationTest.php | 4 ++-- ...nningThirdPartyInitializerProviderTest.php | 7 +++---- ...mePackagesComposerJsonPathProviderTest.php | 2 +- .../DefaultDefinitionProviderFactoryTest.php | 2 +- .../DefaultParameterStoreFactoryTest.php | 2 +- .../DelegatedParameterStoreFactoryTest.php | 4 ++-- ...toryBootstrappingDirectoryResolverTest.php | 2 +- ...asedBootstrappingDirectoryResolverTest.php | 2 +- .../XmlBootstrappingConfigurationTest.php | 16 +++++++-------- .../Cli/AnnotatedContainerCliRunnerTest.php | 18 ++++++++--------- test/Unit/Cli/Command/InitCommandTest.php | 6 +++--- test/Unit/Cli/Command/ValidateCommandTest.php | 6 +++--- test/Unit/Event/EmitterTest.php | 2 +- .../FixtureBootstrappingDirectoryResolver.php | 2 +- test/Unit/Helper/StubBootstrapListener.php | 2 +- 51 files changed, 121 insertions(+), 118 deletions(-) rename src/Bootstrap/{ => Configuration}/BootstrappingConfiguration.php (80%) rename src/Bootstrap/{ => Configuration}/CacheAwareBootstrappingConfiguration.php (94%) rename src/Bootstrap/{ => Configuration}/ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration.php (88%) rename src/Bootstrap/{ => Configuration}/DefaultDefinitionProviderFactory.php (91%) rename src/Bootstrap/{ => Configuration}/DefaultListenerFactory.php (81%) rename src/Bootstrap/{ => Configuration}/DefaultParameterStoreFactory.php (92%) rename src/Bootstrap/{ => Configuration}/DefinitionProviderFactory.php (78%) rename src/Bootstrap/{ => Configuration}/DelegatedParameterStoreFactory.php (93%) rename src/Bootstrap/{ => Configuration}/ListenerFactory.php (74%) rename src/Bootstrap/{ => Configuration}/ParameterStoreFactory.php (84%) rename src/Bootstrap/{ => Configuration}/XmlBootstrappingConfiguration.php (95%) rename src/Bootstrap/{ => DirectoryResolver}/BootstrappingDirectoryResolver.php (76%) rename src/Bootstrap/{ => DirectoryResolver}/ComposerJsonScanningThirdPartyInitializerProvider.php (90%) rename src/Bootstrap/{ => DirectoryResolver}/RootDirectoryBootstrappingDirectoryResolver.php (88%) rename src/Bootstrap/{ => DirectoryResolver}/VendorPresenceBasedBootstrappingDirectoryResolver.php (93%) rename src/Bootstrap/{ => Initializer}/ComposerRuntimePackagesComposerJsonPathProvider.php (93%) rename src/Bootstrap/{ => Initializer}/PackagesComposerJsonPathProvider.php (75%) rename src/Bootstrap/{ => Initializer}/ThirdPartyInitializer.php (86%) rename src/Bootstrap/{ => Initializer}/ThirdPartyInitializerProvider.php (60%) rename src/Bootstrap/{ => Listener}/ServiceFromServiceDefinition.php (84%) rename src/Bootstrap/{ => Listener}/ServiceGatherer.php (69%) rename src/Bootstrap/{ => Listener}/ServiceWiringListener.php (95%) diff --git a/docs/how-to/02-bootstrap-your-container.md b/docs/how-to/02-bootstrap-your-container.md index 45e29a57..a6fd2892 100644 --- a/docs/how-to/02-bootstrap-your-container.md +++ b/docs/how-to/02-bootstrap-your-container.md @@ -224,7 +224,7 @@ By default, boostrapping expects all the path fragments in your configuration to namespace Acme\Demo; -use Cspray\AnnotatedContainer\Bootstrap\Bootstrap;use Cspray\AnnotatedContainer\Bootstrap\DefaultDefinitionProviderFactory;use Cspray\AnnotatedContainer\Bootstrap\DefaultParameterStoreFactory;use Cspray\AnnotatedContainer\ContainerFactory\PhpDiContainerFactory;use Cspray\AnnotatedContainer\Event\Emitter; +use Cspray\AnnotatedContainer\Bootstrap\Bootstrap;use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultDefinitionProviderFactory;use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultParameterStoreFactory;use Cspray\AnnotatedContainer\ContainerFactory\PhpDiContainerFactory;use Cspray\AnnotatedContainer\Event\Emitter; // This method is an implementation provided by the reader $directoryResolver = MyDirectoryResolver::create(); @@ -252,12 +252,7 @@ Setting up caching is something that you must explicitly opt into during your bo namespace Acme\Demo; -use Cspray\AnnotatedContainer\Bootstrap\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\CacheAwareBootstrappingConfigurationProvider; -use Cspray\AnnotatedContainer\Bootstrap\DefaultDefinitionProviderFactory; -use Cspray\AnnotatedContainer\Bootstrap\DefaultParameterStoreFactory; -use Cspray\AnnotatedContainer\Bootstrap\XmlBootstrappingConfigurationProvider;use Cspray\AnnotatedContainer\ContainerFactory\PhpDiContainerFactory; -use Cspray\AnnotatedContainer\Definition\Cache\FileBackedContainerDefinitionCache;use Cspray\AnnotatedContainer\Definition\Serializer\XmlContainerDefinitionSerializer;use Cspray\AnnotatedContainer\Event\Emitter; +use Cspray\AnnotatedContainer\Bootstrap\Bootstrap;use Cspray\AnnotatedContainer\Bootstrap\CacheAwareBootstrappingConfigurationProvider;use Cspray\AnnotatedContainer\Bootstrap\XmlBootstrappingConfigurationProvider;use Cspray\AnnotatedContainer\Definition\Cache\FileBackedContainerDefinitionCache;use Cspray\AnnotatedContainer\Definition\Serializer\XmlContainerDefinitionSerializer;use Cspray\AnnotatedContainer\Event\Emitter; $container = Bootstrap::from(new Emitter()) ->bootstrapContainer( diff --git a/src/Bootstrap/Bootstrap.php b/src/Bootstrap/Bootstrap.php index 986efe66..d93666dd 100644 --- a/src/Bootstrap/Bootstrap.php +++ b/src/Bootstrap/Bootstrap.php @@ -3,6 +3,17 @@ namespace Cspray\AnnotatedContainer\Bootstrap; use Cspray\AnnotatedContainer\AnnotatedContainer; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultDefinitionProviderFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultListenerFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultParameterStoreFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefinitionProviderFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\ListenerFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\ParameterStoreFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\XmlBootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\BootstrappingDirectoryResolver; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\VendorPresenceBasedBootstrappingDirectoryResolver; use Cspray\AnnotatedContainer\ContainerFactory\ContainerFactory; use Cspray\AnnotatedContainer\ContainerFactory\ContainerFactoryOptionsBuilder; use Cspray\AnnotatedContainer\Definition\ContainerDefinition; diff --git a/src/Bootstrap/BootstrappingConfiguration.php b/src/Bootstrap/Configuration/BootstrappingConfiguration.php similarity index 80% rename from src/Bootstrap/BootstrappingConfiguration.php rename to src/Bootstrap/Configuration/BootstrappingConfiguration.php index 5ac44edb..c4ce01e4 100644 --- a/src/Bootstrap/BootstrappingConfiguration.php +++ b/src/Bootstrap/Configuration/BootstrappingConfiguration.php @@ -1,12 +1,11 @@ + * @return Listener */ public function parameterStores() : array; /** - * @return list + * @return Listener */ public function listeners() : array; } diff --git a/src/Bootstrap/CacheAwareBootstrappingConfiguration.php b/src/Bootstrap/Configuration/CacheAwareBootstrappingConfiguration.php similarity index 94% rename from src/Bootstrap/CacheAwareBootstrappingConfiguration.php rename to src/Bootstrap/Configuration/CacheAwareBootstrappingConfiguration.php index 94424f94..087fe19e 100644 --- a/src/Bootstrap/CacheAwareBootstrappingConfiguration.php +++ b/src/Bootstrap/Configuration/CacheAwareBootstrappingConfiguration.php @@ -1,6 +1,6 @@ + * @var Listener */ private readonly array $parameterStores; @@ -42,7 +40,7 @@ public function __construct( } try { - $schemaFile = dirname(__DIR__, 2) . '/annotated-container.xsd'; + $schemaFile = dirname(__DIR__, 3) . '/annotated-container.xsd'; $dom = new DOMDocument(); $dom->loadXML($this->filesystem->read($this->xmlFile)); libxml_use_internal_errors(true); @@ -138,14 +136,14 @@ public function containerDefinitionProvider() : ?DefinitionProvider { } /** - * @return list + * @return Listener */ public function parameterStores() : array { return $this->parameterStores; } /** - * @return list + * @return Listener */ public function listeners() : array { // TODO: Implement listeners() method. diff --git a/src/Bootstrap/BootstrappingDirectoryResolver.php b/src/Bootstrap/DirectoryResolver/BootstrappingDirectoryResolver.php similarity index 76% rename from src/Bootstrap/BootstrappingDirectoryResolver.php rename to src/Bootstrap/DirectoryResolver/BootstrappingDirectoryResolver.php index 9703bcc9..5edefce7 100644 --- a/src/Bootstrap/BootstrappingDirectoryResolver.php +++ b/src/Bootstrap/DirectoryResolver/BootstrappingDirectoryResolver.php @@ -1,6 +1,6 @@ + * @return ThirdPartyInitializer */ public function thirdPartyInitializers() : array; } diff --git a/src/Bootstrap/ServiceFromServiceDefinition.php b/src/Bootstrap/Listener/ServiceFromServiceDefinition.php similarity index 84% rename from src/Bootstrap/ServiceFromServiceDefinition.php rename to src/Bootstrap/Listener/ServiceFromServiceDefinition.php index 842725cf..5d5706a5 100644 --- a/src/Bootstrap/ServiceFromServiceDefinition.php +++ b/src/Bootstrap/Listener/ServiceFromServiceDefinition.php @@ -1,6 +1,6 @@ $type - * @return list> + * @return ServiceFromServiceDefinition */ public function servicesForType(string $type) : array; /** * @template T * @param class-string $attributeType - * @return list + * @return ServiceFromServiceDefinition */ public function servicesWithAttribute(string $attributeType) : array; } diff --git a/src/Bootstrap/ServiceWiringListener.php b/src/Bootstrap/Listener/ServiceWiringListener.php similarity index 95% rename from src/Bootstrap/ServiceWiringListener.php rename to src/Bootstrap/Listener/ServiceWiringListener.php index e4bc88e7..99981689 100644 --- a/src/Bootstrap/ServiceWiringListener.php +++ b/src/Bootstrap/Listener/ServiceWiringListener.php @@ -1,6 +1,6 @@ $type - * @return list> + * @return ServiceFromServiceDefinition */ public function servicesForType(string $type) : array { - /** @var list> $services */ + /** @var ServiceFromServiceDefinition $services */ $services = []; foreach ($this->containerDefinition->serviceDefinitions() as $serviceDefinition) { if ($serviceDefinition->isAbstract()) { diff --git a/src/Cli/AnnotatedContainerCliRunner.php b/src/Cli/AnnotatedContainerCliRunner.php index e59f5dae..4d38f39a 100644 --- a/src/Cli/AnnotatedContainerCliRunner.php +++ b/src/Cli/AnnotatedContainerCliRunner.php @@ -2,14 +2,14 @@ namespace Cspray\AnnotatedContainer\Cli; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingConfiguration; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingDirectoryResolver; -use Cspray\AnnotatedContainer\Bootstrap\ComposerJsonScanningThirdPartyInitializerProvider; -use Cspray\AnnotatedContainer\Bootstrap\ComposerRuntimePackagesComposerJsonPathProvider; -use Cspray\AnnotatedContainer\Bootstrap\ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration; -use Cspray\AnnotatedContainer\Bootstrap\PackagesComposerJsonPathProvider; -use Cspray\AnnotatedContainer\Bootstrap\ThirdPartyInitializerProvider; -use Cspray\AnnotatedContainer\Bootstrap\VendorPresenceBasedBootstrappingDirectoryResolver; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\BootstrappingDirectoryResolver; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\ComposerJsonScanningThirdPartyInitializerProvider; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\VendorPresenceBasedBootstrappingDirectoryResolver; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ComposerRuntimePackagesComposerJsonPathProvider; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\PackagesComposerJsonPathProvider; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ThirdPartyInitializerProvider; use Cspray\AnnotatedContainer\Cli\Command\BuildCommand; use Cspray\AnnotatedContainer\Cli\Command\CacheClearCommand; use Cspray\AnnotatedContainer\Cli\Command\Command; @@ -85,7 +85,7 @@ private static function disabledConfigRequiredCommand(string $commandName) : Dis $howToEnable = wordwrap(sprintf( 'A %s object must be provided. This can be accomplished by running the "init" command.', BootstrappingConfiguration::class - )); + ), 80); assert($howToEnable !== ''); return new DisabledCommand($commandName, $howToEnable); } @@ -97,7 +97,7 @@ private static function disabledCacheRequiredCommand(string $commandName) : Disa $configClass = BootstrappingConfiguration::class; $howToEnable = "A $configClass object with a cache() method that returns a non-null value. For more information, " . "read /docs/how-to/03-caching-container-definition.md."; - $howToEnable = wordwrap($howToEnable); + $howToEnable = wordwrap($howToEnable, 80); assert($howToEnable !== ''); return new DisabledCommand($commandName, $howToEnable); } diff --git a/src/Cli/Command/InitCommand.php b/src/Cli/Command/InitCommand.php index 7f0104f2..f11621c5 100644 --- a/src/Cli/Command/InitCommand.php +++ b/src/Cli/Command/InitCommand.php @@ -3,8 +3,8 @@ namespace Cspray\AnnotatedContainer\Cli\Command; use Cspray\AnnotatedContainer\AnnotatedContainerVersion; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingDirectoryResolver; -use Cspray\AnnotatedContainer\Bootstrap\ThirdPartyInitializerProvider; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\BootstrappingDirectoryResolver; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ThirdPartyInitializerProvider; use Cspray\AnnotatedContainer\Cli\Exception\ComposerConfigurationNotFound; use Cspray\AnnotatedContainer\Cli\Exception\InvalidOptionType; use Cspray\AnnotatedContainer\Cli\Exception\PotentialConfigurationOverwrite; diff --git a/src/Cli/Command/ValidateCommand.php b/src/Cli/Command/ValidateCommand.php index 97261ea9..afc93cf2 100644 --- a/src/Cli/Command/ValidateCommand.php +++ b/src/Cli/Command/ValidateCommand.php @@ -2,9 +2,9 @@ namespace Cspray\AnnotatedContainer\Cli\Command; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingConfiguration; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingDirectoryResolver; -use Cspray\AnnotatedContainer\Bootstrap\ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\BootstrappingDirectoryResolver; use Cspray\AnnotatedContainer\Cli\Exception\ProfileNotString; use Cspray\AnnotatedContainer\Cli\Input\Input; use Cspray\AnnotatedContainer\Cli\Output\TerminalOutput; diff --git a/src/Event/BootstrapEmitter.php b/src/Event/BootstrapEmitter.php index f6b6e38e..4ad9c689 100644 --- a/src/Event/BootstrapEmitter.php +++ b/src/Event/BootstrapEmitter.php @@ -3,7 +3,7 @@ namespace Cspray\AnnotatedContainer\Event; use Cspray\AnnotatedContainer\AnnotatedContainer; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; use Cspray\AnnotatedContainer\Bootstrap\ContainerAnalytics; use Cspray\AnnotatedContainer\Definition\ContainerDefinition; diff --git a/src/Event/Emitter.php b/src/Event/Emitter.php index 966b880a..74a66272 100644 --- a/src/Event/Emitter.php +++ b/src/Event/Emitter.php @@ -3,7 +3,7 @@ namespace Cspray\AnnotatedContainer\Event; use Cspray\AnnotatedContainer\AnnotatedContainer; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; use Cspray\AnnotatedContainer\Bootstrap\ContainerAnalytics; use Cspray\AnnotatedContainer\ContainerFactory\AliasResolution\AliasResolutionReason; use Cspray\AnnotatedContainer\Definition\AliasDefinition; diff --git a/src/Event/Listener/Bootstrap/AfterBootstrap.php b/src/Event/Listener/Bootstrap/AfterBootstrap.php index 962cc0bf..95dabfc0 100644 --- a/src/Event/Listener/Bootstrap/AfterBootstrap.php +++ b/src/Event/Listener/Bootstrap/AfterBootstrap.php @@ -3,7 +3,7 @@ namespace Cspray\AnnotatedContainer\Event\Listener\Bootstrap; use Cspray\AnnotatedContainer\AnnotatedContainer; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; use Cspray\AnnotatedContainer\Bootstrap\ContainerAnalytics; use Cspray\AnnotatedContainer\Definition\ContainerDefinition; use Cspray\AnnotatedContainer\Event\Listener; diff --git a/src/Event/Listener/Bootstrap/BeforeBootstrap.php b/src/Event/Listener/Bootstrap/BeforeBootstrap.php index 6cb1058e..129db1c0 100644 --- a/src/Event/Listener/Bootstrap/BeforeBootstrap.php +++ b/src/Event/Listener/Bootstrap/BeforeBootstrap.php @@ -2,7 +2,7 @@ namespace Cspray\AnnotatedContainer\Event\Listener\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; use Cspray\AnnotatedContainer\Event\Listener; interface BeforeBootstrap extends Listener { diff --git a/src/Exception/InvalidThirdPartyInitializer.php b/src/Exception/InvalidThirdPartyInitializer.php index 8130300f..7bb734b9 100644 --- a/src/Exception/InvalidThirdPartyInitializer.php +++ b/src/Exception/InvalidThirdPartyInitializer.php @@ -2,8 +2,7 @@ namespace Cspray\AnnotatedContainer\Exception; -use Cspray\AnnotatedContainer\Bootstrap\ThirdPartyInitializer; -use Cspray\AnnotatedContainer\Bootstrap\ThirdPartyInitializerProvider; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ThirdPartyInitializer; final class InvalidThirdPartyInitializer extends Exception { diff --git a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/other_src/ThirdInitializer.php b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/other_src/ThirdInitializer.php index 49029ecc..c13cb002 100644 --- a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/other_src/ThirdInitializer.php +++ b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/other_src/ThirdInitializer.php @@ -2,7 +2,7 @@ namespace Cspray\AnnotatedContainer\Fixture\VendorScanningInitializers\Vendor\Package; -use Cspray\AnnotatedContainer\Bootstrap\ThirdPartyInitializer; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ThirdPartyInitializer; class ThirdInitializer extends ThirdPartyInitializer { diff --git a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/FirstInitializer.php b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/FirstInitializer.php index 319a3e6f..28508b90 100644 --- a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/FirstInitializer.php +++ b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/FirstInitializer.php @@ -2,7 +2,7 @@ namespace Cspray\AnnotatedContainer\Fixture\VendorScanningInitializers\Vendor\Package; -use Cspray\AnnotatedContainer\Bootstrap\ThirdPartyInitializer; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ThirdPartyInitializer; // Combined with the #[Service] attribute on SomeService ensures this package // source directory is scanned diff --git a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/SecondInitializer.php b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/SecondInitializer.php index 67a6fe60..66e7b335 100644 --- a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/SecondInitializer.php +++ b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/SecondInitializer.php @@ -2,7 +2,7 @@ namespace Cspray\AnnotatedContainer\Fixture\VendorScanningInitializers\Vendor\Package; -use Cspray\AnnotatedContainer\Bootstrap\ThirdPartyInitializer; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ThirdPartyInitializer; use Cspray\AnnotatedContainer\Fixture\VendorScanningInitializers\DependencyDefinitionProvider; // Ensures that the ThirdPartyDependency is provided, through the DependencyDefinitionProvider diff --git a/test/Unit/Bootstrap/BootstrapTest.php b/test/Unit/Bootstrap/BootstrapTest.php index b267d3fc..276664eb 100644 --- a/test/Unit/Bootstrap/BootstrapTest.php +++ b/test/Unit/Bootstrap/BootstrapTest.php @@ -4,13 +4,13 @@ use Cspray\AnnotatedContainer\AnnotatedContainer; use Cspray\AnnotatedContainer\Bootstrap\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingConfiguration; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingDirectoryResolver; -use Cspray\AnnotatedContainer\Bootstrap\CacheAwareBootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\CacheAwareBootstrappingConfiguration; use Cspray\AnnotatedContainer\Bootstrap\ContainerAnalytics; -use Cspray\AnnotatedContainer\Bootstrap\ServiceFromServiceDefinition; -use Cspray\AnnotatedContainer\Bootstrap\ServiceGatherer; -use Cspray\AnnotatedContainer\Bootstrap\ServiceWiringListener; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\BootstrappingDirectoryResolver; +use Cspray\AnnotatedContainer\Bootstrap\Listener\ServiceFromServiceDefinition; +use Cspray\AnnotatedContainer\Bootstrap\Listener\ServiceGatherer; +use Cspray\AnnotatedContainer\Bootstrap\Listener\ServiceWiringListener; use Cspray\AnnotatedContainer\ContainerFactory\AurynContainerFactory; use Cspray\AnnotatedContainer\ContainerFactory\ContainerFactory; use Cspray\AnnotatedContainer\ContainerFactory\ParameterStore; @@ -22,6 +22,8 @@ use Cspray\AnnotatedContainer\Event\Listener\Bootstrap\AfterBootstrap; use Cspray\AnnotatedContainer\Exception\InvalidBootstrapConfiguration; use Cspray\AnnotatedContainer\Filesystem\Filesystem; +use Cspray\AnnotatedContainer\Fixture\CustomServiceAttribute\Repository; +use Cspray\AnnotatedContainer\Fixture\Fixtures; use Cspray\AnnotatedContainer\Profiles; use Cspray\AnnotatedContainer\StaticAnalysis\ContainerDefinitionAnalysisOptionsBuilder; use Cspray\AnnotatedContainer\StaticAnalysis\DefinitionProvider; @@ -29,13 +31,11 @@ use Cspray\AnnotatedContainer\Unit\Helper\StubBootstrapListener; use Cspray\AnnotatedContainer\Unit\Helper\StubDefinitionProvider; use Cspray\AnnotatedContainer\Unit\Helper\StubParameterStore; -use Cspray\AnnotatedContainer\Fixture\CustomServiceAttribute\Repository; -use Cspray\AnnotatedContainer\Fixture\Fixtures; use Cspray\PrecisionStopwatch\KnownIncrementingPreciseTime; use Cspray\PrecisionStopwatch\Stopwatch; -use PHPUnit\Framework\TestCase; use org\bovigo\vfs\vfsStream as VirtualFilesystem; use org\bovigo\vfs\vfsStreamDirectory as VirtualDirectory; +use PHPUnit\Framework\TestCase; final class BootstrapTest extends TestCase { diff --git a/test/Unit/Bootstrap/CacheAwareBootstrappingConfigurationTest.php b/test/Unit/Bootstrap/CacheAwareBootstrappingConfigurationTest.php index ae22e123..c82f7de1 100644 --- a/test/Unit/Bootstrap/CacheAwareBootstrappingConfigurationTest.php +++ b/test/Unit/Bootstrap/CacheAwareBootstrappingConfigurationTest.php @@ -2,8 +2,8 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingConfiguration; -use Cspray\AnnotatedContainer\Bootstrap\CacheAwareBootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\CacheAwareBootstrappingConfiguration; use Cspray\AnnotatedContainer\Definition\Cache\ContainerDefinitionCache; use Cspray\AnnotatedContainer\Unit\Helper\StubDefinitionProvider; use Cspray\AnnotatedContainer\Unit\Helper\StubParameterStore; diff --git a/test/Unit/Bootstrap/ComposerJsonScanningThirdPartyInitializerProviderTest.php b/test/Unit/Bootstrap/ComposerJsonScanningThirdPartyInitializerProviderTest.php index a8b1d630..c22cfe1c 100644 --- a/test/Unit/Bootstrap/ComposerJsonScanningThirdPartyInitializerProviderTest.php +++ b/test/Unit/Bootstrap/ComposerJsonScanningThirdPartyInitializerProviderTest.php @@ -2,12 +2,11 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\ComposerJsonScanningThirdPartyInitializerProvider; -use Cspray\AnnotatedContainer\Bootstrap\PackagesComposerJsonPathProvider; -use Cspray\AnnotatedContainer\Bootstrap\ThirdPartyInitializer; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\ComposerJsonScanningThirdPartyInitializerProvider; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\PackagesComposerJsonPathProvider; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ThirdPartyInitializer; use Cspray\AnnotatedContainer\Exception\InvalidThirdPartyInitializer; use Cspray\AnnotatedContainer\Filesystem\Filesystem; -use Cspray\AnnotatedContainer\Fixture\Fixtures; use Cspray\AnnotatedContainer\Fixture\VendorScanningInitializers\Vendor\Package\FirstInitializer; use Cspray\AnnotatedContainer\Fixture\VendorScanningInitializers\Vendor\Package\SecondInitializer; use Cspray\AnnotatedContainer\Fixture\VendorScanningInitializers\Vendor\Package\ThirdInitializer; diff --git a/test/Unit/Bootstrap/ComposerRuntimePackagesComposerJsonPathProviderTest.php b/test/Unit/Bootstrap/ComposerRuntimePackagesComposerJsonPathProviderTest.php index d44b59b3..9aed8c11 100644 --- a/test/Unit/Bootstrap/ComposerRuntimePackagesComposerJsonPathProviderTest.php +++ b/test/Unit/Bootstrap/ComposerRuntimePackagesComposerJsonPathProviderTest.php @@ -2,7 +2,7 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\ComposerRuntimePackagesComposerJsonPathProvider; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ComposerRuntimePackagesComposerJsonPathProvider; use PHPUnit\Framework\TestCase; class ComposerRuntimePackagesComposerJsonPathProviderTest extends TestCase { diff --git a/test/Unit/Bootstrap/DefaultDefinitionProviderFactoryTest.php b/test/Unit/Bootstrap/DefaultDefinitionProviderFactoryTest.php index 332215b6..49eac289 100644 --- a/test/Unit/Bootstrap/DefaultDefinitionProviderFactoryTest.php +++ b/test/Unit/Bootstrap/DefaultDefinitionProviderFactoryTest.php @@ -2,7 +2,7 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\DefaultDefinitionProviderFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultDefinitionProviderFactory; use Cspray\AnnotatedContainer\Exception\InvalidDefinitionProvider; use Cspray\AnnotatedContainer\StaticAnalysis\DefinitionProvider; use Cspray\AnnotatedContainer\Unit\Helper\StubDefinitionProvider; diff --git a/test/Unit/Bootstrap/DefaultParameterStoreFactoryTest.php b/test/Unit/Bootstrap/DefaultParameterStoreFactoryTest.php index 5cbff2f8..d48278cc 100644 --- a/test/Unit/Bootstrap/DefaultParameterStoreFactoryTest.php +++ b/test/Unit/Bootstrap/DefaultParameterStoreFactoryTest.php @@ -2,7 +2,7 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\DefaultParameterStoreFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultParameterStoreFactory; use Cspray\AnnotatedContainer\ContainerFactory\ParameterStore; use Cspray\AnnotatedContainer\Exception\InvalidParameterStore; use Cspray\AnnotatedContainer\Unit\Helper\StubParameterStore; diff --git a/test/Unit/Bootstrap/DelegatedParameterStoreFactoryTest.php b/test/Unit/Bootstrap/DelegatedParameterStoreFactoryTest.php index 0135a0df..2b031ce5 100644 --- a/test/Unit/Bootstrap/DelegatedParameterStoreFactoryTest.php +++ b/test/Unit/Bootstrap/DelegatedParameterStoreFactoryTest.php @@ -2,8 +2,8 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\DelegatedParameterStoreFactory; -use Cspray\AnnotatedContainer\Bootstrap\ParameterStoreFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DelegatedParameterStoreFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\ParameterStoreFactory; use Cspray\AnnotatedContainer\Unit\Helper\StubParameterStore; use PHPUnit\Framework\TestCase; diff --git a/test/Unit/Bootstrap/RootDirectoryBootstrappingDirectoryResolverTest.php b/test/Unit/Bootstrap/RootDirectoryBootstrappingDirectoryResolverTest.php index a5f780b5..bbbffd58 100644 --- a/test/Unit/Bootstrap/RootDirectoryBootstrappingDirectoryResolverTest.php +++ b/test/Unit/Bootstrap/RootDirectoryBootstrappingDirectoryResolverTest.php @@ -2,7 +2,7 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\RootDirectoryBootstrappingDirectoryResolver; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\RootDirectoryBootstrappingDirectoryResolver; use PHPUnit\Framework\TestCase; final class RootDirectoryBootstrappingDirectoryResolverTest extends TestCase { diff --git a/test/Unit/Bootstrap/VendorPresenceBasedBootstrappingDirectoryResolverTest.php b/test/Unit/Bootstrap/VendorPresenceBasedBootstrappingDirectoryResolverTest.php index 2d5485b9..a5b69499 100644 --- a/test/Unit/Bootstrap/VendorPresenceBasedBootstrappingDirectoryResolverTest.php +++ b/test/Unit/Bootstrap/VendorPresenceBasedBootstrappingDirectoryResolverTest.php @@ -2,7 +2,7 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\VendorPresenceBasedBootstrappingDirectoryResolver; +use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\VendorPresenceBasedBootstrappingDirectoryResolver; use Cspray\AnnotatedContainer\Filesystem\Filesystem; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; diff --git a/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php b/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php index 4754a57d..b445dcd5 100644 --- a/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php +++ b/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php @@ -2,23 +2,21 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\DefaultDefinitionProviderFactory; -use Cspray\AnnotatedContainer\Bootstrap\DefaultListenerFactory; -use Cspray\AnnotatedContainer\Bootstrap\DefaultParameterStoreFactory; -use Cspray\AnnotatedContainer\Bootstrap\DefinitionProviderFactory; -use Cspray\AnnotatedContainer\Bootstrap\ParameterStoreFactory; -use Cspray\AnnotatedContainer\Bootstrap\XmlBootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultDefinitionProviderFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultListenerFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultParameterStoreFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefinitionProviderFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\ParameterStoreFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\XmlBootstrappingConfiguration; use Cspray\AnnotatedContainer\ContainerFactory\ParameterStore; use Cspray\AnnotatedContainer\Exception\InvalidBootstrapConfiguration; use Cspray\AnnotatedContainer\Filesystem\Filesystem; +use Cspray\AnnotatedContainer\Fixture\Fixtures; use Cspray\AnnotatedContainer\StaticAnalysis\CompositeDefinitionProvider; use Cspray\AnnotatedContainer\StaticAnalysis\DefinitionProvider; use Cspray\AnnotatedContainer\Unit\Helper\StubDefinitionProvider; use Cspray\AnnotatedContainer\Unit\Helper\StubDefinitionProviderWithDependencies; use Cspray\AnnotatedContainer\Unit\Helper\StubParameterStore; -use Cspray\AnnotatedContainer\Fixture\Fixtures; -use org\bovigo\vfs\vfsStream as VirtualFilesystem; -use org\bovigo\vfs\vfsStreamDirectory as VirtualDirectory; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use function Cspray\AnnotatedContainer\Reflection\types; diff --git a/test/Unit/Cli/AnnotatedContainerCliRunnerTest.php b/test/Unit/Cli/AnnotatedContainerCliRunnerTest.php index bcddc191..cccaa93d 100644 --- a/test/Unit/Cli/AnnotatedContainerCliRunnerTest.php +++ b/test/Unit/Cli/AnnotatedContainerCliRunnerTest.php @@ -3,7 +3,7 @@ namespace Cspray\AnnotatedContainer\Unit\Cli; use Cspray\AnnotatedContainer\AnnotatedContainerVersion; -use Cspray\AnnotatedContainer\Bootstrap\BootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; use Cspray\AnnotatedContainer\Cli\AnnotatedContainerCliRunner; use Cspray\AnnotatedContainer\Cli\Command\BuildCommand; use Cspray\AnnotatedContainer\Cli\Command\CacheClearCommand; @@ -66,9 +66,9 @@ public function testSetupWithNullConfigurationHasCorrectBuildCommandHelp() : voi $expected = << Date: Sat, 29 Mar 2025 12:46:18 -0400 Subject: [PATCH 3/5] Add Listeners to config, fix various psalm issues --- known-issues.xml | 16 ++-- phpunit.xml | 2 - psalm.xml | 2 +- src/Bootstrap/Bootstrap.php | 4 +- .../BootstrappingConfiguration.php | 5 +- .../CacheAwareBootstrappingConfiguration.php | 2 +- .../Configuration/DefaultListenerFactory.php | 9 ++- .../Configuration/ListenerFactory.php | 7 +- .../XmlBootstrappingConfiguration.php | 26 ++++++- ...nScanningThirdPartyInitializerProvider.php | 5 +- .../Initializer/ThirdPartyInitializer.php | 11 +++ .../ThirdPartyInitializerProvider.php | 2 +- src/Bootstrap/Listener/ServiceGatherer.php | 4 +- .../Listener/ServiceWiringListener.php | 4 +- src/Cli/AnnotatedContainerCliRunner.php | 2 +- src/Cli/Command/InitCommand.php | 17 +++++ .../AurynContainerFactory.php | 9 +-- src/Exception/InvalidAnnotatedTarget.php | 13 ---- src/Exception/InvalidInjectDefinition.php | 9 --- src/Exception/InvalidServiceDelegate.php | 42 ---------- .../InvalidServiceDelegateDefinition.php | 10 --- .../InvalidServicePrepareDefinition.php | 10 --- ...tatedTargetContainerDefinitionAnalyzer.php | 3 - ...tainerDefinitionAnalysisOptionsBuilder.php | 8 +- .../package/other_src/ThirdInitializer.php | 4 + .../cspray/package/src/FirstInitializer.php | 4 + .../cspray/package/src/SecondInitializer.php | 4 + test/Unit/AnnotatedContainerVersionTest.php | 2 +- test/Unit/Bootstrap/BootstrapTest.php | 58 ++++++++++++++ ...cheAwareBootstrappingConfigurationTest.php | 4 +- ...nningThirdPartyInitializerProviderTest.php | 2 +- .../XmlBootstrappingConfigurationTest.php | 76 +++++++++++++++++++ test/Unit/Cli/Command/InitCommandTest.php | 33 ++++++-- test/Unit/ProfilesTest.php | 2 +- ...erDefinitionAnalysisOptionsBuilderTest.php | 3 + test/Unit/ThirdPartyFunctionsTest.php | 2 +- 36 files changed, 275 insertions(+), 141 deletions(-) rename src/Bootstrap/{DirectoryResolver => Initializer}/ComposerJsonScanningThirdPartyInitializerProvider.php (90%) delete mode 100644 src/Exception/InvalidAnnotatedTarget.php delete mode 100644 src/Exception/InvalidServiceDelegate.php delete mode 100644 src/Exception/InvalidServiceDelegateDefinition.php delete mode 100644 src/Exception/InvalidServicePrepareDefinition.php diff --git a/known-issues.xml b/known-issues.xml index f92060db..46c2a7c3 100644 --- a/known-issues.xml +++ b/known-issues.xml @@ -1,6 +1,11 @@ - + + + + + + @@ -66,7 +71,7 @@ [$serviceDelegateDefinition->classMethod()->class()->name(), $serviceDelegateDefinition->classMethod()->methodName()], $this->parametersForServiceDelegateToArray($injector, $state, $serviceDelegateDefinition), )]]> - + injector->make($id)]]> @@ -234,11 +239,8 @@ - + directories]]> - - - - + diff --git a/phpunit.xml b/phpunit.xml index 493e4762..d9d5d70a 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -20,10 +20,8 @@ - diff --git a/psalm.xml b/psalm.xml index e83fceb2..055fd83d 100644 --- a/psalm.xml +++ b/psalm.xml @@ -36,7 +36,7 @@ - + diff --git a/src/Bootstrap/Bootstrap.php b/src/Bootstrap/Bootstrap.php index d93666dd..fa2f0ec6 100644 --- a/src/Bootstrap/Bootstrap.php +++ b/src/Bootstrap/Bootstrap.php @@ -88,7 +88,9 @@ public function bootstrapContainer( $this->stopwatch->start(); - // add listeners from bootstrapping configuration to emitter + foreach ($this->bootstrappingConfiguration->listeners() as $listener) { + $this->emitter->addListener($listener); + } $analysisOptions = $this->analysisOptions($this->bootstrappingConfiguration); diff --git a/src/Bootstrap/Configuration/BootstrappingConfiguration.php b/src/Bootstrap/Configuration/BootstrappingConfiguration.php index c4ce01e4..d79bd7fd 100644 --- a/src/Bootstrap/Configuration/BootstrappingConfiguration.php +++ b/src/Bootstrap/Configuration/BootstrappingConfiguration.php @@ -3,6 +3,7 @@ namespace Cspray\AnnotatedContainer\Bootstrap\Configuration; use Cspray\AnnotatedContainer\ArchitecturalDecisionRecords\SingleEntrypointDefinitionProvider; +use Cspray\AnnotatedContainer\ContainerFactory\ParameterStore; use Cspray\AnnotatedContainer\Definition\Cache\ContainerDefinitionCache; use Cspray\AnnotatedContainer\Event\Listener; use Cspray\AnnotatedContainer\StaticAnalysis\DefinitionProvider; @@ -20,12 +21,12 @@ public function cache() : ?ContainerDefinitionCache; public function containerDefinitionProvider() : ?DefinitionProvider; /** - * @return Listener + * @return list */ public function parameterStores() : array; /** - * @return Listener + * @return list */ public function listeners() : array; } diff --git a/src/Bootstrap/Configuration/CacheAwareBootstrappingConfiguration.php b/src/Bootstrap/Configuration/CacheAwareBootstrappingConfiguration.php index 087fe19e..8a239c0d 100644 --- a/src/Bootstrap/Configuration/CacheAwareBootstrappingConfiguration.php +++ b/src/Bootstrap/Configuration/CacheAwareBootstrappingConfiguration.php @@ -32,6 +32,6 @@ public function parameterStores() : array { } public function listeners() : array { - // TODO: Implement listeners() method. + return $this->configuration->listeners(); } } diff --git a/src/Bootstrap/Configuration/DefaultListenerFactory.php b/src/Bootstrap/Configuration/DefaultListenerFactory.php index 5600e445..dafcc201 100644 --- a/src/Bootstrap/Configuration/DefaultListenerFactory.php +++ b/src/Bootstrap/Configuration/DefaultListenerFactory.php @@ -6,7 +6,12 @@ final class DefaultListenerFactory implements ListenerFactory { + /** + * @param string|class-string $identifier + * @return Listener + */ public function createListener(string $identifier) : Listener { - // TODO: Implement createListener() method. + assert(is_a($identifier, Listener::class, true)); + return new $identifier(); } -} \ No newline at end of file +} diff --git a/src/Bootstrap/Configuration/ListenerFactory.php b/src/Bootstrap/Configuration/ListenerFactory.php index 61d29b8b..3f98b887 100644 --- a/src/Bootstrap/Configuration/ListenerFactory.php +++ b/src/Bootstrap/Configuration/ListenerFactory.php @@ -6,6 +6,9 @@ interface ListenerFactory { + /** + * @param string|class-string $identifier + * @return Listener + */ public function createListener(string $identifier) : Listener; - -} \ No newline at end of file +} diff --git a/src/Bootstrap/Configuration/XmlBootstrappingConfiguration.php b/src/Bootstrap/Configuration/XmlBootstrappingConfiguration.php index efc3e989..10abcd29 100644 --- a/src/Bootstrap/Configuration/XmlBootstrappingConfiguration.php +++ b/src/Bootstrap/Configuration/XmlBootstrappingConfiguration.php @@ -3,6 +3,7 @@ namespace Cspray\AnnotatedContainer\Bootstrap\Configuration; use Cspray\AnnotatedContainer\ArchitecturalDecisionRecords\SingleEntrypointDefinitionProvider; +use Cspray\AnnotatedContainer\ContainerFactory\ParameterStore; use Cspray\AnnotatedContainer\Definition\Cache\ContainerDefinitionCache; use Cspray\AnnotatedContainer\Event\Listener; use Cspray\AnnotatedContainer\Exception\InvalidBootstrapConfiguration; @@ -24,10 +25,15 @@ final class XmlBootstrappingConfiguration implements BootstrappingConfiguration private readonly ?DefinitionProvider $definitionProvider; /** - * @var Listener + * @var list */ private readonly array $parameterStores; + /** + * @var list + */ + private readonly array $listeners; + public function __construct( private readonly Filesystem $filesystem, private readonly string $xmlFile, @@ -117,9 +123,21 @@ public function __construct( } } + $listeners = []; + $listenerNodes = $xpath->query('/ac:annotatedContainer/ac:listeners/ac:listener/text()'); + if ($listenerNodes instanceof DOMNodeList) { + foreach ($listenerNodes as $listenerNode) { + assert(isset($listenerNode->nodeValue)); + $listenerType = trim($listenerNode->nodeValue); + $listener = $this->listenerFactory->createListener($listenerType); + $listeners[] = $listener; + } + } + $this->directories = $scanDirectories; $this->definitionProvider = $definitionProvider; $this->parameterStores = $parameterStores; + $this->listeners = $listeners; } finally { libxml_clear_errors(); libxml_use_internal_errors(false); @@ -136,17 +154,17 @@ public function containerDefinitionProvider() : ?DefinitionProvider { } /** - * @return Listener + * @return list */ public function parameterStores() : array { return $this->parameterStores; } /** - * @return Listener + * @return list */ public function listeners() : array { - // TODO: Implement listeners() method. + return $this->listeners; } public function cache() : ?ContainerDefinitionCache { diff --git a/src/Bootstrap/DirectoryResolver/ComposerJsonScanningThirdPartyInitializerProvider.php b/src/Bootstrap/Initializer/ComposerJsonScanningThirdPartyInitializerProvider.php similarity index 90% rename from src/Bootstrap/DirectoryResolver/ComposerJsonScanningThirdPartyInitializerProvider.php rename to src/Bootstrap/Initializer/ComposerJsonScanningThirdPartyInitializerProvider.php index 8eb057c8..ee22a0b9 100644 --- a/src/Bootstrap/DirectoryResolver/ComposerJsonScanningThirdPartyInitializerProvider.php +++ b/src/Bootstrap/Initializer/ComposerJsonScanningThirdPartyInitializerProvider.php @@ -1,10 +1,7 @@ > + */ + abstract public function listeners() : array; + + /** + * @return ?class-string + */ abstract public function definitionProviderClass() : ?string; } diff --git a/src/Bootstrap/Initializer/ThirdPartyInitializerProvider.php b/src/Bootstrap/Initializer/ThirdPartyInitializerProvider.php index 3a3d2a32..d21b1b14 100644 --- a/src/Bootstrap/Initializer/ThirdPartyInitializerProvider.php +++ b/src/Bootstrap/Initializer/ThirdPartyInitializerProvider.php @@ -5,7 +5,7 @@ interface ThirdPartyInitializerProvider { /** - * @return ThirdPartyInitializer + * @return list */ public function thirdPartyInitializers() : array; } diff --git a/src/Bootstrap/Listener/ServiceGatherer.php b/src/Bootstrap/Listener/ServiceGatherer.php index 804d76e4..2a8b75d8 100644 --- a/src/Bootstrap/Listener/ServiceGatherer.php +++ b/src/Bootstrap/Listener/ServiceGatherer.php @@ -7,14 +7,14 @@ interface ServiceGatherer { /** * @template T * @param class-string $type - * @return ServiceFromServiceDefinition + * @return list */ public function servicesForType(string $type) : array; /** * @template T * @param class-string $attributeType - * @return ServiceFromServiceDefinition + * @return list */ public function servicesWithAttribute(string $attributeType) : array; } diff --git a/src/Bootstrap/Listener/ServiceWiringListener.php b/src/Bootstrap/Listener/ServiceWiringListener.php index 99981689..58e5bc6b 100644 --- a/src/Bootstrap/Listener/ServiceWiringListener.php +++ b/src/Bootstrap/Listener/ServiceWiringListener.php @@ -29,10 +29,10 @@ public function __construct( /** * @template T of object * @param class-string $type - * @return ServiceFromServiceDefinition + * @return list */ public function servicesForType(string $type) : array { - /** @var ServiceFromServiceDefinition $services */ + /** @var list $services */ $services = []; foreach ($this->containerDefinition->serviceDefinitions() as $serviceDefinition) { if ($serviceDefinition->isAbstract()) { diff --git a/src/Cli/AnnotatedContainerCliRunner.php b/src/Cli/AnnotatedContainerCliRunner.php index 4d38f39a..9a864245 100644 --- a/src/Cli/AnnotatedContainerCliRunner.php +++ b/src/Cli/AnnotatedContainerCliRunner.php @@ -5,8 +5,8 @@ use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; use Cspray\AnnotatedContainer\Bootstrap\Configuration\ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration; use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\BootstrappingDirectoryResolver; -use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\ComposerJsonScanningThirdPartyInitializerProvider; use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\VendorPresenceBasedBootstrappingDirectoryResolver; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ComposerJsonScanningThirdPartyInitializerProvider; use Cspray\AnnotatedContainer\Bootstrap\Initializer\ComposerRuntimePackagesComposerJsonPathProvider; use Cspray\AnnotatedContainer\Bootstrap\Initializer\PackagesComposerJsonPathProvider; use Cspray\AnnotatedContainer\Bootstrap\Initializer\ThirdPartyInitializerProvider; diff --git a/src/Cli/Command/InitCommand.php b/src/Cli/Command/InitCommand.php index f11621c5..fa4681d3 100644 --- a/src/Cli/Command/InitCommand.php +++ b/src/Cli/Command/InitCommand.php @@ -288,6 +288,8 @@ private function generateAndSaveConfiguration(Input $input, array $composer, str $vendor = $scanDirectories->appendChild( $dom->createElementNS(self::XML_SCHEMA, 'vendor') ); + + $listeners = []; foreach ($this->initializerProvider->thirdPartyInitializers() as $thirdPartyInitializer) { $packageRelativeScanDirectories = $thirdPartyInitializer->relativeScanDirectories(); if (count($packageRelativeScanDirectories) > 0) { @@ -314,6 +316,21 @@ private function generateAndSaveConfiguration(Input $input, array $composer, str $dom->createElementNS(self::XML_SCHEMA, 'definitionProvider', $providerClass) ); } + + $listeners = array_merge($listeners, $thirdPartyInitializer->listeners()); + } + + if (count($listeners) > 0) { + $listenersNode = $dom->createElementNS( + self::XML_SCHEMA, + 'listeners' + ); + foreach ($listeners as $listener) { + $listenersNode->appendChild( + $dom->createElementNS(self::XML_SCHEMA, 'listener', $listener) + ); + } + $root->appendChild($listenersNode); } $schemaPath = dirname(__DIR__, 3) . '/annotated-container.xsd'; diff --git a/src/ContainerFactory/AurynContainerFactory.php b/src/ContainerFactory/AurynContainerFactory.php index 84d61042..d2cf46a3 100644 --- a/src/ContainerFactory/AurynContainerFactory.php +++ b/src/ContainerFactory/AurynContainerFactory.php @@ -52,11 +52,6 @@ public function __construct( $this->injector->delegate(Profiles::class, fn() => $this->state->activeProfiles()); } - /** - * @template T - * @param class-string|non-empty-string $id - * @return ($id is class-string ? T : mixed) - */ public function get(string $id) { try { if (!$this->has($id)) { @@ -70,9 +65,7 @@ public function get(string $id) { $id = $namedType->name(); } - /** @var T|mixed $value */ - $value = $this->injector->make($id); - return $value; + return $this->injector->make($id); } catch (InjectionException $injectionException) { throw ContainerException::fromCaughtThrowable($injectionException); } diff --git a/src/Exception/InvalidAnnotatedTarget.php b/src/Exception/InvalidAnnotatedTarget.php deleted file mode 100644 index be5ed274..00000000 --- a/src/Exception/InvalidAnnotatedTarget.php +++ /dev/null @@ -1,13 +0,0 @@ - */ + /** @var list */ private array $directories = []; private ?DefinitionProvider $consumer = null; @@ -20,10 +20,10 @@ private function __construct() { /** * Specify the directories that should be parsed when generating the ContainerDefinition * - * @param string ...$directories + * @param non-empty-string ...$directories * @return static */ - public static function scanDirectories(string...$directories) : self { + public static function scanDirectories(string ...$directories) : self { $instance = new self(); $instance->directories = array_values($directories); return $instance; @@ -48,7 +48,7 @@ public function build() : ContainerDefinitionAnalysisOptions { $this->consumer, ) implements ContainerDefinitionAnalysisOptions { /** - * @param list $directories + * @param non-empty-list $directories * @param DefinitionProvider|null $consumer */ public function __construct( diff --git a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/other_src/ThirdInitializer.php b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/other_src/ThirdInitializer.php index c13cb002..70dd386d 100644 --- a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/other_src/ThirdInitializer.php +++ b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/other_src/ThirdInitializer.php @@ -17,4 +17,8 @@ public function definitionProviderClass() : ?string { public function packageName() : string { return 'cspray/package'; } + + public function listeners() : array { + return []; + } } diff --git a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/FirstInitializer.php b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/FirstInitializer.php index 28508b90..a1f3959f 100644 --- a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/FirstInitializer.php +++ b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/FirstInitializer.php @@ -22,4 +22,8 @@ public function definitionProviderClass() : ?string { public function packageName() : string { return 'cspray/package'; } + + public function listeners() : array { + return []; + } } diff --git a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/SecondInitializer.php b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/SecondInitializer.php index 66e7b335..85bbc54e 100644 --- a/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/SecondInitializer.php +++ b/test/Fixture/VendorScanningInitializers/vendor/cspray/package/src/SecondInitializer.php @@ -20,4 +20,8 @@ public function definitionProviderClass() : string { public function packageName() : string { return 'cspray/package'; } + + public function listeners() : array { + return []; + } } diff --git a/test/Unit/AnnotatedContainerVersionTest.php b/test/Unit/AnnotatedContainerVersionTest.php index 1ba9bcea..b0afc503 100644 --- a/test/Unit/AnnotatedContainerVersionTest.php +++ b/test/Unit/AnnotatedContainerVersionTest.php @@ -6,7 +6,7 @@ use Cspray\AnnotatedContainer\AnnotatedContainerVersion; use PHPUnit\Framework\TestCase; -class AnnotatedContainerVersionTest extends TestCase { +final class AnnotatedContainerVersionTest extends TestCase { public function testGetApiVersionReturnsVersionFileContents() : void { self::assertSame( diff --git a/test/Unit/Bootstrap/BootstrapTest.php b/test/Unit/Bootstrap/BootstrapTest.php index 276664eb..c42a8ce5 100644 --- a/test/Unit/Bootstrap/BootstrapTest.php +++ b/test/Unit/Bootstrap/BootstrapTest.php @@ -6,6 +6,10 @@ use Cspray\AnnotatedContainer\Bootstrap\Bootstrap; use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; use Cspray\AnnotatedContainer\Bootstrap\Configuration\CacheAwareBootstrappingConfiguration; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultDefinitionProviderFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultListenerFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultParameterStoreFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\XmlBootstrappingConfiguration; use Cspray\AnnotatedContainer\Bootstrap\ContainerAnalytics; use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\BootstrappingDirectoryResolver; use Cspray\AnnotatedContainer\Bootstrap\Listener\ServiceFromServiceDefinition; @@ -22,13 +26,16 @@ use Cspray\AnnotatedContainer\Event\Listener\Bootstrap\AfterBootstrap; use Cspray\AnnotatedContainer\Exception\InvalidBootstrapConfiguration; use Cspray\AnnotatedContainer\Filesystem\Filesystem; +use Cspray\AnnotatedContainer\Filesystem\PhpFunctionsFilesystem; use Cspray\AnnotatedContainer\Fixture\CustomServiceAttribute\Repository; use Cspray\AnnotatedContainer\Fixture\Fixtures; use Cspray\AnnotatedContainer\Profiles; use Cspray\AnnotatedContainer\StaticAnalysis\ContainerDefinitionAnalysisOptionsBuilder; use Cspray\AnnotatedContainer\StaticAnalysis\DefinitionProvider; use Cspray\AnnotatedContainer\Unit\Helper\FixtureBootstrappingDirectoryResolver; +use Cspray\AnnotatedContainer\Unit\Helper\StubAnalysisListener; use Cspray\AnnotatedContainer\Unit\Helper\StubBootstrapListener; +use Cspray\AnnotatedContainer\Unit\Helper\StubContainerFactoryListener; use Cspray\AnnotatedContainer\Unit\Helper\StubDefinitionProvider; use Cspray\AnnotatedContainer\Unit\Helper\StubParameterStore; use Cspray\PrecisionStopwatch\KnownIncrementingPreciseTime; @@ -485,4 +492,55 @@ public function testBootstrapFromAnnotatedContainerConventionsWithFilePresentRet $service ); } + + public function testBootstrapWithConfiguredListenersAutomaticallyAddsThemToEmitter() : void { + $emitter = new Emitter(); + $containerFactory = new PhpDiContainerFactory($emitter); + $directoryResolver = new FixtureBootstrappingDirectoryResolver(); + $xml = << + + + + SingleConcreteService + + + + Cspray\AnnotatedContainer\Unit\Helper\StubAnalysisListener + Cspray\AnnotatedContainer\Unit\Helper\StubBootstrapListener + Cspray\AnnotatedContainer\Unit\Helper\StubContainerFactoryListener + + +XML; + VirtualFilesystem::newFile('annotated-container.xml')->at($this->vfs)->setContent($xml); + + $bootstrap = Bootstrap::fromCompleteSetup( + $configuration = new XmlBootstrappingConfiguration( + new PhpFunctionsFilesystem(), + $directoryResolver->configurationPath('annotated-container.xml'), + new DefaultParameterStoreFactory(), + new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() + ), + $containerFactory, + $emitter, + $directoryResolver, + ); + + $bootstrap->bootstrapContainer(); + + self::assertCount(3, $configuration->listeners()); + + $stubAnalysis = $configuration->listeners()[0]; + self::assertInstanceOf(StubAnalysisListener::class, $stubAnalysis); + self::assertCount(3, $stubAnalysis->getTriggeredEvents()); + + $stubBootstrap = $configuration->listeners()[1]; + self::assertInstanceOf(StubBootstrapListener::class, $stubBootstrap); + self::assertCount(2, $stubBootstrap->getTriggeredEvents()); + + $stubFactory = $configuration->listeners()[2]; + self::assertInstanceOf(StubContainerFactoryListener::class, $stubFactory); + self::assertCount(2, $stubFactory->getTriggeredEvents()); + } } diff --git a/test/Unit/Bootstrap/CacheAwareBootstrappingConfigurationTest.php b/test/Unit/Bootstrap/CacheAwareBootstrappingConfigurationTest.php index c82f7de1..3d7f31cb 100644 --- a/test/Unit/Bootstrap/CacheAwareBootstrappingConfigurationTest.php +++ b/test/Unit/Bootstrap/CacheAwareBootstrappingConfigurationTest.php @@ -5,6 +5,7 @@ use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration; use Cspray\AnnotatedContainer\Bootstrap\Configuration\CacheAwareBootstrappingConfiguration; use Cspray\AnnotatedContainer\Definition\Cache\ContainerDefinitionCache; +use Cspray\AnnotatedContainer\Unit\Helper\StubAnalysisListener; use Cspray\AnnotatedContainer\Unit\Helper\StubDefinitionProvider; use Cspray\AnnotatedContainer\Unit\Helper\StubParameterStore; use PHPUnit\Framework\Attributes\DataProvider; @@ -16,7 +17,8 @@ public static function nonCacheMethodsProvider() : array { return [ 'scanDirectories' => ['scanDirectories', ['dir']], 'containerDefinitionProvider' => ['containerDefinitionProvider', new StubDefinitionProvider()], - 'parameterStores' => ['parameterStores', [new StubParameterStore()]] + 'parameterStores' => ['parameterStores', [new StubParameterStore()]], + 'listeners' => ['listeners', [new StubAnalysisListener()]] ]; } diff --git a/test/Unit/Bootstrap/ComposerJsonScanningThirdPartyInitializerProviderTest.php b/test/Unit/Bootstrap/ComposerJsonScanningThirdPartyInitializerProviderTest.php index c22cfe1c..701ac00c 100644 --- a/test/Unit/Bootstrap/ComposerJsonScanningThirdPartyInitializerProviderTest.php +++ b/test/Unit/Bootstrap/ComposerJsonScanningThirdPartyInitializerProviderTest.php @@ -2,7 +2,7 @@ namespace Cspray\AnnotatedContainer\Unit\Bootstrap; -use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\ComposerJsonScanningThirdPartyInitializerProvider; +use Cspray\AnnotatedContainer\Bootstrap\Initializer\ComposerJsonScanningThirdPartyInitializerProvider; use Cspray\AnnotatedContainer\Bootstrap\Initializer\PackagesComposerJsonPathProvider; use Cspray\AnnotatedContainer\Bootstrap\Initializer\ThirdPartyInitializer; use Cspray\AnnotatedContainer\Exception\InvalidThirdPartyInitializer; diff --git a/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php b/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php index b445dcd5..d0270139 100644 --- a/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php +++ b/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php @@ -6,14 +6,19 @@ use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultListenerFactory; use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefaultParameterStoreFactory; use Cspray\AnnotatedContainer\Bootstrap\Configuration\DefinitionProviderFactory; +use Cspray\AnnotatedContainer\Bootstrap\Configuration\ListenerFactory; use Cspray\AnnotatedContainer\Bootstrap\Configuration\ParameterStoreFactory; use Cspray\AnnotatedContainer\Bootstrap\Configuration\XmlBootstrappingConfiguration; use Cspray\AnnotatedContainer\ContainerFactory\ParameterStore; +use Cspray\AnnotatedContainer\Event\Listener; use Cspray\AnnotatedContainer\Exception\InvalidBootstrapConfiguration; use Cspray\AnnotatedContainer\Filesystem\Filesystem; use Cspray\AnnotatedContainer\Fixture\Fixtures; use Cspray\AnnotatedContainer\StaticAnalysis\CompositeDefinitionProvider; use Cspray\AnnotatedContainer\StaticAnalysis\DefinitionProvider; +use Cspray\AnnotatedContainer\Unit\Helper\StubAnalysisListener; +use Cspray\AnnotatedContainer\Unit\Helper\StubBootstrapListener; +use Cspray\AnnotatedContainer\Unit\Helper\StubContainerFactoryListener; use Cspray\AnnotatedContainer\Unit\Helper\StubDefinitionProvider; use Cspray\AnnotatedContainer\Unit\Helper\StubDefinitionProviderWithDependencies; use Cspray\AnnotatedContainer\Unit\Helper\StubParameterStore; @@ -382,4 +387,75 @@ public function testConfigurationFileNotPresentThrowsException() : void { new DefaultListenerFactory() ); } + + public function testConfigurationFileWithListenersPresentReturnsCorrectInstance() : void { + $goodXml = << + + + + src + + + + Cspray\AnnotatedContainer\Unit\Helper\StubAnalysisListener + Cspray\AnnotatedContainer\Unit\Helper\StubBootstrapListener + Cspray\AnnotatedContainer\Unit\Helper\StubContainerFactoryListener + + +XML; + + $this->mockFilePresentFilesystemInteractions('annotated-container.xml', $goodXml); + + $configuration = new XmlBootstrappingConfiguration( + $this->filesystem, + 'annotated-container.xml', + new DefaultParameterStoreFactory(), + new DefaultDefinitionProviderFactory(), + new DefaultListenerFactory() + ); + + self::assertCount(3, $configuration->listeners()); + self::assertContainsOnlyInstancesOf(Listener::class, $configuration->listeners()); + self::assertInstanceOf(StubAnalysisListener::class, $configuration->listeners()[0]); + self::assertInstanceOf(StubBootstrapListener::class, $configuration->listeners()[1]); + self::assertInstanceOf(StubContainerFactoryListener::class, $configuration->listeners()[2]); + } + + public function testConfigurationFileWithListenersUsesListenerFactoryForCreation() : void { + $goodXml = << + + + + src + + + + Cspray\AnnotatedContainer\Unit\Helper\StubAnalysisListener + + +XML; + + $this->mockFilePresentFilesystemInteractions('annotated-container.xml', $goodXml); + + $listener = $this->createMock(Listener::class); + $listenerFactory = $this->createMock(ListenerFactory::class); + $listenerFactory->expects($this->once()) + ->method('createListener') + ->with(StubAnalysisListener::class) + ->willReturn($listener); + + $configuration = new XmlBootstrappingConfiguration( + $this->filesystem, + 'annotated-container.xml', + new DefaultParameterStoreFactory(), + new DefaultDefinitionProviderFactory(), + $listenerFactory + ); + + self::assertCount(1, $configuration->listeners()); + self::assertContainsOnlyInstancesOf(Listener::class, $configuration->listeners()); + self::assertSame($listener, $configuration->listeners()[0]); + } } diff --git a/test/Unit/Cli/Command/InitCommandTest.php b/test/Unit/Cli/Command/InitCommandTest.php index 54547a3b..4a0a9a03 100644 --- a/test/Unit/Cli/Command/InitCommandTest.php +++ b/test/Unit/Cli/Command/InitCommandTest.php @@ -14,6 +14,9 @@ use Cspray\AnnotatedContainer\Exception\ComposerAutoloadNotFound; use Cspray\AnnotatedContainer\Filesystem\Filesystem; use Cspray\AnnotatedContainer\Unit\Helper\InMemoryOutput; +use Cspray\AnnotatedContainer\Unit\Helper\StubAnalysisListener; +use Cspray\AnnotatedContainer\Unit\Helper\StubBootstrapListener; +use Cspray\AnnotatedContainer\Unit\Helper\StubContainerFactoryListener; use Cspray\AnnotatedContainer\Unit\Helper\StubDefinitionProvider; use Cspray\AnnotatedContainer\Unit\Helper\StubInput; use PHPUnit\Framework\MockObject\MockObject; @@ -343,20 +346,35 @@ public function testThirdPartyInitializerProvidersAreAddedToConfiguration() : vo ] ], JSON_THROW_ON_ERROR)); - $thirdPartyInitializer = $this->createMock(ThirdPartyInitializer::class); - $thirdPartyInitializer->expects($this->once()) + $firstInitializer = $this->createMock(ThirdPartyInitializer::class); + $firstInitializer->expects($this->once()) ->method('packageName') ->willReturn('cspray/package-name'); - $thirdPartyInitializer->expects($this->once()) + $firstInitializer->expects($this->once()) ->method('relativeScanDirectories') ->willReturn(['src', 'lib']); - $thirdPartyInitializer->expects($this->once()) + $firstInitializer->expects($this->once()) ->method('definitionProviderClass') ->willReturn(StubDefinitionProvider::class); + $firstInitializer->expects($this->once()) + ->method('listeners') + ->willReturn([StubAnalysisListener::class]); + + $secondInitializer = $this->createMock(ThirdPartyInitializer::class); + $secondInitializer->expects($this->once()) + ->method('relativeScanDirectories') + ->willReturn([]); + $secondInitializer->expects($this->never())->method('packageName'); + $secondInitializer->expects($this->once()) + ->method('definitionProviderClass') + ->willReturn(null); + $secondInitializer->expects($this->once()) + ->method('listeners') + ->willReturn([StubBootstrapListener::class, StubContainerFactoryListener::class]); $this->thirdPartyInitializerProvider->expects($this->once()) ->method('thirdPartyInitializers') - ->willReturn([$thirdPartyInitializer]); + ->willReturn([$firstInitializer, $secondInitializer]); $version = AnnotatedContainerVersion::version(); $definitionProvider = StubDefinitionProvider::class; @@ -381,6 +399,11 @@ public function testThirdPartyInitializerProvidersAreAddedToConfiguration() : vo $definitionProvider + + Cspray\AnnotatedContainer\Unit\Helper\StubAnalysisListener + Cspray\AnnotatedContainer\Unit\Helper\StubBootstrapListener + Cspray\AnnotatedContainer\Unit\Helper\StubContainerFactoryListener + XML; diff --git a/test/Unit/ProfilesTest.php b/test/Unit/ProfilesTest.php index f2519c77..bdf4fd6a 100644 --- a/test/Unit/ProfilesTest.php +++ b/test/Unit/ProfilesTest.php @@ -8,7 +8,7 @@ use PHPUnit\Framework\TestCase; use Closure; -class ProfilesTest extends TestCase { +final class ProfilesTest extends TestCase { public function testProfilesFromListReturnsCorrectArray() : void { $subject = Profiles::fromList(['default', 'dev', 'prod']); diff --git a/test/Unit/StaticAnalysis/ContainerDefinitionAnalysisOptionsBuilderTest.php b/test/Unit/StaticAnalysis/ContainerDefinitionAnalysisOptionsBuilderTest.php index 87b2a5ab..a58820f5 100644 --- a/test/Unit/StaticAnalysis/ContainerDefinitionAnalysisOptionsBuilderTest.php +++ b/test/Unit/StaticAnalysis/ContainerDefinitionAnalysisOptionsBuilderTest.php @@ -31,4 +31,7 @@ public function testWithDefinitionProviderReturnsCorrectInstance() : void { self::assertSame($expected, $compilerOptions->definitionProvider()); } + + public function testNoScanDirectoriesProvidedThrowsExceptionWhenBuilt() : void { + } } diff --git a/test/Unit/ThirdPartyFunctionsTest.php b/test/Unit/ThirdPartyFunctionsTest.php index 0fa44c98..f45f65b2 100644 --- a/test/Unit/ThirdPartyFunctionsTest.php +++ b/test/Unit/ThirdPartyFunctionsTest.php @@ -10,7 +10,7 @@ use function Cspray\AnnotatedContainer\Definition\service; use function Cspray\AnnotatedContainer\Reflection\types; -class ThirdPartyFunctionsTest extends TestCase { +final class ThirdPartyFunctionsTest extends TestCase { use ContainerDefinitionAssertionsTrait; From ce5e01f2709c5919e46fb43a067847ce256a478d Mon Sep 17 00:00:00 2001 From: Charles Sprayberry Date: Sat, 29 Mar 2025 12:57:57 -0400 Subject: [PATCH 4/5] Add phploc to tools --- Justfile | 8 +++++++- phpunit.xml | 2 ++ .../ContainerDefinitionAnalysisOptionsBuilderTest.php | 3 --- tools/phploc/composer.json | 5 +++++ 4 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 tools/phploc/composer.json diff --git a/Justfile b/Justfile index d5c11db1..328d47a4 100644 --- a/Justfile +++ b/Justfile @@ -4,7 +4,7 @@ _default: just --list --unsorted # Install all dependencies necesesary to run Annotated Container tools -install: _install_labrador_cs _install_phpunit _install_psalm _install_ac +install: _install_labrador_cs _install_phpunit _install_psalm _install_phploc _install_ac _install_ac: composer install @@ -18,6 +18,9 @@ _install_phpunit: _install_psalm: cd tools/psalm && composer install +_install_phploc: + cd tools/phploc && composer install + # Run unit tests test *FLAGS: @XDEBUG_MODE=coverage ./tools/phpunit/vendor/bin/phpunit {{FLAGS}} @@ -47,6 +50,9 @@ code-lint: code-lint-fix: @./tools/labrador-cs/vendor/bin/phpcbf -p --standard=./tools/labrador-cs/vendor/cspray/labrador-coding-standard/ruleset.xml --exclude=Generic.Files.LineLength src test +loc: + @./tools/phploc/vendor/bin/phploc src + # Run all CI checks. ALL checks will run, regardless of failures ci-check: -@just test diff --git a/phpunit.xml b/phpunit.xml index d9d5d70a..493e4762 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -20,8 +20,10 @@ + diff --git a/test/Unit/StaticAnalysis/ContainerDefinitionAnalysisOptionsBuilderTest.php b/test/Unit/StaticAnalysis/ContainerDefinitionAnalysisOptionsBuilderTest.php index a58820f5..87b2a5ab 100644 --- a/test/Unit/StaticAnalysis/ContainerDefinitionAnalysisOptionsBuilderTest.php +++ b/test/Unit/StaticAnalysis/ContainerDefinitionAnalysisOptionsBuilderTest.php @@ -31,7 +31,4 @@ public function testWithDefinitionProviderReturnsCorrectInstance() : void { self::assertSame($expected, $compilerOptions->definitionProvider()); } - - public function testNoScanDirectoriesProvidedThrowsExceptionWhenBuilt() : void { - } } diff --git a/tools/phploc/composer.json b/tools/phploc/composer.json new file mode 100644 index 00000000..5e14c258 --- /dev/null +++ b/tools/phploc/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "phploc/phploc": "^7.0" + } +} \ No newline at end of file From 60d163cd865f369995cae4486c7205b203e502f8 Mon Sep 17 00:00:00 2001 From: Charles Sprayberry Date: Sat, 29 Mar 2025 18:44:56 -0400 Subject: [PATCH 5/5] Add support for listener option --- src/Cli/Command/InitCommand.php | 26 ++++ test/Unit/Cli/Command/InitCommandTest.php | 137 ++++++++++++++++++++++ 2 files changed, 163 insertions(+) diff --git a/src/Cli/Command/InitCommand.php b/src/Cli/Command/InitCommand.php index fa4681d3..39d6f187 100644 --- a/src/Cli/Command/InitCommand.php +++ b/src/Cli/Command/InitCommand.php @@ -103,6 +103,13 @@ public function help() : string { will be defined unless options are passed. If you use this configuration option please review Defining Class Configurations detailed below. + 5. Setup configuration to register Listener implementations in the + Emitter. You can provide multiple --listener options when executing this + command to define configured values. The value passed to this option + MUST be a fully-qualified class name. By default, no listeners will be + defined unless options are passed. If you use this configuration option + please review Defining Class Configurations detailed below. + Resolving File Paths ============================================================================ @@ -138,7 +145,14 @@ class name with an empty constructor. If you require constructor dependencies, Add a ParameterStore to the ContainerFactory. This can be used to allow injecting custom values with the Inject Attribute. Please be sure to review Defining Class Configurations if you use this value. + + --listener="Fully\Qualified\Class\Name" + Add a Listener to the Emitter. This can allow custom functionality to + respond when certain events or actions occur during Annotated Container's + lifecycle. Please be sure to review Defining Class Configurations if you + use this value. + SHELL; } @@ -201,6 +215,11 @@ private function validateInput(Input $input) : void { if (is_bool($parameterStore)) { throw InvalidOptionType::fromBooleanOption('parameter-store'); } + + $listener = $input->option('listener'); + if (is_bool($listener)) { + throw InvalidOptionType::fromBooleanOption('listener'); + } } /** @@ -290,6 +309,12 @@ private function generateAndSaveConfiguration(Input $input, array $composer, str ); $listeners = []; + $listenerInput = $input->option('listener'); + if (is_string($listenerInput)) { + $listeners[] = $listenerInput; + } elseif (is_array($listenerInput)) { + $listeners = $listenerInput; + } foreach ($this->initializerProvider->thirdPartyInitializers() as $thirdPartyInitializer) { $packageRelativeScanDirectories = $thirdPartyInitializer->relativeScanDirectories(); if (count($packageRelativeScanDirectories) > 0) { @@ -326,6 +351,7 @@ private function generateAndSaveConfiguration(Input $input, array $composer, str 'listeners' ); foreach ($listeners as $listener) { + assert(is_string($listener)); $listenersNode->appendChild( $dom->createElementNS(self::XML_SCHEMA, 'listener', $listener) ); diff --git a/test/Unit/Cli/Command/InitCommandTest.php b/test/Unit/Cli/Command/InitCommandTest.php index 4a0a9a03..364bfd2b 100644 --- a/test/Unit/Cli/Command/InitCommandTest.php +++ b/test/Unit/Cli/Command/InitCommandTest.php @@ -124,6 +124,13 @@ public function testGetHelp() : void { will be defined unless options are passed. If you use this configuration option please review Defining Class Configurations detailed below. + 5. Setup configuration to register Listener implementations in the + Emitter. You can provide multiple --listener options when executing this + command to define configured values. The value passed to this option + MUST be a fully-qualified class name. By default, no listeners will be + defined unless options are passed. If you use this configuration option + please review Defining Class Configurations detailed below. + Resolving File Paths ============================================================================ @@ -159,7 +166,14 @@ class name with an empty constructor. If you require constructor dependencies, Add a ParameterStore to the ContainerFactory. This can be used to allow injecting custom values with the Inject Attribute. Please be sure to review Defining Class Configurations if you use this value. + + --listener="Fully\Qualified\Class\Name" + Add a Listener to the Emitter. This can allow custom functionality to + respond when certain events or actions occur during Annotated Container's + lifecycle. Please be sure to review Defining Class Configurations if you + use this value. + SHELL; self::assertSame($expected, $this->subject->help()); @@ -531,6 +545,63 @@ public function testSingleParameterStoreRespected() : void { self::assertSame(0, $exitCode); } + public function testSingleListenerRespected() : void { + $this->directoryResolver->expects($this->once()) + ->method('configurationPath') + ->with('annotated-container.xml') + ->willReturn('/config/dir/annotated-container.xml'); + + $this->directoryResolver->expects($this->once()) + ->method('rootPath') + ->with('composer.json') + ->willReturn('/root/composer.json'); + + $this->filesystem->expects($this->exactly(2)) + ->method('exists') + ->willReturnMap([ + ['/config/dir/annotated-container.xml', false], + ['/root/composer.json', true] + ]); + + $this->filesystem->expects($this->once()) + ->method('read') + ->with('/root/composer.json') + ->willReturn(json_encode([ + 'autoload' => [ + 'psr-4' => [ + 'Another\\Namespace\\' => ['src'] + ] + ], + ], JSON_THROW_ON_ERROR)); + + $version = AnnotatedContainerVersion::version(); + $expected = << + + + + src + + + + + + MyListenerClass + + + +XML; + + $this->filesystem->expects($this->once()) + ->method('write') + ->with('/config/dir/annotated-container.xml', $expected); + + $input = new StubInput(['listener' => 'MyListenerClass'], ['init']); + $exitCode = $this->subject->handle($input, $this->output); + + self::assertSame(0, $exitCode); + } + public function testMultipleParameterStoresRespected() : void { $this->directoryResolver->expects($this->once()) ->method('configurationPath') @@ -589,6 +660,64 @@ public function testMultipleParameterStoresRespected() : void { self::assertSame(0, $exitCode); } + public function testMultipleListenersRespected() : void { + $this->directoryResolver->expects($this->once()) + ->method('configurationPath') + ->with('annotated-container.xml') + ->willReturn('/config/dir/annotated-container.xml'); + + $this->directoryResolver->expects($this->once()) + ->method('rootPath') + ->with('composer.json') + ->willReturn('/root/composer.json'); + + $this->filesystem->expects($this->exactly(2)) + ->method('exists') + ->willReturnMap([ + ['/config/dir/annotated-container.xml', false], + ['/root/composer.json', true] + ]); + + $this->filesystem->expects($this->once()) + ->method('read') + ->with('/root/composer.json') + ->willReturn(json_encode([ + 'autoload' => [ + 'psr-4' => [ + 'Another\\Namespace\\' => ['src'] + ] + ], + ], JSON_THROW_ON_ERROR)); + + $version = AnnotatedContainerVersion::version(); + $expected = << + + + + src + + + + + + MyListenerClassOne + MyListenerClassTwo + + + +XML; + + $this->filesystem->expects($this->once()) + ->method('write') + ->with('/config/dir/annotated-container.xml', $expected); + + $input = new StubInput(['listener' => ['MyListenerClassOne', 'MyListenerClassTwo']], ['init']); + $exitCode = $this->subject->handle($input, $this->output); + + self::assertSame(0, $exitCode); + } + public function testDefinitionProviderBooleanThrowsException() : void { $this->expectException(InvalidOptionType::class); $this->expectExceptionMessage('The option "definition-provider" MUST NOT be a flag-only option.'); @@ -613,6 +742,14 @@ public function testParameterStoreBooleanThrowsException() : void { $this->subject->handle($input, $this->output); } + public function testListenerBooleanThrowsException() : void { + $this->expectException(InvalidOptionType::class); + $this->expectExceptionMessage('The option "listener" MUST NOT be a flag-only option.'); + + $input = new StubInput(['listener' => true], ['init']); + $this->subject->handle($input, $this->output); + } + public function testSuccessfulRunHasCorrectOutput() : void { $this->directoryResolver->expects($this->once()) ->method('configurationPath')