Advertisement
Guest User

JSON Fix for Square Thumbs for User Photo

a guest
Aug 20th, 2014
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 15.00 KB | None | 0 0
  1. <?php
  2. /*
  3. Plugin Name: Square Thumbnails for User Photo
  4. Plugin URI: http://wordpress.org/extend/plugins/square-thumbnails-for-user-photo/
  5. Description: Extends the <a href="http://wordpress.org/extend/plugins/user-photo/">User Photo plugin</a> to allow the generation of square thumbnails. (Requires the User Photo plugin, WILL NOT WORK otherwise.)
  6. Author: Simon Wheatley
  7. Version: 1.2.1
  8. Author URI: http://simonwheatley.co.uk/wordpress/
  9. */
  10.  
  11. /*  Copyright 2008 Simon Wheatley
  12.  
  13.     This program is free software; you can redistribute it and/or modify
  14.     it under the terms of the GNU General Public License as published by
  15.     the Free Software Foundation; either version 2 of the License, or
  16.     (at your option) any later version.
  17.  
  18.     This program is distributed in the hope that it will be useful,
  19.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.     GNU General Public License for more details.
  22.  
  23.     You should have received a copy of the GNU General Public License
  24.     along with this program; if not, write to the Free Software
  25.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  26.  
  27. */
  28.  
  29. require_once( dirname (__FILE__) . '/plugin.php' );
  30. require_once( ABSPATH . 'wp-includes/class-json.php' );
  31.  
  32. define( 'ST_MAX_SIDE', 600 ); // The max side dimension we will present for cropping
  33. define( 'ST_IMAGE_JPEG_QUALITY', 85 ); // The JPEG quality to use
  34. define( 'ST_SQUARE_DIMENSION', 80 ); // The length of the sides of the square
  35.  
  36. /**
  37.  *
  38.  * @package default
  39.  * @author Simon Wheatley
  40.  **/
  41. class UserPhotoSquareThumbnails extends UserPhotoSquareThumbnails_Plugin
  42. {
  43.     protected $admin_notices = array();
  44.    
  45.     function UserPhotoSquareThumbnails()
  46.     {
  47.         $this->register_plugin ( 'square-thumbs-for-user-photo', __FILE__);
  48.  
  49.         $this->add_action( 'init', null, 9 );
  50.         $this->add_action( 'admin_notices' );
  51.         // User Photo resizes the image in place in the tmp directory,
  52.         // so we must get in there before that in the chain of actions.
  53.         $this->add_action( 'profile_update' );
  54.         // Check the thumbnail when on your profile, or other people's profiles
  55.         $this->add_action( 'load-profile.php', 'maybe_add_crop_dialog' );
  56.         $this->add_action( 'load-user-edit.php', 'maybe_add_crop_dialog' );
  57.         // Custom action, use do_action( 'stfup_load_profile' ); BEFORE loading the admin header in any custom profile pages
  58.         $this->add_action( 'stfup_load_profile', 'maybe_add_crop_dialog' );
  59.         // Answer crop dialog AJAX calls
  60.         $this->add_action( 'wp_ajax_crop_widget_html', 'crop_widget_html' );
  61.         $this->add_action( 'wp_ajax_crop_commit', 'crop_commit' );
  62.     }
  63.    
  64.     public function init()
  65.     {
  66.         $this->sanity_checks();
  67.     }
  68.    
  69.     public function admin_notices()
  70.     {
  71.         foreach ( $this->admin_notices AS $msg ) {
  72.             $this->print_admin_notice( $msg );
  73.         }
  74.     }
  75.    
  76.     protected function add_admin_notice( $msg )
  77.     {
  78.         $this->admin_notices[] = $msg;
  79.     }
  80.    
  81.     protected function print_admin_notice( $msg )
  82.     {
  83.         echo '<div class="plugin-update">';
  84.         echo $msg;
  85.         echo '</div>';
  86.     }
  87.    
  88.     public function profile_update( $user_id )
  89.     {
  90.         $this->process_image_upload( $user_id );
  91.     }
  92.    
  93.     protected function process_image_upload( $user_id )
  94.     {
  95.         // Process the image upload.
  96.         // We validate for sanity/security only, all messaging to the
  97.         // user is left to the User Photo plugin. We're purely here
  98.         // to get a copy of the original uploaded file before
  99.         // any resizing.
  100.        
  101.         $image_name = @ $_FILES['userphoto_image_file']['name'];
  102.         // Check whether there appears to be an uploaded file
  103.         if ( ! $image_name ) return;
  104.        
  105.         $image_tmp_name = @ $_FILES['userphoto_image_file']['tmp_name'];
  106.         // Check this is a actual successfully uploaded file
  107.         if ( ! is_uploaded_file( $image_tmp_name ) ) return;
  108.        
  109.         $image_error = @ $_FILES['userphoto_image_file']['error'];
  110.         // If there's an upload error, we'll leave it to User Photo to deal with that
  111.         if ( $image_error ) return;
  112.        
  113.         // All looking OK. Let's grab that file.
  114.         $destination_dir = $this->userphoto_dir_path();
  115.        
  116.         // Attempt to make the dir if necessary
  117.         if ( ! file_exists( $destination_dir ) && ! mkdir( $destination_dir, 0777 ) ) {
  118.             // MKDIR failed :(
  119.             // We can take advantage of the User Photo localisations here. Which is nice.
  120.             $this->add_admin_notice( __("The userphoto upload content directory does not exist and could not be created. Please ensure that you have write permissions for the /wp-content/uploads/ directory.", 'user-photo') );
  121.         }
  122.        
  123.         $userdata = get_userdata( $user_id );
  124.         $destination_filename = preg_replace( '/^.+(?=\.\w+$)/', $userdata->user_nicename . '.original', $_FILES['userphoto_image_file']['name'] );
  125.         $destination_path = $destination_dir . '/' . $destination_filename;
  126.        
  127.         // We've already checked that this is a non-dodgy uploaded file (see is_uploaded_file above)
  128.         // so it's safe to use copy rather than move_uploaded_file.
  129.         copy( $image_tmp_name, $destination_path );
  130.        
  131.         // Resize the photo if necessary
  132.         if ( $this->side_longer_than( ST_MAX_SIDE, $destination_path ) ) {
  133.             // Scale the image.
  134.             list($w, $h, $format) = getimagesize( $destination_path );
  135.             $xratio = ST_MAX_SIDE / $w;
  136.             $yratio = ST_MAX_SIDE / $h;
  137.             $ratio = min( $xratio, $yratio );
  138.             $targetw = (int) $w * $ratio;
  139.             $targeth = (int) $h * $ratio;
  140.  
  141.             $src_gd = $this->image_create_from_file( $destination_path );
  142.             assert( $src_gd );
  143.             $target_gd = imagecreatetruecolor( $targetw, $targeth );
  144.             imagecopyresampled ( $target_gd, $src_gd, 0, 0, 0, 0, $targetw, $targeth, $w, $h );
  145.             // create the initial copy from the original file
  146.             // also overwrite the filename (in case the extension isn't accurate)
  147.             $destination_filename = preg_replace( '/^.+(?=\.\w+$)/', $userdata->user_nicename . '.original', $_FILES['userphoto_image_file']['name'] );
  148.             $destination_filename = $this->strip_filename_extension( $destination_filename );
  149.             if ( $format == IMAGETYPE_GIF ) {
  150.                 $destination_filename .= ".gif";
  151.                 $destination_path = $destination_dir . '/' . $destination_filename;
  152.                 imagegif( $target_gd, $destination_path );
  153.             } elseif ( $format == IMAGETYPE_JPEG ) {
  154.                 $destination_filename .= ".jpg";
  155.                 $destination_path = $destination_dir . '/' . $destination_filename;
  156.                 imagejpeg( $target_gd, $destination_path, ST_IMAGE_JPEG_QUALITY );
  157.             } elseif ( $format == IMAGETYPE_PNG ) {
  158.                 $destination_filename .= ".gif";
  159.                 $destination_path = $destination_dir . '/' . $destination_filename;
  160.                 imagepng( $target_gd, $destination_path );
  161.             } else {
  162.                 wp_die( 'Unknown image type. Please upload a JPEG, GIF or PNG.' );
  163.             }
  164.         }
  165.  
  166.         // We won't store the whole path, as things might move around
  167.         update_usermeta( $user_id, "squarethumbs_original_file", $destination_filename );
  168.     }
  169.        
  170.     public function maybe_add_crop_dialog()
  171.     {
  172.         $profileuser = $this->get_profileuser();
  173.        
  174.         // Check if the thumbnail even exists
  175.         // Construct the filename
  176.         $thumbnail = $profileuser->userphoto_thumb_file;
  177.         // If the location wasn't stored, then we need not continue
  178.         if ( ! $thumbnail ) return;
  179.        
  180.         // Check if the existing thumbnail is square
  181.         $filename = $this->userphoto_dir_path() . '/' . $thumbnail;
  182.        
  183.         // Check the file exists, and hasn't been deleted or moved for some reason
  184.         if ( ! file_exists( $filename ) ) return;
  185.        
  186.         // If it's already square, then we can remove the image
  187.         if ( $this->thumbnail_is_square( $filename ) ) {
  188.             $this->remove_original_image();
  189.             return;
  190.         }
  191.  
  192.         // ...obviously not square.... hmmm
  193.        
  194.         // Does an original photo exist? Otherwise we've no chance.
  195.         $original_file = get_usermeta( $profileuser->ID, 'squarethumbs_original_file' );
  196.         $original_path = $this->userphoto_dir_path() . '/' . $original_file;
  197.         if ( ! $original_file || ! file_exists( $original_path ) ) {
  198.             // OK. This is awkward, we're going to have to ask the user to re-upload their pic
  199.             $this->add_admin_notice( __("<strong>The user photo you have previously uploaded is not square.</strong> Please reupload your user photo below, and you will then be able to choose a square crop of it for the thumbnail.") );
  200.             return;
  201.         }
  202.                
  203.         // We'll add the crop dialog.
  204.         // Add the JS. jQuery, imgAreaSelect and our own jQuery reliant script
  205.         wp_enqueue_script( 'jquery' ); // Probably present, but let's be sure
  206.         $image_area_select_js = $this->url() . '/js/jquery.imgareaselect-0.5.min.js';
  207.         wp_enqueue_script( 'square_thumbs_img_area_select', $image_area_select_js );
  208.         $main_js = $this->url() . '/js/crop-dialog.js';
  209.         wp_enqueue_script( 'square_thumbs_crop_dialog', $main_js );
  210.        
  211.         // Add the CSS
  212.         $main_css = $this->url() . '/css/crop-dialog.css';
  213.         wp_enqueue_style( 'square_thumbs_crop_dialog', $main_css );
  214.     }
  215.    
  216.     public function crop_commit()
  217.     {
  218.         $profileuser = $this->get_profileuser();
  219.         $original_file = get_usermeta( $profileuser->ID, 'squarethumbs_original_file' );
  220.  
  221.         $img_src = $this->userphoto_dir_url() . '/' . $original_file;
  222.         $img_path = $this->userphoto_dir_path() . '/' . $original_file;
  223.  
  224.         $x1 = (int) @ $_POST[ 'x1' ];
  225.         $y1 = (int) @ $_POST[ 'y1' ];
  226.         $x2 = (int) @ $_POST[ 'x2' ];
  227.         $y2 = (int) @ $_POST[ 'y2' ];
  228.         $width = (int) @ $_POST[ 'width' ];
  229.         $height = (int) @ $_POST[ 'height' ];
  230.        
  231.         $thumbnail_dimension = get_option( 'userphoto_thumb_dimension' );
  232.  
  233.         $userdata = get_userdata( $profileuser->ID );
  234.         $target_path = $this->userphoto_dir_path() . '/' . $userdata->userphoto_thumb_file;
  235.  
  236.         // Read into GD
  237.         $success = true;
  238.         $src_gd = $this->image_create_from_file( $img_path );
  239.         $target_gd = imagecreatetruecolor( $thumbnail_dimension, $thumbnail_dimension );
  240.         if( $success && ! $target_gd ) {
  241.             $success = false;
  242.         }
  243.         if( ! imagecopyresampled ( $target_gd, $src_gd, 0, 0, $x1, $y1, $thumbnail_dimension, $thumbnail_dimension, $width, $height ) ) {
  244.             $success = false;
  245.         }
  246.  
  247.         // Add some uniqueness into the filename to defeat caching
  248.         $thumb_filename = $this->strip_filename_extension( $userdata->userphoto_thumb_file );
  249.         $thumb_filename_prefix = $thumb_filename; // We'll use this to delete old ones.
  250.         $thumb_filename .= "." . uniqid();
  251.         $thumb_filename .= ".jpg"; // We're always saving a JPG
  252.         // Remove old thumbnail file
  253.         unlink( $target_path );
  254.         $this->unlink_files_prefixed_with( $thumb_filename_prefix );
  255.         update_usermeta( $profileuser->ID, 'userphoto_thumb_file', $thumb_filename );
  256.         // Overwrite target path
  257.         $target_path = $this->userphoto_dir_path() . '/' . $thumb_filename;
  258.        
  259.         if( $success && ! imagejpeg( $target_gd, $target_path, ST_IMAGE_JPEG_QUALITY ) ) {
  260.             $success = false;
  261.         }
  262.        
  263.         // Setup User meta data for new thumbnail size
  264.         update_usermeta( $profileuser->ID, 'userphoto_thumb_height', $thumbnail_dimension );
  265.         update_usermeta( $profileuser->ID, 'userphoto_thumb_width', $thumbnail_dimension );
  266.  
  267.         // Data to send
  268.         $data = array();
  269.         $data['success'] = $success;
  270.         $data['thumbnail_src'] = $this->userphoto_dir_url() . '/' . $thumb_filename;
  271.        
  272.         // Make JSON
  273.         $json = new Services_JSON();
  274.         echo $json->encode( $data );
  275.         exit; // Don't care for anything else getting in on this action
  276.     }
  277.    
  278.     protected function unlink_files_prefixed_with( $prefix )
  279.     {
  280.         $dir_path = $this->userphoto_dir_path();
  281.         if ( $dir_handle = opendir( $dir_path ) ) {
  282.             while ( false !== ( $file = readdir( $dir_handle ) ) ) {
  283.                 if ( stripos( $file, $prefix ) === 0  ) {
  284.                     unlink( $dir_path . '/' . $file );
  285.                 }
  286.             }
  287.             closedir( $dir_handle );
  288.         }
  289.     }
  290.    
  291.     protected function strip_filename_extension( $filename )
  292.     {
  293.         $pos = strrpos($filename, '.');
  294.         if ($pos > 0) {
  295.             return substr($filename, 0, $pos);
  296.         } else {
  297.             return $filename;
  298.         }
  299.     }
  300.  
  301.    
  302.     // The following was lifted from:
  303.     // http://uk.php.net/manual/en/ref.image.php
  304.     // With minor mods: ON error now returns false.
  305.     // No longer accepts xbms (silly format)
  306.     protected function image_create_from_file( $filename )
  307.     {
  308.         static $image_creators;
  309.  
  310.         if (!isset($image_creators)) {
  311.             $image_creators = array(
  312.                 1  => "imagecreatefromgif",
  313.                 2  => "imagecreatefromjpeg",
  314.                 3  => "imagecreatefrompng"
  315.             );
  316.         }
  317.  
  318.         list( $w, $h, $file_type ) = getimagesize($filename);
  319.         if ( isset( $image_creators[$file_type] ) ) {
  320.             $image_creator = $image_creators[ $file_type ];
  321.             if ( function_exists( $image_creator ) ) {
  322.                 return $image_creator( $filename );
  323.             }
  324.         }
  325.  
  326.         // Changed to return false on error
  327.         return false;
  328.     }
  329.    
  330.     protected function side_longer_than( $dimension, $filename )
  331.     {
  332.         list( $width, $height ) = getimagesize( $filename );
  333.         return ( ( $width > $dimension ) || ( $height > $dimension ) );
  334.     }
  335.    
  336.     protected function thumbnail_is_square( $filename )
  337.     {
  338.         list( $width, $height ) = getimagesize( $filename );
  339.         return ( $width == $height );
  340.     }
  341.    
  342.     protected function get_profileuser()
  343.     {
  344.         $user_id = (int) @ $_REQUEST[ 'user_id' ];
  345.        
  346.         if ( ! $user_id ) {
  347.             $current_user = wp_get_current_user();
  348.             $user_id = $current_user->ID;
  349.         }
  350.         return get_user_to_edit( $user_id );
  351.     }
  352.    
  353.     public function crop_widget_html()
  354.     {
  355.         $profileuser = $this->get_profileuser();
  356.         $original_file = get_usermeta( $profileuser->ID, 'squarethumbs_original_file' );
  357.  
  358.         $img_src = $this->userphoto_dir_url() . '/' . $original_file;
  359.  
  360.         // Get the image size
  361.         $img_path = $this->userphoto_dir_path() . '/' . $original_file;
  362.         $img_info = getimagesize( $img_path );
  363.         list( $img_width, $img_height ) = $img_info;
  364.        
  365.         $thumbnail_dimension = get_option( 'userphoto_thumb_dimension' );
  366.  
  367.         $vars = array(
  368.             'img_src' => $img_src,
  369.             'img_height' => $img_height,
  370.             'img_width' => $img_width,
  371.             'thumbnail_dimension' => $thumbnail_dimension
  372.         );
  373.         $html_src = $this->capture_admin ( 'crop_widget_html', $vars );
  374.        
  375.         // Data to send
  376.         $data = array();
  377.         $data['html_src'] = $html_src;
  378.         $data['thumbnail_dimension'] = $thumbnail_dimension;
  379.         $data['img_height'] = $img_height;
  380.         $data['img_width'] = $img_width;
  381.  
  382.         // Make JSON
  383.         $json = new Services_JSON();
  384.         echo $json->encode( $data );
  385.         exit; // Don't care for anything else getting in on this action
  386.     }
  387.  
  388.     protected function escape_for_js( $string )
  389.     {
  390.         return js_escape( $string );
  391.     }
  392.    
  393.     protected function remove_original_image()
  394.     {
  395.         // SWTODO: Remove original image method
  396.     }
  397.    
  398.     protected function userphoto_dir_path()
  399.     {
  400.         $upload_dir = wp_upload_dir();
  401.         return $upload_dir[ 'basedir' ] . "/userphoto";
  402.     }
  403.    
  404.     protected function userphoto_dir_url()
  405.     {
  406.         $upload_dir = wp_upload_dir();
  407.         return $upload_dir[ 'baseurl' ] . "/userphoto";
  408.     }
  409.    
  410.     protected function sanity_checks()
  411.     {
  412.         // Check that the User Photo plugin is present
  413.         if ( ! function_exists( 'userphoto__get_userphoto' ) || ! defined( 'USERPHOTO_PLUGIN_IDENTIFIER' ) ) {
  414.             $this->add_admin_notice( __( 'The <em>Square Thumbnails for User Photo</em> plugin requires the <a href="http://wordpress.org/extend/plugins/user-photo/"><em>User Photo plugin</em></a> to be installed.' ) );
  415.         }
  416.     }
  417. }
  418.  
  419. /**
  420.  * Instantiate the plugin
  421.  *
  422.  * @global
  423.  **/
  424.  
  425. $UserPhotoSquareThumbnails = new UserPhotoSquareThumbnails();
  426.  
  427. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement