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. Jānis Elsts says:

    No, the “Check Again” button only checks for WordPress core updates.

    Put the code wherever it’s convenient. For example, you could create a menu item that calls the checkForUpdates() method (for debugging only).

  2. Richard says:

    From https://github.com/jeremyclark13/automatic-theme-plugin-update,

    set_site_transient(‘update_themes’, null); in functions.php appears to check for updates every time the Admin area is accessed.

  3. Richard says:

    The theme is updated but it’s theme-name.tmp I’ve checked the zip and it unzips correctly to theme-name (i.e. it unzips within its folder). Any idea why this is happening?

    Thanks.

  4. Jānis Elsts says:

    Just to make sure I understand you correctly, does the ZIP match this directory layout?

    theme-name.zip
        /theme-name
            functions.php
            style.css
            ...other files and folders...
    
  5. Richard says:

    Correct. That’s the folder structure. The update goes through the following:

    Unpacking the update…

    Installing the latest version…

    Enabling Maintenance mode…

    Removing the old version of the theme…

    Disabling Maintenance mode…

    Theme updated successfully.

    But through FTP it’s now apparent that the folder ends in.tmp

    I also use set_site_transient(‘update_themes’, null); in functions.php to detect that an update is needed, then comment that out before implementing the update (it crossed my mind that that might be the cause of the problem but it isn’t.)

    All other theme updates from the WP repository go ahead with no problems at all.

  6. Jānis Elsts says:

    Hmm, I don’t know what else could cause that.

    What happens if you update the example theme? Does it also get the “.tmp” suffix?

  7. Richard says:

    Thanks for the email help. Turns out it was my zip programme incorrectly telling me it was in a folder when it wasn’t. I used a different compression programme (7-zip) and it works fine now.

  8. Dejan says:

    Normaly I do not post commnets on sites ,but I will make an exception in this case just to say: Thank You!! For your time and effort for making “Automatic Updates For Private And Commercial Themes”. It is really Awesome Script. All the best to you and your family!

  9. Sisir says:

    For some reason it doesn’t work for me currently. I will wait for an update. Also what happens If I have same theme installed more then once? Unlike plugins you can install a theme multiple times with different directory name.

    Is there any github repo I can follow?

  10. Jānis Elsts says:

    Sorry, but if you don’t elaborate on how it doesn’t work, it’s pretty unlikely that an update will help. I can’t really fix a bug if I don’t know what it is 😉 Did you at least try the example theme?

    Multiple installations should work fine as long as you give each one a unique slug that matches the directory name.

    There is no GitHub repository for this particular library.

  11. Sisir says:

    I am puzzled right now. Fact that I have used this lib before with success. I will post after I track down the issue.

  12. Hello, for some reason the updater keeps checking for another theme similar to my theme name in the WordPress theme repository, it is not checking the metadata file that I included in the functions file, instead it is checking WordPress.org for my theme… Anyone know how to fix this issue?

  13. Jānis Elsts says:

    This library never checks WordPress.org; it doesn’t even have the capability. More likely your functions file isn’t set up right and the custom updater doesn’t work at all, so WordPress uses its default update mechanism for your theme.

    Some ideas:

    – Try the example theme linked in the post and check if the custom updater works there.

    – Make sure the slug you pass to the ThemeUpdateChecker constructor matches your theme directory name.

    – Come up with a different name for your theme. This library can override updates displayed by the default updater, but it’s not recommended. Also, have you considered what would happen if someone installed your theme and the theme from WordPress theme repository on the same site?

  14. […] 原文地址:Automatic Updates For Private And Commercial Themes […]

  15. Eric Schwarz says:

    As I mentioned on the wrong page, sorry, I have a multisite and the updater only works if is on the main blog. Is there any work arounds for this?

  16. Jānis Elsts says:

    Sorry, there’s currently no way around that.

    Here’s why:

    The custom update checker is just a piece of code. For updates to show up, that code needs to be run. Since it’s part of your theme and (presumably) initialized in your functions.php, it will only run when your theme is active and your functions.php is loaded by WordPress. The only situation where WordPress will load a theme’s functions.php file in the network admin (which is where updates normally show up) is when your theme is active on the main site.

  17. sisir says:

    Hey Janis, I am having some problem with the theme upgrader. Unfortunately it doesn’t work (doesn’t show the bubble).

    1. Your script works with your test theme.
    2. Doesn’t work when I put it on my theme.
    3. The json and zip file of the theme is publicly accessible.
    4. Put the function on functions.php file without wrapping with function and with wrapping with function using init hook. Failed both cases.
    5. Tried with different location for json and zip file (both accessible via web). But still no use.

    Can you give me a hint what should I do more to troubleshoot this? You can send me an email to my email address to start a conversation. Appreciate your good work.

  18. Dan says:

    Hello, will this work on multiinstal wordpress? Thank you.

  19. Jānis Elsts says:

    Do you mean WordPress Multisite? Yes, it will work, but only if the theme is active on the main site. Otherwise the update checker will not be run.

  20. Arnaldo says:

    Hey Janis,

    I’m trying to use the same principle to perform automatic updates on a plugin I’ve written. However, the function hooked to the pre_set_site_transient_update_plugins filter never gets called. I put some dummy log lines and echoes over there, nothing. I’m on multisite installation. Any ideas?

    Cheers,
    Arnaldo

Leave a Reply