Skip to content

Instantly share code, notes, and snippets.

@plaidpowered
Last active August 13, 2020 14:07
Show Gist options
  • Save plaidpowered/9e4bd069b8ec990341f1cadf62615eef to your computer and use it in GitHub Desktop.
Save plaidpowered/9e4bd069b8ec990341f1cadf62615eef to your computer and use it in GitHub Desktop.
Mapping Additional Domains with WordPress Multisite
<?php
class DomainMapper {
/**
* Where we store the fully qualified domain URL throughout the lifecycle of the WordPress stack.
*/
private $domain = null;
/**
* Where we store the active site object discovered during the network_short_circuit function.
*/
private $site = null;
public function __construct() {
add_filter( 'pre_get_site_by_path', array( $this, 'network_short_circuit' ), 10, 2 );
add_filter( "blog_option_siteurl", array( $this, 'hijack_blog_option' ), 99, 2 );
add_filter( "blog_option_home", array( $this, 'hijack_blog_option' ), 99, 2 );
add_filter( "pre_option_siteurl", array( $this, 'hijack_get_option' ), 99, 1 );
add_filter( "pre_option_home", array( $this, 'hijack_get_option' ), 99, 1 );
add_filter( 'get_canonical_url', array( $this, 'assign_canonical_url', 11 ) );
}
public function network_short_circuit( $site, $domain ) {
// first let's utilize WordPress's object cache to see if this domain has already been found
// why do a sql lookup if you don't need to?
$cached = wp_cache_get( 'domain_site__' . sanitize_title( $domain ) );
if ( $cached !== false ) {
$this->setup_FQD( $domain );
$this->site = $cached;
return $cached;
}
// The following commented code is how it works with my own setup.
// It will NOT work with yours, unless you're storing domains in the blogmeta table,
// so either do it exactly the same as me, or replace this query with your own process.
/* REPLACE:
$site_id = $wpdb->get_var( $wpdb->prepare(
"SELECT blog_id FROM {$wpdb->blogmeta} WHERE `meta_key` = 'domain' AND `meta_value` = %s",
$domain
) );
*/
if ( ! empty( $site_id ) ) {
$site = \WP_Site::get_instance( $site_id );
$site->domain = $domain;
$this->site = $site;
$this->setup_FQD( $domain );
}
// Store our discovery in the cache for quick lookup later.
wp_cache_set( 'domain_site__' . $domain, $site );
return $site;
}
/**
* Stores the fully qualified domain address in our class for retrieval.
*/
private function setup_FQD( $domain ) {
$protocol = ( ! empty($_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443 ) ? "https://" : "http://";
$this->domain = $protocol . $domain;
}
public function hijack_blog_option( $value, $id ) {
if ( ! empty( $this->domain ) && absint( $id ) === $this->site->ID ) {
return $this->domain;
}
return $value;
}
public function hijack_get_option( $value ) {
if ( ! empty( $this->domain ) ) {
return $this->domain;
}
return $value;
}
/**
* From the get_canonical_url filter, assigns the correct domain to the canonical tag.
* Will require edits based on your WordPress configuration.
*/
public function assign_canonical_url( $url ) {
// You'll need to figure out what the primary domain of each site is on your own, the
// following only works if you're storing the primary domain in the wp_blogmeta table.
/* REPLACE:
$primary_domain = get_site_meta( get_current_blog_id(), 'domain', true );
*/
if ( empty( $primary_domain ) ) {
return $url;
}
// I always force the https, but YMMV
return 'https://' . $primary_domain . $_SERVER['REQUEST_URI'];
}
}
new DomainMapper();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment