From c7a9bc2be59e7f09781ab2402a4dfdb8e7d3d80e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20Es=CC=8Cler?= Date: Fri, 10 Jul 2020 13:53:06 +0200 Subject: [PATCH] move factories into theirs own container --- src/ServiceContainer.php | 37 +++++++++++------------ src/ServiceContainer/FactoryContainer.php | 35 +++++++++++++++++++++ tests/ServiceContainerTest.php | 4 +-- 3 files changed, 55 insertions(+), 21 deletions(-) create mode 100644 src/ServiceContainer/FactoryContainer.php diff --git a/src/ServiceContainer.php b/src/ServiceContainer.php index 06aecd2..22a8141 100644 --- a/src/ServiceContainer.php +++ b/src/ServiceContainer.php @@ -4,10 +4,8 @@ namespace IW; -use IW\ServiceContainer\AliasFactory; -use IW\ServiceContainer\CallableFactory; -use IW\ServiceContainer\ClassnameFactory; use IW\ServiceContainer\EmptyResultFromFactory; +use IW\ServiceContainer\FactoryContainer; use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; @@ -15,12 +13,17 @@ class ServiceContainer implements ContainerInterface { - /** @var callable[] */ - private $factories = []; + /** @var FactoryContainer */ + private $factories; /** @var mixed[] */ private $instances = []; + public function __construct() + { + $this->factories = new FactoryContainer(); + } + /** * Sets an alias for a dependency, it's useful for binding implementations * to a interface. Container will resolve alias as late as possible. @@ -40,7 +43,7 @@ class ServiceContainer implements ContainerInterface */ public function alias(string $alias, string $id): void { - $this->factories[$alias] = new AliasFactory($id); + $this->factories->alias($alias, $id); } /** @@ -55,32 +58,27 @@ public function alias(string $alias, string $id): void */ public function bind(string $id, callable $factory): void { - $this->factories[$id] = new CallableFactory($factory); + $this->factories->bind($id, $factory); } public function factory(string $id): callable { - if (isset($this->factories[$id])) { - return $this->factories[$id]; - } - - return $this->factories[$id] = new ClassnameFactory($id); + return $this->factories->get($id); } /** * Finds an entry of the container by its identifier and returns it. * - * @template T * @param class-string $id Identifier of the entry to look for. * - * @return mixed Entry. + * @return T * * @throws NotFoundExceptionInterface No entry was found for **this** identifier. * @throws ContainerExceptionInterface Error while retrieving the entry. * - * @return T + * @template T */ - public function get($id) // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + public function get($id) // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint,SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint,Generic.Files.LineLength.TooLong { if (isset($this->instances[$id])) { return $this->instances[$id]; // try load a singleton if saved @@ -110,7 +108,7 @@ public function has($id) // phpcs:ignore SlevomatCodingStandard.TypeHints.Parame } // a factory exists - if (isset($this->factories[$id])) { + if ($this->factories->has($id)) { return true; } @@ -137,12 +135,13 @@ public function singleton(string $id) /** * Makes a new instance of a service. Dependencies are resolved from the container. * - * @template T * @param class-string $id ID of entry we want to create new instance of * * @return T + * + * @template T */ - public function make(string $id) + public function make(string $id) // phpcs:ignore SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint,Generic.Files.LineLength.TooLong { $instance = $this->factory($id)($this); diff --git a/src/ServiceContainer/FactoryContainer.php b/src/ServiceContainer/FactoryContainer.php new file mode 100644 index 0000000..00296f2 --- /dev/null +++ b/src/ServiceContainer/FactoryContainer.php @@ -0,0 +1,35 @@ +factories[$alias] = new AliasFactory($id); + } + + public function bind(string $id, callable $factory): void + { + $this->factories[$id] = new CallableFactory($factory); + } + + public function get(string $id): ServiceFactory + { + if (isset($this->factories[$id])) { + return $this->factories[$id]; + } + + return $this->factories[$id] = new ClassnameFactory($id); + } + + public function has(string $id): bool + { + return isset($this->factories[$id]); + } +} diff --git a/tests/ServiceContainerTest.php b/tests/ServiceContainerTest.php index d1e2393..e2817a1 100644 --- a/tests/ServiceContainerTest.php +++ b/tests/ServiceContainerTest.php @@ -109,7 +109,7 @@ public function testBindingCustomFactory(): void */ public function testHasMethod(string $id, bool $has): void { - $container = $this->createPartialMock(ServiceContainer::class, ['make']); + $container = $this->createTestProxy(ServiceContainer::class, ['make']); $container->expects($this->never())->method('make'); if ($has) { @@ -131,7 +131,7 @@ public function testHasASingleton(): void public function testHasAFactory(): void { - $container = $this->createPartialMock(ServiceContainer::class, ['make', 'factory']); + $container = $this->createTestProxy(ServiceContainer::class, ['make', 'factory']); $container->expects($this->never())->method('make'); $container->expects($this->never())->method('factory');