The restrict_manage_users action hook is called twice in Wordpress 4.4

I recently participated in an interesting discussion on Stack Exchange about how to add a filter button just above the Users list table on the Users page in WordPress Admin. To sum up the whole issue, if you used the restrict_manage_users hook to do this in an earlier version of WordPress, your code for filtering the users list will probably not work correctly in WordPress 4.4 without making a small change.

Examining The Issue

In WordPress 4.4, the restrict_manage_users hook is called twice when loading the Users page. (It is only called once in WordPress 4.3.1) This means that if you use that hook to add a drop down select and filter button (or any other input field or html code), your additions will actually show up on the Users page twice, both above the table and below it.

Now, normally you would think that this addition is a great convenience. However, unless you change your code, when the user makes a selection in one of the dropdowns, the other dropdown remains the same. Then when the Filter button is clicked, the form is submitted with two values for that input. One value will contain the selection and the other will be blank. If you use Chrome Developer tools, you can inspect the query vars sent with the get request and you will see what I mean:

Tip: Follow these instructions to inspect the query string parameters:

Open the page in Google Chrome Web Browser and press CTRL+SHIFT+I to open Developer Tools

to open Developer Tools At the top of the tools, select the Network tab.

With the developer tools still open, click on the filter button or submit button or whatever other button that you want to examine the request for. You should see a whole bunch of requests appear.

Click on the request you are interested in. In this case, it’s going to start with users.php.

Click on the Headers tab and scroll down to “Query String Parameters.”

How this Effects Your Code

If you wrote a WordPress plugin that uses both the restrict_manage_users hook and the pre_get_users filter, you likely looked at the $_GET global variable to alter the WP_User_Query. Because of this change, the $_GET variable will be different, and your code might only work if the user uses the bottom dropdown menu and not the top one. This is a very big bug, but fortunately there are several different ways to fix this issue.

The Solution

There are at least 3 different solutions to handling this problem. Visit this WordPress Stack Exchange discussion for example code on how to fix this using PHP.

Here I’m going to present a solution that uses Javascript. Simply add this to your theme’s functions.php file and change the NAME_OF_YOUR_INPUT_FIELD to the name of your input field! Since WordPress automatically loads jQuery on the admin side, you do not have to enqueue any scripts. This snippet of code simply adds a change listener to the dropdown inputs and then automatically updates the other dropdown to match the same value.

add_action( 'in_admin_footer', function() { ?> <script type="text/javascript"> var el = jQuery("[name='NAME_OF_YOUR_INPUT_FIELD']"); el.change(function() { el.val(jQuery(this).val()); }); </script> <?php } );

Questions?

If you tried this solution and are still having an issue, please comment below. There may be use cases where this doesn’t work but I can’t think of any right now. I’m interested in learning and your feedback is important.

Even if you use my javascript solution, I suggest that you read over the other solutions on Stack Exchange because they provide a lot of insight into how to use a static variable and/or your own custom action hook to deal with the issue of WordPress core calling a hook multiple times. Using a static variable is a great way to manage how often your plugin performs certain actions, and doing so could help you future-proof your code.