Brain-WP/BrainMonkey

has_filter doen't work with type hints with namespaces

SergeyBeloglazov opened this issue · 10 comments

Good Day!
Thank you for this module!

I found, that has_filter() doesn't work with full qualified type hints, as it described here:
https://giuseppe-mazzapica.gitbook.io/brain-monkey/wordpress-specific-tools/wordpress-hooks-added
This test
self::assertNotFalse( has_filter('the_title', 'function ( array $foo, Foo\Bar\Baz $baz, Foo\Bar\Bar ...$bar )' ) );
leads to an error

Brain\Monkey\Name\Exception\InvalidCallable: Given string "function ( array $foo, Foo\Bar\Baz $baz, Foo\Bar\Bar ...$bar )" is not a valid PHP callable.

As I inspected the BrainMonkey code, it fails on preg_match() in
brain/monkey/src/Name/ClosureParamStringForm.php on line 62
if ($type && ! preg_match(self::VALID_PARAM_PATTERN, $type)) {
where VALID_PARAM_PATTERN = '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/'.
A type with full qualified type name with namespaces will not satisfy it because it contains slashes .

See also https://stackoverflow.com/questions/41027816/what-are-the-valid-characters-in-php-namespace-names

My composer.lock:

"name": "brain/monkey",
"version": "2.6.0",

Hi @SergeyBeloglazov - good catch, and nice analysis! 🙂

I created a PR, #95, which is pending review.
Once merged, you should be able to use closures with fully-qualified type declarations, both in string form and as actual closure expressions. (See the new functional test.)

Thank You!

Thanks both of you @tfrommen @SergeyBeloglazov

The PR is merged and now.

@tfrommen One of the tests you added is failing on PHP 5.6 (https://github.com/Brain-WP/BrainMonkey/runs/2123646454?check_suite_focus=true), could you please investigate?

At some point I'll deprecate 5.6 but for current major it will stay supported.

@gmazzap hm, so, it seems the issue is that ReflectionParamater::hasType() does not exist in PHP 5.6, which is of course the reason why there is a >= 7 check in the code 😅.

So, I think all we can do here is to remove that particular test for PHP 5.

But that also means that some code using (namespaced) type declarations in string-form callbacks doesn't work as expected in 5.6.
Is that something you are OK with?

Thanks @tfrommen for the quick response.

I'm ok with that. There are other tests that are skipped for 5.6.

The fact that there's a difference in functionality should be documented.

If you have will and time, could you also do that? If not, I'll docs as soon as I can.

I will remove the test, but I don't have time for adding documentation soon. This is mainly because I would have to understand where this (i.e., string-form callbacks) is being used. I assume it's local to expectations around hooks usage, but that would have to be confirmed.

Thanks @tfrommen, I've merged your last PR. I'll add docs as soon as I can and then make a release.

jrfnl commented

@gmazzap @tfrommen I was just looking at this fix and why the PHP 5.6 tests were removed. It actually quite possible to make the code in the ClosureParamStringForm::fromReflectionParameter method compatible with PHP 5.6 and after all, class name based, including FQN type declarations are supported in PHP 5.6.

Would you be interested in a fix for this ?

Would you be interested in a fix for this ?

Why not. And thanks @jrfnl

jrfnl commented

See PR #100.