ClassicPress Plugin Development: Create a Plugin Action Link

ClassicPress PluginsThis post is part of the ClassicPress Plugin Development series in which I am going to look at both best practice for developing plugins and how I approach some requirements as well as some of the functions I commonly use.

When developing a plugin with an settings page, it is quite common to add a link to the settings page on the Plugins page; these links are known as plugin action links. This is an example from my URL Shortener plugin:

URL Shortener action link

The plugin action link can be added by using the add_filter function:

add_filter(string $tag, callable $function_to_add, int $priority = 10, int $accepted_args = 1)

The $tag to use is plugin_action_links, the $function_to_add is the function you need to write to add the link and the accepted_args is 2

Below is an example of the filter using the plugin_action_links tag to add the link to the URL Shortener plugin’s settings page:

add_filter('plugin_action_links', 'azrcrv_urls_add_plugin_action_link', 10, 2);

The azrcrv_urls_add_plugin_action_link function called by the filter is:

/**
 * Add URL Shortener action link on plugins page.
 *
 * @since 1.0.0
 *
 */
function azrcrv_urls_add_plugin_action_link($links, $file){
	static $this_plugin;

	if (!$this_plugin){
		$this_plugin = plugin_basename(__FILE__);
	}

	if ($file == $this_plugin){
		$settings_link = '<a href="'.admin_url('admin.php?page=azrcrv-urls').'">'.esc_html__('Settings' ,'url-shortener').'</a>';
		array_unshift($links, $settings_link);
	}

	return $links;
}

The highlighted section is the menu_slug for the settings page.

Click to show/hide the ClassicPress Plugin Development Series Index

ClassicPress Plugin Development: Loading Back-End Scripts

ClassicPress PluginsThis post is part of the ClassicPress Plugin Development series in which I am going to look at both best practice for developing plugins and how I approach some requirements as well as some of the functions I commonly use.

jQuery itself is automatically loaded by ClassicPress so we don’t need to do anything to load this ourselves in a plugin; it is just our own jQuery script which we need to register and enqueue. There is two ways in which scripts can be loaded in a plugin; I will cover them both, but will note first of all that I typically use the second approach; there is an argument that the first approach is the “correct” one.

The first thing to do when you are loading a script is to register it. This is done using the wp_register_script function which ClassicPress provides.

Continue reading “ClassicPress Plugin Development: Loading Back-End Scripts”

ClassicPress Plugin Development: Loading Front-End Scripts

ClassicPress PluginsThis post is part of the ClassicPress Plugin Development series in which I am going to look at both best practice for developing plugins and how I approach some requirements as well as some of the functions I commonly use.

jQuery itself is automatically loaded by ClassicPress so we don’t need to do anything to load this ourselves in a plugin; it is just our own jQuery script which we need to register and enqueue. There is two ways in which scripts can be loaded in a plugin; I will cover them both, but will note first of all that I typically use the second approach; there is an argument that the first approach is the “correct” one.

The first thing to do when you are loading a script is to register it. This is done using the wp_register_script function which ClassicPress provides.

Continue reading “ClassicPress Plugin Development: Loading Front-End Scripts”

ClassicPress Plugin Development: Loading Back-End Stylesheets

ClassicPress PluginsThis post is part of the ClassicPress Plugin Development series in which I am going to look at both best practice for developing plugins and how I approach some requirements as well as some of the functions I commonly use.

All of the plugins I have written have a settings page in the admin dashboard, either for settings to be configured or for instructions on how to use the plugin. I often have an admin stylesheet which needs to be loaded on the settings page. There is two ways in which stylesheets can be loaded in a plugin; I will cover them both, but will note first of all that I typically use the second approach. There is an argument that the first approach is the “correct” one.

The first thing to do when you are loading a stylesheet is to register it. This is done using the wp_register_style function which ClassicPress provides.

Continue reading “ClassicPress Plugin Development: Loading Back-End Stylesheets”

ClassicPress Plugin Development: Loading Front-End Stylesheets

