Skip to content
This repository was archived by the owner on Feb 6, 2020. It is now read-only.

Commit d8c70fc

Browse files
thomasvargiuweierophinney
authored andcommitted
Added --ignore-unresolved param in ConfigDumperCommand
1 parent 9ea1b16 commit d8c70fc

File tree

5 files changed

+189
-11
lines changed

5 files changed

+189
-11
lines changed

src/Tool/ConfigDumper.php

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Zend\ServiceManager\Tool;
99

10+
use Interop\Container\ContainerInterface;
1011
use ReflectionClass;
1112
use ReflectionParameter;
1213
use Traversable;
@@ -25,13 +26,35 @@ class ConfigDumper
2526
return %s;
2627
EOC;
2728

29+
/**
30+
* @var ContainerInterface
31+
*/
32+
protected $container;
33+
34+
/**
35+
* @param ContainerInterface $container
36+
*/
37+
public function __construct(ContainerInterface $container = null)
38+
{
39+
$this->container = $container;
40+
}
41+
42+
/**
43+
* @param ContainerInterface $container
44+
*/
45+
public function setContainer(ContainerInterface $container)
46+
{
47+
$this->container = $container;
48+
}
49+
2850
/**
2951
* @param array $config
3052
* @param string $className
53+
* @param bool $ignoreUnresolved
3154
* @return array
3255
* @throws InvalidArgumentException for invalid $className
3356
*/
34-
public function createDependencyConfig(array $config, $className)
57+
public function createDependencyConfig(array $config, $className, $ignoreUnresolved = false)
3558
{
3659
$this->validateClassName($className);
3760

@@ -60,22 +83,32 @@ function (ReflectionParameter $argument) {
6083
return $this->createInvokable($config, $className);
6184
}
6285

63-
$config[ConfigAbstractFactory::class][$className] = [];
86+
$classConfig = [];
6487

6588
foreach ($constructorArguments as $constructorArgument) {
6689
$argumentType = $constructorArgument->getClass();
6790
if (is_null($argumentType)) {
91+
if ($ignoreUnresolved) {
92+
// don't throw an exception, just return the previous config
93+
return $config;
94+
}
95+
// don't throw an exception if the class is an already defined service
96+
if ($this->container && $this->container->has($className)) {
97+
return $config;
98+
}
6899
throw new InvalidArgumentException(sprintf(
69100
'Cannot create config for constructor argument "%s", '
70101
. 'it has no type hint, or non-class/interface type hint',
71102
$constructorArgument->getName()
72103
));
73104
}
74105
$argumentName = $argumentType->getName();
75-
$config = $this->createDependencyConfig($config, $argumentName);
76-
$config[ConfigAbstractFactory::class][$className][] = $argumentName;
106+
$config = $this->createDependencyConfig($config, $argumentName, $ignoreUnresolved);
107+
$classConfig[] = $argumentName;
77108
}
78109

110+
$config[ConfigAbstractFactory::class][$className] = $classConfig;
111+
79112
return $config;
80113
}
81114

src/Tool/ConfigDumperCommand.php

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class ConfigDumperCommand
2626
<info>Arguments:</info>
2727
2828
<info>-h|--help|help</info> This usage message
29+
<info>-i|--ignore-unresolved</info> Ignore classes with unresolved
30+
direct dependencies.
2931
<info><configFile></info> Path to a config file for which to generate configuration.
3032
If the file does not exist, it will be created. If it does
3133
exist, it must return an array, and the file will be
@@ -81,7 +83,11 @@ public function __invoke(array $args)
8183

8284
$dumper = new ConfigDumper();
8385
try {
84-
$config = $dumper->createDependencyConfig($arguments->config, $arguments->class);
86+
$config = $dumper->createDependencyConfig(
87+
$arguments->config,
88+
$arguments->class,
89+
$arguments->ignoreUnresolved
90+
);
8591
} catch (Exception\InvalidArgumentException $e) {
8692
$this->helper->writeErrorMessage(sprintf(
8793
'Unable to create config for "%s": %s',
@@ -117,6 +123,12 @@ private function parseArgs(array $args)
117123
return $this->createHelpArgument();
118124
}
119125

126+
$ignoreUnresolved = false;
127+
if (in_array($arg1, ['-i', '--ignore-unresolved'], true)) {
128+
$ignoreUnresolved = true;
129+
$arg1 = array_shift($args);
130+
}
131+
120132
if (! count($args)) {
121133
return $this->createErrorArgument('Missing class name');
122134
}
@@ -157,7 +169,7 @@ private function parseArgs(array $args)
157169
));
158170
}
159171

