Being a developer for a company that uses content management systems to deliver products means that sometimes a client will request functionality that cannot be accomplished natively within the scope of a particular CMS’s core. CMSes excel at providing a general purpose starting point as well as preventing the need to tediously rewrite identical boilerplate code, but can fall short when requirements become exceedingly specific.

WordPress has a seemingly infinite ecosystem of third party adaptable plugins that often deliver exactly what you need, requiring little more than a simple config and some mild command line magic for integration. Sometimes the deliverable action comes close to accomplishing the desired task with low impact shortcomings, making it a near perfect solution, and sometimes there are situations where an ambitious client, with an appetite for specificity, dreams up a rather unconventional functionality request for which no plugin exists.  

In the latter scenario, you are left to either embark upon the assembly of a homebrewed WordPress plugin or try to convince the client that it is not a possibility if deadlines are concrete. While writing a custom plugin is not uncommon, a more likely position to be in is that of having to repair or extend an existing plugin with similar capabilities.

This circumstance of code rehabilitation is an inevitability in the life and career of a developer. From time spent building web applications on top of obfuscated code bases, to the modern cyclic Infinitum of adapting pre-existing infrastructure to satisfy the ebb and flow of web technology, there invariably will be situations where a sprawling monstrosity of spaghetti code is staring you in the face and your manager says “This shouldn’t take too long,” to which you reluctantly agree, and nod to reassure yourself rather than your manager.

You invoke a pragmatic mindset and your objective scientific method ethos to begin dissecting the mostly deprecated code, which fails silently and doesn’t generate any error logs. Rapidly, you develop a mental model of the data flow, where and how HTTP requests are handled, URI routing, where database I/O occurs, and the schema of the database itself. Then, in the midst of your code ingestion, you read the comments at the top of a functions file: “Created xx/xx/2005”.

Existential dread ensues; this code was written over a decade ago. While the peripheral libraries it depends on were changed and adapted by the developers, this digital time capsule has persisted as a relic of a web gone by. Now the burden of proof falls unto you to diagnose this unmaintained bit of once-lively procedural hypertext preprocessor instruction.

This all might seem very anecdotal and that’s because, well, it is. By way of countless stories on developers’ blogs and folklore passed down by other programmers, I’ve come to realize that this is just a rite of passage. While some share their heroic war stories of grappling with incomprehensible code, others are left spinning their wheels with little progress. So, to those who find themselves in this rather precarious situation, here are my three gritty but practical tips to attack the code.

  • If you find yourself reading through WordPress code (or any code for that matter) and you are seeing function calls that look peculiar or unfamiliar, you might find that the developer has built a wrapper class for standard functions. Typically they will build a wrapper class for database transaction capabilities like CRUD. There might have been a specific reason for doing so at the time of development but more often than not it’s because the developer was somewhat of a code elitist who hates other developers. Don’t try to write code that utilizes the functions in these wrapper classes. As is often the case, the custom database wrapper class is not extracting or updating data as intended or at all. If you must, write your own SQL, but do so sparingly and with caution (escape and sanitize all data!). It may be less than performant but as long as it works it can be optimized later if scalability is a concern. Typically, this is where problems come from:  developers attempt to roll a version of their own micro framework within the plugin they are writing. Besides being littered with deprecated WordPress artifacts, it often causes namespace collisions when the core is eventually updated.

This brings me to my next point, use namespacing! Functions in your plugin get thrown into the global namespace along with all of the other non-namespaced functions. Namespaces not only prevent conflicts between native PHP/WordPress functions and the functions you write but they also allow ambiguous class names so that identically named class files can live in the same project and even the same directory. Think of it in the way Java allows for method overloading based on variations in method signatures. It serves to keep your function/class names separate from other developers’ code so that you don’t have to devise an elaborate ad-hoc prefix or postfix function naming convention.

  • Become familiar and comfortable with the WordPress standard functions library. Learn to love it. Over time, rummaging the innards of WordPress plugins built by small studios or individuals, I found that if developers had a more thorough knowledge of the WP functions library there would be far less verbose code floating around the plugin atmosphere. It’s quite possible and in fact very likely that you’ll come across convoluted procedures that are repeated throughout the code base to achieve a task that has already been automated. For example, a common aberration when developing WordPress plugins is crafting a custom solution to simply extract all posts or post meta data. A quick inspection of the documentation reveals that “get_posts” and “get_post_meta” have long been standard members of the WP library with as many custom parameters to query on as you might need.
        //this is a truncated example
<?php $args = array(
    'posts_per_page'   => 5,
    'orderby'          => 'date',
    'order'            => 'DESC',
    'post_type'        => 'post',
    'post_status'      => 'publish',
    'suppress_filters' => true 
);
$posts_array = get_posts( $args ); ?>

It’s also a better way of future proofing your code as WP functions are not often redacted or made obsolete whereas querying for individual columns in a wp table might be problematic if the column data type or name is altered.

  • Become familiar with the WordPress hook system. You can think of hooks as a pseudo internal API in that they enable the code you write to interact with code elsewhere in the project. They are essential to interaction with WordPress core outside of the standard functions library. Hooks can be classified in one of two ways, it can either be an action or a filter hook. In short, action hooks are bits of code that are triggered by specific events while filters allow you to prepare and transform data before it is sent to the frontend or backend (browser/DB). You can write custom hooks or you can choose from an existing comprehensive library of hooks depending on the required functionality. Standard practice for utilizing a WordPress hook is to only run code when it’s needed. Tasks that require global variables to be initialized or functions to be registered into the global namespace, for example, should be running on initialization. Variable declaration and things that are not internal/external function calls run in near-constant time, requiring few system resources. Any server-side rendering of markup or assets will significantly delay page load speed if handled within the hook event. I don’t want to go too far into implementation as that can all be obtained from the WordPress documentation. The purpose of adding this to my list, even if it’s vague, is to make devs more aware of their significance. Hooks, in conjunction with the appropriate use of the WordPress function library, will make your plugin a lean, mean data processing machine.