Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve issue where Symfony2 collection parameters fail to be injected #119

Merged
merged 1 commit into from
Oct 23, 2017
Merged

Resolve issue where Symfony2 collection parameters fail to be injected #119

merged 1 commit into from
Oct 23, 2017

Conversation

glennmcewan
Copy link
Contributor

@glennmcewan glennmcewan commented May 31, 2017

This allows collection parameters defined in Symfony 2 to be injected. Fixes #117.

Currently, they fail to do so as there is a constraint that preg_replace_callback must return a string, but when resolving parameters from Symfony 2's container, you may either get back a string, constant, or collection (see here).

I've swapped to using preg_match which will return a string, and I have changed the method signature of replaceParameters so that it returns the container value of the parameter. Then, if it is not a string, we return it to the caller (to avoid another issue passing it to @escape), otherwise the escape method is still called on it, and then returned.

stof
stof previously requested changes May 31, 2017
@@ -60,10 +60,6 @@ public function resolveArguments(ReflectionClass $classReflection, array $argume
*/
private function resolveArgument($argument)
{
if (is_array($argument)) {
return array_map(array($this, 'resolveArgument'), $argument);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not resolve argument recursively for arrays, which look wrong to me, as it does not allow services inside an array anymore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very strange, I wasn't aware that was in the diff before I committed. I've re-instated that chunk, re-tested my scenarios locally and it's running. Unit tests aren't running on my machine right now so I'm relying on Travis.

@stof
Copy link
Member

stof commented May 31, 2017

and CI complains about your change

Copy link
Contributor

@sroze sroze left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a test case as well please?

return preg_replace_callback('/(?<!%)%([^%]+)%(?!%)/', function($matches) use ($container) {
return $container->getParameter($matches[1]);
}, $argument);
$cleanKey = preg_replace('/(?<!%)%([^%]+)%(?!%)/', '$1', $key);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could probably use preg_match instead then

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, as explained in my comment below, preg_replace worked for some cases, except I needed to check if there was a match before I proceeded. I have updated to use preg_match.

*/
private function replaceParameters(ContainerInterface $container, $argument)
private function replaceParameters(ContainerInterface $container, $key)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you change the behaviour of this method, can you also change its name? Also, why this name change (key) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason for changing the key, this PR was not in a ready state, still undergoing work as I was waiting for the test results from the CI process.

Has the behaviour of the method really changed? I don't think it has. I don't see the benefit of changing the name here, as it does still replace parameters, nothing new other than it will handle parameter collections.


return $this->escape($withParameters);
if (!is_string($resolvedParam)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the ternary operator in the return instead of a if

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can use the ternary operator, but could you tell me the benefit in this case please?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be fair, I won't argue about it, just my personal preference by reading the code. You can leave it this way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preferences are fine, I have no real preference either way; it was just the smallest issue on this PR at the time. My preference is that it's more readable to have a conditional block rather than a ternary in this case, equally I won't argue the point as I don't have any strong concerns either way.

Now the PR is complete, however, I don't mind changing it if that's the style for this repo.

@glennmcewan
Copy link
Contributor Author

@stof / @sroze, could not get unit tests running yesterday so I left it to Travis to run the tests for me.

They failed as the preg_replace method was replacing all strings, and resolving everything that went through that method from the container. It should have instead only pulled values from the container which preg_replace affected, so I have swapped to preg_match and only pulling values from the container if preg_match caught something.

I've also written and tested a Behat scenario for this, where we have a collection-type parameter registered in Symfony's container. Added a couple of new methods to the testapp's FeatureContext to handle this.

@glennmcewan
Copy link
Contributor Author

Done a bit of thinking about how to tackle this nicely, still don't think it's quite refined enough. The unit tests are now passing, and I've added in new ones to cover cases where container parameters are collections.

I made the decision to first check if the given argument is one entire substitution, and in that case, go directly to the container and request the parameter. That handles the case where an argument wants a collection parameter. If that is not the case, then similar logic as before occurs, exception and Exception is thrown if a collection-type parameter is reference in a partial string substitution, because it makes no sense to put a collection-type parameter in to a string.

The builds, except HHVM (HHVM is no longer supported on Ubuntu Precise. Please consider using Trusty with `dist: trusty`.), are now passing. Any thoughts?

@@ -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);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice spot. Resolved.

@sroze
Copy link
Contributor

sroze commented Jun 5, 2017

That's a good one, I'm happy with this. Regarding HHVM, as it's not supported anymore in Symfony 4, you can remove it from the travis.yml file :)

@glennmcewan
Copy link
Contributor Author

@sroze thanks for confirming; I'll remove it in a separate PR as it's not a direct concern for this PR.

@sroze
Copy link
Contributor

sroze commented Jun 21, 2017

@stof are you happy with these changes as well?

@glennmcewan
Copy link
Contributor Author

Rebased, just to make the commit log cleaner.

@stof do you mind reviewing please?

@sroze sroze dismissed stof’s stale review October 23, 2017 09:15

Timed out ;-)

@sroze
Copy link
Contributor

sroze commented Oct 23, 2017

Travis is blocked on PHP 5.3; will remove the support anyway. Thank you @glennunipro!

@sroze sroze merged commit e8ca6b4 into Behat:master Oct 23, 2017
@glennmcewan glennmcewan deleted the 117-array-parameters branch October 24, 2017 14:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants