Skip to content

Instantly share code, notes, and snippets.

@r-a-y
Last active May 17, 2016 12:12
Show Gist options
  • Save r-a-y/e098c67f49a57f5d579c to your computer and use it in GitHub Desktop.
Save r-a-y/e098c67f49a57f5d579c to your computer and use it in GitHub Desktop.
WordPress - Redirects login attempts from sub-sites to the main site to login. Supports mapped domains created by WPMU Domain Mapping.
<?php
/**
* Get login URL.
*
* If redirect URL is passed, this function attempts to see if the redirect
* is using a mapped domain. If so, we switch out the mapped domain with the
* original subdomain and force logins from the main site.
*
* @param string $redirect_to The redirect URL
* @return string
*/
function hwdsb_get_login_url( $redirect_to = '' ) {
if ( function_exists( 'bp_is_root_blog' ) ) {
$is_root_blog = bp_is_root_blog();
$root_blog_id = bp_get_root_blog_id();
} else {
$is_root_blog = is_main_site();
$root_blog_id = 1;
}
if ( $is_root_blog ) {
return '';
}
$login_url = get_site_url( $root_blog_id, 'wp-login.php', 'login' );
$domain = hwdsb_get_original_domain();
if ( ! empty( $redirect_to ) ) {
// reconstruct redirect URL to replace mapped domain with subdomain URL
if ( hwdsb_is_domain_mapping_enabled_for_current_blog() ) {
$redir = parse_url( $redirect_to );
$path = "{$redir['scheme']}://{$domain}{$redir['path']}";
$path = ! empty( $redir['query'] ) ? "{$path}?{$redir['query']}" : $path;
$path = ! empty( $redir['anchor'] ) ? "{$path}#{$redir['anchor']}" : $path;
$redirect_to = $path;
}
$login_url = add_query_arg( 'redirect_to', urlencode( set_url_scheme( $redirect_to ) ), $login_url );
} else {
global $current_blog;
$login_url = add_query_arg( 'redirect_to', urlencode( set_url_scheme( "http://{$domain}/" ) ), $login_url );
}
return $login_url;
}
/**
* Determine if the current blog is domain mapped.
*
* Requires the WPMU Domain Mapping or Mercator plugin.
*
* @return bool
*/
function hwdsb_is_domain_mapping_enabled_for_current_blog() {
// not using mercator or WPMU domain mapping, so stop!
if ( ! function_exists( 'Mercator\\startup' ) && ! function_exists( 'get_original_url' ) ) {
return false;
}
// mercator
if ( function_exists( 'Mercator\\startup' ) ) {
// check if we're on a mapped domain
$mapping = $GLOBALS['mercator_current_mapping'];
if ( ! empty( $mapping ) ) {
return true;
}
return false;
// WPMU Domain Mapping
} else {
$orig_domain = hwdsb_get_original_domain();
if ( $orig_domain !== $GLOBALS['current_blog']->domain ) {
return true;
}
return false;
}
}
/**
* Returns original domain for the current blog.
*
* @return string The domain without the URL scheme (eg. example.com)
*/
function hwdsb_get_original_domain() {
// WPMU Domain Mapping
if ( function_exists( 'get_original_url' ) ) {
$orig_domain = get_original_url( 'siteurl' );
$orig_domain = substr( $orig_domain, strpos( $orig_domain, '://' ) + 3 );
return $orig_domain;
// Mercator and everything else
} else {
return $GLOBALS['current_blog']->domain;
}
}
/**
* Redirects login attempts from sub-sites to the main site to login.
*/
add_action( 'login_init', function() {
if ( function_exists( 'bp_is_root_blog' ) ) {
$is_root_blog = bp_is_root_blog();
$root_blog_id = bp_get_root_blog_id();
} else {
$is_root_blog = is_main_site();
$root_blog_id = 1;
}
if ( $is_root_blog ) {
return;
}
// Bail from post password submissions
if ( ! empty( $_GET['action'] && 'postpass' === $_GET['action'] ) ) {
return;
}
$logout = ! empty( $_GET['action'] ) && 'logout' === $_GET['action'] ? true : false;
$redirect_to = ! empty( $_GET['redirect_to'] ) ? $_GET['redirect_to'] : '';
$login_url = hwdsb_get_login_url( $redirect_to );
// bail out of logout attempts
if ( $logout || ! empty( $_GET['loggedout' ] ) ) {
return;
}
wp_redirect( $login_url );
die();
} );
/**
* Filters the login URL only when on a mapped domain.
*/
add_filter( 'login_url', function( $retval, $redirect_to ) {
if ( false === hwdsb_is_domain_mapping_enabled_for_current_blog() ) {
return $retval;
}
// we're on a mapped domain, do the replacement
return hwdsb_get_login_url( $redirect_to );
}, 30, 2 );
/**
* Redirect subdomain requests to their mapped domain equivalent.
*
* Requires WPMU Domain Mapping plugin.
*/
add_action( 'template_redirect', function() {
global $wpdb;
if ( ! function_exists( 'get_original_url' ) || is_user_logged_in() ) {
return;
}
if ( hwdsb_is_domain_mapping_enabled_for_current_blog() ) {
return;
}
$domain = $wpdb->get_var( "SELECT domain FROM {$wpdb->dmtable} WHERE blog_id = '{$wpdb->blogid}' AND active = 1 LIMIT 1" );
if ( empty( $domain ) ) {
return;
}
wp_redirect( esc_url_raw( set_url_scheme( 'http://' . $domain . $_SERVER['REQUEST_URI'] ) ) );
die();
}, 0 );
/**
* Hack Domain Mapping to allow us to use Remote Login to visit frontend.
*
* Logging into a subdomain will redirect to the mapped domain.
*/
add_filter( 'site_option_dm_remote_login', function( $retval ) {
if ( 0 != $retval || ! function_exists( 'get_original_url' ) ) {
return $retval;
}
if ( did_action( 'get_header' ) ) {
return $retval;
}
// this is to pass the check in remote_login_js()
if ( isset( $_GET['dm'] ) ) {
return 1;
}
return $retval;
} );
/**
* Reimplement Domain Mapping's JS.
*
* Only works if Domain Mapping's Remote Login is disabled.
*/
add_action( 'wp_head', function() {
global $current_site, $current_blog, $wpdb;
if ( ! function_exists( 'get_original_url' ) ) {
return;
}
if ( 0 != get_site_option( 'dm_remote_login' ) || ! is_user_logged_in() ) {
return;
}
if ( hwdsb_is_domain_mapping_enabled_for_current_blog() ) {
return;
}
$referer = wp_get_referer();
// do not break customizer links from WP adminbar
if ( false !== strpos( $referer, '/wp-admin/customize.php' ) ) {
return;
}
$domain = $wpdb->get_var( "SELECT domain FROM {$wpdb->dmtable} WHERE blog_id = '{$wpdb->blogid}' AND active = 1 LIMIT 1" );
if ( empty( $domain ) ) {
return;
}
$protocol = is_ssl() ? 'https://' : 'http://';
$hash = get_dm_hash();
echo "<script src='{$protocol}{$current_site->domain}{$current_site->path}?dm={$hash}&amp;action=load&amp;blogid={$current_blog->blog_id}&amp;siteid={$current_blog->site_id}&amp;t=" . mt_rand() . "&amp;back=" . urlencode( esc_url_raw( $protocol . $domain . $_SERVER[ 'REQUEST_URI' ] ) ) . "' type='text/javascript'></script>";
} );
/**
* Change admin URLs on mapped domains to use the subdomain URL on the frontend.
*
* @param string $url URL to check.
* @return string
*/
function hwdsb_set_admin_url_to_subdomain( $url ) {
// bail if we're on a subdomain
if ( false === hwdsb_is_domain_mapping_enabled_for_current_blog() ) {
return $url;
}
// bail if we're in the admin area
if ( is_admin() ) {
return $url;
}
$domain = hwdsb_get_original_domain();
// darn customizer
if ( 'clean_url' === current_filter() ) {
$url = str_replace( '%3A%2F%2F' . $GLOBALS['current_blog']->domain, '%3A%2F%2F' . $domain, $url );
// everything else
} else {
$url = str_replace( '://' . $GLOBALS['current_blog']->domain, '://' . $domain, $url );
$url = set_url_scheme( $url, 'https' );
}
return $url;
}
add_filter( 'admin_url', 'hwdsb_set_admin_url_to_subdomain', 9999999999999 );
add_filter( 'clean_url', 'hwdsb_set_admin_url_to_subdomain', 9999999999999 );
/**
* AJAX should always obey the current scheme when on the front end.
*
* When FORCE_SSL_ADMIN is set to true, the 'ajaxurl' will always use HTTPS.
* This causes issues when a user is on the frontend and attempting to use
* an AJAX post action since the frontend traditionally uses
* HTTP. This function switches calls to 'admin-ajax.php' to always respect
* the current URL scheme.
*
* @param string $url URL to check
* @return string
*/
function hwdsb_set_admin_url_scheme( $url ) {
if ( hwdsb_is_domain_mapping_enabled_for_current_blog() ) {
return $url;
}
if ( is_admin() ) {
return $url;
}
if ( false === strpos( $url, 'admin-ajax.php' ) ) {
return $url;
}
return set_url_scheme( $url, is_ssl() ? 'https' : 'http' );
}
add_filter( 'admin_url', 'hwdsb_set_admin_url_scheme', 99 );
/**
* Remove WPMU Domain Mapping's default logout routine.
*/
add_action( 'plugins_loaded', function() {
remove_action( 'wp_logout', 'remote_logout_loader', 9999 );
} );
/**
* Redirects logout attempts to the main site.
*
* Reimplements WPMU Domain Mapping's logout routine.
*/
add_action( 'login_init', function() {
if ( false === hwdsb_is_domain_mapping_enabled_for_current_blog() ) {
return;
}
if ( ! function_exists( 'get_original_url' ) ) {
return;
}
$logout = ! empty( $_GET['action'] ) && 'logout' === $_GET['action'] ? true : false;
if ( false === $logout ) {
return;
}
// clear login cookies for current site
wp_clear_auth_cookie();
// now clear login cookies for main site
// use WPMU Domain Mapping's code from remote_logout_loader() here
global $current_site, $current_blog, $wpdb;
$wpdb->dmtablelogins = $wpdb->base_prefix . 'domain_mapping_logins';
$protocol = is_ssl() ? 'https://' : 'http://';
$hash = get_dm_hash();
$key = md5( time() );
$wpdb->query( $wpdb->prepare( "INSERT INTO {$wpdb->dmtablelogins} ( `id`, `user_id`, `blog_id`, `t` ) VALUES( %s, 0, %d, NOW() )", $key, $current_blog->blog_id ) );
$url = $protocol . $current_site->domain . $current_site->path . "?dm={$hash}&action=logout&blogid={$current_blog->blog_id}&k={$key}&t=" . mt_rand();
// redirect to main site to logout
wp_redirect( $url );
die();
} );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment