File: //proc/1526/task/1529/cwd/shoetique/wp-content/plugins/manual-image-crop/lib/ManualImageCrop.php
<?php
/**
* Class responsible for all the logic
* @author tomasz
*
*/
class ManualImageCrop {
private static $instance;
/**
* Returns the instance of the class [Singleton]
* @return ManualImageCrop
*/
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new ManualImageCrop();
}
return self::$instance;
}
private function __construct() {
}
/**
* Enqueues all necessary CSS and Scripts
*/
public function enqueueAssets() {
add_thickbox();
wp_register_style( 'rct-admin', plugins_url('assets/css/mic-admin.css', dirname( __FILE__ ) ) );
wp_enqueue_style( 'rct-admin' );
wp_register_style( 'jquery-jcrop', plugins_url('assets/css/jquery.Jcrop.min.css', dirname( __FILE__ ) ) );
wp_enqueue_style( 'jquery-jcrop' );
wp_enqueue_script( 'jquery-color', plugins_url('assets/js/jquery.color.js', dirname( __FILE__ )), array( 'jquery') );
wp_enqueue_script( 'jquery-jcrop', plugins_url('assets/js/jquery.Jcrop.min.js', dirname( __FILE__ )), array( 'jquery') );
wp_enqueue_script( 'miccrop', plugins_url('assets/js/microp.js', dirname( __FILE__ )), array( 'jquery') );
}
/**
* Hooks Editor Links into proper places
*/
public function addEditorLinks() {
add_action( 'media_row_actions', array($this, 'addMediaEditorLinks'), 10, 2 );
add_action( 'admin_post_thumbnail_html', array($this, 'addCropFeatureImageEditorLink'), 10, 2 );
add_action( 'print_media_templates', array($this, 'addAttachementEditLink') );
add_action( 'admin_print_footer_scripts', array($this, 'addAfterUploadAttachementEditLink') );
}
/**
* Adds links in media library list
*/
public function addMediaEditorLinks($links, $post) {
if (preg_match('/image/', $post->post_mime_type)) {
$links['crop'] = '<a class="thickbox mic-link" rel="crop" title="Manual Image Crop" href="' . admin_url( 'admin-ajax.php' ) . '?action=mic_editor_window&postId=' . $post->ID . '">' . __('Crop','microp') . '</a>';
}
return $links;
}
/**
* Adds link below "Remove featured image" in post editing form
*/
public function addCropFeatureImageEditorLink($content, $post) {
$content .= '<a id="micCropFeatureImage" class="thickbox mic-link" rel="crop" title="' . __('Manual Image Crop','microp') . '" href="' . admin_url( 'admin-ajax.php' ) . '?action=mic_editor_window&postId=' . get_post_thumbnail_id($post) . '">' . __('Crop featured image','microp') . '</a>
<script>
setInterval(function() {
if (jQuery(\'#remove-post-thumbnail\').is(\':visible\')) {
jQuery(\'#micCropFeatureImage\').show();
}else {
jQuery(\'#micCropFeatureImage\').hide();
}
}, 200);
</script>';
return $content;
}
/**
* Adds link in the ligthbox media library
*/
public function addAttachementEditLink() { ?>
<script>
var micEditAttachemtnLinkAdded = false;
var micEditAttachemtnLinkAddedInterval = 0;
jQuery(document).ready(function() {
micEditAttachemtnLinkAddedInterval = setInterval(function() {
if (jQuery('.details .edit-attachment').length) {
try {
var mRegexp = /\?post=([0-9]+)/;
var match = mRegexp.exec(jQuery('.details .edit-attachment').attr('href'));
jQuery('.crop-image-ml.crop-image').remove();
jQuery('.details .edit-attachment').after( '<a class="thickbox mic-link crop-image-ml crop-image" rel="crop" title="<?php _e("Manual Image Crop","microp"); ?>" href="' + ajaxurl + '?action=mic_editor_window&postId=' + match[1] + '"><?php _e('Crop Image','microp') ?></a>' );
} catch (e) {
console.log(e);
}
}
if (jQuery('.attachment-details .details-image').length) {
try {
var postId = jQuery('.attachment-details').attr('data-id');
jQuery('.button.crop-image-ml.crop-image').remove();
jQuery('.button.edit-attachment').after( ' <a class="thickbox mic-link crop-image-ml crop-image button" rel="crop" title="<?php _e("Manual Image Crop","microp"); ?>" href="' + ajaxurl + '?action=mic_editor_window&postId=' + postId + '"><?php _e('Crop Image','microp') ?></a>' );
} catch (e) {
console.log(e);
}
}
}, 500);
});
</script>
<?php
}
/**
* Adds link in the ligthbox media library
*/
public function addAfterUploadAttachementEditLink() {
?>
<script>
var micEditAttachemtnLinkAdded = false;
var micEditAttachemtnLinkAddedInterval = 0;
jQuery(document).ready(function() {
micEditAttachemtnLinkAddedInterval = setInterval(function() {
if (jQuery('#media-items .edit-attachment').length) {
jQuery('#media-items .edit-attachment').each(function(i, k) {
try {
var mRegexp = /\?post=([0-9]+)/;
var match = mRegexp.exec(jQuery(this).attr('href'));
if (!jQuery(this).parent().find('.edit-attachment.crop-image').length && jQuery(this).parent().find('.pinkynail').attr('src').match(/upload/g)) {
jQuery(this).after( '<a class="thickbox mic-link edit-attachment crop-image" rel="crop" title="<?php _e("Manual Image Crop","microp"); ?>" href="' + ajaxurl + '?action=mic_editor_window&postId=' + match[1] + '"><?php _e('Crop Image','microp') ?></a>' );
}
} catch (e) {
console.log(e);
}
});
}
}, 500);
});
</script>
<?php
}
private function filterPostData() {
$imageSizes = get_intermediate_image_sizes();
$data = array(
'attachmentId' => filter_var($_POST['attachmentId'], FILTER_SANITIZE_NUMBER_INT),
'editedSize' => in_array($_POST['editedSize'], $imageSizes) ? $_POST['editedSize'] : null,
'select' => array(
'x' => filter_var($_POST['select']['x'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION),
'y' => filter_var($_POST['select']['y'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION),
'w' => filter_var($_POST['select']['w'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION),
'h' => filter_var($_POST['select']['h'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION),
),
'previewScale' => filter_var($_POST['previewScale'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION)
);
if (isset($_POST['mic_quality'])) {
$data['mic_quality'] = filter_var($_POST['mic_quality'], FILTER_SANITIZE_NUMBER_INT);
} else {
$data['mic_quality'] = 60;
}
if (isset($_POST['make2x'])) {
$data['make2x'] = filter_var($_POST['make2x'], FILTER_VALIDATE_BOOLEAN);
}
return $data;
}
/**
* Crops the image based on params passed in $_POST array
*/
public function cropImage() {
global $_wp_additional_image_sizes;
$data = $this->filterPostData();
$dst_file_url = wp_get_attachment_image_src($data['attachmentId'], $data['editedSize']);
if (!$dst_file_url) {
exit;
}
$uploadsDir = wp_upload_dir();
// checks for ssl. wp_upload_dir does not handle ssl (ssl admin trips on this and subsequent ajax success to browser)
if (is_ssl()) {
$uploadsDir['baseurl'] = preg_replace('#^http://#i', 'https://', $uploadsDir['baseurl']);
}
if ( function_exists( '_load_image_to_edit_path' ) ) {
// this function is consider as private, but it return proper image path. Notice it is in function_exists condition
$src_file = _load_image_to_edit_path( $data['attachmentId'], 'full' );
$dst_file = _load_image_to_edit_path( $data['attachmentId'], $data['editedSize'] );
} else {
$src_file_url = wp_get_attachment_image_src( $data['attachmentId'], 'full' );
if ( ! $src_file_url ) {
echo json_encode( array( 'status' => 'error', 'message' => 'wrong attachment' ) );
exit;
}
$src_file = str_replace( $uploadsDir['baseurl'], $uploadsDir['basedir'], $src_file_url[0] );
$dst_file = str_replace( $uploadsDir['baseurl'], $uploadsDir['basedir'], $dst_file_url[0] );
}
//checks if the destination image file is present (if it's not, we want to create a new file, as the WordPress returns the original image instead of specific one)
if ($dst_file == $src_file) {
$attachmentData = wp_generate_attachment_metadata( $data['attachmentId'], $dst_file );
//overwrite with previous values
$prevAttachmentData = wp_get_attachment_metadata($data['attachmentId']);
if (isset($prevAttachmentData['micSelectedArea'])) {
$attachmentData['micSelectedArea'] = $prevAttachmentData['micSelectedArea'];
}
//saves new path to the image size in the database
wp_update_attachment_metadata( $data['attachmentId'], $attachmentData );
//new destination file path - replaces original file name with the correct one
$dst_file = str_replace( basename($attachmentData['file']), $attachmentData['sizes'][ $data['editedSize'] ]['file'], $dst_file);
//retrieves the new url to file (needet to refresh the preview)
$dst_file_url = wp_get_attachment_image_src($data['attachmentId'], $data['editedSize']);
}
//sets the destination image dimensions
if (isset($_wp_additional_image_sizes[$data['editedSize']])) {
$dst_w = min(intval($_wp_additional_image_sizes[$data['editedSize']]['width']), $data['select']['w'] * $data['previewScale']);
$dst_h = min(intval($_wp_additional_image_sizes[$data['editedSize']]['height']), $data['select']['h'] * $data['previewScale']);
} else {
$dst_w = min(get_option($data['editedSize'].'_size_w'), $data['select']['w'] * $data['previewScale']);
$dst_h = min(get_option($data['editedSize'].'_size_h'), $data['select']['h'] * $data['previewScale']);
}
if (!$dst_w || !$dst_h) {
echo json_encode (array('status' => 'error', 'message' => 'wrong dimensions' ) );
exit;
}
//prepares coordinates that will be passed to cropping function
$dst_x = 0;
$dst_y = 0;
$src_x = max(0, $data['select']['x']) * $data['previewScale'];
$src_y = max(0, $data['select']['y']) * $data['previewScale'];
$src_w = max(0, $data['select']['w']) * $data['previewScale'];
$src_h = max(0, $data['select']['h']) * $data['previewScale'];
$size = wp_get_image_editor( $src_file )->get_size();
$is_higher = ( $dst_h > $size["height"] );
$is_wider = ( $dst_w > $size["width"] );
if ( $is_higher || $is_wider ) {
if ( $is_higher ) {
$scale = $src_h / $size["height"];
} else {
$scale = $src_w / $size["width"];
}
$src_w = $src_w / $scale;
$src_h = $src_h / $scale;
$src_x = $src_x / $scale;
$src_y = $src_y / $scale;
}
//saves the selected area
$imageMetadata = wp_get_attachment_metadata($data['attachmentId']);
$imageMetadata['micSelectedArea'][$data['editedSize']] = array(
'x' => $data['select']['x'],
'y' => $data['select']['y'],
'w' => $data['select']['w'],
'h' => $data['select']['h'],
'scale' => $data['previewScale'],
);
wp_update_attachment_metadata($data['attachmentId'], $imageMetadata);
if ( function_exists('wp_get_image_editor') ) {
$img = wp_get_image_editor( $src_file );
if ( ! is_wp_error( $img ) ) {
$img->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, false );
$img->set_quality( $data['mic_quality'] );
$saveStatus = $img->save( $dst_file );
if ( is_wp_error( $saveStatus ) ) {
echo json_encode( array( 'status' => 'error', 'message' => 'WP_ERROR: ' . $saveStatus->get_error_message() ) );
exit;
}
}else {
echo json_encode (array('status' => 'error', 'message' => 'WP_ERROR: ' . $img->get_error_message() ) );
exit;
}
} else {
//determines what's the image format
$ext = pathinfo($src_file, PATHINFO_EXTENSION);
if ($ext == "gif"){
$src_img = imagecreatefromgif($src_file);
} else if($ext =="png"){
$src_img = imagecreatefrompng($src_file);
} else {
$src_img = imagecreatefromjpeg($src_file);
}
if ($src_img === false ) {
echo json_encode (array('status' => 'error', 'message' => 'PHP ERROR: Cannot create image from the source file' ) );
exit;
}
$dst_img = imagecreatetruecolor($dst_w, $dst_h);
$resampleReturn = imagecopyresampled($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
if ($resampleReturn === false ) {
echo json_encode (array('status' => 'error', 'message' => 'PHP ERROR: imagecopyresampled' ) );
exit;
}
$imageSaveReturn = true;
if ($ext == "gif"){
$imageSaveReturn = imagegif($dst_img, $dst_file);
} else if($ext =="png"){
$imageSaveReturn = imagepng($dst_img, $dst_file);
} else {
$imageSaveReturn = imagejpeg($dst_img, $dst_file, $quality);
}
if ($imageSaveReturn === false ) {
echo json_encode (array('status' => 'error', 'message' => 'PHP ERROR: imagejpeg/imagegif/imagepng' ) );
exit;
}
}
// Generate Retina Image
if( isset( $data['make2x'] ) && $data['make2x'] === 'true' ) {
$dst_w2x = $dst_w * 2;
$dst_h2x = $dst_h * 2;
$dot = strrpos($dst_file,".");
$dst_file2x = substr($dst_file,0,$dot).'@2x'.substr($dst_file,$dot);
// Check image size and create the retina file if possible
if ( $src_w > $dst_w2x && $src_h > $dst_h2x) {
if ( function_exists('wp_get_image_editor') ) {
$img = wp_get_image_editor( $src_file );
if ( ! is_wp_error( $img ) ) {
$img->crop( $src_x, $src_y, $src_w, $src_h, $dst_w2x, $dst_h2x, false );
$img->set_quality( $quality );
$img->save($dst_file2x);
}else {
echo json_encode (array('status' => 'error', 'message' => 'WP_ERROR: ' . $img->get_error_message() ) );
exit;
}
} else {
$dst_img2x = imagecreatetruecolor($dst_w2x, $dst_h2x);
$resampleReturn = imagecopyresampled($dst_img2x, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w2x, $dst_h2x, $src_w, $src_h);
if ($resampleReturn === false ) {
echo json_encode (array('status' => 'error', 'message' => 'PHP ERROR: imagecopyresampled' ) );
exit;
}
$imageSaveReturn = true;
if ($ext == "gif"){
$imageSaveReturn = imagegif($dst_img2x, $dst_file2x);
} else if($ext =="png"){
$imageSaveReturn = imagepng($dst_img2x, $dst_file2x);
} else {
$imageSaveReturn = imagejpeg($dst_img2x, $dst_file2x, $quality);
}
if ($imageSaveReturn === false ) {
echo json_encode (array('status' => 'error', 'message' => 'PHP ERROR: imagejpeg/imagegif/imagepng' ) );
exit;
}
}
}
}
// update 'mic_make2x' option status to persist choice
if( isset( $data['make2x'] ) && $data['make2x'] !== get_option('mic_make2x') ) {
update_option('mic_make2x', $data['make2x']);
}
//returns the url to the generated image (to allow refreshing the preview)
echo json_encode (array('status' => 'ok', 'file' => $dst_file_url[0] ) );
exit;
}
}