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.
Download
- Client library (requires WP 3.2 or later, tested up to 4.0-alpha)
- Example theme
- Example metadata file
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:
- Create a publicly accessible “metadata file” that describes the latest version of your theme.
- 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.
A little more information – it seems the iframe is being set to 1024 by 800. Checking other plugins and theme, it seems that 800×600 is more common. I’d like to fix this – could you please tell me where this is being set?
I don’t know. The update checker does not create the iframe or specify the size, it just hands WordPress the page URL and lets WP core do the rest. It would probably take a lot of digging to figure out how WP calculates the width and height.
Okay, thanks. It seems weird that they call that bigger iframe in the theme update, but a smaller one on plugins.
In case anyone else runs into this – here’s the problem in a nutshell…
The WP auto-updater functionality assumes you are releasing a theme in the repository for free, and therefore is hard-coded to display the theme page in the thickbox window.
Then, they added negative margins at the top to hide the wordpress.org site header.
Obviously, no one would ever want to release a commercial theme and not go through the repository….sigh….
So, our only options are to finesse this in css. I’ve managed to work around this by adding a div at the very top of my html changelog file, and give it a height of 88px to match the header on wordpress.org.
That will push things back into view.
Note, that you will probably not see the very top of the window and the close button. I tested this on official release themes by installing old versions of twenty eleven and twenty twelve – and they are cut off also due to the way this whole thing is implemented.
So if you get a little creative with your details html file, you can make it look acceptable to your end users.
Well done with the research. I’ll add a link to your comment to the post so that it’s easier to find.
I Janis, I can’t get details page shown to my clients, I think everything setup correctly, clients can get my theme update from their dashboard, but there’s no “View version 1.2.3 details” link:
http://f.nio2.com/image-sWVGTfWhnv.png
Do you have any idea?
Thanks.
That’s normal, for themes the “view details” link only shows up in Appearance -> Themes.
This class is a godsend. Thanks so much. Integrates beautifully and simply with the theme I’m coding.
Hi, I got little problem here. I’ve followed your tutorial, I’ve checked the code, I’ve checked the database. I think I know how this library working, when I see the database. I’m pretty sure that the library update the information that needed by theme to update. But, unlucky me, I can’t see any notification in manage theme area. Can you suggest me something? I really confused why the notifications not showing
Try installing and activating the example theme. Does it display an update notification? If it does, take a look at how it uses the library and see if you can figure out what it does differently.
Hi Janis,
I’ve tried your suggestion. but in a hundred times I never find the notification text. Can you guide me how the library work? maybe I can fix it by myself. Just contact me by email
Hi Janis,
The problem solved. Your library just don’t work on multisite, I use multisite in development by the way. Thank you for create this easy update library
Hi,
is it possible to show the info “There is a new version of theme XXX available” of a parent-theme on the update notificaton of a child-theme?
THX Marc
No, that is not possible.
hi,
thanks for the fast answer. Is it possible to change the screenshot.png if there is a new version available. if this possible i can show an image width a flag “NEW”?!
As far as I know, there’s no easy way to change the displayed screenshot. You might be able to achieve it with some JavaScript trickery, though. For example, you could add some JS to the Themes page that finds the appropriate image and replaces the URL.
Would it be possible to give an idiot’s guide to how to check for updates manually for testing purposes? Rather than having to wait 12 hours for WP to do it’s thing? Thanks.
At the moment the only way to do a manual check is to run
$updateChecker->checkForUpdates();
Thanks 🙂
A follow up question: does pressing the Updates –> Check again button trigger an update check?
And, where would I put $updateChecker->checkForUpdates(); ?