Excluding your plugin or theme from update checks

There has been a vigorous discussion going on regarding what data WordPress installs send to WordPress.org when doing update checks. Because WordPress (the software) doesn’t know whether a theme or plugin is listed in the WordPress.org repositories, it has to check them all, and let the repository sort it out. Some have expressed concern that private plugins developed for a single client could contain sensitive information in their headers, like contact information for the developer, etc.

If you, as a plugin or theme developer, would like to exclude one of your plugins or themes from the update array, the following code will do the trick.

For plugins:

function cws_hidden_plugin_12345( $r, $url ) {
	if ( 0 !== strpos( $url, 'http://api.wordpress.org/plugins/update-check' ) )
		return $r; // Not a plugin update request. Bail immediately.
 
	$plugins = unserialize( $r['body']['plugins'] );
	unset( $plugins->plugins[ plugin_basename( __FILE__ ) ] );
	unset( $plugins->active[ array_search( plugin_basename( __FILE__ ), $plugins->active ) ] );
	$r['body']['plugins'] = serialize( $plugins );
	return $r;
}

add_filter( 'http_request_args', 'cws_hidden_plugin_12345', 5, 2 );

Just change the cws_hidden_plugin_12345 string (two instances) to a namespaced function name for your plugin, and you’re good to go.

For themes:

function cws_hidden_theme_12345( $r, $url ) {
	if ( 0 !== strpos( $url, 'http://api.wordpress.org/themes/update-check' ) )
		return $r; // Not a theme update request. Bail immediately.

	$themes = unserialize( $r['body']['themes'] );
	unset( $themes[ get_option( 'template' ) ] );
	unset( $themes[ get_option( 'stylesheet' ) ] );
	$r['body']['themes'] = serialize( $themes );
	return $r;
}

add_filter( 'http_request_args', 'cws_hidden_theme_12345', 5, 2 );

Put this in your theme’s functions.php Again, just change the cws_hidden_theme_12345 string (two instances) to a namespaced function name for your theme. Do note that this will only hide the ACTIVE theme. This code doesn’t get run if the theme isn’t active. If you want to hide non-active themes, you’ll have to put this code in a plugin and instead of using get_option( 'template' ) or get_option( 'stylesheet' ) you’d hardcode the values for the inactive theme you want to hide.

Just a note: I don’t want the comments to turn into another battlefield for the update check debate. I’m putting my code where my mouth is and showing you how you can keep private plugins/themes from contacting WordPress.org if you so wish. Comments about this code are welcomed!

