Welcome to the official blog for the Plugins Team.
The team acts as gate-keepers and fresh eyes on newly submitted plugins, as well as reviewing any reported security or guideline violations.
Quick Links
The team acts as gate-keepers and fresh eyes on newly submitted plugins, as well as reviewing any reported security or guideline violations.
Quick Links
Many WordPress plugins use the setlocale() function.
While it’s generally safe to use setlocale() to get various information about a specific locale, it’s essential to understand that using setlocale() to perform string manipulations has significant disadvantages.
The goal of this article is to raise awareness about those disadvantages.
So, what are they?
setlocale() is not thread-safe. If you run WordPress on shared hosting, you may experience sudden changes in locale settings, as though your 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 never called setlocale().setlocale() to detect the current locale don’t process some characters correctly, even if the correct locale is set with setlocale().Take a look at this 3vl4.org example.
The expected output of the script is Ž, but the actual output is Ů.
These are some recommendations on using setlocale() that could make using it safer:
setlocale() to process strings in different encodings unless absolutely unavoidable.setlocale() with LC_ALL. Instead, specify the exact categoryCategory The 'category' taxonomy lets you group posts / content together that share a common bond. Categories are pre-defined and broad ranging. of functions you need (e.g., LC_MONETARY, LC_NUMERIC).C should be used as the default locale setting.At least once a day, someone has to explain that the only esc_ function you can use to sanitize is esc_url_raw(). This stems from what was (at the time) a logical change. The function sanitize_url() was an alias for esc_url_raw() and it’s redundant to have both.
Except …
Over the years, WordPress has evolved and improved function names to the point that we can nearly say “Use sanitize_ functions to sanitize and esc_ functions to escape” which makes life a lot easier for new users. They don’t have to remember any odd-functions-out except the wp_kses* ones.
For WordPress 5.9, I made a ticket to restore sanitize_url() and I’m delighted to be able to say that it’s back! It’s un-deprecated!
Nothing, except the name.
Yes, for now. Eventually we’d like to wean people off it, but it’s a process. No worries. If you’re using it, we won’t ding you.
Because now you (and anyone else) can look at $variable = sanitize_url( $_POST['variable_url'] ); and know “Ah, yes, this is sanitized.”
No. I’m posting this because I promised some of the people I made that ticket for that I would 🙂 It’s delayed because I’ve been swamped.
It’s something that changes very little for most people, but will greatly help newer developers and minimize their confusion. And that? That is a fantastic thing!
Tell the people who run the sniffer, but keep in mind they’re probably adding in a bunch of changes, so it may take a while 🙂 Be cognizant of the work they do and respectful of the time they give you. Helps everyone.
tl;dr – We strongly recommend you use tagged folders for your releases of your plugins. Future you will thank you.
While we have always advocated for people to use a tag folder with their plugins instead of trunk, it persists that a number of developers like using the “Stable TagTag Tag is one of the pre-defined taxonomies in WordPress. Users can add tags to their WordPress posts along with categories. However, while a category may cover a broad range of topics, tags are smaller in scope and focused to specific topics. Think of them as keywords used for topics discussed in a particular post.” of trunk. There are logical reasons for this. Having your stable tag be trunk feels like it’s one less thing to keep in mind when you update your 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 for a new release.
The problem with that setup is that you suddenly made it harder for everyone else to keep tabs on your plugin, to make sure they downloaded the correct version, and worst of all … you made it nearly impossible to roll back to a previous release. And with the advent of automated plugin updates, that last one is going to be damaging to you in the long run.
In fact, here’s what you’re making worse:
So what’s the right way?
svn add and so on as needed)svn cp trunk tags/1.2.3 — this will copy from trunk to the tag foldersvn ci -m "Releasing new version" — this will push both trunk and tagThat’s it. You’re done. Now you can upload and edit trunk all you want, for a dev version, and as long as the readme points to the proper stable tag, your users won’t get any updates.
Okay, but what if you want to have a trunk version for testing? Do not edit the stable tag in the trunk readme! It’s that value that tells WordPress which version is ‘stable’ and if you’re working on 1.2.3, keep stable as 1.2.2 in trunk and no one will get the new code until you’re ready.
#release, #svn, #tagsIf you’re not clear about the difference between WordPress actions and filters, you may end up breaking the page layout of WordPress – maybe days, months, or even years after you’ve written and implemented a new filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. hook.
The difference can be difficult for new developers to grasp – after all, hooking an action or filter runs your code, either way, right? Well, yes, it does, but filters can be executed several times, in different locations as the webpage is being built (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., body, footer, etc.), and even in the admin back-end. More importantly, filters do not send anything to the webpage! Filter hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same. receive their data / text as an argument, and then “return” the modified (or original) data / text at the end. They do not use “echo”, “print”, “printf”, etc. – they should not send anything to the webpage. If you need to output something directly to the webpage, use an action – that’s what they’re for.
WordPress includes jQuery with coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.. Most everyone knows this. But did you also know WordPress includes a great deal of other libraries for your use.
You should take the time to check the documentation on wp_enqueue_script().
But that list actually isn’t complete! For a complete list of registered files inspect `$GLOBALS[‘wp_scripts’]` in the admin UIUI UI is an acronym for User Interface - the layout of the page the user interacts with. Think ‘how are they doing that’ and less about what they are doing.. Registered scripts might change per requested page. You can also check out the massive amounts of files in wp-includes to see even more.
My point, though, is that 90% of the time, you don’t need ‘your own’ version of something. We have it.
Even datepicker folks (jquery-ui-datepicker).
Check if core works. If you call it right, most of the time it will.
With the httpHTTP HTTP is an acronym for Hyper Text Transfer Protocol. HTTP is the underlying protocol used by the World Wide Web and this protocol defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands./2 and httpsHTTPS HTTPS is an acronym for Hyper Text Transfer Protocol Secure. HTTPS is the secure version of HTTP, the protocol over which data is sent between your browser and the website that you are connected to. The 'S' at the end of HTTPS stands for 'Secure'. It means all communications between your browser and the website are encrypted. This is especially helpful for protecting sensitive data like banking information. features of WordPress on the future plan, it’s time for a reminder about how to enqueue things. If you haven’t read John’s post about https configurations, please do. We want to make things work well for everyone and future proof your code 🙂
A common method to enqueue fonts is to use the CSSCSS CSS is an acronym for cascading style sheets. This is what controls the design or look and feel of a site. url like this:
wp_enqueue_style( 'my_awesome_css', 'http://somecoolurl.com/my-awesome.min.css' );
The problem with this, as we move to more and more of an https world, is that will cause errors with people who want that beautiful green padlock. In order to make their life easier, please use protocol relative URLs in your enqueues:
wp_enqueue_style( 'my_awesome_css', '//somecoolurl.com/my-awesome.min.css' );
It’s really that simple. The future will thank you.
Edit: Yes, if a url has HTTPS and you can use it, use it. Eventually we’ll all be https and none of this will matter, but hard coding in http is making life difficult 🙂
When you have a 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, it’s important that you get notified when people have support questions. We have a way for you to keep up to date on these things and have since the Great Plugin Refresh of 2012. But for those of you who missed the news or need a refresher, here we go.
We’ve always had a couple convenience views of plugin-committers and plugin-contributors, and these are still there as well. Committers are managed in on the Admin tab (i.e. people who have access to commit code via SVNSVN Short for "SubVersioN", it's the code management system used to maintain the plugins hosted on WordPress.org. It's similar to git.), while contributors are taken from readme.txt (which is why it’s important for you to use the proper WPORG forum ID, capitalization and all).
Example URLS:
https://wordpress.org/support/view/plugin-committer/Otto42
https://wordpress.org/support/view/plugin-contributor/Otto42
Your username is case sensitive. Otto42 will work, otto42 will not. Not sure what yours is? Go to https://wordpress.org/support/profile/ (yes, that works for everyone) and look at the 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.:

