Skip to content

Commit

Permalink
Update ServiceArgumentResolver to handle Symfony Container Collection…
Browse files Browse the repository at this point in the history
…s (array arguments). Includes tests.
  • Loading branch information
glennmcewan committed Sep 7, 2017
1 parent ebfc2e6 commit 19bb955
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 12 deletions.
4 changes: 2 additions & 2 deletions features/bundle_suite.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ Feature: Bundle suites
When I run "behat -s simple --no-colors"
Then it should pass with:
"""
1 scenario (1 passed)
2 scenarios (2 passed)
"""

Scenario: Features should be loaded from all bundle suites
When I run "behat --no-colors"
Then it should pass with:
"""
3 scenarios (3 passed)
4 scenarios (4 passed)
"""
2 changes: 1 addition & 1 deletion features/locator.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Feature: Bundle locator
When I run "behat --no-colors '@BehatSf2DemoBundle'"
Then it should pass with:
"""
3 scenarios (3 passed)
4 scenarios (4 passed)
"""

Scenario: Specific features should be loaded from the bundle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,25 @@ function it_resolves_parameters_starting_and_ending_with_percentage_sign_if_they
ContainerInterface $container
) {
$container->getParameter('parameter')->willReturn('param_value');
$container->hasParameter('parameter')->willReturn(true);

$this->resolveArguments($reflectionClass, array('parameter' => '%parameter%'))->shouldReturn(
array('parameter' => 'param_value')
);
}

function it_resolves_parameters_starting_and_ending_with_percentage_sign_if_they_point_to_parameter_collection(
ReflectionClass $reflectionClass,
ContainerInterface $container
) {
$container->getParameter('parameter')->willReturn(array('Param 1', 'Param 2'));
$container->hasParameter('parameter')->willReturn(true);

$this->resolveArguments($reflectionClass, array('parameter' => '%parameter%'))->shouldReturn(
array('parameter' => array('Param 1', 'Param 2'))
);
}

function it_resolves_parameters_inside_strings(
ReflectionClass $reflectionClass,
ContainerInterface $container
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\HttpKernel\KernelInterface;

/**
Expand Down Expand Up @@ -74,9 +75,13 @@ private function resolveArgument($argument)
return $service;
}

$withParameters = $this->replaceParameters($container, $argument);
$resolvedParam = $this->replaceParameters($container, $argument);

return $this->escape($withParameters);
if (!is_string($resolvedParam)) {
return $resolvedParam;
}

return $this->escape($resolvedParam);
}

/**
Expand Down Expand Up @@ -108,15 +113,49 @@ private function getServiceName($argument)
}

/**
* @param ContainerInterface $container
* @param string $argument
* @return string
* Sanitise the container key given by the Behat config file,
* and retrieve the parameter from the Container.
*
* First, check if the whole string is one substitution, if it is, then pull it from the container.
*
* Secondly, iterate over all substitutions in the string. Exception is thrown if referencing a
* collection-type parameter when the key is not an entire substitution.
*
* This is to handle the case where we're given an argument which should return a
* collection-type parameter from the container.
*
* @param ContainerInterface $container
* @param string $argument
* @throws InvalidArgumentException
* @return mixed
*/
private function replaceParameters(ContainerInterface $container, $argument)
{
return preg_replace_callback('/(?<!%)%([^%]+)%(?!%)/', function($matches) use ($container) {
return $container->getParameter($matches[1]);
}, $argument);
if (preg_match('/^(?<!%)%([^%]+)%(?!%)$/', $argument, $matches)) {
$replaced = $matches[1];

if ($container->hasParameter($replaced)) {
return $container->getParameter($replaced);
}

return $replaced;
}

return preg_replace_callback(
'/(?<!%)%([^%]+)%(?!%)/',
function ($matches) use ($container) {
$parameter = $container->getParameter($matches[1]);

if (is_array($parameter)) {
throw new InvalidArgumentException(
'Cannot reference a collection-type parameter with string interpolation.'
);
}

return $parameter;
},
$argument
);
}

/**
Expand Down
3 changes: 3 additions & 0 deletions testapp/app/config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ framework:

parameters:
custom_app: 'behat-test-app'
collection_param:
- 'Param 1'
- 'Param 2'
2 changes: 2 additions & 0 deletions testapp/behat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ default:
- "%%kernel.environment%%"
- "%%kernel.debug%%"
- "%%kernel.name%%"
nestedParam: 'nested_parameter_%%custom_app%%'
collectionParam: '%%collection_param%%'
bundle: 'BehatSf2DemoBundle'
filters:
tags: '@web'
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,23 @@ public function itShouldBeSetToValue($val)
{
\PHPUnit_Framework_Assert::assertSame($val, $this->containerParameters[$this->parameterKey]);
}

/**
* @Then the value should be an array
*/
public function theValueShouldBeAnArray()
{
\PHPUnit_Framework_Assert::assertInternalType('array', $this->containerParameters[$this->parameterKey]);
}

/**
* @Then the array should contain only the values :arg
* @param string $arg Comma delimited string, to represent an array's values
*/
public function theArrayShouldContainOnlyTheValues($arg)
{
$values = explode(',', $arg);

\PHPUnit_Framework_Assert::assertSame($values, $this->containerParameters[$this->parameterKey]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class WebContext extends MinkContext implements KernelAwareContext
{
private $kernel;

public function __construct(Session $session, $simpleParameter, $simpleArg, array $services, array $params)
public function __construct(Session $session, $simpleParameter, $simpleArg, array $services, array $params, $nestedParam, $collectionParam)
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,10 @@ Feature: Kernel access
Then there should be "custom_app" parameter
And it should be set to "behat-test-app" value
But there should not be "custom2" parameter

Scenario: Allow handling of container parameters which are collections
Given I have a kernel instance
When I get container parameters from it
Then there should be "collection_param" parameter
And the value should be an array
And the array should contain only the values "Param 1,Param 2"

0 comments on commit 19bb955

Please sign in to comment.