Category Archives: wordpress

The pleasure of being a lone wolf

The WordPress consulting world has, of late, been all about consolidation and upsizing. Firms get larger by hiring independents and acquiring smaller businesses. Every week I read countless tweets and blog posts about the joys of working for a larger team: the camaraderie, the efficiencies of scale, the pleasure of getting a regular paycheck. And as a longtime solo freelancer, I’m very sensitive to the shortcomings of being a lone wolf.

At the same time, I try not to forget the beauty of going it alone. First and foremost is the flexibility. Aside from my personal expenses, I have no payroll and practically no overhead. I’m able to turn down work that seems unpleasant or doesn’t jibe with my philosophical predilections, even when the work would pay very well. If I have a good few months and feel like not taking on any more projects for a while, I can do so. I can spend as much time as I’d like working pro bono on free software. On the flip side, when someone approaches with a project that sounds fun but might not pay well, I can take it, guilt-free.

Flying solo also means that I’m constantly being integrated in and out of new teams and projects. I’m constantly exposed to new workflows, new tools, new technologies, new ideas. Sometimes the rootlessness feels lonely, but it can also be exhilarating.

It’s not so bad being a loner.

Getting started with WordPress plugin development

I got an email with the following question, and figured I may as well answer publicly. The question comes from someone who’s an experienced programmer, but has never worked with WordPress before.

[…] I wondered if you had some helpful advice on learning the basics of WP plugin development. I’m mostly hoping there are frameworks/libraries that the community is currently using.

I don’t know of a widely-used library of general WP plugin development tools. Partly this is because WP itself partially qualifies as a “library”, insofar as it provides ready-to-use functions for saving data to the database, URL routing, template loading, user management, etc. And partly it’s because the architecture of WP is so wide open that it’d be difficult to build a more generalized library that covered even a majority of the possible modifications you might make to stock WordPress.

That said, here are a few useful tools that I know of:

  • The official WP documentation on writing a plugin is good for learning about plugin manifests as well as a top-level overview of the aspects of plugin development.
  • The official Plugin API page is also a good starting point. It explains WP’s hook system, which is the foundation for plugin development.
  • Pippin Williamson has written a series called Plugin Development 101 that features a set of video tutorials on common plugin development techniques. Costs a couple bucks, but Pippin is a smart dude and I’m sure the videos are a really good way to get started.
  • There are a couple of tools that can be used to generate boilerplate and basic file setup for plugins. The ones I know of are https://github.com/tommcfarlin/WordPress-Plugin-Boilerplate and the wp scaffold plugin command in WP-CLI.
  • The book Professional WordPress Plugin Development is very solid, and a good investment for those who like to learn this kinda stuff through books.

My #1 piece of advice to people getting started with WP plugin development is to find a plugin that does something sorta like what they are trying to do and to reverse engineer it. For me, this is far faster and more practical than any hello-world tutorial or sequential set of lessons. YMMV.

If anyone has other suggestions, please feel free to add them in the comments.

WP-CLI tools for BuddyPress

I think we can all agree that WP-CLI is the cat’s pajamas. Starting today, I’ll be maintaining a small (but growing) library of BuddyPress commands for WP-CLI: wp-cli-buddypress. Available commands are currently quite meager (and quite biased toward my needs as a developer rather than a site admin), but I’ll be building more, and would be delighted to receive pull requests.

Commit messages, tickets, and inline docs

As a Trained Academicâ„¢, I try to think about software documentation in terms of audience and purpose. Who is going to read technical docs? What will they be trying to learn by reading them? I use these questions as a lens for writing different kinds of documentation.

I like to think of commit messages as the canonical technical narrative of the project. These messages matter most for two groups of people: those following the ongoing development of the project, and those intrepid future souls who are combing through logs to track the lineage of given bit of code. The needs of the two groups are similar, which suggests certain content and formatting for commit messages. Both groups are scanning sizable streams of changesets, and thus need a quick way to disregard those that are irrelevant to them. That’s where the one-line summary is helpful, for git log and GUIs like this. Beyond the summary, they usually need a bit more context, a bird’s-eye summary of the problem the changeset is intended to fix. They need pointers to full discussions (ie, linked tickets). And because in projects like WordPress the changelog is also an attribution log, they need reference to the person responsible for the fix (“props”). It’s these kinds of needs I’m thinking about when I structure commit messages like this. (Side note: I’m a big fan of this post arguing for a similar commit message format.)

Tickets are bug notices or feature requests as they appear in the project’s issue tracker. The primary audience here is the developers, designers, and users who are currently involved in the ongoing development of the software. It’s a workspace, and it’s messy. Tickets may contain extended discussions, with numerous digressions and dead-end patches. It’s for this reason that issue tickets are not a replacement for good commit messages. Commit messages contain justification for changesets, while trackers contain the process that led to that justification.

Inline docs, primarily in the form of function/method/class docblocks, are intended first and foremost for developers who are currently trying to figure out how the software works. As a rule, these people don’t care about the history of the project, or the reasoning that led to a given piece of code. The documentation should answer questions like: where is this function used in the codebase? if I put x into the function, what will I get out of it? etc. While it’s often good to have pointers to the project history in certain cases – such as a link to a ticket that explains why an unintuitive bit of code works in the way it does – it probably does more harm than good to litter inline documentation with details about the project’s intellectual history. That’s what blame tools are for.

It goes without saying that there are gray areas. Commit messages, tickets, and inline docs all have the same “text” as their subject: the codebase. And the intended audiences for the three kinds of documentation are frequently overlapping. Still, I think it’s helpful to keep the distinctions in mind. When you write documentation, you’re writing the story of the project as it’ll be understand by future coder-historians. You want to make sure that the story makes sense.

