Created
January 8, 2013 13:56
-
-
Save anonymous/4483994 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* Plugin Name: PB Responsive Images | |
* Plugin URI: http://wordpress.org/extend/plugins/pb-responsive-images/ | |
* Description: Adds support for the proposed responsive image format in post content, and helper functions for theme authors. | |
* Author: Phenomblue | |
* Version: 1.3 | |
* Author URI: http://www.phenomblue.com/ | |
* | |
* ------------------------------------- | |
* | |
* @package PB Responsive Images | |
* @category Plugin | |
* @author Jacob Dunn | |
* @link http://www.phenomblue.com/ Phenomblue | |
* @version 1.3 | |
* | |
* ------------------------------------- | |
* | |
* For Further information, see http://www.w3.org/community/respimg/ | |
* | |
* ------------------------------------- | |
* | |
* PB Responsive Images is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
/* LESS EDITING BELOW */ | |
define('RIP_VERSION', '1.3'); | |
define('RIP_FILE', __FILE__); | |
define('RIP_BASENAME', plugin_basename(RIP_FILE)); | |
// Activation/Deactivation | |
register_activation_hook( RIP_FILE, 'RIP::activate' ); | |
register_deactivation_hook( RIP_FILE, 'RIP::deactivate' ); | |
// Includes | |
require_once(dirname(__FILE__).'/options.php'); | |
require_once(dirname(__FILE__).'/shortcode.php'); | |
require_once(dirname(__FILE__).'/config.php'); | |
// Initialize | |
RIP::get_manager(); | |
class RIP{ | |
private static $_singleton; | |
public static function get_manager() | |
{ | |
if(!isset(self::$_singleton)){ | |
self::$_singleton = new RIP(); | |
} | |
return self::$_singleton; | |
} | |
public static function get_picture($image,$options = false) | |
{ | |
$manager = self::get_manager(); | |
/* We can pass in an options object as the primary argument, | |
* but only if we're providing sources. | |
* | |
* In that case, the second argument is our main image wrapper attributes | |
*/ | |
if(is_a($image,'RIPOptions') || (is_array($image) && isset($image[0]['src']))){ | |
$attributes = $options; | |
$options = $image; | |
$image = false; | |
} | |
$options = $manager->parse_options($options); | |
$image = $manager->parse_image($image); | |
return ($image === false && isset($options->sources)) | |
? $manager->format_sources($options,$attributes) | |
: $manager->format_content_image($image,$options)->output; | |
} | |
public static function set_options($options) | |
{ | |
$manager = self::get_manager(); | |
$manager->_set_options($options); | |
} | |
public static function reset_options() | |
{ | |
$manager = self::get_manager(); | |
$manager->_reset_options(); | |
} | |
public static function activate() | |
{ | |
add_option('rip_options',array(),'','yes'); | |
} | |
public static function deactivate() | |
{ | |
global $wp_rewrite; | |
delete_option('rip_options'); | |
$wp_rewrite->flush_rules(); | |
} | |
/* End Static Methods */ | |
public function init() | |
{ | |
add_filter('the_content',array(&$this,'the_content')); | |
if(RIPOptions::options()->enable_scripts) | |
wp_enqueue_script('picturefill'); | |
if(RIPOptions::options()->disable_wordpress_resize){ | |
add_filter('option_large_size_h',array(&$this,'disable_resize_options')); | |
add_filter('option_large_size_w',array(&$this,'disable_resize_options')); | |
add_filter('option_medium_size_h',array(&$this,'disable_resize_options')); | |
add_filter('option_medium_size_w',array(&$this,'disable_resize_options')); | |
add_filter('option_thumbnail_size_h',array(&$this,'disable_resize_options')); | |
add_filter('option_thumbnail_size_w',array(&$this,'disable_resize_options')); | |
} | |
} | |
public function disable_resize_options($value) | |
{ | |
// If this is the media page, return the value - we don't want to overwrite what's stored in the database | |
if(function_exists('get_current_screen') && get_current_screen()->id == 'options-media') return $value; | |
// Returning 0 for every set size forces WordPress to not resize images | |
return 0; | |
} | |
public function generate_rewrite_rules() | |
{ | |
global $wp_rewrite; | |
$options = RIPOptions::options(); | |
// Need to check to see if we haven't set a base yet | |
if($options->slir_base == ''){ | |
$options->slir_base = ($wp_rewrite->using_mod_rewrite_permalinks()) | |
? '{base-url}/slir/' | |
: '{plugin-url}/slir/?r='; | |
} | |
if($wp_rewrite->using_mod_rewrite_permalinks()){ | |
$base = str_replace(site_url().'/','',$options->slir_base).'(.*)$'; | |
$rules = array( | |
$base => 'wp-content/plugins/pb-responsive-images/slir/index.php?r=$1' | |
); | |
$wp_rewrite->non_wp_rules = $rules + $wp_rewrite->non_wp_rules; | |
} | |
} | |
public function the_content($content,$options = false) | |
{ | |
global $post; | |
if(is_feed()) return $content; | |
$options = $this->parse_options($options); | |
$images = $this->scrub_for_images($content,$options); | |
if($images) foreach ($images as $image) { | |
$content = str_replace($image->original, $image->output, $content); | |
} | |
return $content; | |
} | |
public function parse_image($image){ | |
// False may be passed in if we're bypassing slir to use our own images | |
if($image === false) return false; | |
// Can pass an image, or an array with image attibutes | |
if(is_array($image)){ | |
// Create an object for formatting | |
return (object)array( | |
'original'=>sprintf('<img src="%1$s" %2$s >', | |
$image['src'], | |
$this->attributes_to_string($image) | |
), | |
'attributes'=>$image | |
); | |
}else{ | |
return $this->scrub_image($image); | |
} | |
} | |
/* End Public Methods */ | |
private $options; | |
private function __construct() | |
{ | |
$this->options = RIPOptions::options(); | |
$this->register_scripts(); | |
add_action('init',array(&$this,'init')); | |
add_action('generate_rewrite_rules',array(&$this,'generate_rewrite_rules')); | |
} | |
private function _set_options($options) | |
{ | |
$this->options = $this->parse_options($options); | |
} | |
private function _reset_options() | |
{ | |
$this->options = RIPOptions::options(); | |
} | |
private function register_scripts() | |
{ | |
wp_register_script( 'matchmedia', | |
plugins_url('scripts/matchmedia.js',RIP_FILE), | |
array(), | |
RIP_VERSION, | |
false); | |
wp_register_script( 'picturefill', | |
plugins_url('scripts/picturefill.js',RIP_FILE), | |
array('matchmedia'), | |
RIP_VERSION, | |
false); | |
} | |
private function scrub_for_images($content,$options) | |
{ | |
$results = preg_match_all('#<img([^\>]*)>(?![^<]*</(noscript|picture)>)#mi', $content, $matches); | |
if($results){ | |
$images = array(); | |
foreach ($matches[0] as $key => $original) { | |
$image = $this->scrub_image($original); | |
array_push($images, $this->format_content_image($image,$options)); | |
} | |
return $images; | |
} | |
return false; | |
} | |
private function scrub_image($original) | |
{ | |
$image = array('original'=>$original,'attributes'=>array()); | |
preg_match_all('!([^\s]+)=[\'"]([^\'"]*)[\'"]!mi',$original,$attributes,PREG_SET_ORDER); | |
foreach($attributes as $attribute){ | |
$image['attributes'][$attribute[1]] = $attribute[2]; | |
} | |
return (object)$image; | |
} | |
private function format_content_image($image,$options) | |
{ | |
$image->output = $image->original; | |
// If no src | |
if(!$image->attributes['src']) return $image; | |
// If we have a root-relative link, sub in the site_url | |
if(strpos($image->attributes['src'], '/') === 0) | |
$image->attributes['src'] = site_url() . $image->attributes['src']; | |
// If we have a relative link, figure out the root-relative url | |
if(strpos($image->attributes['src'], 'http') !== 0) | |
$image->attributes['src'] = $this->convert_to_root_relative($image->attributes['src']); | |
// Make sure it's on our server | |
if(strpos($image->attributes['src'],site_url()) === false) return $image; | |
// Make sure this isn't flagged as non-responsive | |
if($image->attributes['class'] && strpos($image->attributes['class'], 'non-responsive') !== false) return $image; | |
// Compile the Picture tag set | |
$sources = array(); | |
foreach ($options->formats as $key => $format) { | |
$attributes = array(); | |
if(preg_match('#min-device-pixel-ratio:(\d+)#i', $format->media, $pixel_ratio)){ | |
$pixel_ratio = floatval($pixel_ratio[1]); | |
// Set the width for this element | |
if(preg_match('#w(\d+)#i', $format->query, $dest_width)){ | |
$dest_width = floatval($dest_width[1]); | |
// Make sure the initial image width is not too small for this density | |
if(!isset($image->attributes['width']) || $dest_width < intval($image->attributes['width'])) | |
$attributes['width'] = ($dest_width / $pixel_ratio); | |
} | |
} | |
// Our base path | |
$source = sprintf('%1$s%2$s%3$s', | |
$options->slir_base, | |
$format->query, | |
str_replace(site_url(), '', $image->attributes['src']) | |
); | |
// Our base attributes | |
$attributes['src'] = $source; | |
$attributes['media'] = $format->media; | |
// Add our source | |
array_push($sources,sprintf('<span %1$s></span>',$this->attributes_to_string($attributes,'','span'))); | |
// Add the fallback, if requested | |
if($format->fallback) | |
array_push($sources,sprintf('<noscript><img src="%1$s" %2$s></noscript>', | |
$source, | |
$this->attributes_to_string($image->attributes,'src'))); | |
} | |
$image->output = sprintf('<span data-picture data-alt="%3$s" %1$s>%2$s</span>', | |
$this->attributes_to_string($image->attributes,'src,alt','span'), | |
implode("\n", $sources), | |
$image->attributes['alt']); | |
return $image; | |
} | |
private function format_sources($options,$main_attributes = false) | |
{ | |
// Compile the Picture tag set | |
$sources = array(); | |
foreach ($options->sources as $key => $format) { | |
array_push($sources,sprintf('<span data-src="%1$s" data-media="%2$s" %3$s></span>', | |
$format->src, | |
$format->media, | |
$this->attributes_to_string($format->attributes,false,'span'))); | |
if($format->fallback){ | |
// We need to pull alt in | |
$format->attributes['alt'] = $main_attributes['alt']; | |
array_push($sources,sprintf('<noscript><img src="%1$s" %2$s></noscript>', | |
$format->src, | |
$this->attributes_to_string($format->attributes))); | |
} | |
} | |
return sprintf('<span data-picture %2$s>%1$s</span>', | |
implode("\n", $sources), | |
$this->attributes_to_string($main_attributes,false,'span')); | |
} | |
private function convert_to_root_relative($src){ | |
$url_parts = explode('/', trim ( $this->page_url() ,'/' )); | |
while(strpos($src, '../') === 0 && $url_parts != null){ | |
array_pop($url_parts); | |
$src = substr($src, 3); | |
} | |
$src = implode('/', $url_parts) . '/' . $src; | |
return $src; | |
} | |
private function page_url() { | |
$pageURL = 'http'; | |
if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";} | |
$pageURL .= "://"; | |
if ($_SERVER["SERVER_PORT"] != "80") { | |
$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"]; | |
} else { | |
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]; | |
} | |
return $pageURL; | |
} | |
private $valid_attributes = array( | |
'global'=>array('accesskey','class','contenteditable','contextmenu','dir','draggable','dropzone','hidden','id','lang','spellcheck','style','tabindex','title'), | |
'img'=>array('align','alt','border','crossorigin','height','hspace','ismap','longdesc','src','usemap','vspace','width') | |
); | |
private function attributes_to_string($attributes,$exclude = false,$element = 'img'){ | |
$output = array(); | |
$exclude = ($exclude === false) ? array('src') : explode(',', $exclude); | |
foreach ($attributes as $key => $value) { | |
$format = ( | |
in_array($key, $this->valid_attributes['global']) || | |
(isset($this->valid_attributes[$element]) && in_array($key, $this->valid_attributes[$element])) | |
) | |
? '%1$s="%2$s"' | |
: 'data-%1$s="%2$s"'; | |
if(!in_array($key, $exclude)) array_push($output,sprintf($format,$key,$value)); | |
} | |
return implode(' ', $output); | |
} | |
private function parse_options($options){ | |
// Can pass an array of formats, or a RIPOPtions object | |
if(is_array($options) && count($options) > 0){ | |
$rip_options = new RIPOptions(); | |
if(isset($options[0]['query'])) | |
$rip_options->formats = $options; | |
else if(isset($options[0]['src'])) | |
$rip_options->sources = $options; | |
$options = $rip_options; | |
} | |
if($options === false || !is_a($options,'RIPOptions')) | |
$options = $this->options; | |
return $options; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment