Automatic Updates For Private And Commercial Themes

Update 2017-06-20: This library has been deprecated. Please use PUC instead. It’s more current and it supports both themes and plugins.


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 GPL and 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 :

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

  1. flavius says:

    i don’t know if it’s wordpress related or this class related, so i’m asking here. is there a way to display the “There is a new version of THEME_NAME available. View version 2.0 details or update automatically.” message wherever i want?

    thanks

  2. Jānis Elsts says:

    Sure, though the specifics will depend on where/how you want to display it.

    WordPress stores the update data in the “update_themes” transient. Your theme can read it and, if necessary, display an update notification wherever it wants. See the theme_update_available() function in /wp-admin/includes/themes.php for details on how WordPress does it.

  3. Any thoughts on this error? The server is underpowered and I’m moving to a new host, but until then?

    Fatal error: ThemeUpdateChecker::injectUpdate() [themeupdatechecker.injectupdate]: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "ThemeUpdate" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in /home/account/public_html/wp-content/themes/seo-theme/plugins/update.php on line 177

  4. Jānis Elsts says:

    Are you using a persistent object caching plugin (e.g. Memcache or similar)? Some of those plugins can unintentionally change the load order of database options, which would cause problems like this.

  5. Sisir says:

    hey, its sisir again. It seems the update notification is not shows when version goes into four digit. Like 2.1.0.0 to 2.1.0.1.

    What is your thought?

  6. Jānis Elsts says:

    Strange, the code that compares the installed and available versions should be able to handle any number of digits. Could this be caused by something else, e.g. the library not retrieving the metadata file properly?

  7. Sisir says:

    I have done some check after that. I think the cause might be something else. Not sure what older version of my theme was able to pull the upgrade. The update domain is using cloudflare.com that might be the issue. But when i access the metadata file via web browser it shows the latest version.

    I am still working on this issue. I might change the domain for the update. I will let you know.

  8. Sisir says:

    The problem was fixed. It was a bug on my code. Sorry about that 🙂

  9. […] 最近Yuxin寫了一個FDTime的佈景並有釋出,有關注的讀者應該有發現版號1.1.0已經有後台佈景自動偵測佈景版本更新的功能,而且能夠像官方的佈景一樣能夠一鍵升級,再也不用請佈景使用者去下載檔案再覆蓋,相當方便。這個功能的實現是我在國外的網站看到的,阿湯的S+佈景也有這個功能,這篇是寫給有在開發佈景並給他人使用的佈景開發者,如果你是下載別人的佈景就不用閱讀這篇了。 […]

  10. Soso says:

    Need help.
    I don’t know why bu in update core page, the notification appears but it doen’t able to show current version of the theme.

    Its telling: current version , available upgrade to 1.0.4
    actually it doesn’t show current version no metter what. Checked stylesheet and there is Version in the header as its should be.

    So whats the problem ?
    Anyone?

    tnx

  11. Jānis Elsts says:

    Does the current version show up if you remove the updater library?

  12. Andres Bott says:

    there’s a bug in the actual class: the methods addQueryArgFilter, addHttpRequestArgFilter and addResultFilter uses the unset parameter themeName in add_filter, but apply filter uses the right paramenter theme.

  13. Jānis Elsts says:

    Thanks for reporting the bug. Fixed it.

  14. Bryce says:

    Love this and it’s working great for me, but I noticed that when an update is available, it says in the updates section it refers to my theme in lowercase and doesn’t state the theme’s current version. Also, for me it’s still displaying an update even if the theme is up to date. The only way I could solve this was by temporarily changing the theme-update json file name but this isn’t practical as everytime I change it back with a new version, users with the up to date version will be asked to update.

    Could this be caused because it’s a WP installation running on a localserver?

  15. Jānis Elsts says:

    WordPress takes the theme name from your style.css, so unless it’s lower-cased, I don’t know why it would show up in lowercase on the Updates page.

    Are you using the correct directory name in the update checker constructor? For example, if your theme is located in /wp-content/themes/example-theme, you would use “example-theme” as the directory/slug.

    Finally, I don’t think this has anything do to with your WP installation running on a local server. I’ve tested the library on my own local server(s) multiple times without issue.

  16. Brodie says:

    I’ve set this up on a parent theme and it works great, but when setup on a child theme in addition it only checks for the parent theme updates. I made sure each new ThemeUpdateChecker has a unique name. Is this a limitation?

  17. Jānis Elsts says:

    It should work with child themes, too. Take a look at how the example theme (link in the post) is set up – it’s actually a child theme of TwentyTen.

  18. Bdoie001 says:

    I can get it to work on either a child theme or a parent theme. It’s when I have automatic updates setup on both the parent and child theme I have issues. I made sure to declare a new Update object for each theme with different names so they don’t conflict but it seems like the child theme isn’t taking.

    I’ll keep poking around the code, thanks for the reply.

  19. Eric Schwarz says:

    Not sure the last time you check but my multi wordpress 3.4 doesn’t work with you example theme at all, even tried that plugin to trip the update process too.

Leave a Reply