Skip to content
This repository was archived by the owner on Apr 29, 2025. It is now read-only.

Commit e8ca6b4

Browse files
authored
Merge pull request #119 from glennunipro/117-array-parameters
Resolve issue where Symfony2 collection parameters fail to be injected
2 parents 319b56c + 19bb955 commit e8ca6b4

File tree

9 files changed

+95
-12
lines changed

9 files changed

+95
-12
lines changed

features/bundle_suite.feature

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ Feature: Bundle suites
77
When I run "behat -s simple --no-colors"
88
Then it should pass with:
99
"""
10-
1 scenario (1 passed)
10+
2 scenarios (2 passed)
1111
"""
1212

1313
Scenario: Features should be loaded from all bundle suites
1414
When I run "behat --no-colors"
1515
Then it should pass with:
1616
"""
17-
3 scenarios (3 passed)
17+
4 scenarios (4 passed)
1818
"""

features/locator.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Feature: Bundle locator
77
When I run "behat --no-colors '@BehatSf2DemoBundle'"
88
Then it should pass with:
99
"""
10-
3 scenarios (3 passed)
10+
4 scenarios (4 passed)
1111
"""
1212

1313
Scenario: Specific features should be loaded from the bundle

spec/Behat/Symfony2Extension/Context/Argument/ServiceArgumentResolverSpec.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,25 @@ function it_resolves_parameters_starting_and_ending_with_percentage_sign_if_they
2323
ContainerInterface $container
2424
) {
2525
$container->getParameter('parameter')->willReturn('param_value');
26+
$container->hasParameter('parameter')->willReturn(true);
2627

2728
$this->resolveArguments($reflectionClass, array('parameter' => '%parameter%'))->shouldReturn(
2829
array('parameter' => 'param_value')
2930
);
3031
}
3132

33+
function it_resolves_parameters_starting_and_ending_with_percentage_sign_if_they_point_to_parameter_collection(
34+
ReflectionClass $reflectionClass,
35+
ContainerInterface $container
36+
) {
37+
$container->getParameter('parameter')->willReturn(array('Param 1', 'Param 2'));
38+
$container->hasParameter('parameter')->willReturn(true);
39+
40+
$this->resolveArguments($reflectionClass, array('parameter' => '%parameter%'))->shouldReturn(
41+
array('parameter' => array('Param 1', 'Param 2'))
42+
);
43+
}
44+
3245
function it_resolves_parameters_inside_strings(
3346
ReflectionClass $reflectionClass,
3447
ContainerInterface $container

src/Behat/Symfony2Extension/Context/Argument/ServiceArgumentResolver.php

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\DependencyInjection\ContainerInterface;
1717
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
1818
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
19+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1920
use Symfony\Component\HttpKernel\KernelInterface;
2021

2122
/**
@@ -74,9 +75,13 @@ private function resolveArgument($argument)
7475
return $service;
7576
}
7677

77-
$withParameters = $this->replaceParameters($container, $argument);
78+
$resolvedParam = $this->replaceParameters($container, $argument);
7879

79-
return $this->escape($withParameters);
80+
if (!is_string($resolvedParam)) {
81+
return $resolvedParam;
82+
}
83+
84+
return $this->escape($resolvedParam);
8085
}
8186

8287
/**
@@ -108,15 +113,49 @@ private function getServiceName($argument)
108113
}
109114

110115
/**
111-
* @param ContainerInterface $container
112-
* @param string $argument
113-
* @return string
116+
* Sanitise the container key given by the Behat config file,
117+
* and retrieve the parameter from the Container.
118+
*
119+
* First, check if the whole string is one substitution, if it is, then pull it from the container.
120+
*
121+
* Secondly, iterate over all substitutions in the string. Exception is thrown if referencing a
122+
* collection-type parameter when the key is not an entire substitution.
123+
*
124+
* This is to handle the case where we're given an argument which should return a
125+
* collection-type parameter from the container.
126+
*
127+
* @param ContainerInterface $container
128+
* @param string $argument
129+
* @throws InvalidArgumentException
130+
* @return mixed
114131
*/
115132
private function replaceParameters(ContainerInterface $container, $argument)
116133
{
117-
return preg_replace_callback('/(?<!%)%([^%]+)%(?!%)/', function($matches) use ($container) {
118-
return $container->getParameter($matches[1]);
119-
}, $argument);
134+
if (preg_match('/^(?<!%)%([^%]+)%(?!%)$/', $argument, $matches)) {
135+
$replaced = $matches[1];
136+
137+
if ($container->hasParameter($replaced)) {
138+
return $container->getParameter($replaced);
139+
}
140+
141+
return $replaced;
142+
}
143+
144+
return preg_replace_callback(
145+
'/(?<!%)%([^%]+)%(?!%)/',
146+
function ($matches) use ($container) {
147+
$parameter = $container->getParameter($matches[1]);
148+
149+
if (is_array($parameter)) {
150+
throw new InvalidArgumentException(
151+
'Cannot reference a collection-type parameter with string interpolation.'
152+
);
153+
}
154+
155+
return $parameter;
156+
},
157+
$argument
158+
);
120159
}
121160

122161
/**

testapp/app/config/config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ framework:
1111

1212
parameters:
1313
custom_app: 'behat-test-app'
14+
collection_param:
15+
- 'Param 1'
16+
- 'Param 2'

testapp/behat.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ default:
3030
- "%%kernel.environment%%"
3131
- "%%kernel.debug%%"
3232
- "%%kernel.name%%"
33+
nestedParam: 'nested_parameter_%%custom_app%%'
34+
collectionParam: '%%collection_param%%'
3335
bundle: 'BehatSf2DemoBundle'
3436
filters:
3537
tags: '@web'

testapp/src/Behat/Sf2DemoBundle/Features/Context/FeatureContext.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,23 @@ public function itShouldBeSetToValue($val)
6262
{
6363
\PHPUnit_Framework_Assert::assertSame($val, $this->containerParameters[$this->parameterKey]);
6464
}
65+
66+
/**
67+
* @Then the value should be an array
68+
*/
69+
public function theValueShouldBeAnArray()
70+
{
71+
\PHPUnit_Framework_Assert::assertInternalType('array', $this->containerParameters[$this->parameterKey]);
72+
}
73+
74+
/**
75+
* @Then the array should contain only the values :arg
76+
* @param string $arg Comma delimited string, to represent an array's values
77+
*/
78+
public function theArrayShouldContainOnlyTheValues($arg)
79+
{
80+
$values = explode(',', $arg);
81+
82+
\PHPUnit_Framework_Assert::assertSame($values, $this->containerParameters[$this->parameterKey]);
83+
}
6584
}

testapp/src/Behat/Sf2DemoBundle/Features/Context/WebContext.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class WebContext extends MinkContext implements KernelAwareContext
1111
{
1212
private $kernel;
1313

14-
public function __construct(Session $session, $simpleParameter, $simpleArg, array $services, array $params)
14+
public function __construct(Session $session, $simpleParameter, $simpleArg, array $services, array $params, $nestedParam, $collectionParam)
1515
{
1616
}
1717

testapp/src/Behat/Sf2DemoBundle/Features/kernel_access.feature

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,10 @@ Feature: Kernel access
99
Then there should be "custom_app" parameter
1010
And it should be set to "behat-test-app" value
1111
But there should not be "custom2" parameter
12+
13+
Scenario: Allow handling of container parameters which are collections
14+
Given I have a kernel instance
15+
When I get container parameters from it
16+
Then there should be "collection_param" parameter
17+
And the value should be an array
18+
And the array should contain only the values "Param 1,Param 2"

0 commit comments

Comments
 (0)