73 thoughts on “Excluding your plugin or theme from update checks

  1. Hi,

    Thank you for you code. I just have a short note on your code. It would be better (WordPress Coding Standards) to write:

    if ( 0 !== ….

    or

    if ( false !== …

    .. sorry for bothering you with that.

  2. Antoher nice use I can think of for this is when I create a plugin (for my own use) that has the same name as one in the repo. I usually rename them to remove the update reminders, but this seems like a cool alternate solution for plugins that I don’t plan to release.

    Thanks!

    • Oh, nice! I do that too — I have custom Akismet versions I maintain for clients (don’t put registered user comments through Akismet, only pings, etc), and didn’t think of using this to prevent updates from showing as available for that.

  3. I’m a little shaky on “namespaced function name”

    I am guessing the following replacements would do the trick:

    function mysecret12( $r, $url )

    add_filter( ‘http_request_args’, ‘mysecret12′, 5, 2 );

    Or do I need to take a course on php?

  4. Hi Mark,

    If the hook and associated function is in the plugin and the plugin is deactivated, this will not work… so privacy on automatic checks is not 100% done with that fix.

    For personnal needs (plugin folders can contain customized data and automatic upgrade by deleting existing folder content removes these datas), i tried to deactivate plugin automatic upgrade message
    http://core.trac.wordpress.org/ticket/11227

    So to make automatic checks “discardable” and automatic upgrade message “customizable”,
    fix must include new code inside WordPress supporting new optional tags in plugin header.

    Example for those optional tags :

    AutoUpgrade_checks: none (optional)

    AutoUpgrade_text: your text here… (optional)

    Regards

  5. Thanks for this Mark,

    It’s been a tricky problem I’ve been trying to get around for some time now. I did notice that when I tried this on a 2.7 install it didn’t work. When I upgraded to 2.8.6 it fixed the issue.

    Just a note for anyone else out there having issues.

  6. Hi there, Sorry to bother you but could you help me with auto upgrade check of private plugins and themes on developer`s site (site other than wordpress.org).

    Any pointers would be of great help.

  7. Matt Jensen says:

    Hi Mark

    Looks good, thanks very much for the info.

    I was hoping you could clarify a few things:
    - When does the WordPress request/http_request_args event get called by WordPress and how often do you know? I’ve Googled it but there’s not much info about it
    - Am I right in saying that this will NOT remove update messages for plugins that already have update messages? ie. it only affects future update requests? I tried editing the plugins I don’t want to show update messages (because I’ve modified them) to add Upgrade Check: none
    Upgrade Text: your text here
    as per ‘Arena’s comments and link at http://core.trac.wordpress.org/ticket/11227
    however it hasn’t removed the update messages for those plugins (yet).

    All I want to do is remove the update messages for plugins I’ve modified so that the update messages don’t show and so that other administrators don’t update the plugins and overwrite the changes. What would you recommend as the best method for that? FYI in this case I’m not so concerned about ‘plugin privacy’ as per the original intention of your code.

    Thanks again
    Matt

  8. I’m interest in the comment from Rohit. It seems that in the absence of a paid marketplace from wordpress it would be beneficial to have an update check api. Where we can point the plugin to the restful url of our choice to check for an update and require user authentication for download of the update. I will have to review the code required to do this myself. Much like what is available with wpmudev.

    It would be so much better if we just had an app store style approach so that automatic could make money by providing the transaction method and plugin developers could be unleashed to just author code.

    If anyone knows of a solution for this I’d love to hear about it.

  9. Great post – it never even occurred to me that WordPress checked WordPress.org for plugins that didn’t exist there. When you think about it it’s obvious, I guess I’d never considered it before.

    This code will be going in all of my custom / non-WordPress.org plugins now.

  10. Hi Mark, big thanks for the code snippet – hopefully it’s just what I’ve been looking for. However, I must be missing something as I’m not sure how you mean for the code to work.

    I understand as far as adding the snippet into functions.php – I need to exclude a particular plugin, lets call it “joffplugin”.

    I’ve named the function “exclude_joffplugin” so I’ve now got:
    function exclude_joffplugin( $r, $url ) {…

    But what’s next? Does the code exclude ALL plugins from update checks? If so, how do I specify just my plugin?

    • WordPress’s update checker sends the filename of the main file of each installed/active plugin to WP. For your plugin ‘joffplugin’ this file is probably ‘joffplugin/joffplugin.php’ (I suspect it’s probably REQUIRED to be that file… but I haven’t double-checked). That’s file joffplugin.php in directory joffplugin

      The disable code for plugins doesn’t go in the theme’s functions.php, rather it goes in your plugin’s code – in your case in joffplugin/joffplugin.php. The bit you’re missing is that plugin_basename(__FILE__) is a reference to your filename… ie ‘joffplugin/joffplugin.php’. So this code removes your plugin’s filename from both the list of installed plugins and the list of active plugins before those lists are sent to WP for update checking.

      [PS Mark - thank you SO MUCH for this code - just what I needed]

  11. Hi,
    this works well but it seems to be only applicable to a single plugin per wordpress installation. I found that it had “cannot redeclare” issues if applied to more than one plugin.

    Is there a way around this so it can be applied to more than one plugin?

    • Peter,

      I would think that there should be a way to change the function name using a variable.. example:

      function cws_hidden_plugin_$plugin_name
      should produce a function uniquely named for your plugin.. if you have a “$plugin_name” variable defined somewhere else in the plugin code.

      The same should be true for themes.

      My syntax may not be 100% correct for the variable-controlled function name. Better check in the official guide: http://php.net/manual/en/functions.variable-functions.php

  12. Update to my previous post – I see now. Of course, you change the function name each time – sorry missed that. If the update message is already there, an easy way of cleaning that out is to update the plugin header version number to something way higher than the next version, refresh the plugins page and it will be removed, AND when you return the version number back again, it still remains gone, so all good. This is a good solution, thanks.

  13. Hi Tristan – thanks for quick response. Yes it was as easy as just altering the function name. No variable, just alter the function name each time to whatever you want (as long as you alter both instances to match in both the original function call, and in the “add_filter”. I am only testing it out to see if I can use it in future, and the first time I tried on two sepearate plugins with cws_hidden_plugin_12345 on both d’uh. On the second plugin I changed just one number, so..cws_hidden_plugin_12347 and all good.

    • The reason I suggested using a variable for the function name (and, because it wouldn’t make sense otherwise, the call to the function) is that then you never have to change the function or the call… it could be a separate file that you just always “include”.. the only thing you have to remember is to update the variable “plugin_name” or “$theme_name” or whatever you call it. And since a lot of theming functions (I do side work converting Joomla templates to be WordPress themes) require a “$shortname” variable (themes with options pages use that one a lot for database storage location), that variable would be one almost guaranteed to be part of the code already.

  14. Marty says:

    can this be used to target a single plugin? I don’t really think I understand it. I’ve got some wordpress chops, but this just escapes me.

    • Joff says:

      Likewise Marty, I think I’m 99% there but missing that final piece of the jigsaw to understand what’s going on. I’m guessing you’re in the same position as me – see my post above?

  15. Hi – fyi, the theme disable notice does not work in a MultiSite 3.1.1 network – at least not with the P2 theme … i suspect it might have something to do with a theme being network enabled or site enabled (although i tried both) and/or not being able to find path to theme ..??… cordially, chuck scott

    ps – while i did not use your plugin disable code, i did use similar code from Pete Mall at DeveloperMind.com and here to, Multisite network had issue about file path for plugin – comment thread which details that issue can be found here -> http://developersmind.com/2010/06/12/preventing-wordpress-from-checking-for-updates-for-a-plugin/#comment-773

  16. This doesn’t seem to work for me.

    I added the following code to the bottom of the theme’s functions.php file but it still displays an update is available for the theme.

    function hide_showcase_theme( $r, $url ) {

    if ( 0 !== strpos( $url, ‘http://api.wordpress.org/themes/update-check’ ) )

    return $r; // Not a theme update request. Bail immediately.

    $themes = unserialize( $r['body']['themes'] );

    unset( $themes[ get_option( 'template' ) ] );

    unset( $themes[ get_option( 'stylesheet' ) ] );

    $r['body']['themes'] = serialize( $themes );

    return $r;

    }

    add_filter( ‘http_request_args’, ‘hide_showcase_theme’, 5, 2 );

    Should this be working?

    Many thanks,

    • I’m having the same problems. I added the code to a theme that was already asking for updates, does this have anything to do with that??

      Or has something changed in WP to cause this to stop working, as the original post was in 2009, and it is now 2012?

  17. thanks for posting this. every time my client will update the plug-ins when there is notification , i lost my customizations and again i have to update.This helped me a lot.

  18. Dexter says:

    Why don’t you just change the plugin/theme version to something like 99999? Usually I open the plugin php file and edit the version number, so the plugin will never ask for update. If you want it back to chack updates, just edit the version to 0.1.

Comments are closed.