Selectively Disabling CDN Enabler Rewriting

Written by Dan Mossop

CDN Enabler is a useful plugin for rewriting URLs on your site to point to their equivalents on a CDN such as KeyCDN.

CDN Enabler's rewriting is quite simplistic, however – it simply checks for and rewrites any applicable URLs within the entire HTML of the page. In some circumstances, this is undesirable. For example, my Divi code snippet module is for displaying source code "as is", and URLs included in that code should not be modified by CDN Enabler. Since CDN Enabler itself doesn't provide a way of preventing the rewriting short of manually excluding every URL used in the source code, I needed a way to programmatically disable CDN Enabler's rewriting as appropriate. Here's a couple of solutions I came up with:

Disabling Rewriting on an Entire Page

The first approach I came up with for selectively disable CDN Enabler's URL rewriting is to remove the action it registers to actually perform the rewriting. This can be done with the following PHP code:
add_filter('template_redirect', 'disable_cdn_enabler_rewrites', 9);

function disable_cdn_enabler_rewrites($content) {
	remove_action('template_redirect', 'CDN_Enabler::handle_rewrite_hook', 10);
}
The code above will disable CDN Enabler on any page it is called on. Most likely you'll want to add additional checks to only call the action / remove the hook on certain pages where it is problematic. Otherwise the code above would effectively disable the plugin on all pages.

Disabling Rewriting for Some Content / URLs Only

While the method above is effective, it was a bit too heavy handed for my needs. Were I to use it, it would have disabled the use of the CDN entirely on any pages a code snippet module was used. Obviously this could have an undesirable impact on performance.

To address this, I came up with this improved solution. It's more complicated, but basically it grabs the content of the raw content of the post, uses a modified version of CDN Enabler's own code to get any URLs within that content, and then adds them as exclusions to CDN Enabler's option (via a filter). The end result is that URLs in the content assigned to the $excluded_content variable won't be converted to CDN URLs. In this example I've assigned the entire page content to $excluded_content, but really you'd want to extract some specific part of the page to exclude from processing (for example, when I use it, I extract the code snippet code from the module's shortcode, should it appear within the page).

The only thing you should need to modify for your own needs is the body of the pre_get_options function to get the content / URLs you wish to exclude.

Here's the code:

add_action('template_redirect', array(new cdn_enabler_fix(), 'pre_get_options'), 9);

class cdn_enabler_fix {
	
	private $excluded_urls = array();
	
	public function __construct() {}
	
	public function pre_get_options() {
		
		// Get the post content
		global $post;
		if (!isset($post) || !isset($post->ID)) { return; }
		$content = get_post_field('post_content', $post->ID);
		
		// Get and store the content to exclude from CDN Enabler URL replacement
		$excluded_content = $content
		
		// Get URLs to exclude
		$this->excluded_urls = $this->get_urls($excluded_content);
		
		// Filter the CDN Enabler option to add the exclusions
		add_filter('option_cdn_enabler', array($this, 'add_exclusions'));
	}
	
	function add_exclusions($options) {
	
		if (!is_array($options)) { return $options; }
		
		
		// Add the excluded URLs to the CDN Enabler option
		$urls = implode(',', $this->excluded_urls);
		$options['excludes'] = empty($options['excludes'])?$urls:$options['excludes'].','.$urls;
		
		return $options;
	}
	
	// Extract a list of URLs from the excluded content that CDN enabler could rewrite
	// - Based on CDN Enabler's own regex code (v1.0.7)
	public function get_urls($content) {

		$options = wp_parse_args(
			get_option('cdn_enabler', array()),
			array(
				'url'             => get_option('home'),
				'dirs'            => 'wp-content,wp-includes',
				'excludes'        => '.php',
				'relative'        => 1,
				'https'           => 0,
				'keycdn_api_key'  => '',
				'keycdn_zone_id'  => '',
			)
		);

		// check if HTTPS and use CDN over HTTPS enabled
		if (!$options['https'] && isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') {
			return array();
		}
		
		// get dir scope in regex format
		$input = explode(',', $options['dirs']);
		if ($options['dirs'] == '' || count($input) < 1) {
			return 'wp\-content|wp\-includes';
		}
		$dirs = implode('|', array_map('quotemeta', array_map('trim', $input)));
		
		$url = quotemeta(get_option('home'));
		$relative_url = substr($url, strpos($url, '//'));
		
		$blog_url = $options['https']
			? '(https?:|)'.$relative_url
			: '(http:|)'.$relative_url;

		// regex rule start
		$regex_rule = '#(?<=[(\"\'])';

		// check if relative paths
		if ($options['relative']) {
			$regex_rule .= '(?:'.$blog_url.')?';
		} else {
			$regex_rule .= $blog_url;
		}

		// regex rule end
		$regex_rule .= '/(?:((?:'.$dirs.')[^\"\')]+)|([^/\"\']+\.[^/\"\')]+))(?=[\"\')])#';
		
		$matches = array();
		preg_match_all($regex_rule, $content, $matches);
		
		return $matches[0];
	}
}

Want get more out of Divi?

Hundreds of new features for Divi
in one easy-to-use plugin

0 Comments

Submit a Comment

Comments are manually moderated and approved at the time they are answered. A preview is shown while pending but may disappear if your are cookies cleared - don't worry though, the comment is still in the queue.

Your email address will not be published. Required fields are marked *.

Enhance Your Code Snippets Module with Precision

Maximize your Divi site's functionality with the Divi Code Snippet Module. Effortlessly display source code with syntax highlighting for over 70 languages, ensuring your code appears exactly as intended without unwanted modifications.

About Dan Mossop

Dan is a Scottish-born web developer, now living in Brisbane with his wife and son. He has been sharing tips and helping users with Divi since 2014. He created Divi Booster, the first Divi plugin, and continues to develop it along with 20+ other Divi plugins. Dan has a PhD in Computer Science, a background in web security and likes a lot of stuff, 

0 Comments

Submit a Comment

Comments are manually moderated and approved at the time they are answered. A preview is shown while pending but may disappear if your are cookies cleared - don't worry though, the comment is still in the queue.

Your email address will not be published. Required fields are marked *.

We may earn a commission when you visit links on our website.