Software Engineering in WordPress, PHP, and Backend Development

Tag: WordPress Plugins (Page 1 of 2)

How to Successfully Deregister Anonymous Functions in WordPress

When I first started writing about anonymous functions in WordPress back in January, I didn’t anticipate it spanning over three articles reaching into the fourth month of the year. But here we are.

That said, this final article in the series aims to help provide a short introduction to a number of technical ideas both in PHP and WordPress to explain why deregistering anonymous functions is nearly impossible.

And it provides a way for us to actually get contextual information about every single hook and callback in an instance of WordPress so we can handle the anonymous functions as we see fit all through the use of a plugin.


Recall from the first article, the reason I started writing about anonymous functions in WordPress all stemmed from a tweet (or post or whatever they are currently called) that stated:

I do wish developers would stop using WordPress hooks with (what I think are called) anonymous functions […].

They are very hard if not impossible to unhook.

And the short of it is that it’s true: Anonymous functions are easy to register against WordPress hooks and are difficult to deregister.

But it’s not impossible.

Continue reading

Using Custom Templates with Rewrite Rules in WordPress Plugins

Assume you’re working on a custom WordPress plugin that includes its own template for rendering data. The difference in this template is that it’s not one that you’ll apply to a page or custom post type in WordPress, but it will instead be its own page with access to the WordPress core functions.

This works well enough for a plugin, right? 🙂. Credit.

For example, say you’re generating a report for a given user ID and you want the page to incorporate fonts from Google, perhaps a third-party library, and it look as if it’s not even part of the WordPress core application.

The head element of the page may look something like this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title><?php echo getName($userId); ?></title>
    <link rel="stylesheet" href="<?php echo getAsset("/lib/reset.css"); ?>">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Sans">
  </head>

