[wp-trac] [WordPress Trac] #59126: remove_filter - missing support for "First class callable"
WordPress Trac
noreply at wordpress.org
Wed Aug 16 22:57:53 UTC 2023
#59126: remove_filter - missing support for "First class callable"
-------------------------------+-----------------------------
Reporter: jave.web | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: General | Version: 6.3
Severity: normal | Keywords:
Focuses: php-compatibility |
-------------------------------+-----------------------------
PHP 8.1 introduced something called "First class callable" or First-class
Callable Syntax -
[https://www.php.net/releases/8.1/en.php#first_class_callable_syntax]
Which basically means much easier way to reference any function,
especially class methods - both dynamic and static like so:
{{{
$this->myDynamicCallback(...);
self::myStaticCallback(...);
}}}
''**The 3 dots "..." are not omission - it is the syntax**''
Now this syntax actually works for `add_filter` however, it can fail (and
I've encountered cases where it fails) for `remove_filter` which leads to
very unexpected results.
Temporary bypass can be done using `remove_all_filters` or the old-school
syntax `[__CLASS__, 'myStaticCallback']`.
The core issue is in the function `_wp_filter_build_unique_id` which
generates the key under which the callback is stored, more specifically,
in the way how the PHP's `spl_object_hash` work - this sentence from docs
"This id can be used as a hash key for storing objects, or for identifying
an object, **as long as the object is not destroyed**."
Now this is an educated wild guess, but I would guess that the callable
objects created by the First-class callable syntax may not live that long
and garbage collector can destroy them if it sees fit.
Anyways... the core is - `spl_object_hash` is NOT the right tool to cache
ALL callables, but can only be used where the callable is passed around
(e.g. stored in a variable) and therefore it is ensured it's still the
same object (I would hope).
**Solution**
...for such cases is to create a `\ReflectionFunction` instance and check
for `getClosureScopeClass()` and `getName()` :-)
https://www.php.net/manual/en/class.reflectionfunction.php
https://www.php.net/manual/en/reflectionfunctionabstract.getclosurescopeclass.php
https://www.php.net/manual/en/reflectionfunctionabstract.getname.php
--
Ticket URL: <https://core.trac.wordpress.org/ticket/59126>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list