Writing a Plugin for Performance Lab

Once you have proposed a new plugin and there is consensus that it should be added to the Performance Lab project, you can add the code to the WordPress/performance repository on GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged be the repository owner. https://github.com/. This article outlines the requirements for such plugins.

Plugin requirements

Foundationally, the requirements for the performance team’s plugins are no different than for any other WordPress plugins to host in the WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party directory. Please refer to the Plugin Handbook for requirements and best practices. There are however a few additional requirements, outlined in this section. Feel free to skip to the Example section if you prefer to start with reference code.

Hosting and development

While plugins should be hosted in the WordPress plugin directory as usual, development should preferably happen in the WordPress/performance repository on GitHub, which is a monorepo to centralize the development of all the performance team’s plugins with common infrastructure and best practices.

In the repository, each plugin gets its own directory within the root /plugins folder, using the plugin’s (intended) slug as the directory name. Within that folder, you need at the very least a readme.txt file and a plugin main file with the relevant headers, similarly to any other WordPress plugin.

Header requirements

For the plugin headers (main file and readme), please consider the following:

  • The “Plugin URI” should point to the plugin’s directory within the WordPress/performance repository.
  • The requirement headers “Requires at least” and “Requires PHPPHP PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. https://www.php.net/manual/en/preface.php.” should be aligned with the other plugins in the GitHub repository, unless there is a very good reason to diverge from it.
  • The “Author” should be set to “WordPress Performance Team”, and “Author URI” should be set to “https://make.wordpress.org/performance/”.
  • The “License” should be set to “GPLv2 or later”, and “License URI” should be set to “https://www.gnu.org/licenses/gpl-2.0.html”.
  • The “Contributors” (only relevant for the readme) should be set to “wordpressdotorg”.

For a quick start, feel free to copy the main file and readme headers from any of the other plugins in the GitHub repository.

Code requirements

Other than the plugin main file and readme, you are free to structure the code in any way, as long as you are following the WordPress Coding Standards. However, please consider the recommendations outlined in the next section.

There are only a few extra requirements:

  • At the beginning of the plugin main file, a plugin-specific version constant should be defined, following an early return check for whether the constant is already defined, to prevent duplicate loading. This constant needs to be maintained indefinitely and must always match the plugin’s current version in the “Version” headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes..
    • While you can choose any name for the constant, a good convention is the capitalized plugin slug followed by a “version” suffix. For example, if the plugin slug is “my-plugin”, the constant could be called “MY_PLUGIN_VERSION”.
  • The plugin main file should only be used to load code from other files. It should not contain any declarations of functions, classes, etc.

A “phpcs.xml.dist” configuration file for PHPCodeSniffer should be added to the plugin’s directory (see the “webp-uploads” plugin directory for example). It should rely on the main PHPCodeSniffer config in the repository to automatically follow the shared code style requirements. Other than that, the file should only contain minimum configuration, typically to set the plugin text domain correctly.

Plugin recommendations

  • Plugins should be written with a future WordPress coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. merge in mind and therefore use coding patterns already established in WordPress core. For this reason, using PHP language features like autoloaders, interfaces, or traits is discouraged unless they are truly needed for the respective plugin.
  • Plugins should always be accompanied by tests, preferably covering every function and class method.
  • Plugins should include a generator metaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. tag so that it is possible to gather performance metrics for them in the field. The generator tag content should be in the format of “plugin-slug v.e.r.s.i.o.n”. For example, if the plugin slug is “my-plugin” and the current version is “1.1.0”, the generator tag content would be “my-plugin 1.1.0”.
  • If possible, plugins should refrain from including infrastructure tooling such as build scripts, Docker containers etc. When such functionalities are needed, they should preferably be implemented in a central location in the GitHub repository, in a way that they can be reused by other plugins as well – one goal of the monorepo is to minimize the infrastructure code duplication that is often seen between different projects today.

Example

Let’s assume the plugin slug is “my-plugin”. Since the plugin is just a demo plugin, all it does is at a hook that unconditionally shows an admin notice.

As such, you need files such as the following:

  • plugins/my-plugin/hooks.php (file with the actual functionality)
  • plugins/my-plugin/load.php (plugin main file)
  • plugins/my-plugin/phpcs.xml.dist (PHPCodeSniffer configuration file)
  • plugins/my-plugin/readme.txt (readme)

Here’s the contents of the plugin main file:

<?php
/**
* Plugin Name: My Plugin
* Plugin URI: https://github.com/WordPress/performance/tree/trunk/plugins/my-plugin
* Description: Enhances performance for something.
* Requires at least: 6.5
* Requires PHP: 7.0
* Version: 1.0.0
* Author: WordPress Performance Team
* Author URI: https://make.wordpress.org/performance/
* License: GPLv2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: my-plugin
*
* @package my-plugin
*/

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

// Define required constant.
if ( defined( 'MY_PLUGIN_VERSION' ) ) {
return;
}

define( 'MY_PLUGIN_VERSION', '1.0.0' );

require_once __DIR__ . '/hooks.php';

Here’s the contents of the hooks.php file which contains the plugin functionality. This is purely included for reference, this file could do anything as needed for the plugin. As outlined before, it’s a good practice to always include a generator meta tag for the plugin.

<?php
/**
* Hook callbacks used for My Plugin.
*
* @package my-plugin
*/

/**
* Displays an admin notice that the plugin is active.
*
* @since 1.0.0
*/
function my_plugin_show_admin_notice() {
wp_admin_notice(
__( 'The "My Plugin" plugin is currently active.', 'my-plugin' ),
array( 'type' => 'info' )
);
}
add_action( 'admin_notices', 'my_plugin_show_admin_notice' );

/**
* Displays the HTML generator meta tag for the plugin.
*
* See {@see 'wp_head'}.
*
* @since 1.0.0
*/
function my_plugin_render_generator_meta_tag() {
// Use the plugin slug as it is immutable.
echo '<meta name="generator" content="my-plugin ' . esc_attr( MY_PLUGIN_VERSION ) . '">' . "\n";
}
add_action( 'wp_head', 'my_plugin_render_generator_meta_tag' );

Here’s the contents of the phpcs.xml.dist file. This can generally look the same for every plugin, except that the text domain has to be adjusted to match the specific plugin slug.

<?xml version="1.0"?>
<ruleset name="WPP-MyPlugin">
<description>WordPress Coding Standards for My Plugin Plugin</description>

<rule ref="../../bin/phpcs/phpcs.ruleset.xml"/>

<config name="text_domain" value="my-plugin"/>

<file>.</file>
</ruleset>

Last but not least, the readme.txt file simply needs to follow the general WordPress.org readme requirements. The following is an extract of just the header portion of what it could look like for this demo plugin.

=== My Plugin ===

Contributors: wordpressdotorg
Requires at least: 6.5
Tested up to: 6.5
Requires PHP: 7.0
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Tags: tag1, tag2, tag3

Enhances performance for something.

== Description ==

Main readme sections go here…
s
search
c
compose new post
r
reply
e
edit
t
go to top
j
go to the next post or comment
k
go to the previous post or comment
o
toggle comment visibility
esc
cancel edit post or comment