From 900833e6f0f9fd5208ebc1a6653f0fd36e43edc6 Mon Sep 17 00:00:00 2001 From: tux-rampage Date: Wed, 6 Dec 2017 06:39:22 +0100 Subject: [PATCH 1/9] Add test case for generator factory --- test/Container/GeneratorFactoryTest.php | 62 +++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 test/Container/GeneratorFactoryTest.php diff --git a/test/Container/GeneratorFactoryTest.php b/test/Container/GeneratorFactoryTest.php new file mode 100644 index 00000000..78b219b0 --- /dev/null +++ b/test/Container/GeneratorFactoryTest.php @@ -0,0 +1,62 @@ +getContainer()); + $this->assertInstanceOf(InjectorGenerator::class, $result); + } + + public function testFactoryUsesServicesFromContainer() + { + $container = $this->getMockBuilder(ContainerInterface::class)->getMockForAbstractClass(); + $container->expects($this->atLeastOnce()) + ->method('has') + ->with(InjectorInterface::class) + ->willReturn(true); + + $container->expects($this->atLeastOnce()) + ->method('has') + ->with(ConfigInterface::class) + ->willReturn(true); + + $container->method('has')->willReturn(false); + + $container->expects($this->atLeastOnce()) + ->method('get') + ->with(InjectorInterface::class) + ->willReturn(new Injector()); + + $container->expects($this->atLeastOnce()) + ->method('get') + ->with(ConfigInterface::class) + ->willReturn(new Config()); + + $factory = new GeneratorFactory(); + $factory($container); + } +} From 37c9cad91d73e87a91df7d28d922328d4ac86d7d Mon Sep 17 00:00:00 2001 From: tux-rampage Date: Wed, 6 Dec 2017 06:43:16 +0100 Subject: [PATCH 2/9] Add generator factory --- src/Container/GeneratorFactory.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/Container/GeneratorFactory.php diff --git a/src/Container/GeneratorFactory.php b/src/Container/GeneratorFactory.php new file mode 100644 index 00000000..76778470 --- /dev/null +++ b/src/Container/GeneratorFactory.php @@ -0,0 +1,23 @@ +create($container); + } +} From f31987dfb20e2fd33274cd955f69d4f2d119e114 Mon Sep 17 00:00:00 2001 From: tux-rampage Date: Wed, 6 Dec 2017 06:47:04 +0100 Subject: [PATCH 3/9] Fix use statement order --- test/Container/GeneratorFactoryTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Container/GeneratorFactoryTest.php b/test/Container/GeneratorFactoryTest.php index 78b219b0..50fd44a8 100644 --- a/test/Container/GeneratorFactoryTest.php +++ b/test/Container/GeneratorFactoryTest.php @@ -9,12 +9,12 @@ use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; -use Zend\Di\InjectorInterface; -use Zend\Di\Injector; -use Zend\Di\Container\GeneratorFactory; use Zend\Di\CodeGenerator\InjectorGenerator; -use Zend\Di\ConfigInterface; use Zend\Di\Config; +use Zend\Di\ConfigInterface; +use Zend\Di\Container\GeneratorFactory; +use Zend\Di\Injector; +use Zend\Di\InjectorInterface; /** * @covers Zend\Di\Container\GeneratorFactory From 8a7fc189816c850c42a4ac20aac649132e20af1b Mon Sep 17 00:00:00 2001 From: tux-rampage Date: Thu, 7 Dec 2017 12:52:16 +0100 Subject: [PATCH 4/9] Refactor container usage test to test one aspect per test --- test/Container/GeneratorFactoryTest.php | 33 ++++++++++++++----------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/test/Container/GeneratorFactoryTest.php b/test/Container/GeneratorFactoryTest.php index 50fd44a8..5967bb26 100644 --- a/test/Container/GeneratorFactoryTest.php +++ b/test/Container/GeneratorFactoryTest.php @@ -31,30 +31,35 @@ public function testInvokeCreatesGenerator() $this->assertInstanceOf(InjectorGenerator::class, $result); } - public function testFactoryUsesServicesFromContainer() + /** + * Data provider for testFactoryUsesServiceFromContainer + */ + public function provideContainerServices() { - $container = $this->getMockBuilder(ContainerInterface::class)->getMockForAbstractClass(); - $container->expects($this->atLeastOnce()) - ->method('has') - ->with(InjectorInterface::class) - ->willReturn(true); + return [ + // serviceName, provided instance + 'config' => [ConfigInterface::class, new Config()], + 'injector' => [InjectorInterface::class, new Injector()] + ]; + } + /** + * @dataProvider provideContainerServices + */ + public function testFactoryUsesServiceFromContainer(string $serviceName, $instance): void + { + $container = $this->getMockBuilder(ContainerInterface::class)->getMockForAbstractClass(); $container->expects($this->atLeastOnce()) ->method('has') - ->with(ConfigInterface::class) + ->with($serviceName) ->willReturn(true); $container->method('has')->willReturn(false); $container->expects($this->atLeastOnce()) ->method('get') - ->with(InjectorInterface::class) - ->willReturn(new Injector()); - - $container->expects($this->atLeastOnce()) - ->method('get') - ->with(ConfigInterface::class) - ->willReturn(new Config()); + ->with($serviceName) + ->willReturn($instance); $factory = new GeneratorFactory(); $factory($container); From 429002cd57cac027655fbcd5ddbada933b8de560 Mon Sep 17 00:00:00 2001 From: tux-rampage Date: Fri, 8 Dec 2017 17:01:17 +0100 Subject: [PATCH 5/9] Add missing test cases --- test/ConfigProviderTest.php | 31 ++++++++++- test/Container/GeneratorFactoryTest.php | 74 ++++++++++++++++--------- 2 files changed, 76 insertions(+), 29 deletions(-) diff --git a/test/ConfigProviderTest.php b/test/ConfigProviderTest.php index 4e408932..8459f207 100644 --- a/test/ConfigProviderTest.php +++ b/test/ConfigProviderTest.php @@ -10,18 +10,21 @@ use PHPUnit\Framework\TestCase; use Zend\Di\ConfigProvider; use PHPUnit\Framework\Constraint\IsType; +use Zend\Di\CodeGenerator\InjectorGenerator; +use Zend\Di\InjectorInterface; +use Zend\Di\ConfigInterface; /** * @coversDefaultClass Zend\Di\Module */ class ConfigProviderTest extends TestCase { - public function testInstanceIsInvokable() + public function testInstanceIsInvokable(): void { $this->assertInternalType(IsType::TYPE_CALLABLE, new ConfigProvider()); } - public function testProvidesDependencies() + public function testProvidesDependencies(): void { $provider = new ConfigProvider(); $result = $provider(); @@ -29,4 +32,28 @@ public function testProvidesDependencies() $this->assertArrayHasKey('dependencies', $result); $this->assertEquals($provider->getDependencyConfig(), $result['dependencies']); } + + /** + * Provides service names that should be defined with a factory + */ + public function provideExpectedServicesWithFactory(): iterable + { + return [ + // service name + 'injector' => [ InjectorInterface::class ], + 'config' => [ ConfigInterface::class ], + 'generator' => [ InjectorGenerator::class ], + ]; + } + + /** + * Test if a service is provided by factory definition + * + * @dataProvider provideExpectedServicesWithFactory + */ + public function testProvidesFactoryDefinition(string $serviceName): void + { + $result = (new ConfigProvider())->getDependencyConfig(); + $this->assertArrayHasKey($serviceName, $result['factories']); + } } diff --git a/test/Container/GeneratorFactoryTest.php b/test/Container/GeneratorFactoryTest.php index 5967bb26..95f81411 100644 --- a/test/Container/GeneratorFactoryTest.php +++ b/test/Container/GeneratorFactoryTest.php @@ -7,6 +7,7 @@ namespace ZendTest\Di\Container; +use org\bovigo\vfs\vfsStream; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Zend\Di\CodeGenerator\InjectorGenerator; @@ -14,7 +15,7 @@ use Zend\Di\ConfigInterface; use Zend\Di\Container\GeneratorFactory; use Zend\Di\Injector; -use Zend\Di\InjectorInterface; +use Zend\ServiceManager\ServiceManager; /** * @covers Zend\Di\Container\GeneratorFactory @@ -27,41 +28,60 @@ public function testInvokeCreatesGenerator() $injector = new Injector(); $factory = new GeneratorFactory(); - $result = $factory($injector->getContainer()); + $result = $factory->create($injector->getContainer()); $this->assertInstanceOf(InjectorGenerator::class, $result); } - /** - * Data provider for testFactoryUsesServiceFromContainer - */ - public function provideContainerServices() - { - return [ - // serviceName, provided instance - 'config' => [ConfigInterface::class, new Config()], - 'injector' => [InjectorInterface::class, new Injector()] - ]; - } - - /** - * @dataProvider provideContainerServices - */ - public function testFactoryUsesServiceFromContainer(string $serviceName, $instance): void + public function testFactoryUsesDiConfigContainer(): void { $container = $this->getMockBuilder(ContainerInterface::class)->getMockForAbstractClass(); - $container->expects($this->atLeastOnce()) - ->method('has') - ->with($serviceName) - ->willReturn(true); - - $container->method('has')->willReturn(false); + $container->method('has')->willReturnCallback(function ($type) { + return ($type == ConfigInterface::class); + }); $container->expects($this->atLeastOnce()) ->method('get') - ->with($serviceName) - ->willReturn($instance); + ->with(ConfigInterface::class) + ->willReturn(new Config()); $factory = new GeneratorFactory(); - $factory($container); + $factory->create($container); + } + + public function testSetsOutputDirectoryFromConfig() + { + $vfs = vfsStream::setup(uniqid('zend-di')); + $expected = $vfs->url(); + $container = new ServiceManager(); + $container->setService('config', [ + 'dependencies' => [ + 'auto' => [ + 'aot' => [ + 'directory' => $expected + ], + ], + ], + ]); + + $generator = (new GeneratorFactory())->create($container); + $this->assertEquals($expected, $generator->getOutputDirectory()); + } + + public function testSetsNamespaceFromConfig() + { + $expected = 'ZendTest\\Di\\' . uniqid('Generated'); + $container = new ServiceManager(); + $container->setService('config', [ + 'dependencies' => [ + 'auto' => [ + 'aot' => [ + 'namespace' => $expected, + ], + ], + ], + ]); + + $generator = (new GeneratorFactory())->create($container); + $this->assertEquals($expected, $generator->getNamespace()); } } From 8153e4dcd5a46c3a1406360ca78526605d342024 Mon Sep 17 00:00:00 2001 From: tux-rampage Date: Fri, 8 Dec 2017 17:01:50 +0100 Subject: [PATCH 6/9] Implement generator factory --- src/CodeGenerator/GeneratorTrait.php | 8 +++++++ src/CodeGenerator/InjectorGenerator.php | 8 +++++++ src/ConfigProvider.php | 3 ++- src/Container/GeneratorFactory.php | 28 ++++++++++++++++++++++++- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/CodeGenerator/GeneratorTrait.php b/src/CodeGenerator/GeneratorTrait.php index 074846ba..6d224c6b 100644 --- a/src/CodeGenerator/GeneratorTrait.php +++ b/src/CodeGenerator/GeneratorTrait.php @@ -80,4 +80,12 @@ public function setOutputDirectory(string $dir, ?int $mode = null) : self return $this; } + + /** + * @return string + */ + public function getOutputDirectory(): ?string + { + return $this->outputDirectory; + } } diff --git a/src/CodeGenerator/InjectorGenerator.php b/src/CodeGenerator/InjectorGenerator.php index 7d411846..1275e0f8 100644 --- a/src/CodeGenerator/InjectorGenerator.php +++ b/src/CodeGenerator/InjectorGenerator.php @@ -146,6 +146,14 @@ private function generateAutoload() $this->autoloadGenerator->generate($classmap); } + /** + * Returns the namespace this generator uses + */ + public function getNamespace(): string + { + return $this->namespace; + } + /** * Generate the injector * diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index c85346fd..54b5bc71 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -34,7 +34,8 @@ public function getDependencyConfig() : array return [ 'factories' => [ InjectorInterface::class => Container\InjectorFactory::class, - ConfigInterface::class => Container\ConfigFactory::class + ConfigInterface::class => Container\ConfigFactory::class, + CodeGenerator\InjectorGenerator::class => Container\GeneratorFactory::class, ], 'abstract_factories' => [ Container\ServiceManager\AutowireFactory::class diff --git a/src/Container/GeneratorFactory.php b/src/Container/GeneratorFactory.php index 76778470..77d79698 100644 --- a/src/Container/GeneratorFactory.php +++ b/src/Container/GeneratorFactory.php @@ -8,12 +8,38 @@ namespace Zend\Di\Container; use Psr\Container\ContainerInterface; +use Zend\Di\CodeGenerator\InjectorGenerator; +use Zend\Di\ConfigInterface; +use Zend\Di\Definition\RuntimeDefinition; +use Zend\Di\Resolver\DependencyResolver; class GeneratorFactory { + private function getConfig(ContainerInterface $container) + { + if ($container->has(ConfigInterface::class)) { + return $container->get(ConfigInterface::class); + } + + return (new ConfigFactory())->create($container); + } + public function create(ContainerInterface $container) { - // TODO: Implement the factory + $config = $container->has('config') ? $container->get('config') : []; + $diConfig = $this->getConfig($container); + $aotConfig = $config['dependencies']['auto']['aot'] ?? []; + $resolver = new DependencyResolver(new RuntimeDefinition(), $diConfig); + $namespace = $aotConfig['namespace'] ?? null; + + $resolver->setContainer($container); + $generator = new InjectorGenerator($diConfig, $resolver, $namespace); + + if (isset($aotConfig['directory'])) { + $generator->setOutputDirectory($aotConfig['directory']); + } + + return $generator; } public function __invoke(ContainerInterface $container) From 7781e61184bd205ac31ad77b19bbf11485b1f820 Mon Sep 17 00:00:00 2001 From: tux-rampage Date: Fri, 8 Dec 2017 17:15:31 +0100 Subject: [PATCH 7/9] Add test for construct with custom namespace --- test/CodeGenerator/InjectorGeneratorTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/CodeGenerator/InjectorGeneratorTest.php b/test/CodeGenerator/InjectorGeneratorTest.php index 5b971db0..15ac2070 100644 --- a/test/CodeGenerator/InjectorGeneratorTest.php +++ b/test/CodeGenerator/InjectorGeneratorTest.php @@ -58,4 +58,14 @@ public function testGeneratedInjectorIsValidCode() include $this->dir . '/GeneratedInjector.php'; $this->assertTrue(class_exists($class, false)); } + + public function testSetCustomNamespace() + { + $expected = self::DEFAULT_NAMESPACE . uniqid(); + $config = new Config(); + $resolver = new DependencyResolver(new RuntimeDefinition(), $config); + $generator = new InjectorGenerator($config, $resolver, $expected); + + $this->assertEquals($expected, $generator->getNamespace()); + } } From 839dafbe2f5ba552cd77709caeec86c5801868cc Mon Sep 17 00:00:00 2001 From: tux-rampage Date: Fri, 8 Dec 2017 17:26:25 +0100 Subject: [PATCH 8/9] Add missing test for invoke --- test/Container/GeneratorFactoryTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/Container/GeneratorFactoryTest.php b/test/Container/GeneratorFactoryTest.php index 95f81411..6b0fc30e 100644 --- a/test/Container/GeneratorFactoryTest.php +++ b/test/Container/GeneratorFactoryTest.php @@ -84,4 +84,21 @@ public function testSetsNamespaceFromConfig() $generator = (new GeneratorFactory())->create($container); $this->assertEquals($expected, $generator->getNamespace()); } + + public function testInvokeCallsCreate() + { + $mock = $this->getMockBuilder(GeneratorFactory::class) + ->setMethods(['create']) + ->enableProxyingToOriginalMethods() + ->getMock(); + + $container = $this->getMockBuilder(ContainerInterface::class) + ->getMockForAbstractClass(); + + $mock->expects($this->once()) + ->method('create') + ->with($container); + + $mock($container); + } } From 3c27630304e7edd27e7477f8fec6dcbe10a0513c Mon Sep 17 00:00:00 2001 From: tux-rampage Date: Fri, 8 Dec 2017 17:26:38 +0100 Subject: [PATCH 9/9] Add typehints --- src/Container/GeneratorFactory.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Container/GeneratorFactory.php b/src/Container/GeneratorFactory.php index 77d79698..30f2dc5a 100644 --- a/src/Container/GeneratorFactory.php +++ b/src/Container/GeneratorFactory.php @@ -15,7 +15,7 @@ class GeneratorFactory { - private function getConfig(ContainerInterface $container) + private function getConfig(ContainerInterface $container): ConfigInterface { if ($container->has(ConfigInterface::class)) { return $container->get(ConfigInterface::class); @@ -24,7 +24,7 @@ private function getConfig(ContainerInterface $container) return (new ConfigFactory())->create($container); } - public function create(ContainerInterface $container) + public function create(ContainerInterface $container): InjectorGenerator { $config = $container->has('config') ? $container->get('config') : []; $diConfig = $this->getConfig($container); @@ -42,7 +42,7 @@ public function create(ContainerInterface $container) return $generator; } - public function __invoke(ContainerInterface $container) + public function __invoke(ContainerInterface $container): InjectorGenerator { return $this->create($container); }