The second version works because preg_match_all
is called from within the class scope and will execute the callback immediately.
But the add_filter
function only adds the callback to the global $wp_filter
array. The callbacks in that array are then called at a later stage from outside the class you defined the method in. Consequently, visibility rules apply making the callback inaccessible.
You can¹ get around this by wrapping the call to the method into an anonymous function, e.g.
public function __construct()
{
add_filter(
'plugin_action_links',
function($links, $file) {
return $this->AddSettingsLink($links, $file);
},
10,
2
);
}
However, this requires at least PHP 5.4 (see changelog in Manual) due to $this
being unavailable in the anonymous function before that version.
Another option would be to have the SettingsHandler
implement __invoke
to turn it into a Functor, e.g. you add
public function __invoke($links, $file)
{
return $this->AddSettingsLink($links, $file);
}
and change the ctor code to
add_filter('plugin_action_links', $this, 10, 2);
Since the class implements __invoke
as a public entry point, the instance can be used as callback. This way, you can keep the private stuff private.
On a side note, I'd move the code adding the filter outside the class. Having it in the ctor makes the class less testable (yeah, I know no one tests WP plugins, but still). Instead, put it into your plugin file and then include everything else required from there, e.g.
// your-plugin.php
include 'SettingsHandler.php';
add_filter('plugin_action_links', new SettingsHandler, 10, 2);
But that's up to you.
¹Note: apparently this doesn't work in Wordpress because it will try to serialize the closure somewhere along the way. In general, this a working pattern to provide private methods as callbacks.