The Complete Guide to WordPress Plugin Maintenance
So you’ve created a little plugin. Now what? If you’d like to share your work with the world, why not release it in the WordPress Plugin Repository?
This is great practice, it helps others, can get you noticed, and can even be one of the founding blocks for your future business.
In this article I’ll show you how you can get your plugin accepted into the WordPress.org directory and how you can maintain it once it’s out in the open. I’ll be focussing on the techniques I use at the moment, but this isn’t to say there aren’t others – perhaps some might work even better.
Take a look at how I do things, learn from it, make it better and let us know in the comments what you are up to.
Note that this article contains some advanced material, especially towards the end. Don’t get discouraged if you don’t understand symlinks, working with git, Vagrant and other fancy tech. The basics of creating and maintaining a plugin is not that difficult. Work within your comfort zone and learn about advanced techniques when you’re ready. In other words: Don’t worry if you don’t understand the whole article!
Creating Your Plugin
Every plugin is different so there isn’t a lot I can say specifically but there is a good amount of general advice to follow. Some of it will help get your plugin accepted, some of it will help make it easily maintainable. Here are just a couple of things you should keep in mind before you submit your plugin.
Make Sure Not To Reinvent The Wheel
The “reinventing the wheel” metaphor doesn’t really work here. A much better saying would be to make sure not to “reinvent the redundant pyrophoric igniters”. WordPress veterans are often cross with developers for writing custom code for something in WordPress that already exists. The issue isn’t that developers like to write redundant code, they just don’t know it’s there. From their point of view they are inventing, not re-inventing, but I digress.
If you are creating a function which you think should be in WordPress, it probably is. Use Google, open up the Codex and rummage around a bit.
Use A Logical Structure
PHP has an include feature for a reason – use it. If you’re writing a plugin that communicated with the Mailchimp API, put the functions (or better yet, a class) that do the talking in a separate file. Create a nice folder structure for scripts, styles, images – just like you would for a website.
Follow a structure guideline within files as well. Name functions similarly, comment generously, add table of contents (more on this later), keep related functions close together and so on.
Use Hooks Properly
Plugins can’t be created properly without hooks, that’s beyond a doubt. In many cases there are a number of hooks you could use for the same purpose. While multiple approaches may work, there may be A Way of doing things, especially with init hooks. Look at the documentation for the hook you are using to make sure you’re implementing it correctly.
Apart from using hooks you can create your own, developers and users will thank you for it. By creating hooks you can let other plugins or even themes overwrite your functionality.
This is mighty useful for developers creating app type packages for their clients. If you don’t know how to create your own hooks take a look at our WordPress hook guide.
Be Consistent and Clear
I think this is the most important aspect of being a programmer period. If you are consistent it doesn’t matter if your code isn’t perfect. Making code written consistently better is infinitely easier than making inconsistent code better. In addition, be as clear as you can. If your plugin lists Tweets don’t store a Tweet’s data in the
$t variable, it makes no sense. Those extra 3 characters won’t give you carpal tunnel syndrome, go ahead and use
$tweet. The same goes for function names. Instead of
add_hastag_links_to_tweet_text(). The first function could list hastags in a tweet, it could actually send out a Tweet with hashtags, who knows? The second function name is much more descriptive.
Clarity also means making sure your function names in the global namespace are unique so they don’t clash with others’. You can use classes to get around this but for smaller plugins you’ll want to prefix them. A prefix derived from your plugin’s name is best. If you’re creating an “Awesome Google Analytics” widget using “aga_” as the prefix is just fine.
Document Your Code
I don’t just mean type the odd inline comment. Go full-on phpDoc on your plugin and do it properly. WordPress uses it, other developers use it, you should too. The syntax is easy to learn, all you need to do is write a short description of the function and document the parameters, return values, global variables used and some other details.
Translate Your Plugin
There are a lot of non English speakers out there and another host of users who do speak English but would rather work in their native tongue. Why not let them when making your plugin translatable is so easy! We even have a translation guide for you to help you out.
Preparing For the Repository
There are a few things you’ll need to be aware of and add to your plugin to get into the repository. First of all, you’ll need to name your plugin something unique. Do a quick search in the repository and make sure nothing like it exists. Then, make sure the folder name of your plugin is derived from the name. This is not strictly necessary, but it helps. Non-caps latin characters and dashes are best, the folder name for “My Awesome Plugin” could be “my-awesome-plugin”. Your next task is to create a readme file. This should be named
readme.txt and placed in your plugin’s root directory.
The Readme file contains all the information about a plugin that is shown on the main plugin page in the repository. The “Description”, “Changelog”, “Installation”, “FAQ”, “Screenshots” and “Other Notes” sections are all populated from there. WordPress has a readme template to help you out and a handy readme validator you can use to check your work.
Note that the readme file needs to be formatted in a specific way but it does not use Markdown (sadly). Sections are separated with titles wrapped in double equal signs, sub-sections use titles wrapped in single equal signs. Anything you write besides the allowed sections will get added to the “Other Notes” Section. Take a look at the skeleton below for a good overview.
Finally, the most important step is testing. Try and get a developer and a non-developer to test it as well. The developer knows where issues may arise from bad code, general users are great at catching non-code errors – little overlooked bits.
Also make sure that your plugin’s main file has the correct and complete header. The comment at the top of this file should have the plugin name, description, version, author, author URI and licence information. Here’s how the header of Easy Featured Images looks, we’ll be using this plugin as an example throughout this article.
Easy Featured Images
Before we submit our imaginary plugin let’s go through all the files in an actual plugin, Easy Featured Images. This is a perfect candidate for us because I showed you how the whole thing was built right here on WPMU DEV. If you want to get up to speed take a look at the how-to article.
Structure-wise the plugin contains a number of files, but only three of them are actually needed for the functionality. Let me break it down:
easy-featured-images.phpis the main plugin file and contains all the PHP code
style.cssis the stylesheet for the backend styles
license.txtis a copy of the GNU GPL 2 license
readme.txtis the readme file we discussed above
humans.txtis a convention for indicating the humans behind a product, see humanstxt.org for more info
langdirectory: This directory contains the translations. They need to be named [plugin-folder]-[locale].po and [plugin-folder]-[locale].mo. I have a
translations.potfile in there if someone wants to translate into another language, it contains an untranslated version of the strings.
Submitting Our Plugin
Once everything has been coded, tested and prepared it’s time to submit. You will need to link to a zip folder of your plugin so you should upload it somewhere safe. You can use any location you like, from your website to a free file hosting service, just make sure it is reachable by anyone. Head on over to the Add Your Plugin page and fill out the form.
There are two important things to remember here. The plugin name you type will be directly converted to the plugin slug which can not be changed later. The name will be converted to lower case, spaces will be converted to dashes and all special characters will be removed.
The second thing to note is that the description you give in the box is meant for the review team, it will not be shown anywhere. Don’t paste in your readme file or just the description of the plugin. You may want to tell them why the plugin is useful, where they can go to test it easily and so on.
There are almost always 50+ plugins in the review queue so anything you can do to make the life of the review team easier is appreciated I’m sure. If the plugin provides front-end functionality I usually set it up on my own website and give them a link, just in case it is useful to them.
Don’t forget that the women and men reviewing your plugin are doing it for free. Be nice, be patient and a thank you never hurt anyone.
Once your plugin has been reviewed you will get an email of its acceptance or its rejection. If the plugin is rejected you will get a reason for the rejection so you can go back and try again. Assuming everything goes well, your plugin should be reviewed soon. I’ve had plugins reviewed in 8 hours but I’ve also had one in the queue for 72 hours, it depends on their workload, be patient! You should receive an email much like the one below:
Adding the Plugin to the Repository
Once the automated system creates your repository you’ll have an empty space for a plugin, but not the plugin itself. You’ll need to use SVN (a version control system) to access your repository and work with it. If you’re on a Mac you’re in luck, SVN is already installed as a command line tool. If you’re on a popular Linux distro chances are you have it as well. If you’re on Windows it’s a bit more difficult to get a command line tool
I’ve successfully used the tool from Collab.net myself. You need the Subversion command line tools (not Subversion Edge). Once installed you should be able to go to your command line, type
svn --version and get a proper output. You can also try this package from Sourceforge or the SilkSVN client. If you’re on OSX or Linux pop open your terminal and go from there.
If you prefer a graphical user interface there are tons of those about. Just search for “Subversion Clients” in Google. This should bring up quite a few. Tortoise SVN is a popular free choice.
I will use the command line and I will refer to both the Windows command prompt and the OSX and Linux terminals as “terminal” for short.
Uploading With SVN
I can’t get into a full tutorial on SVN but I highly recommend reading the free SVN Book. Aside from teaching you SVN specifically it tells you all about version control in general which is great! That said, I’ll explain every step as I go along.
First I create a directory which I plan to use for all my upcoming plugins. Let’s call this directory “wordpress-plugins” and place it within our main user folder. I navigate to this directory using the terminal. On Windows type
cd %userprofile%/wordpress-plugins, on OSX and Linux type
1.6 million WordPress Superheroes read and trust our blog. Join them and get daily posts delivered to your inbox - free!
To get the contents of the repository WordPress has created for you type the following command:
Make sure to replace the URL there with the repository URL in the acceptance email WordPress sent you. After a bit of thinking, the contents of the repository will be added inside a folder which has the same name as your plugin. Within that folder you will find four folders:
trunkholds the most recent version of your plugin
tagshold older versions of your plugin
branchesare usually used for the implementation larger scale features
assetsis used to store images and screenshots for the plugin, you may need to create this directory yourself
Right now our main concern is the
trunk directory. Go to the original location of your plugin and copy all the files and folders within it and paste it into the
trunk directory. Now go back to the terminal and issue the following command:
svn add *. This will add all the files you’ve just pasted to the list of files to be added to the repository. The next step is to upload your work:
svn commit or
svn ci for short tells SVN that you would like to commit your changes to the repository. The
-m parameter allows you to add a commit message which will be stored along with the changes. Once you’ve committed successfully, your plugin will appear inline in a few minutes (it usually takes a couple of seconds).
Working With SVN
If you need to modify your plugin you’ll need to commit your changes. I’ll talk in detail about what you should change during updates further down, for now, let’s look at the nuts and bolts with SVN.
During an update to your plugin you are likely going to add, delete and change files. When deleting a file I highly recommend doing it from the command line with SVN because that will remove it from the repository as well. Use
svn delete unwanted.php for example.
Similarly to deleting a file, adding it by creating it in the plugin folder is not enough, it will not be added to the repository when you commit. You’ll need to issue
svn add newfile.php to add it. You don’t need to worry about modified files too much, they will be handled by SVN automatically.
svn status command is helpful when you want to see exactly what has been added, what hasn’t been added, which files are being removed and which have changed. If you’d like more info I recommend the previously mentioned SVN book and WordPress has a short article about it as well.
Updating Your Plugin
Once you’ve released your plugin you may add new features and fix new bugs. You should increment the version number accordingly to make sure users get notified of the changes. Let’s take a look at some of the practical things you’ll need to do during an update once you’ve actually written all the code.
First, open the main plugin file and increment the version number. The versioning method in the repository is all over the place, it comes down to your personal preference. I suggest using the x.x.x format. I personally use the numbers to represent how big a change was. 1.0.0 is the initial version, 1.0.1 would be a minor bug fix followed by another couple of bug fixes at once, brining the version to 1.0.2.
if I then implement a larger new feature I would increase the number to 1.1.0. If I make a major change I increment the first number making it 2.0.0. I would do this even if I recoded the whole plugin, making it better, but without offering any bug fixes or features. If you prefer something more ordered you can take a look at semantic versioning.
Next, go into your
readme.txt file and take a quick peek at the “Tested up to” line at the top. If a new WordPress version is imminent or the current version is higher than your tested up to version you should make sure your plugin works on the new version and increment this number accordingly.
Browse through your readme file and make sure everything is correct. If you’ve added a new feature perhaps you want to add it to your description. One place where you’ll definitely need to edit is the changelog section. It is most common to use headings with bullet points, something like this:
If you’ve made a change which requires the users’ attention you can add the “Upgrade Notice” section to your readme file. The sections should correspond to the version upgrade notices:
This notice is shown in the backend plugin list, our example would look like this:
Note that this is for important update information only, not humdrum details like when you’ve added an awesome feature or a translation.
If you have a
humans.txt file like I do you should open that and change the updated date within. Finally, if you have a version number or a date anywhere else which may need to be changed you should do so now.
Once you’re done you can commit your changes with a descriptive commit message. Once committed your plugin will be updated in a few minutes and users will start getting update notifications.
Beautifying the Plugin Listing
To make your plugin and the WordPress plugins page itself nice-looking I recommend you spend a few minutes in the
assets folder of your plugin repository. There are three image files you can add here which represent your plugin:
icon-128x128.pngis the icon shown beside your plugin in the plugin directory and admin plugin searches
icon-256x256.pngis the retina version of the previous image, it should be twice the size
banner-772x250.pngis the wide featured image shown on the single page of your plugin. The name of your plugin will take up some space in the bottom left so plan accordingly!
Once uploaded, these images will be displayed on WordPress.org and admins across the globe pretty quickly.
Taking Things a Step Further
Like many developers I prefer git over SVN because the Git workflow is better suited to me and more importantly: by using Github, others can contribute more easily. In other words, Github uses the great git for version control but also allows for social coding.
If you don’t want to follow this step no worries, it’s not needed at all. It does require some knowledge of git but luckily there’s a book for that as well, the git book.
All the plugins I create actually start out as Github repositories. I create a structure I borrowed from the WordPress Plugin Boilerplate, it looks something like the structure on the left.
Note that this is much the same. The only difference is that the root directory contains three files (a changelog, a license and a readme file) and a directory which is named the same as the plugin. This is the directory which would be considered the root of the svn repository, it contains the assets, trunk, tags and branches.
README.md file is displayed on the github repo for the plugin. It is geared more toward developers so it doesn’t contain some basic info like installation. The
CHANGELOG.md file is almost always the same as the changelog in the plugin’s
readme.txt. It only differs if I make a change which only affects the non-plugin files like the
Once the coding of my plugin is finished I zip up the trunk directory within the repository, upload it somewhere and submit it. Once it has been accepted I basically copy-paste the contents of the directory into the SVN repository.
Updating Your Plugin
During the plugin’s lifetime I consider the Github repository to be “THE” plugin. I make all changes there first, mirroring them to the official SVN repository.
If I’m creating a new version I’ll create a tag in the github repository and commit all my changes. At this point, if someone were using the Github repo to stay up to date they would already have access to the new version.
To update the official SVN repo I create a tag from the trunk if I need to. I then delete the whole trunk directory. I then copy-paste the trunk directory from my git repo to my SVN repo.
Once done, I fire up the terminal and take care of the changes. I delete all files that are no longer present and add all new files. Finally, I commit and a new version is born.
Note that this sounds a bit tedious which is because it is. There are some ways to mirror git and SVN like git-svn but I’ve never had the time to check it out, perhaps in a next post!
For me the overhead of copy-pasting is not too bad. If I needed a quick solution I would probably write some sort of bash script (or batch file for Windows) which would allow me to copy paste things with quick commands.
Accepting Code Contributions
Github makes it super-easy to accept contributions in the form of pull requests. Here’s the gist of it: Alice likes your repository but wants to make a change, perhaps add a translation. She clones your repository, making an exact copy if it on her account. She then works on it as usual. Once she’s ready she should have a working version of the plugin with a new translation.
Github allows Alice to create a pull request which is essentially an action that can merge Alice’s changes into the original repository. Github will tell you if a pull request can be merged automatically and will allow you to add the new functionality with the push of a button.
In the above example I needed to do next to nothing to end up with a German translation. A developer was kind enough to share his work, all I needed to do was push the merge button and update the plugin in the SVN repository.
I thought it would also be useful to share how I go about making changes to my plugins. Since the plugin is stored in a way that doesn’t really allow it to be developed from within the repository it seems difficult to work with it.
One way is to check out only the contents of the trunk directory into a folder within a WordPress installation’s plugins directory. In theory this works fine but leads to confusion later on, especially if you have a number of local WordPress installs.
The best way I found was to work straight from the full Github repository and use symlinking to hook the plugin up with WordPress. This means that my repositories are in a completely different directory.
Multiple symlinks can also point to the same directory which is handy because I can symlink the plugin to multiple WordPress installations.
If I change the plugin in the central location it is reflected in all linked installations. My folder structure is shown on the right.
As you can see from the
Vagrantfile this is a Vagrant powered virtual machine. The html is where all the web files live, this is the root of the server. The html directory’s sub-folders are actual WordPress installations. Open up the
testing folder and you would be greeted by
wp-content and friends.
github folder houses all my WordPress plugin github repositories. The
wordpress folder contains all the SVN repositories. I then use the terminal to SSH into my vagrant machine using
I navigate to the plugins directory of a WordPress installation, for example:
cd /var/www/html/development/wp-content/plugins. While in that directory I create the symlink:
The first part is the path to the trunk directory within the Github repo, the second is the folder to symlink it to. At the end of this process your plugin will show up in the WordPress installation but the files are actually stored elsewhere – neat!
If you’re interested in Vagrant and symlinking we have a guide for both. You can read all about using Vagrant for WordPress and some must have WordPress tools where I covered symlinking in more detail.
This might have taken a while to write and read but actually doing it doesn’t take as much time as you’d think. The first time round it will take a lot more since everything will be new to you but once you get used to it and hit your stride you’ll be able to update a plugin in a minute.
Do you have a great way of developing plugins, have you put more automation into your workflow? Let loose in the comments and let us know.