Last active
August 29, 2015 14:04
-
-
Save ericnicolaas/2d7c7db263550aeeb423 to your computer and use it in GitHub Desktop.
Wordpress Customizer Retina Image Control: Sofa_Customizer_Retina_Image_Control class
This file contains 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 | |
if ( ! defined( 'ABSPATH' ) ) { | |
exit; // Exit if accessed directly | |
} | |
if ( ! class_exists( 'WP_Customize_Control' ) ) return; | |
if ( ! class_exists( 'Sofa_Customizer_Retina_Image_Control' ) ) : | |
/** | |
* Adds a new control for retina images. | |
* | |
* @class Sofa_Customizer_Retina_Image_Control | |
* @author Studio 164a | |
* @category Admin | |
* @package Crafted/Admin/Customizer/Controls | |
* @since 1.0 | |
*/ | |
class Sofa_Customizer_Retina_Image_Control extends WP_Customize_Image_Control { | |
/** | |
* @access public | |
* @var string | |
*/ | |
public $type = 'image'; | |
/** | |
* Constructor. | |
* | |
* If $args['settings'] is not defined, use the $id as the setting ID. | |
* | |
* @uses WP_Customize_Image_Control::__construct() | |
* @param WP_Customize_Manager $manager | |
* @param string $id | |
* @param array $args | |
* @return void | |
* @since 1.0 | |
*/ | |
public function __construct( $manager, $id, $args ) { | |
parent::__construct( $manager, $id, $args ); | |
/** | |
* Usually, this control will be instantiated during the customize_register | |
* event, so if that is the current filter, call the method directly. | |
*/ | |
if ( current_filter() == 'customize_register' ) { | |
$this->customize_register( $manager ); | |
} | |
/** | |
* If the customize_register action has not taken place yet, register the | |
* hook. | |
*/ | |
elseif ( ! did_action( 'customize_register' ) ) { | |
add_action('customize_register', array(&$this, 'customize_register')); | |
} | |
/** | |
* The customize_register action has come and gone, so this control will fail. | |
*/ | |
else { | |
wp_die( __('Sofa_Customizer_Retina_Image_Control must be instantiated before | |
or during the customize_register action.', 'crafted') ); | |
} | |
add_action('customize_save', array(&$this, 'customize_save')); | |
add_action('customize_save_after', array(&$this, 'customize_save_after')); | |
} | |
/** | |
* Register an extra control & setting for any setting using this control. | |
* | |
* @see customize_register hook | |
* | |
* @param WP_Customize_Manager $wp_customize | |
* @return void | |
* @since 1.0 | |
*/ | |
public function customize_register($wp_customize) { | |
$checkbox_id = $this->id . '_is_retina'; | |
$wp_customize->add_setting( $checkbox_id, array( | |
'transport' => 'postMessage' | |
) ); | |
$wp_customize->add_control( $checkbox_id, array( | |
'settings' => $checkbox_id, | |
'label' => __( 'Is this image retina-ready?', 'crafted' ), | |
'section' => $this->section, | |
'priority' => $this->priority + 0.2, | |
'type' => 'checkbox' | |
) ); | |
} | |
/** | |
* Before the customizer has finished saving each of the fields, store the current image state. | |
* | |
* @see customize_save hook | |
* @see Crafted_Customizer::set_current_image_state() | |
* | |
* @param WP_Customize_Manager $wp_customize | |
* @return void | |
* @access public | |
* @since 1.0 | |
*/ | |
public function customize_save(WP_Customize_Manager $wp_customize) { | |
$this->set_current_image_state(); | |
} | |
/** | |
* After the customizer has finished saving each of the fields, check whether we're using a retina image. | |
* | |
* @see customize_save_after hook | |
* | |
* @param WP_Customize_Manager $wp_customize | |
* @return void | |
* @access public | |
* @since 1.0 | |
*/ | |
public function customize_save_after(WP_Customize_Manager $wp_customize) { | |
/** | |
* If the image has changed, update the meta we store for the image. | |
*/ | |
if ( $this->is_image_changed() ) { | |
$this->update_image( get_theme_mod( $this->id ) ); | |
} | |
} | |
/** | |
* Save the image's ID and dimensions. | |
* | |
* If the image is optimised for retina, create a non-retina copy. | |
* | |
* @param string $image_url | |
* @return void | |
* @access private | |
* @since 1.0 | |
*/ | |
private function update_image($image_url) { | |
/** | |
* Save the image's post ID, width and height to the theme settings. | |
*/ | |
$image_id = sofa_get_image_id_from_url( $image_url ); | |
$image_meta = wp_get_attachment_metadata( $image_id ); | |
set_theme_mod( $this->id . '_id', $image_id ); | |
/** | |
* If the image is retina-optimised, create a non-retina copy. | |
*/ | |
$non_retina = false; | |
if ( get_theme_mod( $this->id . '_is_retina' ) ) { | |
$non_retina = $this->create_non_retina_copy( $image_id, $image_meta ); | |
} | |
/** | |
* If the image is not retina optimised or something went wrong while trying | |
* to save the retina image, save the original image's dimensions. | |
*/ | |
if ( $non_retina === false || is_wp_error( $non_retina ) ) { | |
set_theme_mod( $this->id . '_width', $image_meta['width'] ); | |
set_theme_mod( $this->id . '_height', $image_meta['height'] ); | |
} | |
} | |
/** | |
* Create a non-retina version of the image. | |
* | |
* @param int $image_id The post ID of the original image. | |
* @param array image_meta An array containing the image's URL, width and height. | |
* @return WP_Error|array | |
* @access private | |
* @since 1.0 | |
*/ | |
private function create_non_retina_copy($image_id, array $image_meta) { | |
/** | |
* Retrieve the path to the image. | |
*/ | |
$image_path = get_attached_file( $image_id ); | |
/** | |
* Use the path to rewrite the filename. | |
*/ | |
$filename = explode( '/', $image_path ); | |
$filename = $filename[ count( $filename ) - 1 ]; | |
$resized_path = str_replace( $filename, 'resized_' . $filename, $image_path ); | |
/** | |
* Create a WP_Image_Editor instance of the image. | |
*/ | |
$resized_image = wp_get_image_editor( $image_path ); | |
/** | |
* Calculate the dimensions of the non-retina version. | |
* | |
* This will be half the retina version, rounded down and divided by two. | |
*/ | |
$resized_width = floor( $image_meta['width'] / 2 ); | |
$resized_height = floor( $image_meta['height'] / 2 ); | |
/** | |
* Resize the image and save it. | |
*/ | |
$resized_image->resize( $resized_width, $resized_height, true ); | |
$saved = $resized_image->save( $resized_path ); | |
/** | |
* If something went wrong during the save process, return the result, which | |
* will be an instance of WP_Error. | |
*/ | |
if ( is_wp_error( $saved ) ) { | |
return $saved; | |
} | |
/** | |
* Save the image's dimensions. | |
*/ | |
set_theme_mod( $this->id . '_width', $resized_width ); | |
set_theme_mod( $this->id . '_height', $resized_height ); | |
/** | |
* Save the non-retina version's image URL | |
*/ | |
$upload_dir = wp_upload_dir(); | |
$resized_url = str_replace( $upload_dir['path'], $upload_dir['url'], $saved['path'] ); | |
update_post_meta( $image_id, '_non_retina', $resized_url ); | |
/** | |
* Return the resized image. | |
*/ | |
return $saved; | |
} | |
/** | |
* A image's state is simply the contatenation of two values: its retina setting and its path. | |
* | |
* This is used to determine whether the image is changed when the customizer's settings are saved. | |
* | |
* @see Crafted_Customizer::set_current_image_state() | |
* @see Crafted_Customizer::is_image_changed() | |
* | |
* @return string The state as a simple string. | |
* @access private | |
* @since 1.0 | |
*/ | |
private function get_image_state() { | |
return get_theme_mod( $this->id . '_is_retina' ) . '_' . get_theme_mod( $this->id ); | |
} | |
/** | |
* This sets the private image_state property to the current image state. | |
* | |
* @see Crafted_Customizer::get_image_state() | |
* | |
* @return void | |
* @access private | |
* @since 1.0 | |
*/ | |
private function set_current_image_state() { | |
$this->image_state = $this->get_image_state(); | |
} | |
/** | |
* Checks whether the image state has changed since it was originally set. | |
* | |
* @see Crafted_Customizer::get_image_state() | |
* | |
* @return bool | |
* @access private | |
*/ | |
private function is_image_changed() { | |
return $this->get_image_state() != $this->image_state; | |
} | |
} | |
endif; // End class_exists check. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Very nice. How do I call the low resolution image or the retina one on my website?