But you there are two other requirements:

  1. You want to access the report through a pretty link that includes the $userId (perhaps something like /information/42
  2. You want to use core functions for getting user metadata through functions like get_user_meta.

To do this, you need to have custom templates with rewrite rules in your WordPress plugin. Again, this is not a custom template in the WordPress sense and you’ll only have as many rewrite rules as you do templates.

Custom Templates with Rewrite Rules

1. The Plugin Structure

This can be structured however you want, but I find it easiest to have the rules set in their own file that’s included in the plugin’s bootstrap file or in the core plugin’s file.

I also think it’s easiest to keep the template in its own template directory where you can also house other templates. The main reason for this being that if you have custom rewrite rules, each rule can map to its own template.

In the example I’m going to give throughout this article, I’m going to have the rules located in the plugin bootstrap file which I’m calling plugin.php and I’m going to have the template in a directory called templates. The template will be called information.php so that it maps to the permalink structure I’m going to set up.

So aim to have:

  • plugin.php in the root of your plugin
  • templates/information.php in the root of your plugin

Note that the information.php template does not need to include the standard WordPress template headers because this isn’t that type of template.

2. The Template

This template can be as involved and complicated or as simple as you like. For the purposes of this post and to keep the code easy to follow, I’m just going to render user’s first name and last name from the user metadata table.

For example:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title><?php echo getName($userId); ?></title>
    <link rel="stylesheet" href="<?php echo getAsset("/lib/reset.css"); ?>">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Sans">
    <link rel="stylesheet" href="<?php echo getAsset("index.css"); ?>">
  </head>
  <body>
    <div id="container">
        <header>
            <h1>Hello World</h1>
        </header>
        <main>
            <?php echo get_user_meta($userId, 'first_name', true) . ' ' . get_user_meta($userId, 'last_name', true); ?>
        </main>
        <footer>
            <p>&copy; <?php echo date('Y'); ?> Tom McFarlin</p>
        </footer>
    </div><!-- #container -->
  </body>
</html>

Obviously, though, you can mark this up however you find necessary. You can even incorporate additional functions that are in plugin.php or whatever file you want to incorporate additional logic to add functionality to the template.

You may see that I have a getAsset function in the head element of this page. This is what that function looks like in plugin.php:

function getAsset(string $filename)
{
    if (0 < stripos($filename, '.css')) {
        return trailingslashit(plugins_url('acme-info')) . "/assets/css/$filename";
    }

    if (0 < stripos($filename, '.js')) {
        return trailingslashit(plugins_url('acme-info')) . "/assets/js/$filename";
    }
}

This is useful for that I’m doing in a template like this but additional functionality and the reason behind doing this is outside the scope of this article. I’m showing that it can be done.

3. The Rewrite Rules

To set up the custom rewrite rules, you’ll need three functions:

First, set up the rewrite rule whenever the plugin is activated so that it persists as long as the plugin is activated. To do this, set up a function that looks like this:

register_activation_hook(__FILE__, function () {
    add_rewrite_rule(
        '^information/([0-9]+)/?',
        'index.php?user_id=$matches[1]',
        'top'
    );

    flush_rewrite_rules();
});

This will add a rewrite rule whenever the plugin is activated to that you can use information/42 and have it passed to the WordPress core application with the digit representing the ID for the user account you want to retrieve.

We also flush the rewrite rules when the plugin is activated so the new rules take affect.

Next, set up the deactivation hook so the custom rewrite rule is removed and is flushed from the WordPress application so no lingering functionality from the plugin works:

register_deactivation_hook(__FILE__, function () {
    flush_rewrite_rules();
});

Finally, set up the functionality so that it does the following:

  1. Filters the REQUEST_URI and sanitizes the URL,
  2. Separates the URL into parts by running explode on the URL
  3. Verifying the URL is properly structured
  4. Redirecting to the custom information.php template
  5. Handling errors if the file doesn’t exists, the user ID is invalid, or the URL is invalid.

It’s a lot of code for stronger functionality (hence my post on using ChatGPT for writing more secure code) but it should be clear enough given the notes above.

add_action('template_redirect', function () {
    $requestUri = filter_var($_SERVER['REQUEST_URI'], FILTER_SANITIZE_URL);
    $requestUriParts = array_values(array_filter(explode('/', $requestUri)));

    if (
        count($requestUriParts) === 2 &&
        strtolower($requestUriParts[0]) === 'report' &&
        ctype_digit($requestUriParts[1])
    ) {
        $userId = intval($requestUriParts[1]);

        // Validate $userId and ensure it's within an appropriate range
        if ($userId > 0 && $userId <= 1000000) { // Adjust the upper limit as needed
            $templatePath = plugin_dir_path(__FILE__) . 'templates/information.php';

            // Check if the template file exists before including it
            if (file_exists($templatePath)) {
                include $templatePath;
                exit;
            } else {
                // Handle the case where the template file is missing
                die('Report template not found.');
            }
        } else {
            // Handle invalid user IDs
            die('Invalid user ID.');
        }
    } else {
        // Handle invalid URLs
        die('Invalid URL.');
    }
});

At this point, assuming you’re trying to access https://yourEnvironment.com/information/42 then you’ll be redirected to the custom template outlined in the second step above.

Notice that you’re still able to read the userId and you’re able to use built-in WordPress functions to render whatever information you deem necessary for your solution.

References

On the Market for Utility Plugins

Years ago, I started writing small utility plugins that helped me maintain any given task on managing this site or projects that I was building for others.

Some of these plugins I’ve kept just for me because they are quickly put together and built in such a way that are geared towards this site; others I’ve open-sourced, shared, and/or installed on other sites because a person with whom I was working was interested in the functionality or because it was niche enough that it solved a single problem they didn’t want to deal with.

Many of these have been archived because I didn’t need them, didn’t want to maintain them, or no longer had a use for them. Case in point: Page Template Dashboard.

But these types of plugins, at least for me, date back over a decade. The first plugin I ever released in the WordPress Plugin Repository was called Tipsy Social Icons. This year, it will be 11 years old (not that I maintain it anymore but get a look at the plugin page to get some good social web nostalgia).

It was written one afternoon when there was a rare snow storm in Georgia and we couldn’t go anywhere. 🙃

Anyway, there’s something to be said for large plugins that greatly extend WordPress in all kinds of ways such that we practically have full applications running within WordPress that help users do things far beyond posts, pages, taxonomies, and user management. Be it something that runs in the browser, something that serves as a headless application, or something else. There’s a reason WordPress can be referred to as the operating system for the web.

But there’s also something to be said for small tools or utilities that do something either that require user interaction or that take care of something behind the scenes. I see the occasional discussion about this [whenever I am lurking] on Twitter, in newsletters, or in other Slack channels [in which I am lurking].

That is, people seem to be interested in them, people want to build them (or they want them built), but they seem fewer and far between given the size of other plugins that are available.

So it raises a question: Where are they? Is there a market for utility plugins? Are they overshadowed by larger projects? Is it too hard to find them given the way GitHub or the WordPress Plugin Repository is structured?

These aren’t loaded questions; instead, they’re general musings on the whole thing.


For those of you reading this who have been in WordPress for a long time, you’ll remember some of this and for those of you who may be newer consider it a cautionary tale:

  • Years ago, we had what was essentially a race to the bottom for product pricing. The idea was something like “s/he who sells the most at the lowest price wins.” This could be for plugins but it started with themes.
  • Then we moved in the subscription model which we see every where both inside WordPress and outside of WordPress.

It’s not that I need an lesson on economics to understand this dynamic but there’s also alternatives especially in projects that aren’t the backbone of a person’s livelihood or their business.

People talk a lot about “side hustles” and each person has their own motivations for having them. (That is, some want to turn them into full businesses, some just want a hobby.)

This is where I think this idea of utility plugins come into the picture again (granted, I don’t think this is an elegant term to describe a product but that’s beside the point – for now).

Instead, I think there’s a small model by which extremely simple plugins can be marketed for a specific problem and sold at a price that doesn’t require a subscription, that doesn’t drain a person’s wallet, and that helps them when using WordPress by simply doing a job that keeps them from having to do it.

Further, “extremely simple” may be an overloaded phrase. Some of the simplest solutions are not in how few lines of code or how much is going on behind the scenes but how simple it comes across to the user.

  • Does it require activation, user input, settings values, and so on
  • Does it just require activation?

Alternatively, simple plugins can be just that. It might be an anonymous function that’s associated with a hook that adds or removes a single UI element.

Despite talking semantics here, that’s not what I’m after. Instead, I’m talking about a market for utility plugins where a utility plugin is defined as a single plugin that’s activated and does one thing with minimal user input and that enhances or streamlines their work within WordPress.

It does a job they don’t want to do (maybe once, maybe multiple times, maybe always), stays out of their way, and allows them to focus on what they need or what they want to do.


Personally, I think there’s a market for them. I don’t know how large or how small it is nor do I think there’s a consistent price point at which they can be placed (how do you value someone’s time when it’s a single WordPress installation that’s a hobby or someone who maintains an entire set of WordPress installations?).

There are ways to test this, though. And I’ve a list of ~25 plugins that I’d love to actually try to implement.

How to Run Custom Functionality Once in Multiple Plugins

Over the years, I think the concept of a “drop-in” plugin has become overloaded. What once referred to a very specific type of functionality has evolved to mean a couple of things.

  1. One of the definitions retains the original definition which is you can place specific files into the plugins directory to replace core WordPress functionality. These are not standard WordPress plugins, though. For example, you’ll likely often see files like advanced-cache.php or object-cache.php in the plugins directory. These are the original type of ‘drop-ins’ when it comes to working with WordPress.
  2. Another definition are plugins that aren’t specifically mu-plugins and they aren’t standalone plugins either. Instead, these are pieces of functionality that can be dropped into any other plugin and add functionality. Say you have two different plugins that are used by a lot of people and you want to give them the ability to add a feature without activating a new plugin. The way in which you can do this is have them drop a file into their existing plugin.

Here’s the challenge with the second definition: When you drop functionality of into the context of another plugin, that plugin may not be the only one already running the same code.

In other words, say you have a file called acme-functionality.php that can be added to any plugin. If you drop acme-functionality.php into multiple, activated plugins then you may end up with all kinds of results none of which are ideal. And why isn’t it ideal? Because you want the code to run only once.

What’s a way to check to see if a file is already running in the context of another plugin before running it’s code?

Continue reading

Dracula Theme for Preformatted WordPress Blocks

When working on the articles for the Backend Engineer Learns to Build Block Editor Blocks series, I wasn’t happy with how the code samples were looking within the articles.

Previously, I’ve written – here and here – about my being a fan of the work done by Zeno Rocha in the Dracula Theme. Ideally, I wanted to be able to have the color scheme of the code in my articles match the theme. Something like a Dracula Theme for WordPress Blocks.

That’s when I found highlight.js and a Dracula theme for it. So I wrote a small plugin for WordPress that works with the existing Preformatted block and changes the color scheme to match that of Dracula.

I call it WP Dracula Highlight.js or, more simply, Dracula Highlight.

Continue reading
« Older posts

© 2024 Tom McFarlin

Theme by Anders NorenUp ↑