WordPress-Plugin-Boilerplate
WordPress-Plugin-Boilerplate copied to clipboard
Using the plugins_api filter.
Hey guys!
I feel I'm missing something incredibly obvious. I'm trying to use the plugins_api filter to show the View Details link on the plugins.php page. The function is working correctly for all plugins except mine. I feel it has something to do with how I register the filter.
Here's is my function. When I remove if( $this->plugin_name !== $args->slug ) I can see the View Details on other plugins except mine. I checked the $args->slug and $this->plugin_name and they are identical.
public function view_details( $res, $actions, $args ){
$action = 'plugin_information';
// do nothing if this is not about getting plugin information
if( $action !== 'plugin_information' )
return false;
//do nothing if it is not our plugin
if( $this->plugin_name !== $args->slug )
return false;
// trying to get from cache first
if( false == $remote = get_transient( 'xxx' ) ) {
// info.json is the file with the actual plugin information on the server
$remote = wp_remote_get( 'http://xxx.local/info.json', array(
'timeout' => 10,
'headers' => array(
'Accept' => 'application/json'
) )
);
if ( !is_wp_error( $remote ) && isset( $remote['response']['code'] ) && $remote['response']['code'] == 200 && !empty( $remote['body'] ) ) {
set_transient( 'xxx, $remote, 43200 ); // 12 hours cache
}
}
if( $remote ) {
$remote = json_decode( $remote['body'] );
$res = new stdClass();
$res->name = $remote->name;
$res->slug = $this->plugin_name;
$res->version = $remote->version;
$res->tested = $remote->tested;
$res->tested = $remote->homepage;
$res->requires = $remote->requires;
$res->author = '<a href="https:/xxx.com">Chris Schwartze</a>';
$res->author_profile = 'https://profiles.wordpress.org/xxx';
$res->download_link = $remote->download_url;
$res->trunk = $remote->download_url;
$res->last_updated = $remote->last_updated;
$res->sections = array(
'changelog' => $remote->sections->changelog
);
if( !empty( $remote->sections->screenshots ) ) {
$res->sections['screenshots'] = $remote->sections->screenshots;
}
return $res;
}
return false;
}
Here's my class-plugin-name.php
/**
* Register all of the hooks related to the admin area functionality
* of the plugin.
*
* @since 1.0.0
* @access private
*/
private function define_admin_hooks() {
$this->loader->add_filter('plugins_api' , $plugin_admin, 'view_details', 10, 3);
}
Any pointers would be really appreciated!
What is $plugin_admin in the define_admin_hooks() method? :)
Thanks for the quick reply @dingo-d
$plugin_admin = new My_Plugin_Name_Admin($this->get_plugin_name(), $this->get_version());
Did you put it inside the method? Because you'll either need to add it inside the method to make this variable available inside the method, or maybe add it in the constructor like $this->plugin_admin, and then use it as such inside the method
$this->loader->add_filter('plugins_api' , $this->plugin_admin, 'view_details', 10, 3);
@dingo-d Apologies, maybe I wasn't clear enough with my example.
I believe $this->plugin_name' is setup in public function __construct()' out of the box. At least, I haven't made much changes to that function. Here it is in full:
public function __construct()
{
if (defined('PLUGIN_NAME_VERSION')) {
$this->version = PLUGIN_NAME_VERSION;
} else {
$this->version = '1.0.0';
}
$this->plugin_name = 'juggle-for-woocommerce';
$this->load_dependencies();
$this->set_locale();
$this->define_admin_hooks();
$this->define_public_hooks();
}
Ok, I wanted you to do this yourself (learning experience) but I'll help :D
Either do this:
public function __construct()
{
if (defined('PLUGIN_NAME_VERSION')) {
$this->version = PLUGIN_NAME_VERSION;
} else {
$this->version = '1.0.0';
}
$this->plugin_name = 'juggle-for-woocommerce';
$this->load_dependencies();
$this->set_locale();
$this->define_admin_hooks();
$this->define_public_hooks();
$this->plugin_admin = new My_Plugin_Name_Admin( $this->plugin_name, $this->version );
}
/**
* Register all of the hooks related to the admin area functionality
* of the plugin.
*
* @since 1.0.0
* @access private
*/
private function define_admin_hooks() {
$this->loader->add_filter('plugins_api' , $this->plugin_admin, 'view_details', 10, 3);
}
or do this:
/**
* Register all of the hooks related to the admin area functionality
* of the plugin.
*
* @since 1.0.0
* @access private
*/
private function define_admin_hooks() {
$plugin_admin = new My_Plugin_Name_Admin($this->get_plugin_name(), $this->get_version());
$this->loader->add_filter('plugins_api' , $plugin_admin, 'view_details', 10, 3);
}
I'm usually doing the second way, even though it's not perfect.
Hope this helps :)
@dingo-d Appreciate that! I actually have $plugin_admin = new My_Plugin_Name_Admin($this->get_plugin_name(), $this->get_version()); in my private function define_admin_hooks(), I didn't mention it at first because I assumed it was common practice, since it's included in the boilerplate: https://github.com/DevinVinson/WordPress-Plugin-Boilerplate/blob/60940a97614170845242849d0b78e6def0d06073/plugin-name/includes/class-plugin-name.php#L155
My bad... any other ideas?
Is your plugin hosted on wordpress.org?
@dingo-d No it isn't, but I know it's possible to override the plugin details. I'm trying to do this basically: https://rudrastyh.com/wordpress/self-hosted-plugin-update.html
Ok, then you need to turn on the debugging, and put a bunch of error_log()s around and see where your method breaks. See if it's called at all, if not, why.
@dingo-d Yeah, I've been digging for a while—hence why I'm here. it's being called, everywhere except on my plugin. Last resort is probably Stackoverflow ;)
So after some more debugging, I can see it's working fine except on my own plugin instance. Heck another function that hooks into site_transient_update_plugin is working and I can see WordPress showing an update notification (the red icon in the menu) but not below my plugin. I feel this has to do with how it loads in the plugin boilerplate as I just tried it on a vanilla plugin and it worked fine.
If anyone ever tried to set up a View Details link on the plugins.php page let me know. I'd love to figure this one out.
I just pasted the code and got an error
set_transient( 'xxx, $remote, 43200 ); // 12 hours cache
You're missing a ' in xxx :)
set_transient( 'xxx', $remote, 43200 ); // 12 hours cache
But besides that, the filter won't fire. It did fire when I viewed 'view details' of another plugin when I tested this.
Try asking on wordpress.stackowerflow :/
@dingo-d thanks for sticking with me, I appreciate it.
I was probably missing an ' because I removed some code when I was editing my first post. I just checked my code, and it's there.
But exactly, it only fires when you view 'view details' of another plugin... 👎
i guess i'll reside to SO.
I've worked it out as I was facing the exact same problem with Boilerplate and the referenced plugins_api code. The issue is in the Update function where the plugin filename is set. It's set using plugin_basename( FILE ) which actually returns 'plugin/admin/class-plugin-admin.php' but you want it to return plugin/plugin.php. Hardcode that (replacing it with the name of your plugin) and it'll work.
@1jump2 Thank you Sir, it works :)
@1jump2 Yes, it works!
The example had the plugin_basename( __FILE__ ) because it was the main plugin file. In my case, and probably yours and the OP's, the updater was in a different file. Hardcoding the plugin slug fixed the issue.