What I love about WordPress plugins

(Sam Saffron) #1

Often I hear people complain about PHP and WordPress, having developed my first hodge-podge WordPress plugin, I feel a bit wiser and wanted to share what I liked about the experience. In particular areas I think we should try to emulate:

###1 file/folder = 1 plugin

To install a WordPress plugin manually, all you need to do is copy a single file into the plugins directory and you are done.

This file is highly portable, it contains metadata at the top in a nice comment.

This comment is consumed by WordPress and allows it to extract version information, author name, home page and more.

If a plugin is composed of multiple files its distributed as a zip file, the zip file can be extracted into the plugin directory, shared by email, hacked on etc.

No dependency on Ruby Gems, no need to learn voodoo about packaging, anyone can get started trivially by hacking on a single file.

###No need to restart when hacking on a plugin

You can hack all you will on these plugin files, as soon as you save them and refresh the browser your changes are live.

###Central registry

There is a WordPress controlled central registry of plugins and extensions, this allow WordPress to control what plugins they will make available to the public and strip out ones that are big security problems and so on.

Its fantastic to be able to use the admin interface to find and update plugins.

###Hooks everywhere

Almost all operations in WordPress can be intercepted and amended. Don’t like the way it renders comments, you can register your own filter that overrides the way WordPress renders comments. There are 100s of filters you can override, there are 100s of actions you can be notified on.

A simple Ruby’ish example to demonstrate the power … imagine if you could add a single file somewhere with this contents:

Discourse.filter('update.topic.title') do |old|
   old.gsub(/!+/, "!")

Kaboom you are done, titles can no longer contain more than one ! mark.

###Plugin activation and de-activation

All plugins can easily be activated and de-activated from the admin interface, this makes it really easy to troubleshoot and experiment

###Localization system

I am quite fond of the GetText and the more modern ICU Message Format, already discussed here:


I know it is early days for us, nonetheless I think there is a lot I would like us to emulate.

There is also plenty of crazy, we can skip emulating that.

Proposal for a (hash) tagging feature
(gregmolnar) #2

No need to restart when hacking on a plugin
You can hack all you will on these plugin files, as soon as you save them and refresh the browser your changes are live.

You can do the same with discourse in development mode. I don’t think the discourse team should encourage people to hack on production systems :).

(Patrick Klug) #3

as a user, the central plugin repository and the fact that you could update both the wordpress installation and the plugins from the dashboard was the only reason I switched from serendipity to wordpress. It’s one of the most user friendly web apps to install, configure and maintain.

(Lowell Heddings) #4

One thing to think about: For the hosted Discourse forums, are you going to allow any plugins?

Perhaps an optional set of approved and pre-installed plugins that can be enabled or disabled?

Obviously there are security concerns, and you can’t let people create their own plugins, but having nearly infinite forum customization would definitely be a great selling point. WordPress.com Enterprise has (approved) plugins. Regular accounts don’t.

(Lowell Heddings) #5

One more thought about Wordpress plugins… over the years, I have installed and hacked on many hundreds of plugins, and the single biggest problem is:

  • Lousy performance because of multiple SQL calls in a loop, generating hundreds or thousands of requests against the database per page load.

