diff --git a/src/ContainerWordPress/Contracts/Provider.php b/src/ContainerWordPress/Contracts/Provider.php new file mode 100644 index 0000000..422f8fa --- /dev/null +++ b/src/ContainerWordPress/Contracts/Provider.php @@ -0,0 +1,51 @@ + $config + */ + public function __construct( + /** @var Container|ContainerAdapter $container */ + protected readonly Container $container, + protected readonly Dot $config + ) { + } + + /** + * {@inheritDoc} + */ + public function isDeferred(): bool { + return $this->deferred; + } + + /** + * {@inheritDoc} + */ + public function provides(): array { + return []; + } + + /** + * {@inheritDoc} + */ + public function boot(): void { + } +} diff --git a/src/ContainerWordPress/README.md b/src/ContainerWordPress/README.md index 3d944d7..ae8a5f7 100644 --- a/src/ContainerWordPress/README.md +++ b/src/ContainerWordPress/README.md @@ -23,6 +23,7 @@ Foundation container contract: namespace My\App; +use Adbar\Dot; use lucatume\DI52\Container; use StellarWP\Foundation\Container\Contracts\Container as ContainerContract; use StellarWP\Foundation\ContainerWordPress\Contracts\Container as WPContainerContract; @@ -35,11 +36,35 @@ $container = new ContainerAdapter(new FoundationContainerAdapter(new Container() // Bind the concrete to the interface, so anytime we ask for a container we get this one. $container->bind(ContainerContract::class, $container); $container->bind(WPContainerContract::class, $container); + +// Register project configuration. See the Foundation Container README for a fuller config.php example. +$container->bind(Dot::class, new Dot(require_once dirname(__FILE__) . '/config.php')); ``` Everything the [Foundation Container](https://github.com/stellarwp/foundation-container) can do, this wrapper can do too — binding, singletons, service providers, contextual bindings, and so on. +## Service Providers + +When a provider needs WordPress-specific container helpers, extend the WordPress-aware provider base: + +```php +container->registerOnAction( 'init', Other_Provider::class ); + } +} +``` + +The base Foundation provider still works for providers that only need the standard container API. + ## WordPress helpers On top of the base container API, this wrapper adds hook-aware service provider diff --git a/tests/Support/Fixtures/ContainerWordPress/WordPressAwareProvider.php b/tests/Support/Fixtures/ContainerWordPress/WordPressAwareProvider.php new file mode 100644 index 0000000..04827a7 --- /dev/null +++ b/tests/Support/Fixtures/ContainerWordPress/WordPressAwareProvider.php @@ -0,0 +1,22 @@ +container->registerOnAction(self::ACTION, FirstProvider::class); + } + + public function container(): Container { + return $this->container; + } +} diff --git a/tests/wpunit/ContainerWordPress/ProviderTest.php b/tests/wpunit/ContainerWordPress/ProviderTest.php new file mode 100644 index 0000000..3e1f5d6 --- /dev/null +++ b/tests/wpunit/ContainerWordPress/ProviderTest.php @@ -0,0 +1,71 @@ +adapter = new ContainerAdapter(new FoundationContainerAdapter(new DI52Container())); + + $this->adapter->bind(FoundationContainer::class, $this->adapter); + $this->adapter->bind(WPContainerContract::class, $this->adapter); + $this->adapter->singleton(Dot::class, new Dot()); + } + + /** + * Build the "registered" action name the adapter fires for a provider or alias. + */ + private function registered_action(string $identifier): string { + return 'nexcess/foundation/container/wp/' . $identifier . '/registered'; + } + + /** + * Count how many times a WordPress action fires while a callback is attached. + */ + private function count_action(string $action): callable { + $original = did_action($action); + + return static fn (): int => did_action($action) - $original; + } + + public function test_it_is_a_providable_provider_with_a_wordpress_container(): void { + $provider = $this->adapter->get(WordPressAwareProvider::class); + + $this->assertInstanceOf(Providable::class, $provider); + $this->assertInstanceOf(WordPressAwareProvider::class, $provider); + $this->assertSame($this->adapter, $provider->container()); + $this->assertFalse($provider->isDeferred()); + $this->assertSame([], $provider->provides()); + } + + public function test_it_allows_subclasses_to_use_wordpress_container_methods(): void { + $fired = $this->count_action($this->registered_action(FirstProvider::class)); + + $this->adapter->register(WordPressAwareProvider::class); + + $this->assertSame(0, $fired()); + + do_action(WordPressAwareProvider::ACTION); + + $this->assertSame(1, $fired()); + + do_action(WordPressAwareProvider::ACTION); + + $this->assertSame(1, $fired()); + } +}