A less finicky BuddyPress search

BuddyPress search, out of the box, is not very good. Say you’re looking for a group called “History of Wars in America”. The search term Wars in America will return the group, but America Wars will not. (Technical reason: search terms get lumped as a single string into a MySQL LIKE clause.)

I have some ideas about how to improve this behavior in BuddyPress itself, including stealing some of the goodies that recently went into WordPress. But for now, here’s a simple drop-in filter that fixes the word-wise problem.

(if the formatting is messed up, view the original at https://gist.github.com/boonebgorges/8301715)

Something very similar would work for members searches, though the query variables passed along to the filters probably have a slightly different syntax. (I made these changes for City Tech OpenLab, whose members queries are custom anyway.)

Again, this filter is not perfect – it doesn’t try to do any caching, it doesn’t look for literal strings in quotes, etc – but you might find it useful until some real fixes are in place in BP.

Affirmations for the free software developer

A friend recently came to me to express some frustration. He’s the leader of a relatively new free software project, and was having his first run-in with a user who was making extensive, arguably unreasonable support demands, in a tone that was increasingly hostile. If you’ve ever contributed to a public project, you have probably had similar experiences.

I responded to him with the following words of “wisdom”. Nothing terribly original here, but I have to remind myself of these points on a regular basis.

  • For every one user who engages with you in an unpleasant way, there are 10 users who provide feedback and request support in a friendly and reasonable manner, and 100 people who are using the software happily and asking for nothing.
  • People only bother to complain about something if they care about it.
  • Obviously, you want to be fair and kind to people who come to you for help. But your capacity to give a shit is like currency: it exists in finite quantities. It’s better to spend it on something that’ll provide positive good in the world, than to dump it into a bottomless pit.

Vim function for correcting whitespace to WP standards

When doing client work, especially in a team, I like to urge adherence to the WordPress coding standards. This is especially important with whitespace, in particular when other members of the team have their IDEs set up in certain ways that frustrate the standards. I wrote this quick little functions for your .vimrc that does some whitespace cleanup in the currently open buffer. (I’m sure there are a thousand better ways to do it, and you should feel free to let me know in the comments. This is just what I put together in 15 minutes.)

I’ve mapped it to F8. Modify as you’d like.

WordPress/BuddyPress registration and the Office 365 email filter

Just tore through the following problem on a client site (independently discovered by Martha Burtis here). WordPress/BuddyPress sites that allow for self-registration send out emails with activation links of the form: http://example.com/activate/?key=12345 (for BuddyPress) and http://example.com/wp-activate.php?key=12345 (for WordPress multisite). This format trips up the link filter that Microsoft’s Office 365 email service uses. After some experimentation, I figured out that the problem is the word ‘key’ in a URL parameter – once this term is removed from the URL, it passes right through the filter.

So, you can fix the problem by changing the URL parameter in the activation emails. That means (a) changing the text of the email, and (b) changing the server-side logic to expect something other than ‘key’. Here’s how to do it in BuddyPress:

[code language=”php”]
function bbg_activation_email_content( $message ) {
return str_replace( ‘?key=’, ‘?activationk=’, $message );
}
add_filter( ‘bp_core_activation_signup_user_notification_message’, ‘bbg_activation_email_content’ );

function bbg_screen_activation() {
global $bp;

if ( !bp_is_current_component( ‘activate’ ) )
return false;

// Check if an activation key has been passed
if ( isset( $_GET[‘activationk’] ) ) {

// Activate the signup
$user = apply_filters( ‘bp_core_activate_account’, bp_core_activate_signup( $_GET[‘activationk’] ) );

// If there were errors, add a message and redirect
if ( !empty( $user->errors ) ) {
bp_core_add_message( $user->get_error_message(), ‘error’ );
bp_core_redirect( trailingslashit( bp_get_root_domain() . ‘/’ . $bp->pages->activate->slug ) );
}

// Check for an uploaded avatar and move that to the correct user folder
if ( is_multisite() )
$hashed_key = wp_hash( $_GET[‘activationk’] );
else
$hashed_key = wp_hash( $user );

// Check if the avatar folder exists. If it does, move rename it, move
// it and delete the signup avatar dir
if ( file_exists( bp_core_avatar_upload_path() . ‘/avatars/signups/’ . $hashed_key ) )
@rename( bp_core_avatar_upload_path() . ‘/avatars/signups/’ . $hashed_key, bp_core_avatar_upload_path() . ‘/avatars/’ . $user );

bp_core_add_message( __( ‘Your account is now active!’, ‘buddypress’ ) );

$bp->activation_complete = true;
}

bp_core_load_template( apply_filters( ‘bp_core_template_activate’, array( ‘activate’, ‘registration/activate’ ) ) );
}
remove_action( ‘bp_screens’, ‘bp_core_screen_activation’ );
add_action( ‘bp_screens’, ‘bbg_screen_activation’ );
[/code]

You’d have to do something in the same spirit when not using BuddyPress. For the email, filter ‘wpmu_signup_user_notification_email’. Catching the request and overriding ‘key’ will be trickier. I haven’t experimented with it, but maybe you can hook to ‘activate_header’, detect the presence of $_GET['activationk'], and then redirect to the ‘key=’ URL that wp-activate.php expects.

Hopefully this is enough to help if you’re having the problem.

WP DPLA 0.3 – important update

I’ve just released version 0.3 of my plugin WP DPLA (described more here). Anyone running this plugin is strongly encouraged to update immediately, as this update fixes (among a number of other, minor things) a major bug that was causing the DPLA API to get hammered. Boo Boone.

Many thanks to Phunk Gadoury for giving me a heads up about this issue.