I’m not sure if there’s a way you can handle that (maybe by not allowing extra database calls in a loop? Perhaps automated testing to see how many database calls a plugin adds to a topic page, or a list page?

I dunno, just figured I would share the #1 problem that I’ve had to deal with. Eventually I stopped using other people’s plugins and started writing them all myself. Which leads to my gripe as a plugin writer:

  • Bad documentation of filters, actions, and (especially) the page lifecycle.

Which event fires first, init_something, save_post or insert_post? Am I hooking early enough into the process? It’s a disaster.

(Christopher Allen Poole) #6

Don’t know about the rest of the world, but the issue that I have with WordPress is the fact that the code under the hood demonstrates a clear delight in flaunting best practices at every turn. I actually had to modify a VirtualHost to accommodate for misuse of certain functions. I’d think that at the least it could avoid the constant references to global variables…

I do agree with Geek though, the quasi abusive relationship it has with the database is horrible.

(Christopher Allen Poole) #7

I’ve found that hyper-aggressive caching can solve some of those problems, but the underlying issue is that a framework’s plugin developers will behave much in the same way that the framework developers behave. In this case, they are largely a group of people who are willing to shove best practices off a cliff with the sentiment, “HEY! Look! It works!” and damn the consequences.

On my own site I’ve actually completely forgone 99% of the plugins in favor of the one plugin which will let me add my own PHP to the posts &c. I also make manual tweaks to the WP source itself and then keep a git repo to track the diff’s so I can revert or merge when I update the source. Not sustainable for clients, but it works if it is an option.

(Lowell Heddings) #8

I did that when I first started, and you should stop doing that. It’s not sustainable, let me tell you. With all the security releases all the time, it’s important to keep WP updated, and that’s really difficult if you are hacking the source code.

Plus you can do Anything with a wordpress plugin. There’s just no reason these days to modify the source.

(zimbatm) #9

Similarly: Firefox extensions can do anything with the browser but when some of them will slow the browser down inevitably it’s Firefox who gets the blame. Chrome mitigate that problem by providing a security sandbox.

(Xavier Lange) #10

Would it be OK to just rely on Ruby’s monkey patching for plugins? Or will you need to annotate discourse application code?

(Sam Saffron) #11

The same is a kind of funny definition. There are a few issues. At the moment you would need to:

  1. Create a new gem for you plugin, good luck with that
  2. Amend your Gemfile and rebundle, meaning you would have a divergent Gemfile and Gemfile.lock to what we ship in our Github repo
  3. On local have a special Gemfile that sourced your local files.
  4. And the killer is, after you make any changes to your local copy of your plugin you would have to reload thin, cause it would not have the proper “require_dependency” in place to force a reload.

So no, I don’t think its anywhere close to the WordPress level of usability. The question on whether we re-load files in a plugin directory in prd is purely a performance issue, since if you muck with them and restarted your server you would get the new plugin anyway.

(Sam Saffron) #12

I am still thinking through a lot of this. I think that at VERY high levels, if you pay us enough money, we would allow custom plugins (our cost would be isolation, which means we would be forced to eat up a bunch of memory to isolate you)

At the medium end I think the disable enable from a set of approved and vetted plugins is the best approach.

At the low levels I would say we pick the plugins.

(Sam Saffron) #13

I would be strongly against monkey patching as a means for plugins, so against I would not allow a plugin into the main repo if it monkey patches.

Monkey patching is a nightmare to diagnose, if we refactor a method we leave your monkey patch hanging dry, it is too flexible and completely non-documentable.

The only system I would be comfortable is a tight well documented list of callbacks you can intercept and amend. As an advantage we could call the right callbacks on a virtual host basis.

(Sander Datema) #14

Makes me think of the way Apple handles its multitasking on iOs. They allow you to use about seven ways to enter the depths of the system (GPS, etc). So there’s no direct access.
Maybe you could disallow plugin devs to directly access the database and in stead offer them some kind of API that will keep the app running smoothly.

(Lowell Heddings) #15

That’s not a bad idea, though I think it would probably limit what people can do with the plugins.

WordPress basically forces everybody to go through their database interface (I mean, not really, but everybody does). The problem is that they don’t offer an easy way to load up a set of data and then use that data in a loop. You’d have to write that yourself, and it’s not offered simply in the API. Or if it is, I haven’t seen it.

I think one of the big things that could be offered in a plugin API is a great caching system, and make sure that everybody is using it.

(Rarst) #16

While it is working and convenient approach, it is not without issues:

  1. Only WordPress itself can machine-read that information. Outside of WP context you need to roll your own code (or extract relevant bits from WP core) to access it.

  2. In case of a folder WP doesn’t know which file has metadata header. It must traverse all PHP files in directory root to locate it. This doesn’t matter in normal operation, but does matter for dealing with plugins in bulk.

  3. It is not all of information. There is second set in header of readme.txt file, which mostly deals with data for official plugin repository and (again) is in custom format (Markdown dialect, slightly incompatible with real Markdown).

In a nutshell while WP approach to plugin meta data is functional and good enough, it’s probably not how it would look if it was engineered now.

For example Composer uses single file with fixed name (composer.json) in package root, that is easily read by anything that can parse JSON, has fixed schema to validate against and section for custom data.

What about people who want to roll their own repository? Central repository is highly convenient. However at some point preference of centralized infrastructure crosses a line and becomes a lock in.

There is a balance here of how much plugin controls this, how much software core controls this and how much repository controls this. In case of WordPress balance of power completely belongs to repository:

  • plugin has a say (via adding extra code to deal with it) until it is deactivated, then it has no say at all

  • core just collects and submits all plugin and theme data to update check API

  • repository uses mysterious and proprietary logic to determine and serve updates

The take away lesson here - is that there are a lot more nuances to the formula than simply having central repository.

  • How much power central repository wields? Is it as little as informational and download serving? Is it as large as up to remote kill switch? While kill switch is not explicitly present in WP infrastructure it can be used in that way in some circumstances.

  • Your software is open source. Is your infrastructure going to be? Can someone check out and run own instance of infrastructure approximately as easily as software itself?

(Rarst) #17

I am not sure what improvement to “loading set of” data you expect. ORM? What precisely do you mean by “data” here?

(Lowell Heddings) #18

Example: You want to show the pageviews on each post in a list of 20.

So you add a filter or template tag into the loop. That function is executed 20 times, each time, grabbing the pageviews for that post from the database.

That ends up with 20 different database calls.

Alternatively, you could register to pull a set of data for every item in the loop, ahead of time, with a single SQL call to grab all 20 at once. Then pull from that array or other storage mechanism during the loop.

(Rarst) #19

If you store (or mirror) data in post meta it is getting cached in object cache. Not persistent by default, but should be using persistent plugin on any considerable sized site.

WordPress is quite smart about database access and caching, it’s also getting smarter about it from version to version. The issues with them are often educational (it takes time and expertise, while dealing with lacking documentation) rather than technical shortcomings.

(Lowell Heddings) #20

Perhaps that is the answer. A preferred, high-performance metadata storage mechanism that is encouraged from the start.