Again, as I have stated in a comment, I don't know that you can meeting all of your conditions with 100% certainty. What follows is what I believe to be about as close as you can get while working within WordPress.
- Use a MU-Plugin.
- Write your callback is such a way that is difficult, if not
impossible, to remove.
First, use a must-use plugin. Create a directory in wp-content
called mu-plugins
. Files in that location load automatically and cannot be disabled except by deleting them, so your users would need some kind of server access-- (s)FTP or shell access. This gives you a bit more control.
Second, WordPress provides a mechanism to remove callbacks from hooks, but you need to know the name of the callback. You can use that fact to make it, at least, more difficult to remove.
To do that, you can use an anonymous class, like so:
class Hard_To_Remove {
function __construct() {
add_action('wp_footer',array($this,'print_to_footer'));
}
function print_to_footer() {
echo 'Hello, I am a footer message';
}
}
new Hard_To_Remove();
It can't be easily removed because there is no easy way to refer to the callback, whereas written as follows it could be removed.
class Hard_To_Remove {
function __construct() {
add_action('wp_footer',array($this,'print_to_footer'));
}
function print_to_footer() {
echo 'Hello, I am a footer message';
}
}
$htr = new Hard_To_Remove();
remove_action('wp_footer',array($htr,'print_to_footer'));
Closures create the same difficulty. You can't easily refer to the callback to remove it.
add_action(
'wp_footer',
function() {
echo 'Hello, I am a footer message';
}
);
However, you can get around that limitation by inspecting the global
variable $wp_filter
.
add_action(
'wp_footer',
function() {
global $wp_filter;
var_dump($wp_filter['wp_footer']);
}
);
It would be a bit cludgy, but it should be possible to remove those filters.
It is always possible that a theme omits wp_footer()
but that should be fairly rare.
You could use the shutdown
hook, which should always run, but it would print your content outside the closing </html>
tag.