Update: This question was initially about how to log a user out without confirmation, but from a "pretty" URL without a logout nonce. However, in retrospect I realize this is a security issue that goes against the entire reason WordPress requires a nonce to log out in the first place, so I've updated both the question and the answer to show a better way of implementing a smooth logout without any overt "wp" strings in the link.
I would like to add a menu item that logs the user out without asking for confirmation. To this end, I have attempted to create a redirection to the actual logout URL with a proper WordPress nonce added to bypass the user confirmation page, like so:
/**
* Adds a nonce to a bare logout link in a menu,
* presented in the form of a GET query (the "t" is for "token")
*/
add_filter('wp_nav_menu_objects', function($sorted_menu_items) {
foreach ($sorted_menu_items as $item)
if (preg_match('#^/logout/?$#', $item->url) === 1)
$item->url .= '?t='.wp_create_nonce();
return $sorted_menu_items;
});
/**
* Redirects the user to the real logout page
* & bypasses confirmation by using the previously-
* added nonce/token
*/
add_action('template_redirect', function() {
if (empty($_SERVER['REQUEST_URI'])) return;
$uri = $_SERVER['REQUEST_URI'];
if (preg_match('#^/logout/?\?t=([0-9A-Fa-f]+)#', $uri, $matches) === 1) {
wp_redirect(home_url(
'/wp-login.php?action=logout&redirect_to=%2F&_wpnonce='.$matches[1]
), 302);
exit;
}
})
This does succeed in redirecting the user to the logout page with nonce added. However, the presence of the nonce doesn't actually stop the confirmation page from appearing! In fact, on the confirmation page itself, the final logout link has its own separate nonce.