Automatic Updates For Private And Commercial Themes

This is a PHP library that lets you add automatic update notifications and single-click updates to any WordPress theme. It’s purpose is to be easy to integrate for developers and to provide a familiar experience to theme users. From the users’ point of view, update notifications generated by this library will look and function just like those displayed by WP itself.

Dashboard screenshot

An update notification for a theme not hosted on wordpress.org

Download

License

This library is licensed under the GPLand is distributed free of charge. If you find it useful, consider making a donation. Commercial licensing (e.g. for projects that can’t use an open-source license) is available upon request.

Quick-Start Guide

There are two things you will need to do:

  1. Create a publicly accessible “metadata file” that describes the latest version of your theme.
  2. Add the update checker to your theme and tell it where to find that file.

First, the metadata file. Open your favourite text editor and copy the following JSON code into a new file:

{
  "version" : "2.0",
  "details_url" : "http://example.com/example-theme/details.html",
  "download_url" : "http://examle.com/example-theme/example-theme.zip"
}

Replace the placeholder values with your own data. As you can probably guess, version is the version number of your theme. details_url specifies the page that the user will see if they click the “View version 1.2.3 details” link in an update notification. Set this field to your “What’s New In Version 1.2.3″ page or the theme homepage (tip: if you notice that your page looks strange when viewed from the WP dashboard, see this comment).

Finally, download_url is the URL where the latest version of the theme can be downloaded. This field is optional. If you leave it out, the user will still get an update notification when a new version comes out, but there will be no “update automatically” link. They’ll have to download and install the update manually.

Upload the metadata file to your website. You can use any directory and file name you like; just remember that the file URL should be accessible from wherever someone might install your theme.

Next, lets add the update checker library to you theme. Copy the “theme-updates” directory from the client library to your theme. Then add the following to your functions.php:

//Initialize the update checker.
require 'theme-updates/theme-update-checker.php';
$example_update_checker = new ThemeUpdateChecker(
    'example-theme',
    'http://example.com/example-theme/info.json'
);

Again, replace the placeholders with your own settings. The first argument should be the name of your theme’s directory. For example, if your theme lives in /wp-content/themes/my-theme/, use “my-theme” here. The second argument should be the URL of the metadata file you just created.

Congratulations, your theme now supports automatic updates :) The update checker will automatically query the metadata file every 12 hours, checking to see if a new version is available. If it finds one, it will display a standard theme update notification on the Dashboard. Your users will be able to install the new version with a single click.

The ThemeUpdateChecker class

Class constructor
The library is configured by passing a number of arguments to the ThemeUpdateChecker constructor. They are, in order :

  • $theme –  The theme directory name, sometimes called the “slug”.
  • $metadataUrl – The URL of the theme metadata file.
  • $enableAutomaticChecking – Enable/disable automatic update checking. If set to FALSE, you’ll need to explicitly call the checkForUpdates method to, err, check for updates. Defaults to TRUE.

checkForUpdates()
Manually trigger an update check. This is useful if you want to do update checks on your own schedule. checkForUpdates has no parameters and does not return anything. If you want to actually retrieve the latest update, use requestUpdate instead.

requestUpdate()
Retrieve update information from the configured metadata URL. Returns either an instance of ThemeUpdate, or NULL if there is no newer version available or if there’s an error.

deleteStoredData()
The update checker stores various update-related bookkeeping data in a DB option. Call this method to delete that data. This is can be useful is your theme provides some kind of “uninstall” feature.

addQueryArgFilter($callback)
Register a callback for filtering query arguments. Whenever the update checker needs to retrieve the metadata file, it will first run each filter callback and attach the query arguments that they return to the metadata URL. This lets you pass arbitrary data to the server hosting the metadata. For example, commercial themes could use it to implement some kind of authorization scheme where only paying users get automatic updates.

The callback function will be passed an associative array of query arguments and should return a modified array. By default, the update checker will append the following query arguments to the URL:

  • installed_version – the currently installed version of the theme.

This method takes one parameter – the callback function.

addHttpRequestArgFilter($callback)
Register a callback for filtering arguments passed to wp_remote_get. The callback function should take one argument – an associative array of arguments – and return a modified array or arguments. See the WP documentation for details about what arguments are available and how they work. This method takes one parameter – the callback function.

addResultFilter($callback)
Register a callback for filtering theme info retrieved from the metadata URL. The callback function should take two arguments. If a theme update was retrieved successfully, the first argument will be an instance of ThemeUpdate. Otherwise, it will be NULL. The second argument will be the corresponding return value of wp_remote_get (see WP docs for details). The callback function should return an instance of ThemeUpdate, or NULL. This method takes one parameter – the callback function.

Related posts :

139 Responses to “Automatic Updates For Private And Commercial Themes”

  1. Dalton says:

    This is awesome, thank you! I can’t wait to give it a try!

  2. Sisir says:

    Awesome.. That was quick. I did not imagine you will do this that a short period. Really appreciate that. Also like the details page idea. Now i can show the changelog. :)

    Really appreciate your work!

  3. Sisir says:

    Hi, I can’t get it working. Tried everything you said. here how i use the code:

    require('includes/php/update/theme-update-checker.php');
    $updateChecker = new ThemeUpdateChecker(
    	'CityStir',
    	'http://citystir.com/update/latest/metadata.json'
    	);
    

    Check the metadata.json url it is publicly accessible. I also tried deactivate the theme then activate again, deleting then installing again (in local pc) . Even i tried

    $updateChecker->checkForUpdates();

    in the code. But nothing worked.

    Any help?

  4. White Shadow says:

    Hmm, try changing ‘CityStir’ to ‘citystir’ there. Maybe WP expects it to be in lowercase.
    Also, what does $updateChecker->requestUpdate() return?

  5. Sisir says:

    Changed

    CityStir

    to

    citystir

    . But not worked. What should i do to see what

    $updateChecker->requestUpdate();

    returning?

  6. White Shadow says:

    Something like this:

    $update = $updateChecker->requestUpdate();
    var_dump($update);
    

    If a newer version is available, this should output a bunch of metadata about that version. If something goes wrong or if the version in metadata.json is the same as the currently installed one, it will output NULL instead.

  7. Sisir says:

    Thanks! Here is the output:

    object(ThemeUpdate)#96 (3) { 
    ["version"]=> string(5) "2.0.1" ["details_url"]=> string(40) "http://citystir.com/update/changelog.php" 
    ["download_url"]=> string(46) "http://citystir.com/update/latest/citystir.zip" 
    } 
    

    I am using wordpress version 3.1 and php 5+ in my local pc.

  8. White Shadow says:

    Good, that means the update is being retrieved correctly. Given that it doesn’t show up in the Dashboard, there’s probably a bug in the part of the library that inserts the update into WP’s internal data structures.

    However, it’s already past midnight in this part of the world, so I’m not going to investigate the issue further right now.

  9. Sisir says:

    No problem. Take your time :) its also 3.30 in the morning here.. :D Good night..

  10. White Shadow says:

    Okay, the most likely reason why an update might not show up is if the theme slug/stylesheet name passed to the ThemeUpdateChecker constructor is incorrect. If this is the case, the update checker won’t be able to determine what version is currently installed, so it won’t know it needs to display the update.

    You can determine what value you should use by deactivating the theme, then examining the URL of the “Activate” link. It will look something like this:

    http://example.com/wp-admin/themes.php?action=activate&template=twentyten&stylesheet=twentyten&…

    You need the bit after “stylesheet=”. In this case, that’s “twentyten”. Use this string as the first argument to ThemeUpdateChecker().

    If that doesn’t help, here’s a modified version of the theme-update-checker.php that will output some possibly-useful debug messages at various stages of its operation: theme-update-checker-debug.zip

  11. Sisir says:

    Cool! That worked! The thing is the slug name should be same as current theme folder name and the theme zip file name should be as “slug.zip”

    Thank you very much!

  12. Sisir says:

    One feature request. Update bubbles like the plugins and update notice on update section on dashboard :D

  13. White Shadow says:

    It should already show the standard update bubble on the Dashboard -> Updates menu. Does it not?

  14. Sisir says:

    Yes. It does. I was wondering if the bubbles can be shown in the Appearance -> themes. Like the plugin menu :) Don’t know if its possible or not.

    Thanks!

  15. White Shadow says:

    It’s possible, but the implementation would probably be non-trivial and hacky. I’d rather not.

  16. Sisir says:

    No big deal! :) Take care. Paypal is banned in my country. I will see if i can get you some donation by some of my friends.

    Keep up your great work!

  17. Connor says:

    Hey White Shadow,

    Nice work on this, works real smooth. Was wondering if there’s an easy way to increase the frequency of calls home from every 12 hours to every minute. 12 hours will work fine in production mode, but with beta users I’d like to push updates every few minutes.

  18. White Shadow says:

    You could just call the checkForUpdates() function directly. If you want to set your own schedule, try the cron functions.

  19. Rilwis says:

    This library and the similar one for updating plugin are awesome. It saves me couple of hours wrapping up from a tutorial I found on the Internet. Thanks for sharing!

  20. Benjamin says:

    This is great stuff. Are you the one selling this on codecanyon.net? or has someone taken your gpl code and packaged it as their own?

Leave a Reply