160-
return $this->createArguments(self::COMMAND_DUMP, $configFile, $config, $class);
172+
return $this->createArguments(self::COMMAND_DUMP, $configFile, $config, $class, $ignoreUnresolved);
161173
}
162174

163175
/**
@@ -178,15 +190,17 @@ private function help($resource = STDOUT)
178190
* which it will be written.
179191
* @param array $config Parsed configuration.
180192
* @param string $class Name of class to reflect.
193+
* @param bool $ignoreUnresolved If to ignore classes with unresolved direct dependencies.
181194
* @return \stdClass
182195
*/
183-
private function createArguments($command, $configFile, $config, $class)
196+
private function createArguments($command, $configFile, $config, $class, $ignoreUnresolved)
184197
{
185198
return (object) [
186-
'command' => $command,
187-
'configFile' => $configFile,
188-
'config' => $config,
189-
'class' => $class,
199+
'command' => $command,
200+
'configFile' => $configFile,
201+
'config' => $config,
202+
'class' => $class,
203+
'ignoreUnresolved' => $ignoreUnresolved,
190204
];
191205
}
192206

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
/**
3+
* @link http://github.com/zendframework/zend-servicemanager for the canonical source repository
4+
* @copyright Copyright (c) 2016 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license http://framework.zend.com/license/new-bsd New BSD License
6+
*/
7+
8+
namespace ZendTest\ServiceManager\TestAsset;
9+
10+
class ObjectWithObjectScalarDependency
11+
{
12+
public function __construct(SimpleDependencyObject $simpleDependencyObject, ObjectWithScalarDependency $dependency)
13+
{
14+
}
15+
}

test/Tool/ConfigDumperCommandTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Zend\ServiceManager\Tool\ConfigDumperCommand;
1616
use Zend\Stdlib\ConsoleHelper;
1717
use ZendTest\ServiceManager\TestAsset\InvokableObject;
18+
use ZendTest\ServiceManager\TestAsset\ObjectWithObjectScalarDependency;
1819
use ZendTest\ServiceManager\TestAsset\ObjectWithScalarDependency;
1920
use ZendTest\ServiceManager\TestAsset\SimpleDependencyObject;
2021

@@ -59,6 +60,14 @@ public function helpArguments()
5960
];
6061
}
6162

63+
public function ignoreUnresolvedArguments()
64+
{
65+
return [
66+
'short' => ['-i'],
67+
'long' => ['--ignore-unresolved'],
68+
];
69+
}
70+
6271
/**
6372
* @dataProvider helpArguments
6473
*/
@@ -110,6 +119,41 @@ public function testGeneratesConfigFileWhenProvidedConfigurationFileNotFound()
110119
$this->assertEquals([], $factoryConfig[InvokableObject::class]);
111120
}
112121

