Big discovery, check edit 3, way down.
What I'm trying to do, in short: Based on an AJAX call (which is tied to an user clicking), I'm installing a plugin. This button that tells my PHP to "install this plugin" is on a custom page that I've made with add_theme_page
.
I've registered this function inside my class that helps me with an AJAX request:
public function __construct()
{
add_action( 'wp_ajax_parse_plugin_request', array( $this, 'parsePluginInstallRequest' ) );
}
The function being:
public function parsePluginInstallRequest()
{
check_ajax_referer( 'plugin_routines', 'security' );
$data = json_decode( stripslashes( $_POST['plugin_install_request_data'] ), true );
//$data is what comes when an user clicks a button, just a handle for the plugin that needs to be installed.
$this->installPlugin( $data['plugin-slug'] );
}
And so, it calls installPlugin
which is just a wrapper for a quick and dirty "install plugin". The thing is, that line of code:
$this->installPlugin( $data['plugin-slug'] );
Works just fine out of this call, even tested with a wp_send_json
inside of installPlugin
to see whether or not it was being called and it's being called.
My JS script that calls everything: //This is being called in the back-end, on a custom page. function requestPluginAction(plugin_data) {
var ajaxsecurity = setup_page_params.plugins_routines_nonce
jQuery.ajax(
{
url: ajaxurl,
type: 'POST',
dataType: 'json',
data: {
action: 'parse_plugin_request',
security: ajaxsecurity,
plugin_install_request_data: plugin_data
},
success: function (response) {
console.log(response);
},
error: function (error) {
console.log(error);
}
}
);
}
I have checked multiple times that, indeed, the data is getting passed correctly, so, PHP sees what it needs to see in order to work.
But to no avail.
A few notes: I am extending the WP_Upgrader
minimally, just making it's WP_Upgrader_Skin
not output anything, but rather, return data.
I've put debugging messages everywhere in these classes, output buffering, breakpoints and what not, yet I still can't understand why it does this.
In the back-end, I could install plugins lightning fast, 3-4 at once, but when the call to installPlugin
comes from AJAX, it doesn't do anything. At all.
My one and only idea is that when I'm inside my wp_ajax
hook'd function, parsePluginInstallRequest
, it simply is too early to call the install, put it this way:
I'm trying to install a plugin when the plugins haven't loaded / other things haven't loaded, basically this parsePluginInstallRequest
is hooked to: wp_ajax_parse_plugin_request
, so I am calling the install of a plugin on this hook.
It might be too early and my installer fails horribly because WordPress is not done yet.
But then, how can I fire this event for installing on user-click, when the install doesn't work at that point in time? It's a contradiction.
Edit 1:
It seems that if I output anything (with var_dump) before the main content of my custom page, the AJAX calls no longer work at all, so putting a simple echo
or wp_send_json
within my parsePluginInstallRequest
no longer works and it returns all kinds of things.
Edit 2:
I'm getting my list of plugins using TGMPA, I just checked and the array of plugins that is 100% populated, when being called from an AJAX context is empty.
So, if I call installPlugins
from outside of the wp_ajax-$hook_here
context, it registers the array and it all works, but if I do it from the inside, it doesn't see the array coming from TGMPA.
Leads me to think that I'm firing my AJAX way too soon and it doesn't catch TGMA's populating of the array I need to use.
Edit 3: Big stuff.
After 8 exhausting hours, I finally got to the core. I'm drawing my array from TGMPA. Thing is, TGMPA fires on init
, now, remember, I'm on a page added by add_theme_page
and I'm firing my AJAX on this page. My call to installPlugins
is registered to also go off when the user clicks my button, so on wp_ajax_parse_plugin_request
.
Thing is - my installPlugins
which parses TGMPA's array, like this:
foreach( $plugins['install'] as $plugin_key => $plugin_data ) {
$this->upgrader->install( $plugin_data['source'] );
Will always have $plugins
empty, because TGMPA hasn't yet populated the plugin, since we're not hitting init
as of yet.
So what I did was, go on ahead, copy what TGMPA's array actually is and hard-code that array into the installPlugins
function and voila - it works.
So, the real question is: how do I make my AJAX hook after init
, so that $plugins
can be populated?