15

I am developing a free plugin for connection a external support system to WordPress to be able to authenticate users on WordPress.

For this, currently from the external system, the user is sent to WordPress's login page with this at the end

?action=freshdesk-remote-login

My plugin then checks if the user is logged into WP, if not it shows the login form and after successful login, redirects them back to the 3rd party site.

The redirect is done using something like this: wp_redirect( $sso_url );

Now this works well, but I plan to offer a shortcode which could be added to a page the user chooses. Now once a user goes to this page, if they are logged in, they should be forwarded to the 3rd party site, if not, then to the login page.

Is there a way you could suggest wp_redirect to work inside a shortcode?

4 Answers 4

23

As @Rarst explains, shortcodes normally run too late for you to redirect from inside one. They usually run on the the_content hook which is well after content is sent to the browser. If you need to redirect based on the presence of a shortcode you need to check for that shortcode before any content leaves the server.

function pre_process_shortcode() {
  if (!is_singular()) return;
  global $post;
  if (!empty($post->post_content)) {
    $regex = get_shortcode_regex();
    preg_match_all('/'.$regex.'/',$post->post_content,$matches);
    if (!empty($matches[2]) && in_array('yourshortcodeslug',$matches[2]) && is_user_logged_in()) {
      // redirect to third party site
    } else {
      // login form or redirect to login page
    }
  }
}
add_action('template_redirect','pre_process_shortcode',1);

That is "proof of concept". The particular conditions you need will likely be different. Note that that is a pretty "heavy" bit of processing. I would make sure it only runs where absolutely necessary.

4
  • Thanks a tonne. This is just perfect and exactly what I was looking for. Commented Jun 2, 2013 at 14:52
  • Hello, I added some checks to make sure this code only runs on a specific page, however I noticed, that placing the wp_redirect inside a shortcode also works fine. I tried with javascript and also with wp_redirect( $sso_url ); and it just worked. Commented Jun 5, 2013 at 16:51
  • 1
    wp_redirect does not work in a shortcode under normal conditions. I just checked. If it is working for you, your theme or a plugin is doing something much like what I suggested to make it work.
    – s_ha_dum
    Commented Jun 5, 2013 at 17:10
  • Yes you are right. Sorry to waste your time. I had multiple instances of your code. I am back to using your above code :) Commented Jun 5, 2013 at 18:58
5

wp_redirect() performs redirect via HTTP headers so technically it won't (or at least shouldn't) work after page output started. So you can't just use this function in shortcode.

Which doesn't mean however you can't use shortcode to control it. You could check for fitting conditions (if is page and page contains shortcode) before output started (somewhere around template_redirect hook) and perform redirect then.

Another option would be to output conditionally JavaScript that will perform redirect after page have loaded.

4
  • Hello I found this:` function pippin_login_form_shortcode( $atts, $content = null ) { extract( shortcode_atts( array( 'redirect' => '' ), $atts ) ); if (!is_user_logged_in()) { if($redirect) { $redirect_url = $redirect; } else { $redirect_url = get_permalink(); } $form = wp_login_form(array('echo' => false, 'redirect' => $redirect_url )); } return $form; } add_shortcode('loginform', 'pippin_login_form_shortcode');` Here it seems the wp_redirect is placed inside a shortcode. Commented Jun 1, 2013 at 12:38
  • The link is pippinsplugins.com/wordpress-login-form-short-code Commented Jun 1, 2013 at 12:39
  • @HarishChouhan where do you see wp_redirect() in that code?
    – Rarst
    Commented Jun 1, 2013 at 12:43
  • Hello, I'm sorry you are right. In the example code it just saves the URL and not actually redirect. So accordingly to you, JavaScript based redirect seem to be my only option? Commented Jun 1, 2013 at 13:01
0

Simple JavaScript solution:

Shortcode:

[js_logout]

functions.php:

add_shortcode('js_logout', 'js_logout');
function js_logout() {
    // redirect to home
    $logout_url = html_entity_decode(wp_logout_url(home_url()));

    return '<p>' . __('If you are not redirected automatically, click here:') . ' <a href="' . $logout_url . '">Logout</a></p><script>window.location.href = "' . $logout_url . '";</script>';
}
0

Here's a one line solution.

Put this in your functions.php file:

add_action( 'template_redirect', function () {
    ob_start();
} );

ob_start() begins output buffering, when the template_redirect actions are completed, and nothing has been sent to the browser. That means wp_redirect() works from anywhere:

wp_redirect( $url );
exit;

including in a shortcode. If the script terminates normally, without an exit, the buffer is automatically flushed and the whole page is sent at that time.

Cheeky ... but it seems to work for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.