122+
/**
123+
* @dataProvider ignoreUnresolvedArguments
124+
*/
125+
public function testGeneratesConfigFileIgnoringUnresolved($argument)
126+
{
127+
$command = $this->command;
128+
vfsStream::newDirectory('config', 0775)
129+
->at($this->configDir);
130+
$config = vfsStream::url('project/config/test.config.php');
131+
132+
$this->helper->writeLine('<info>[DONE]</info> Changes written to ' . $config)->shouldBeCalled();
133+
134+
$this->assertEquals(0, $command([$argument, $config, ObjectWithObjectScalarDependency::class]));
135+
136+
$generated = include $config;
137+
$this->assertInternalType('array', $generated);
138+
$this->assertArrayHasKey(ConfigAbstractFactory::class, $generated);
139+
$factoryConfig = $generated[ConfigAbstractFactory::class];
140+
$this->assertInternalType('array', $factoryConfig);
141+
$this->assertArrayHasKey(SimpleDependencyObject::class, $factoryConfig);
142+
$this->assertArrayHasKey(InvokableObject::class, $factoryConfig);
143+
$this->assertContains(InvokableObject::class, $factoryConfig[SimpleDependencyObject::class]);
144+
$this->assertEquals([], $factoryConfig[InvokableObject::class]);
145+
146+
$this->assertArrayHasKey(ObjectWithObjectScalarDependency::class, $factoryConfig);
147+
$this->assertContains(
148+
SimpleDependencyObject::class,
149+
$factoryConfig[ObjectWithObjectScalarDependency::class]
150+
);
151+
$this->assertContains(
152+
ObjectWithScalarDependency::class,
153+
$factoryConfig[ObjectWithObjectScalarDependency::class]
154+
);
155+
}
156+
113157
public function testEmitsErrorWhenConfigurationFileDoesNotReturnArray()
114158
{
115159
$command = $this->command;

test/Tool/ConfigDumperTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace ZendTest\ServiceManager\Tool;
99

10+
use Interop\Container\ContainerInterface;
1011
use PHPUnit_Framework_TestCase as TestCase;
1112
use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory;
1213
use Zend\ServiceManager\Exception\InvalidArgumentException;
@@ -16,6 +17,7 @@
1617
use ZendTest\ServiceManager\TestAsset\DoubleDependencyObject;
1718
use ZendTest\ServiceManager\TestAsset\FailingFactory;
1819
use ZendTest\ServiceManager\TestAsset\InvokableObject;
20+
use ZendTest\ServiceManager\TestAsset\ObjectWithObjectScalarDependency;
1921
use ZendTest\ServiceManager\TestAsset\ObjectWithScalarDependency;
2022
use ZendTest\ServiceManager\TestAsset\SecondComplexDependencyObject;
2123
use ZendTest\ServiceManager\TestAsset\SimpleDependencyObject;
@@ -101,6 +103,76 @@ public function testCreateDependencyConfigWithoutTypeHintedParameterExcepts()
101103
);
102104
}
103105

106+
public function testCreateDependencyConfigWithContainerAndNoServiceWithoutTypeHintedParameterExcepts()
107+
{
108+
self::expectException(InvalidArgumentException::class);
109+
self::expectExceptionMessage(
110+
'Cannot create config for constructor argument "aName", '
111+
. 'it has no type hint, or non-class/interface type hint'
112+
);
113+
$container = $this->prophesize(ContainerInterface::class);
114+
$container->has(ObjectWithScalarDependency::class)
115+
->shouldBeCalled()
116+
->willReturn(false);
117+
$this->dumper->setContainer($container->reveal());
118+
$config = $this->dumper->createDependencyConfig(
119+
[ConfigAbstractFactory::class => []],
120+
ObjectWithScalarDependency::class
121+
);
122+
}
123+
124+
public function testCreateDependencyConfigWithContainerWithoutTypeHintedParameter()
125+
{
126+
$container = $this->prophesize(ContainerInterface::class);
127+
$container->has(ObjectWithScalarDependency::class)
128+
->shouldBeCalled()
129+
->willReturn(true);
130+
$this->dumper->setContainer($container->reveal());
131+
$config = $this->dumper->createDependencyConfig(
132+
[ConfigAbstractFactory::class => []],
133+
ObjectWithObjectScalarDependency::class
134+
);
135+
self::assertEquals(
136+
[
137+
ConfigAbstractFactory::class => [
138+
SimpleDependencyObject::class => [
139+
InvokableObject::class,
140+
],
141+
InvokableObject::class => [],
142+
ObjectWithObjectScalarDependency::class => [
143+
SimpleDependencyObject::class,
144+
ObjectWithScalarDependency::class,
145+
],
146+
]
147+
],
148+
$config
149+
);
150+
}
151+
152+
public function testCreateDependencyConfigWithoutTypeHintedParameterIgnoringUnresolved()
153+
{
154+
$config = $this->dumper->createDependencyConfig(
155+
[ConfigAbstractFactory::class => []],
156+
ObjectWithObjectScalarDependency::class,
157+
true
158+
);
159+
self::assertEquals(
160+
[
161+
ConfigAbstractFactory::class => [
162+
SimpleDependencyObject::class => [
163+
InvokableObject::class,
164+
],
165+
InvokableObject::class => [],
166+
ObjectWithObjectScalarDependency::class => [
167+
SimpleDependencyObject::class,
168+
ObjectWithScalarDependency::class,
169+
],
170+
]
171+
],
172+
$config
173+
);
174+
}
175+
104176
public function testCreateDependencyConfigWorksWithExistingConfig()
105177
{
106178
$config = [

0 commit comments

Comments
 (0)