The name in the grey header is capitalized, thus he must use a capital_O_dangit.
Otto fixed this, lowercase works, still, check your login name because I know some of you have weird spaces and stuff
Since anyone can add you as a plugin contributor, I recommend following plugin-committer.
The RSS URLs for this look like https://wordpress.org/support/rss/view/plugin-committer/Otto42
At this time, we don’t have email for this.
Every single plugin allows you to follow it by email. Go to the Support Page for your plugin, scroll down to the bottom, and you’ll see this:

RSS and email. Done. Even if there are no posts you can register for those emails, so make that a part of your workflow.
So, I’ve had this working for a while, but not a lot of people noticed, so I figured I’d spell it out explicitly.
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 pages have special magic Google markup. This is what allows many of the Google tricks we do for plugin pages to work. If you’ve ever searched for one of our plugins on Google, you may have noticed that it says it’s “free” as well as showed the rating as stars and such. This is all using Google’s Rich Snippets functionality with markup from the schema.org specifications.
One of the magic tricks we do is to point to your WordPress.org Profiles page as the “author” of the plugin. It’s your plugin, after all, and you deserve the credit. But promoting the authorship is only half the picture, it helps if Google also knows who you are as an author. Then they can do something clever too:

This is a sample entry for one of my plugins from the Rich Snippets Testing tool. The photo and authorship info may not show up on every search result that gets my plugin up on Google’s search results, but it certainly doesn’t hurt. But to get this information to be capable of showing, Google needs to connect your profile and user information on WordPress.org with a profile and user information from Google+. To do this, there’s two steps:
Step 1: Edit your WordPress.org profile to include a link to your Google+ account. You can do this yourself, and you can see how I did it on my Profiles page. I included this link in my “About Me” section: https://plus.google.com/100201852715113506716?rel=author
Note that the ?rel=author bit is important, that’s what tells Google that you are the author here and links your G+ account to this page.
Step 2: Tell Google that you contribute to WordPress.org. To do this, go to your Google+ Profile. In the “Links” section you will find a “Contributor To” area. You need to add two links to this area:
After doing both these steps, you can try your plugin’s URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org in the Rich Snippets tool yourself, and voila, you’ll see the magic. Note that you may not see it in the actual Google search results for weeks, and it may never appear. Google shows snippets like these on terms of their own choosing. All you’re doing here is to give them the data that lets their engine do the magic, if it can.
Every once in a while, somebody pings me to say that their 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 isn’t showing up properly in the directory. Almost always it’s a problem with the plugin itself having incorrect information somehow. So I thought I’d do a quick post to explain some aspects of the plugin directory, and explain some of the more obvious stuff which a lot of people miss.
First, let’s briefly go over the layout of your plugin in the SVNSVN Short for "SubVersioN", it's the code management system used to maintain the plugins hosted on WordPress.org. It's similar to git. repository. There’s three directories created by default, and an optional fourth one that you can create yourself.
Trunk: The /trunk directory is where your plugin code should live. The trunk can be considered to be the latest and greatest code. It’s the development version. Hopefully, the code in trunk should always be working code, but it may be buggy from time to time because it’s not necessarily the “stable” version. For simple plugins, the trunk may be the only version of the code that exists, and that’s fine as well.
Tags: The /tags directory is where you can put versions of the plugin at some specific point in time. Usually, you’ll use version numbers for the subdirectories here. So version 1.0 of the plugin would be in /tags/1.0, version 1.1 would be in /tags/1.1, and so forth. Again, not every plugin uses tags for versioning.
Branches: The /branches directory is a place that you can use to store branches of the plugin. Perhaps versions that are in development, or test code, etc. 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/ system does not use the branches directory for anything at all, it’s considered to be strictly for developers to use as they need it.
Assets: The last optional directory doesn’t exist by default (Edit: It does now, older plugins may be missing it, but all newly added plugins will get it by default.) You can create it yourself though. Just make a directory called “assets” next to those other three directories. Assets currently only has one use, which is to store the banner image to be displayed on your plugin page. We may use it for more things in the future. For now, you can just make an image, name it banner-772x250.png or banner-772x250.jpg, and put it in there. Easy.
Additional Info: Since creating this post, some new files have been added to the assets folder. You can create a banner-1544x500.png or banner-1544x500.jpg now too. This high-resolution banner will be shown to users with high-resolution displays, such as phones or tablets or certain newer laptops. Additionally, screenshots which once lived in the plugin’s own directory can now be moved from there into the assets directory. This allows the screenshots to be shown on the plugin page, but not included in the download of the plugin, reducing file size. It’s recommended to put screenshot files in /assets.
All plugins contain a main 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. file, and almost all plugins have a readme.txt file as well. The readme.txt file is intended to be written using a subset of markdown. The example readme.txt explains most everything pretty well, but there’s a few little tidbits that are worth pointing out.
First is the concept of the “Stable TagTag Tag is one of the pre-defined taxonomies in WordPress. Users can add tags to their WordPress posts along with categories. However, while a category may cover a broad range of topics, tags are smaller in scope and focused to specific topics. Think of them as keywords used for topics discussed in a particular post.”. When WordPress.org parses the readme.txt, the very first thing it does is to look at the readme.txt in the /trunk directory, and then read that “Stable Tag” line. If the Stable Tag is missing, or is set to “trunk”, then the version of the plugin in /trunk is considered to be the stable version. If the Stable Tag is set to anything else, then it will go and look in /tags/ for the referenced version. So a Stable Tag of “1.2.3” will make it look for /tags/1.2.3/.
Important bit: Everything else is read from this new location. If the Stable Tag is 1.2.3 and /tags/1.2.3/ exists, then nothing in trunk will be read any further for parsing by any part of the system. If you try to change the description of the plugin in /trunk/readme.txt, and Stable Tag isn’t trunk, then your changes won’t do anything on your plugin page. Everything comes from the readme.txt in the file being pointed to by the Stable Tag.
Now let’s get to the plugin information itself. The WordPress.org directory reads the main plugin PHP file to get things like the Name of the plugin, the Plugin URI, and most importantly, the version number. On the plugin page, you’ll see the download button which reads “Download Version 1.2.3” or similar. That version number comes from the plugin’s main PHP file.
Some people get this versoning confused due to the tags system. The Stable Tag points to a subdirectory in the /tags directory. But the version of the plugin is not actually that, it’s the version that is listed in the plugin’s PHP file itself. If you have changed Stable Tag to 1.4 and the plugin still says 1.3 in the PHP file, then the version listed will be 1.3.
Back to the readme.txt. There’s a line called “Contributors”. This line has always been expected to be WordPress.org usernames only. WordPress reads those, gets information about that user, gets their gravatarGravatar Is an acronym for Globally Recognized Avatar. It is the avatar system managed by WordPress.com, and used within the WordPress software. https://gravatar.com/., name, etc, and makes the authors listing. If you put anything here that’s not a WordPress.org username, then it doesn’t look nearly as good. No picture, no link, just text.
Other information in the readme.txt is read and used at various points on the Plugin listing. The Donate link makes a “Donate to this plugin” link in the sidebarSidebar A sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme.. The “Requires at least” and “Tested up to” fields are used for compatibility checking, even on the WordPress installation itself. Few people get these wrong.
One thing a lot of people get wrong is this line:
“Here is a short description of the plugin. This should be no more than 150 characters. No markup here.”
That bit is serious, and you should read it again. That one line people get wrong more often than anything else. That line of text is the single line description of the plugin which shows up in big letters right under the plugin name, and if it’s longer than 150 characters, it gets cutoff and makes your plugin page look silly.
Markdown allows for easy linking in your readme.txt as well. Just write like this to link a word to a URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org:
[WordPress](http://wordpress.org)
Videos can be put into your readme.txt too. A YouTube or Vimeo link on a line by itself will be auto-embedded. It’s also possible to embed videos hosted on VideoPress using the wpvideo shortcode. More on that topic here: http://wpdevel.wordpress.com/2010/02/20/plugins-can-now-include-videos-in-their-readme-txt-files/
I don’t think I covered everything, but hopefully that will explain some of the more obscure features of the directory and how it works. If it reduces the number of times people send me the question “why didn’t my version change show up in the directory”, then I think this post was time well spent. 🙂
During the development of WordPress 3.4 I have spent some time working on improving the rewrite APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways.. One of the tickets this involved was #16303: “Improve documentation and usability of WP_Rewrite Endpoint support”. Endpoints are a really cool feature of the rewrite API, but unfortunately also little known and misunderstood. So, with this post my aim is to get more 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 developers to read and understand the new and improved endpoint documentation.
Using endpoints allows you to easily create rewrite rules to catch the normal WordPress URLs, but with a little extra at the end. For example, you could use an endpoint to match all post URLs followed by “gallery” and display all of the images used in a post, e.g. http://example.com/my-fantastic-post/gallery/.
A simple case like this is relatively easy to achieve with your own custom rewrite rules. However, the power of endpoints shines for more complex situations. What if you wanted to recognise URLs for posts and pages ending with “gallery”? What if you wanted to be able to catch multiple different archive URLs, e.g. day, month, year and categoryCategory The 'category' taxonomy lets you group posts / content together that share a common bond. Categories are pre-defined and broad ranging. archives, with “xml” appended in order to output an XML representation of the archive? For these situations endpoints are very useful as they allow you to add a string to the end of multiple rewrite structures with a single function call.
There is one function for interacting with endpoints: add_rewrite_endpoint(). It takes two parameters $name and $places.
$name is a string and is, wait for it… the name of the endpoint. $name is what is used in the URL and is the name of the query variable that the endpoint URL will be rewritten to. For example, an endpoint named “print” added to post permalinks would use a URL like http://example.com/my-awesome-post/print/.
$places is an integer value which represents the locations (places) to which the endpoint will be added, e.g. posts, pages or year achives. To understand $places you need to learn about the endpoint mask constants.
In wp-includes/rewrite.php (browse wp-includes/rewrite.php on Trac) a number of constants are defined all with names beginning with “EP_”:
define('EP_NONE', 0); // 0000000000000
define('EP_PERMALINK', 1); // 0000000000001
define('EP_ATTACHMENT', 2); // 0000000000010
define('EP_DATE', 4); // 0000000000100
define('EP_YEAR', 8); // 0000000001000
// ...
define('EP_PAGES', 4096); // 1000000000000
define('EP_ALL', 8191); // 1111111111111
These are the endpoint masks which describe sets of URLs; post permalinks are described by EP_PERMALINK, year archives are EP_YEAR, etc. They should be thought of in terms of their binary values (see the comment I’ve added to the end of each line). Every EP_* mask, except for EP_ALL, is a different power of two and so has a different bit set to one. This allows us to build up combinations of endpoint masks by using the bitwise OR operator:
// all posts or attachments EP_PERMALINK | EP_ATTACHMENT // 0000000000011 // all full dates (yyyy/mm/dd), years or pages EP_DATE | EP_YEAR | EP_PAGES // 1000000001100
$places should also be thought of as a binary number. It should be set to one of the EP_* constants or a combination of them using the bitwise OR operator. If we wanted to add our endpoint to all post permalinks we would use EP_PERMALINK. For both posts and pages: EP_PERMALINK | EP_PAGES. For posts, pages, and categories: EP_PERMALINK | EP_PAGES | EP_CATEGORIES. There is also a special value to add an endpoint to all URLs that support endpoints: EP_ALL.
NB: The values of the EP_* constants are not guaranteed to stay the same which is why you must say
$places = EP_PERMALINKand not$places = 2. This is particularly important forEP_ALLwhich will change every time a new endpoint mask is added.
It’s time to put this information into practise. The running example will be a plugin that adds JSON representations of our content using a new rewrite endpoint called “json”. So, the goal is to get URLs such as http://example.com/about/json/ to return a JSON response that gives information about the “about” page. To add the “json” endpoint to post and page rewrite structures:
add_rewrite_endpoint( 'json', EP_PERMALINK | EP_PAGES );
This is called in a function hooked into the init action:
function makeplugins_add_json_endpoint() {
add_rewrite_endpoint( 'json', EP_PERMALINK | EP_PAGES );
}
add_action( 'init', 'makeplugins_add_json_endpoint' );
Now we want to act on requests for JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. content. This is done by hooking into template_redirect. We want to detect appropriate requests and include our custom template for serving up posts and pages in JSON format:
function makeplugins_json_template_redirect() {
global $wp_query;
// if this is not a request for json or a singular object then bail
if ( ! isset( $wp_query->query_vars['json'] ) || ! is_singular() )
return;
// include custom template
include dirname( __FILE__ ) . '/json-template.php';
exit;
}
add_action( 'template_redirect', 'makeplugins_json_template_redirect' );
And we’re done. For a full example plugin see https://gist.github.com/2891111.
The best way to understand how anything works is to take a look at the source, so let’s do that. Endpoints are added with the add_rewrite_endpoint() function in wp-includes/rewrite.php:
/**
* Add an endpoint, like /trackback/.
*
* Adding an endpoint creates extra rewrite rules for each of the matching
* places specified by the provided bitmask. For example:
*
* <code>
* add_rewrite_endpoint( 'json', EP_PERMALINK | EP_PAGES );
* </code>
*
* will add a new rewrite rule ending with "json(/(.*))?/?$" for every permastruct
* that describes a permalink (post) or page. This is rewritten to "json=$match"
* where $match is the part of the URL matched by the endpoint regex (e.g. "foo" in
* "/json/foo/").
*
* A new query var with the same name as the endpoint will also be created.
*
* When specifying $places ensure that you are using the EP_* constants (or a
* combination of them using the bitwise OR operator) as their values are not
* guaranteed to remain static (especially EP_ALL).
*
* Be sure to flush the rewrite rules - flush_rewrite_rules() - when your plugin gets
* activated and deactivated.
*
* @since 2.1.0
* @see WP_Rewrite::add_endpoint()
* @global object $wp_rewrite
*
* @param string $name Name of the endpoint.
* @param int $places Endpoint mask describing the places the endpoint should be added.
*/
function add_rewrite_endpoint( $name, $places ) {
global $wp_rewrite;
$wp_rewrite->add_endpoint( $name, $places );
}
So this is just a wrapper for the add_endpoint() method of the WP_Rewrite class. Although the (excellent!) documentation gives us some clues as to what it does we’ll have to dig deeper to find the how:
/**
* Add an endpoint, like /trackback/.
*
* See {@link add_rewrite_endpoint()} for full documentation.
*
* @see add_rewrite_endpoint()
* @since 2.1.0
* @access public
* @uses WP::add_query_var()
*
* @param string $name Name of the endpoint.
* @param int $places Endpoint mask describing the places the endpoint should be added.
*/
function add_endpoint($name, $places) {
global $wp;
$this->endpoints[] = array ( $places, $name );
$wp->add_query_var($name);
}
Another very short and simple function. All it does is append the two parameters passed to it to the private $endpoints property of the WP_Rewrite class and also add a new query variable using WP::add_query_var().
Okay, so that’s still not useful for a full understanding of endpoints. All we know is that the arguments you pass to add_rewrite_endpoint() are stored in a private array of the $wp_rewrite global. To find out more we’ll have to search wp-includes/rewrite.php for “>endpoints” (i.e. code accessing the WP_Rewrite::$endpoints property). There are only three references to this: WP_Rewrite::add_endpoint() we have seen, WP_Rewrite::init() is boring (initialising the array), and the third is WP_Rewrite::generate_rewrite_rules():
$ep_query_append = array ();
foreach ( (array) $this->endpoints as $endpoint) {
//match everything after the endpoint name, but allow for nothing to appear there
$epmatch = $endpoint[1] . '(/(.*))?/?$';
//this will be appended on to the rest of the query for each dir
$epquery = '&' . $endpoint[1] . '=';
$ep_query_append[$epmatch] = array ( $endpoint[0], $epquery );
}
// ... a lot of code removed ...
foreach ( (array) $ep_query_append as $regex => $ep) {
//add the endpoints on if the mask fits
if ( $ep[0] & $ep_mask || $ep[0] & $ep_mask_specific )
$rewrite[$match . $regex] = $index . '?' . $query . $ep[1] . $this->preg_index($num_toks + 2);
}
In the code above the first foreach is looping through the defined endpoints and building a new array called $ep_query_append. This new array uses regular expressions that match a specific endpoint as keys and the values are the endpoint $places and $epquery which is a partial query string to append to a full query. So, for our JSON endpoint example we would get:
$ep_query_append[ 'json(/(.*))?/?$' ] = array( EP_PERMALINK | EP_PAGES, '&json=' );
The second loopLoop The Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop. generates the final rewrite rules for our endpoint. It loops through $ep_query_append checking if the current permastructure being generated has an endpoint mask, $ep_mask, that matches any of the endpoints. If the bitwise AND produces a non-zero value then there’s a match and the endpoint rewrite rules should be added to this permastructure.
For our JSON example, if WP_Rewrite::generate_rewrites_rules() has been called for the posts permalink structure then $ep_mask = EP_PERMALINK and $ep[0] = EP_PERMALINK | EP_PAGES. The bitwise AND of these values produces 1, therefore a new entry is added to $rewrite. Assuming that the post permalink structure is “/%postname%/” it would look something like:
$rewrite[ '([^/]+)/json(/(.*))?/?$' ] = 'index.php?name=$1&json=$3'
This is the final rewrite rule for our JSON endpoint applied to post permalinks. It matches a request for “post-slug/json/” and sets up the appropriate query variables “name” and “json”. Our template_redirect hook now picks this up and produces the required response.
And you made it to the end, phew! Time for a drink…
I hope that after all of that you understand how to use endpoints and how they work. If you have any questions please don’t hesitate to ask them in the comments. Always remember that the best way to understand a function is to look at the source and follow its execution.