Skip to content
Snippets Groups Projects
Select Git revision
  • 5914f569c21e2100e5ec2afbebe8ad7f90a3e80c
  • master default
  • 0.1.5
  • 0.1.4
  • 0.1.3
  • 0.1.2
  • v0.1.1
7 results

cdn-rewrite.php

Blame
  • cdn-rewrite.php 7.15 KiB
    <?php
    /*
    Plugin Name: CDN Rewrite
    Plugin URI: http://voceconnect.com/
    Description: Rewrites asset URLs to CDN
    Version: 0.1
    Author: Chris Scott, Michael Pretty
    Author URI: http://voceconnect.com/
    */
    
    require_once('voce-settings.php');
    
    class CDN_Rewrite {
    
    	const OPTION_GENERAL = 'cdn_general';
    
    	private $submenu_general;
    
    	private $cdn_root_url;
    	private $file_extensions;
    
    	private $css_file_extensions;
    	private $css_cdn_root_url;
    
    	private $js_file_extensions;
    	private $js_cdn_root_url;
    
    	private $blog_details;
    
    	public function __construct() {
    		$this->cdn_root_url = untrailingslashit($this->get_setting('root_url'));
    		$this->file_extensions = $this->get_setting('file_extensions');
    
    		$this->css_cdn_root_url = untrailingslashit($this->get_setting('css_root_url'));
    		$this->css_file_extensions = $this->get_setting('css_file_extensions');
    
    		$this->js_cdn_root_url = untrailingslashit($this->get_setting('js_root_url'));
    		$this->js_file_extensions = $this->get_setting('js_file_extensions');
    }
    
    	public function initialize() {
    		if (!class_exists('Voce_Settings')) {
    			return;
    		}
    
    		add_action('admin_menu', array($this, 'add_options_page'));
    		if ('' == $this->file_extensions || '' == $this->cdn_root_url) {
    			add_action('admin_notices', array($this, 'settings_warning'));
    			return;
    		}
    
    		if('/' != $this->cdn_root_url) {
    			$action = (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) ? 'xmlrpc_call' : 'template_redirect';
    			add_action($action, array($this, 'start_buffer'), 1);
    		}
    	}
    
    	/**
    	 * get general setting
    	 *
    	 * @param string $setting setting name
    	 * @return mixed setting value or false if not set
    	 */
    	private function get_setting($setting) {
    		$settings = get_option(self::OPTION_GENERAL);
    		if(!$settings || !is_array($settings)) {
    			$settings = array(
    				'file_extensions' => 'bmp|bz2|gif|ico|gz|jpg|jpeg|mp3|pdf|png|rar|rtf|swf|tar|tgz|txt|wav|zip',
    				'css_file_extensions' => 'css',
    				'js_file_extensions' => 'js'
    			);
    			update_option(self::OPTION_GENERAL, $settings);
    		}
    		return (isset($settings[$setting])) ? $settings[$setting] : false;
    	}
    
    	public function settings_warning() {
    		echo "<div class='update-nag'>The CDN Rewrite plugin is missing some required settings.</div>";
    	}
    
    	/**
    	 * adds the options page
    	 *
    	 * @return void
    	 */
    	public function add_options_page() {
    		$this->submenu_general = add_options_page('CDN Rewrite', 'CDN Rewrite', 'manage_options', self::OPTION_GENERAL, array($this, 'submenu_general'));
    		$settings = new Voce_Settings(self::OPTION_GENERAL, self::OPTION_GENERAL);
    
    		$section = $settings->add_section('api', 'CDN Rewrite Settings', $this->submenu_general);
    		$section->add_field('root_url', 'CDN Root URL (required)', 'field_input', array('description' => 'The base URL of the CDN.'));
    		$section->add_field('file_extensions', 'File Extensions (required)', 'field_input');
    		$section->add_field('css_root_url', 'CDN Root URL for CSS Files (optional)', 'field_input', array('description' => 'The base URL of the CDN for CSS Files.'));
    		$section->add_field('css_file_extensions', 'File Extensions for CSS Files (required)', 'field_input');
    		$section->add_field('js_root_url', 'CDN Root URL for JS Files (optional)', 'field_input', array('description' => 'The base URL of the CDN for JS Files.'));
    		$section->add_field('js_file_extensions', 'File Extensions for JS Files (optional)', 'field_input');
    	}
    
    	/**
    	 * callback to display submenu_external
    	 *
    	 * @return void
    	 */
    	function submenu_general() {
    		?>
    		<div class="wrap">
    			<h2>CDN Rewrite Settings</h2>
    			<form method="post" action="options.php">
    				<?php settings_fields(self::OPTION_GENERAL); ?>
    				<?php do_settings_sections($this->submenu_general); ?>
    				<p class="submit">
    					<input name="Submit" type="submit" class="button-primary" value="<?php esc_attr_e('Save Changes'); ?>" />
    				</p>
    			</form>
    		</div>
    		<?php
    	}
    
    	/**
    	 * start output buffering.
    	 *
    	 */
    	public function start_buffer() {
    		ob_start(array($this, 'filter_urls'));
    	}
    
    	/**
    	 * Callback for output buffering.  Search content for urls to replace
    	 *
    	 * @param string $content
    	 * @return string
    	 */
    	public function filter_urls($content) {
    
    		$root_url = $this->get_site_root_url();
    		$xml_begin = $xml_end = '';
    		if (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) {
    			$xml_begin = '>';
    			$xml_end = '<';
    		}
    		$regex = '#(?<=[(\"\''.$xml_begin.'])'.quotemeta($root_url).'(?:(/[^\"\''.$xml_end.')]+\.('.join('|', array($this->file_extensions,$this->css_file_extensions,$this->js_file_extensions)).')))#';
    		$content = preg_replace_callback($regex, array($this, 'url_rewrite'), $content);
    
    		return $content;
    	}
    
    	/**
    	 * Returns the root url of the current site
    	 *
    	 * @return string
    	 */
    	public function get_site_root_url() {
    		if(is_multisite() && !is_subdomain_install()) {
    			$root_blog = get_blog_details(1);
    			$root_url = $root_blog->siteurl;
    		} else {
    			$root_url = site_url();
    		}
    		return $root_url;
    	}
    
    	/**
    	 * Returns the details for the current blog
    	 *
    	 * @return object
    	 */
    	public function get_this_blog_details() {
    		if(!isset($this->blog_details)) {
    			global $blog_id;
    			$this->blog_details = get_blog_details($blog_id);
    		}
    		return $this->blog_details;
    	}
    
    	/**
    	 * Callback for url preg_replace_callback.  Returns corrected URL
    	 *
    	 * @param array $match
    	 * @return string
    	 */
    	public function url_rewrite($match) {
    		global $blog_id;
    		$path = $match[1];
    		//if is subfolder install and isn't root blog and path starts with site_url and isnt uploads dir
    		if(is_multisite() && !is_subdomain_install() && $blog_id !== 1) {
    			$bloginfo = $this->get_this_blog_details();
    			if((0 === strpos($path, $bloginfo->path)) && (0 !== strpos($path, $bloginfo->path.'files/'))) {
    				$path = '/'.substr($path, strlen($bloginfo->path));
    			}
    		}
    		if('/' !== $this->css_cdn_root_url && preg_match("/^.*\.(".$this->css_file_extensions.")$/i", $path) ) {
    			return $this->css_cdn_root_url . $path;
    		}
    		if('/' !== $this->js_cdn_root_url && preg_match("/^.*\.(".$this->js_file_extensions.")$/i", $path) ) {
    			return $this->js_cdn_root_url . $path;
    		}
    		return $this->cdn_root_url . $path;
    	}
    
    }
    add_action('init', array(new CDN_Rewrite(), 'initialize'));
    
    class CDN_VersionAssets {
    
    	private $default_version = '';
    	private $root_url;
    
    	public function __construct() {
    		$this->root_url = site_url();
    	}
    
    	public function initialize() {
    		add_filter('style_loader_src', array($this, 'replace_version'), 10);
    		add_filter('script_loader_src', array($this, 'replace_version'), 10);
    		add_filter('stylesheet_uri', array($this, 'replace_version'), 10);
    	}
    
    	public function on_template_redirect() {
    		$this->default_version = @filemtime(get_stylesheet_directory().'/style.css');
    	}
    
    	private function get_version($url) {
    		if(0 === strpos($url, $this->root_url)) {
    			$parts = parse_url($url);
    			$file_path = str_replace(site_url('/'), ABSPATH, $parts['scheme'].'://'.$parts['host'].$parts['path']);
    			if(	!($version = @filemtime($file_path)) ) {
    				$version = $this->default_version;
    			}
    			return $version;
    		}
    		return false;
    	}
    
    	public function replace_version($src) {
    		if( $new_version = $this->get_version($src) ) {
    			return add_query_arg('ver', $new_version, $src);
    		}
    		return $src;
    	}
    }
    add_action('init', array(new CDN_VersionAssets(), 'initialize'));