ClassicPress PluginsThis post is part of the ClassicPress Plugin Development series in which I am going to look at both best practice for developing plugins and how I approach some requirements as well as some of the functions I commonly use.

Virtually all of the plugins I have written have output to the front end of a site, usually through use of shortcodes. As there is front end output, I have needed to create a stylesheet which means the plugin needs to load it. There is two ways in which stylesheets can be loaded in a plugin; I will cover them both, but will note first of all that I typically use the second approach. There is an argument that the first approach is the “correct” one.

The first thing to do when you are loading a stylesheet is to register it. This is done using the wp_register_style function which ClassicPress provides.

Continue reading “ClassicPress Plugin Development: Loading Front-End Stylesheets”

ClassicPress Plugin Development: Structure of a Plugin

ClassicPress PluginsThis post is part of the ClassicPress Plugin Development series in which I am going to look at both best practice for developing plugins and how I approach some requirements as well as some of the functions I commonly use.

Before you start developing a plugin, I’d recommend deciding on the plugin structure you want to use. At the simplest level, a plugin only actually requires the file which holds enough code for the plugin and the folder it sits within, but in reality you will have other files which are needed as well, such as style sheets, language files, images and so on.

Planning a structure for the plugin will ensure your plugin files are well organised which will make it easier to work with both now and again in future.

John Alarcon of Code Potent, did a blog post on this subject a while ago. I use a structure fairly similar to the one he described, and have used the same format for showing the structure I use.

Continue reading “ClassicPress Plugin Development: Structure of a Plugin”

ClassicPress Plugin Development: Using Namespaces

ClassicPress PluginsThis post is part of the ClassicPress Plugin Development series in which I am going to look at both best practice for developing plugins and how I approach some requirements as well as some of the functions I commonly use.

In the last post in this series, on whether to use namespaces, I discussed whether they should be used or not and noted that I do not currently use them, but am debating whether I should.

At present, the azrcrv_tt_post_tweet function in my To Twitter plugin is called from a few other plugins in order to send a tweet; the function calls looks like this:

$tweet_result = azrcrv_tt_post_tweet($parameters);

This calls this function:

function azrcrv_tt_post_tweet($parameters){

If I was to update my plugins to use namespaces, in the To Twitter plugin a namespace would be added to the top of the PHP file (only the opening PHP tags and any comments should be before the namespace declaration). If I do make this change, I would use a developer and plugin specific namespace:

namespace azurecurve\ToTwitter;

The function to post the tweet, and all other functions, could then be renamed to remove the current developer and plugin specific prefixes thusly:

function post_tweet($parameters){

The other plugins which call this function, would need the function call to be amended to include the namespace:

$tweet_result = \azurecurve\ToTwitter\post_tweet($parameters);

With namespaces, it is possible to use a function name which matches that in the global namespace. For example, the get_option function is a standard ClassicPress function used to get the options for a plugin. I can create a function with the same name in a plugin without a conflict.

Calling the below will call the function in the plugin:

$options = get_option('azrcrv-tt');

To call the standard ClassicPress version in the global namespace I would prefix the function call with a \:

$options = \get_option('azrcrv-tt');

The final point to handle, is if you are using a ClassicPress hook such as add_action you are passing a string which will be executed in the global namespace so you need to pass the namespace of your plugin as part of the hook:

add_action('admin_menu', 'azurecurve\ToTwitter\create_admin_menu');

There is a predefined PHP constant available which you can use to avoid putting your namespace in many parts of your plugin; this can be useful in future if you need to change your namespace, as you then ony need to change the declaration at the top of the plugin:

add_action('admin_menu', __NAMESPACE__.'\create_admin_menu');

The same principles would apply PHP classes as well, but as I said in the coding paradigms blog post, I am not developing using object oriented programming and so am not covering classes.

Click to show/hide the ClassicPress Plugin Development Series Index

ClassicPress Plugin Development: To Use Namepsaces or Not

ClassicPress PluginsThis post is part of the ClassicPress Plugin Development series in which I am going to look at both best practice for developing plugins and how I approach some requirements as well as some of the functions I commonly use.

Namespaces are a standard feature of PHP, post version 5.2. A namespace is a way of addressing the problem of isolation. For example, if you have a function called load_cs in one part of your code, then you cannot use the same name elsewhere. For ClassicPress this also means that having that function in one plugin, you cannot have the same name in another plugin.

To avoid this problem with ClassicPress, the common approach is to prefix function names (and class names) with a developer and plugin specific prefix; I typically use azrcrv_{nn}_ where the highlighted section is one to four letters to represent the specific plugin (e.g. e for Events, uam for Update Admin Menu or smtp for SMTP).

John Alarcon, Code Potent, uses namespaces in all of his plugins so does not need to use developer and plugin specific prefixes; instead he uses a developer and plugin name namespace. For example, the PHP Error Log Viewer uses the following namespace declaration:

// Declare the namespace.
namespace CodePotent\PhpErrorLogViewer;

I started developing plugins for WordPress (back in 2013) before namespaces were introduced to PHP and have never adopted them. I rewrote my WordPress plugins specifically for ClassicPress in 2019 after I migrated all of my sites, but did not adopt namespaces. Partly this was to maintain some backward compatibility as some of the plugins have functions which are intended to be called from outside the plugin (such as URL Shortener which is typically called to display the shortlink in a theme) and partly because at the time I didn’t especially see the benefit.

As time has passed and I’ve created more plugins, I am thinking that was a mistake and I should have introduced namespaces when I did the ClassicPress rewrite; if I make this change now to existing plugins, this would, under semver, be a breaking change necessitating a major version number increase.

If you are starting off developing for ClassicPress, I would encourage you to seriously consider using namespaces in your development of plugins.

Click to show/hide the ClassicPress Plugin Development Series Index

ClassicPress Plugin Development: Coding Standards

ClassicPress PluginsThis post is part of the ClassicPress Plugin Development series in which I am going to look at both best practice for developing plugins and how I approach some requirements as well as some of the functions I commonly use.

In the last post, I covered using semantic versioning or (semver) when developing plugins for ClassicPress.

When developing plugins, ClassicPress largely uses the same coding standards as WordPress:

From the coding standard links above, I do follow the ones for HTML and CSS pretty much 100%, but the PHP one has a few items for which I take a slightly different approach. The idea behind coding standards is to make code readable to other people, so I largely take the view that if there is part of the standard you don’t like, then as long as you’re consistent in how you break the standard, code will still be readable.

The above opinion on adhering to coding standards is in reference to greenfield development; if contributing to an existing plugin, code to the standards used for that plugin. If contributing to core, then adhere to the standards as written.

Click to show/hide the ClassicPress Plugin Development Series Index

ClassicPress Plugin Development: Semantic Versioning 2.0

ClassicPress PluginsThis post is part of the ClassicPress Plugin Development series in which I am going to look at both best practice for developing plugins and how I approach some requirements as well as some of the functions I commonly use.

When developing plugins for ClassicPress, you need to develop using semantic versioning (or semver) as this will be a requirement of the ClassicPress Directory.

Semantic Versioning is a versioning scheme for using meaningful version numbers which can be used to avoid incompatibilities.

semver version numbering works using three segments:

  1. MAJOR version when you make breaking changes where users will need to take some action during an upgrade.
  2. MINOR version when you add functionality in a backwards compatible manner which users can simply apply without taking any other action.
  3. PATCH version when you make backwards compatible bug fixes which, like MINOR versions users can apply without taking any other action.

One key point to note when using semver, is that when a versioned release has been made, nothing in that release can be changed; a new version with incremented number must be released instead.

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format; pre-release versions often have a MAJOR version number of 0. When a plugin is ready for release to production it should be released as version 1.0.0.

Continue reading “ClassicPress Plugin Development: Semantic Versioning 2.0”