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

Commit 2758533

Browse files
committed
Merge branch 'hotfix/176'
Close #176
2 parents 9ea1b16 + 309dc00 commit 2758533

File tree

7 files changed

+220
-32
lines changed

7 files changed

+220
-32
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ All notable changes to this project will be documented in this file, in reverse
66

77
### Added
88

9-
- Nothing.
9+
- [#176](https://github.com/zendframework/zend-servicemanager/pull/176) adds
10+
the options `-i` or `--ignore-unresolved` to the shipped
11+
`generate-deps-for-config-factory` command. This flag allows it to build
12+
configuration for classes resolved by the `ConfigAbstractFactory` that
13+
typehint on interfaces, which was previously unsupported.
1014

1115
### Deprecated
1216

doc/book/console-tools.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@ document details each.
99
$ ./vendor/bin/generate-deps-for-config-factory
1010
Usage:
1111

12-
generate-deps-for-config-factory [-h|--help|help] <configFile> <className>
12+
generate-deps-for-config-factory [-h|--help|help] [-i|--ignore-unresolved] <configFile> <className>
1313

1414
Arguments:
1515

16-
-h|--help|help This usage message
17-
<configFile> Path to a config file for which to generate configuration.
18-
If the file does not exist, it will be created. If it does
19-
exist, it must return an array, and the file will be
20-
updated with new configuration.
21-
<className> Name of the class to reflect and for which to generate
22-
dependency configuration.
16+
-h|--help|help This usage message
17+
-i|--ignore-unresolved Ignore classes with unresolved direct dependencies.
18+
<configFile> Path to a config file for which to generate
19+
configuration. If the file does not exist, it will
20+
be created. If it does exist, it must return an
21+
array, and the file will be updated with new
22+
configuration.
23+
<className> Name of the class to reflect and for which to
24+
generate dependency configuration.
2325

2426

2527
Reads the provided configuration file (creating it if it does not exist),
@@ -33,6 +35,13 @@ will read the named configuration file (creating it if it does not exist), and
3335
merge any configuration it generates with the return values of that file,
3436
writing the changes back to the original file.
3537
38+
Since 3.2.1, the tool also supports the `-i` or `--ignore-unresolved` flag.
39+
Use these flags when you have typehints to classes that cannot be resolved.
40+
When you omit the flag, such classes will cause the tool to fail with an
41+
exception message. By adding the flag, you can have it continue and produce
42+
configuration. This option is particularly useful when typehints are on
43+
interfaces or resolve to services served by other abstract factories.
44+
3645
## generate-factory-for-class
3746
3847
```bash

src/Tool/ConfigDumper.php

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<?php
22
/**
33
* @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)
4+
* @copyright Copyright (c) 2016-2017 Zend Technologies USA Inc. (http://www.zend.com)
55
* @license http://framework.zend.com/license/new-bsd New BSD License
66
*/
77

88
namespace Zend\ServiceManager\Tool;
99

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

29+
/**
30+
* @var ContainerInterface
31+
*/
32+
private $container;
33+
34+
/**
35+
* @param ContainerInterface $container
36+
*/
37+
public function __construct(ContainerInterface $container = null)
38+
{
39+
$this->container = $container;
40+
}
41+
2842
/**
2943
* @param array $config
3044
* @param string $className
45+
* @param bool $ignoreUnresolved
3146
* @return array
3247
* @throws InvalidArgumentException for invalid $className
3348
*/
34-
public function createDependencyConfig(array $config, $className)
49+
public function createDependencyConfig(array $config, $className, $ignoreUnresolved = false)
3550
{
3651
$this->validateClassName($className);
3752

@@ -60,22 +75,32 @@ function (ReflectionParameter $argument) {
6075
return $this->createInvokable($config, $className);
6176
}
6277

63-
$config[ConfigAbstractFactory::class][$className] = [];
78+
$classConfig = [];
6479

6580
foreach ($constructorArguments as $constructorArgument) {
6681
$argumentType = $constructorArgument->getClass();
6782
if (is_null($argumentType)) {
83+
if ($ignoreUnresolved) {
84+
// don't throw an exception, just return the previous config
85+
return $config;
86+
}
87+
// don't throw an exception if the class is an already defined service
88+
if ($this->container && $this->container->has($className)) {
89+
return $config;
90+
}
6891
throw new InvalidArgumentException(sprintf(
6992
'Cannot create config for constructor argument "%s", '
7093
. 'it has no type hint, or non-class/interface type hint',
7194
$constructorArgument->getName()
7295
));
7396
}
7497
$argumentName = $argumentType->getName();
75-
$config = $this->createDependencyConfig($config, $argumentName);
76-
$config[ConfigAbstractFactory::class][$className][] = $argumentName;
98+
$config = $this->createDependencyConfig($config, $argumentName, $ignoreUnresolved);
99+
$classConfig[] = $argumentName;
77100
}
78101

102+
$config[ConfigAbstractFactory::class][$className] = $classConfig;
103+
79104
return $config;
80105
}
81106

src/Tool/ConfigDumperCommand.php

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
33
* @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)
4+
* @copyright Copyright (c) 2016-2017 Zend Technologies USA Inc. (http://www.zend.com)
55
* @license http://framework.zend.com/license/new-bsd New BSD License
66
*/
77

@@ -21,17 +21,19 @@ class ConfigDumperCommand
2121
const HELP_TEMPLATE = <<< EOH
2222
<info>Usage:</info>
2323
24-
%s [-h|--help|help] <configFile> <className>
24+
%s [-h|--help|help] [-i|--ignore-unresolved] <configFile> <className>
2525
2626
<info>Arguments:</info>
2727
28-
<info>-h|--help|help</info> This usage message
29-
<info><configFile></info> Path to a config file for which to generate configuration.
30-
If the file does not exist, it will be created. If it does
31-
exist, it must return an array, and the file will be
32-
updated with new configuration.
33-
<info><className></info> Name of the class to reflect and for which to generate
34-
dependency configuration.
28+
<info>-h|--help|help</info> This usage message
29+
<info>-i|--ignore-unresolved</info> Ignore classes with unresolved direct dependencies.
30+
<info><configFile></info> Path to a config file for which to generate
31+
configuration. If the file does not exist, it will
32+
be created. If it does exist, it must return an
33+
array, and the file will be updated with new
34+
configuration.
35+
<info><className></info> Name of the class to reflect and for which to
36+
generate dependency configuration.
3537
3638
Reads the provided configuration file (creating it if it does not exist),
3739
and injects it with ConfigAbstractFactory dependency configuration for
@@ -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) 2017 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: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
33
* @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)
4+
* @copyright Copyright (c) 2016-2017 Zend Technologies USA Inc. (http://www.zend.com)
55
* @license http://framework.zend.com/license/new-bsd New BSD License
66
*/
77

@@ -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;

0 commit comments

Comments
 (0)