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/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/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/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/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 beffab3b..fa2f0ec6 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;
@@ -33,6 +44,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 +53,8 @@ public static function fromAnnotatedContainerConventions(
$filesystem,
$directoryResolver->configurationPath('annotated-container.xml'),
$parameterStoreFactory,
- $definitionProviderFactory
+ $definitionProviderFactory,
+ $listenerFactory
);
return self::fromCompleteSetup(
@@ -75,6 +88,10 @@ public function bootstrapContainer(
$this->stopwatch->start();
+ foreach ($this->bootstrappingConfiguration->listeners() as $listener) {
+ $this->emitter->addListener($listener);
+ }
+
$analysisOptions = $this->analysisOptions($this->bootstrappingConfiguration);
$this->emitter->emitBeforeBootstrap($this->bootstrappingConfiguration);
diff --git a/src/Bootstrap/BootstrappingConfiguration.php b/src/Bootstrap/Configuration/BootstrappingConfiguration.php
similarity index 79%
rename from src/Bootstrap/BootstrappingConfiguration.php
rename to src/Bootstrap/Configuration/BootstrappingConfiguration.php
index d2bc6830..d79bd7fd 100644
--- a/src/Bootstrap/BootstrappingConfiguration.php
+++ b/src/Bootstrap/Configuration/BootstrappingConfiguration.php
@@ -1,11 +1,12 @@
*/
public function parameterStores() : array;
+
+ /**
+ * @return list
+ */
+ public function listeners() : array;
}
diff --git a/src/Bootstrap/CacheAwareBootstrappingConfiguration.php b/src/Bootstrap/Configuration/CacheAwareBootstrappingConfiguration.php
similarity index 86%
rename from src/Bootstrap/CacheAwareBootstrappingConfiguration.php
rename to src/Bootstrap/Configuration/CacheAwareBootstrappingConfiguration.php
index d1ba5a59..8a239c0d 100644
--- a/src/Bootstrap/CacheAwareBootstrappingConfiguration.php
+++ b/src/Bootstrap/Configuration/CacheAwareBootstrappingConfiguration.php
@@ -1,6 +1,6 @@
configuration->parameterStores();
}
+
+ public function listeners() : array {
+ return $this->configuration->listeners();
+ }
}
diff --git a/src/Bootstrap/ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration.php b/src/Bootstrap/Configuration/ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration.php
similarity index 88%
rename from src/Bootstrap/ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration.php
rename to src/Bootstrap/Configuration/ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration.php
index ddb7d121..f7b7af79 100644
--- a/src/Bootstrap/ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration.php
+++ b/src/Bootstrap/Configuration/ContainerDefinitionAnalysisOptionsFromBootstrappingConfiguration.php
@@ -1,7 +1,8 @@
$identifier
+ * @return Listener
+ */
+ public function createListener(string $identifier) : Listener {
+ assert(is_a($identifier, Listener::class, true));
+ return new $identifier();
+ }
+}
diff --git a/src/Bootstrap/DefaultParameterStoreFactory.php b/src/Bootstrap/Configuration/DefaultParameterStoreFactory.php
similarity index 92%
rename from src/Bootstrap/DefaultParameterStoreFactory.php
rename to src/Bootstrap/Configuration/DefaultParameterStoreFactory.php
index 76eaf395..2fa724e4 100644
--- a/src/Bootstrap/DefaultParameterStoreFactory.php
+++ b/src/Bootstrap/Configuration/DefaultParameterStoreFactory.php
@@ -1,6 +1,6 @@
$identifier
+ * @return Listener
+ */
+ public function createListener(string $identifier) : Listener;
+}
diff --git a/src/Bootstrap/ParameterStoreFactory.php b/src/Bootstrap/Configuration/ParameterStoreFactory.php
similarity index 84%
rename from src/Bootstrap/ParameterStoreFactory.php
rename to src/Bootstrap/Configuration/ParameterStoreFactory.php
index 56eba195..ffa1cde7 100644
--- a/src/Bootstrap/ParameterStoreFactory.php
+++ b/src/Bootstrap/Configuration/ParameterStoreFactory.php
@@ -1,6 +1,6 @@
+ */
+ private readonly array $listeners;
+
public function __construct(
private readonly Filesystem $filesystem,
private readonly string $xmlFile,
private readonly ParameterStoreFactory $parameterStoreFactory,
- private readonly DefinitionProviderFactory $definitionProviderFactory
+ private readonly DefinitionProviderFactory $definitionProviderFactory,
+ private readonly ListenerFactory $listenerFactory,
) {
if (!$this->filesystem->isFile($this->xmlFile)) {
throw InvalidBootstrapConfiguration::fromFileMissing($this->xmlFile);
}
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);
@@ -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);
@@ -142,6 +160,13 @@ public function parameterStores() : array {
return $this->parameterStores;
}
+ /**
+ * @return list
+ */
+ public function listeners() : array {
+ return $this->listeners;
+ }
+
public function cache() : ?ContainerDefinitionCache {
return null;
}
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 @@
>
+ */
+ abstract public function listeners() : array;
+
+ /**
+ * @return ?class-string
+ */
abstract public function definitionProviderClass() : ?string;
}
diff --git a/src/Bootstrap/ThirdPartyInitializerProvider.php b/src/Bootstrap/Initializer/ThirdPartyInitializerProvider.php
similarity index 76%
rename from src/Bootstrap/ThirdPartyInitializerProvider.php
rename to src/Bootstrap/Initializer/ThirdPartyInitializerProvider.php
index b8ba4ed6..d21b1b14 100644
--- a/src/Bootstrap/ThirdPartyInitializerProvider.php
+++ b/src/Bootstrap/Initializer/ThirdPartyInitializerProvider.php
@@ -1,6 +1,6 @@
$type
- * @return list>
+ * @return list
*/
public function servicesForType(string $type) : 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..58e5bc6b 100644
--- a/src/Bootstrap/ServiceWiringListener.php
+++ b/src/Bootstrap/Listener/ServiceWiringListener.php
@@ -1,6 +1,6 @@
$type
- * @return list>
+ * @return list
*/
public function servicesForType(string $type) : array {
- /** @var list> $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 e59f5dae..9a864245 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\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;
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..39d6f187 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;
@@ -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');
+ }
}
/**
@@ -288,6 +307,14 @@ private function generateAndSaveConfiguration(Input $input, array $composer, str
$vendor = $scanDirectories->appendChild(
$dom->createElementNS(self::XML_SCHEMA, 'vendor')
);
+
+ $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) {
@@ -314,6 +341,22 @@ 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) {
+ assert(is_string($listener));
+ $listenersNode->appendChild(
+ $dom->createElementNS(self::XML_SCHEMA, 'listener', $listener)
+ );
+ }
+ $root->appendChild($listenersNode);
}
$schemaPath = dirname(__DIR__, 3) . '/annotated-container.xsd';
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/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/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/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 49029ecc..70dd386d 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 {
@@ -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 319a3e6f..a1f3959f 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
@@ -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 67a6fe60..85bbc54e 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
@@ -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 b267d3fc..c42a8ce5 100644
--- a/test/Unit/Bootstrap/BootstrapTest.php
+++ b/test/Unit/Bootstrap/BootstrapTest.php
@@ -4,13 +4,17 @@
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\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\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,20 +26,23 @@
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\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 {
@@ -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 ae22e123..3d7f31cb 100644
--- a/test/Unit/Bootstrap/CacheAwareBootstrappingConfigurationTest.php
+++ b/test/Unit/Bootstrap/CacheAwareBootstrappingConfigurationTest.php
@@ -2,9 +2,10 @@
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\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 a8b1d630..701ac00c 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\Initializer\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 965d62be..d0270139 100644
--- a/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php
+++ b/test/Unit/Bootstrap/XmlBootstrappingConfigurationTest.php
@@ -2,22 +2,26 @@
namespace Cspray\AnnotatedContainer\Unit\Bootstrap;
-use Cspray\AnnotatedContainer\Bootstrap\DefaultDefinitionProviderFactory;
-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\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;
-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;
@@ -64,6 +68,7 @@ public function testXmlDoesNotValidateSchemaThrowsError() : void {
'/my/path/to/annotated-container.xml',
new DefaultParameterStoreFactory(),
new DefaultDefinitionProviderFactory(),
+ new DefaultListenerFactory()
);
}
@@ -91,6 +96,7 @@ public function testValidXmlReturnsScanDirectories() : void {
'/path/to/annotated-container.xml',
new DefaultParameterStoreFactory(),
new DefaultDefinitionProviderFactory(),
+ new DefaultListenerFactory()
);
self::assertSame(
@@ -124,6 +130,7 @@ public function testValidXmlReturnsDefinitionProvider() : void {
'/path/annotated-container.xml',
new DefaultParameterStoreFactory(),
new DefaultDefinitionProviderFactory(),
+ new DefaultListenerFactory()
);
$provider = $configuration->containerDefinitionProvider();
self::assertInstanceOf(
@@ -158,6 +165,7 @@ public function testDefinitionProviderEmptyIfNoneDefined() : void {
'annotated-container.xml',
new DefaultParameterStoreFactory(),
new DefaultDefinitionProviderFactory(),
+ new DefaultListenerFactory()
);
self::assertNull($config->containerDefinitionProvider());
@@ -182,6 +190,7 @@ public function testCacheDirNotSpecifiedReturnsNull() : void {
'annotated-container.xml',
new DefaultParameterStoreFactory(),
new DefaultDefinitionProviderFactory(),
+ new DefaultListenerFactory()
);
self::assertNull($config->cache());
}
@@ -205,6 +214,7 @@ public function testCacheIsAlwaysNull() : void {
'annotated-container.xml',
new DefaultParameterStoreFactory(),
new DefaultDefinitionProviderFactory(),
+ new DefaultListenerFactory()
);
self::assertNull($config->cache());
@@ -232,6 +242,7 @@ public function testParameterStoresReturned() : void {
'annotated-container.xml',
new DefaultParameterStoreFactory(),
new DefaultDefinitionProviderFactory(),
+ new DefaultListenerFactory()
);
self::assertCount(1, $config->parameterStores());
@@ -271,6 +282,7 @@ public function createParameterStore(string $identifier) : ParameterStore {
'annotated-container.xml',
$parameterStoreFactory,
new DefaultDefinitionProviderFactory(),
+ new DefaultListenerFactory()
);
self::assertCount(1, $config->parameterStores());
@@ -304,7 +316,8 @@ public function createProvider(string $identifier) : DefinitionProvider {
$this->filesystem,
'annotated-container.xml',
new DefaultParameterStoreFactory(),
- $consumerFactory
+ $consumerFactory,
+ new DefaultListenerFactory()
);
$provider = $config->containerDefinitionProvider();
@@ -347,7 +360,8 @@ public function testVendorScanDirectoriesIncludedInList() : void {
$this->filesystem,
'annotated-container.xml',
new DefaultParameterStoreFactory(),
- new DefaultDefinitionProviderFactory()
+ new DefaultDefinitionProviderFactory(),
+ new DefaultListenerFactory()
);
self::assertSame(
@@ -369,7 +383,79 @@ public function testConfigurationFileNotPresentThrowsException() : void {
$this->filesystem,
'annotated-container.xml',
new DefaultParameterStoreFactory(),
- new DefaultDefinitionProviderFactory()
+ new DefaultDefinitionProviderFactory(),
+ 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/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 = <<subject->help());
@@ -343,20 +360,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 +413,11 @@ public function testThirdPartyInitializerProvidersAreAddedToConfiguration() : vo
$definitionProvider
+
+ Cspray\AnnotatedContainer\Unit\Helper\StubAnalysisListener
+ Cspray\AnnotatedContainer\Unit\Helper\StubBootstrapListener
+ Cspray\AnnotatedContainer\Unit\Helper\StubContainerFactoryListener
+
XML;
@@ -508,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')
@@ -566,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.');
@@ -590,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')
diff --git a/test/Unit/Cli/Command/ValidateCommandTest.php b/test/Unit/Cli/Command/ValidateCommandTest.php
index 47700841..933a76b7 100644
--- a/test/Unit/Cli/Command/ValidateCommandTest.php
+++ b/test/Unit/Cli/Command/ValidateCommandTest.php
@@ -3,10 +3,12 @@
namespace Cspray\AnnotatedContainer\Unit\Cli\Command;
use Cspray\AnnotatedContainer\Attribute\Service;
-use Cspray\AnnotatedContainer\Bootstrap\BootstrappingConfiguration;
+use Cspray\AnnotatedContainer\Bootstrap\Configuration\BootstrappingConfiguration;
use Cspray\AnnotatedContainer\Cli\Command\ValidateCommand;
use Cspray\AnnotatedContainer\Cli\Exception\ProfileNotString;
use Cspray\AnnotatedContainer\Cli\Output\TerminalOutput;
+use Cspray\AnnotatedContainer\Fixture\LogicalConstraints\DuplicateServiceType\DummyService;
+use Cspray\AnnotatedContainer\Fixture\LogicalConstraints\LogicalConstraintFixtures;
use Cspray\AnnotatedContainer\LogicalConstraint\Check\DuplicateServiceDelegate;
use Cspray\AnnotatedContainer\LogicalConstraint\Check\DuplicateServiceName;
use Cspray\AnnotatedContainer\LogicalConstraint\Check\DuplicateServicePrepare;
@@ -17,8 +19,6 @@
use Cspray\AnnotatedContainer\Unit\Helper\FixtureBootstrappingDirectoryResolver;
use Cspray\AnnotatedContainer\Unit\Helper\InMemoryOutput;
use Cspray\AnnotatedContainer\Unit\Helper\StubInput;
-use Cspray\AnnotatedContainer\Fixture\LogicalConstraints\DuplicateServiceType\DummyService;
-use Cspray\AnnotatedContainer\Fixture\LogicalConstraints\LogicalConstraintFixtures;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
diff --git a/test/Unit/Event/EmitterTest.php b/test/Unit/Event/EmitterTest.php
index 733372a5..639d2d62 100644
--- a/test/Unit/Event/EmitterTest.php
+++ b/test/Unit/Event/EmitterTest.php
@@ -4,7 +4,7 @@
use Closure;
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/test/Unit/Helper/FixtureBootstrappingDirectoryResolver.php b/test/Unit/Helper/FixtureBootstrappingDirectoryResolver.php
index 178f5559..ddb3bb9a 100644
--- a/test/Unit/Helper/FixtureBootstrappingDirectoryResolver.php
+++ b/test/Unit/Helper/FixtureBootstrappingDirectoryResolver.php
@@ -2,7 +2,7 @@
namespace Cspray\AnnotatedContainer\Unit\Helper;
-use Cspray\AnnotatedContainer\Bootstrap\BootstrappingDirectoryResolver;
+use Cspray\AnnotatedContainer\Bootstrap\DirectoryResolver\BootstrappingDirectoryResolver;
use Cspray\AnnotatedContainer\Fixture\Fixtures;
final class FixtureBootstrappingDirectoryResolver implements BootstrappingDirectoryResolver {
diff --git a/test/Unit/Helper/StubBootstrapListener.php b/test/Unit/Helper/StubBootstrapListener.php
index 560a615c..df18f2c6 100644
--- a/test/Unit/Helper/StubBootstrapListener.php
+++ b/test/Unit/Helper/StubBootstrapListener.php
@@ -3,7 +3,7 @@
namespace Cspray\AnnotatedContainer\Unit\Helper;
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\Bootstrap\AfterBootstrap;
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/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;
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