File: //proc/self/cwd/wp-content/plugins/crop-thumbnails/functions/editor.php
<?php
namespace crop_thumbnails;
/**
* Contains all code inside the croping-window
*/
class CPT_ForbiddenException extends \Exception {}
class CropPostThumbnailsEditor {
protected $debugOutput = '';
public static function rest_cropdata() {
try {
$cpte = new CropPostThumbnailsEditor();
return $cpte->getCropData();
} catch(\InvalidArgumentException $e) {
return new \WP_REST_Response(CropPostThumbnailsEditor::getErrorData('FAILURE while processing request: '.$e->getMessage()), 400);
} catch(CPT_ForbiddenException $e) {
return new \WP_REST_Response(CropPostThumbnailsEditor::getErrorData('ERROR not allowed.'), 403);
} catch(\Exception $e) {
return new \WP_REST_Response(CropPostThumbnailsEditor::getErrorData('FAILURE while processing request.'), 400);
}
}
/**
* Will return an error-object for the frontend
* @param string $errorMsg the provided errormessage
* @return array
*/
public static function getErrorData($errorMsg) {
return [
'lang' => self::getLangArray(),
'nonce' => wp_create_nonce($GLOBALS['CROP_THUMBNAILS_HELPER']->getNonceBase()),
'error' => $errorMsg
];
}
/**
* Fix html-encoded language strings
* Note: abstraction to keep the code DRY
* @param string $msg the language string to fix
* @return string
*/
protected static function fixJsLangStrings($msg) {
return str_replace('"','"',esc_js($msg));
}
/**
* Returns the lang-array needed for the js-app to work
* @return Array
*/
protected static function getLangArray() {
return [
'warningOriginalToSmall' => self::fixJsLangStrings(__('Warning: the original image is too small to be cropped in good quality with this thumbnail size.','crop-thumbnails')),
'cropDisabled' => self::fixJsLangStrings(__('Cropping is disabled for this post-type.','crop-thumbnails')),
'waiting' => self::fixJsLangStrings(__('Please wait until the images are cropped.','crop-thumbnails')),
'rawImage' => self::fixJsLangStrings(__('Raw','crop-thumbnails')),
'pixel' => self::fixJsLangStrings(__('pixel','crop-thumbnails')),
'instructions_overlay_text' => self::fixJsLangStrings(__('Choose an image size.','crop-thumbnails')),
'instructions_header' => self::fixJsLangStrings(__('Quick Instructions','crop-thumbnails')),
'instructions_step_1' => self::fixJsLangStrings(__('Step 1: Choose an image-size from the list.','crop-thumbnails')),
'instructions_step_2' => self::fixJsLangStrings(__('Step 2: Change the selection of the image above.','crop-thumbnails')),
'instructions_step_3' => self::fixJsLangStrings(__('Step 3: Click on "Save Crop".','crop-thumbnails')),
'label_crop' => self::fixJsLangStrings(__('Save Crop','crop-thumbnails')),
'label_same_ratio_mode' => self::fixJsLangStrings(__('Images with same ratio','crop-thumbnails')),
'label_same_ratio_mode_nothing' => self::fixJsLangStrings(__('Do nothing','crop-thumbnails')),
'label_same_ratio_mode_select' => self::fixJsLangStrings(__('Select together','crop-thumbnails')),
'label_same_ratio_mode_group' => self::fixJsLangStrings(__('Group together','crop-thumbnails')),
'label_deselect_all' => self::fixJsLangStrings(__('deselect all','crop-thumbnails')),
'label_large_handles' => self::fixJsLangStrings(__('use large handles','crop-thumbnails')),
'dimensions' => self::fixJsLangStrings(__('Dimensions:','crop-thumbnails')),
'ratio' => self::fixJsLangStrings(__('Ratio:','crop-thumbnails')),
'cropped' => self::fixJsLangStrings(__('cropped','crop-thumbnails')),
'lowResWarning' => self::fixJsLangStrings(__('Original image size too small for good crop quality!','crop-thumbnails')),
'notYetCropped' => self::fixJsLangStrings(__('Not yet cropped by WordPress.','crop-thumbnails')),
'message_image_orientation' => self::fixJsLangStrings(__('This image has an image orientation value in its exif-metadata. Be aware that this may result in rotatated or mirrored images on safari ipad / iphone.','crop-thumbnails')),
'script_connection_error' => self::fixJsLangStrings(__('The plugin can not correctly connect to the server.','crop-thumbnails')),
'noPermission' => self::fixJsLangStrings(__('You are not permitted to crop the thumbnails.','crop-thumbnails')),
'unknownError' => self::fixJsLangStrings(__('An unknown error occured.','crop-thumbnails')),
'infoNoImageSizesAvailable' => self::fixJsLangStrings(__('No image sizes for cropping available.','crop-thumbnails')),
'headline_selected_image_sizes' => self::fixJsLangStrings(__('Selected image sizes','crop-thumbnails')),
];
}
public function getCropData() {
global $content_width;//include nasty content_width
$content_width = 9999;//override the idioty
$options = $GLOBALS['CROP_THUMBNAILS_HELPER']->getOptions();
$result = [
'options' => $options,
'sourceImageId' => null,
'sourceImage' => [
'original_image' => null,
'full' => null,
'large' => null,
'medium_large' => null,
],
'cropBaseSize' => 'full',
'sourceImageMeta' => null,
'postTypeFilter' => null,
'imageSizes' => array_values($GLOBALS['CROP_THUMBNAILS_HELPER']->getImageSizes()),
'lang' => self::getLangArray(),
'nonce' => wp_create_nonce($GLOBALS['CROP_THUMBNAILS_HELPER']->getNonceBase())
];
//simple validation
if(empty($_REQUEST['imageId'])) {
throw new \InvalidArgumentException('Missing Parameter "imageId".');
}
$imagePostObj = get_post(intval($_REQUEST['imageId']));
if(empty($imagePostObj) || $imagePostObj->post_type!=='attachment') {
throw new \InvalidArgumentException('Image with ID:'.intval($_REQUEST['imageId']).' could not be found');
}
$result['sourceImageId'] = $imagePostObj->ID;
if(!CptSaveThumbnail::isUserPermitted( $imagePostObj->ID )) {
throw new CPT_ForbiddenException();
}
if(!empty($_REQUEST['posttype']) && post_type_exists($_REQUEST['posttype'])) {
$result['postTypeFilter'] = $_REQUEST['posttype'];
}
$result['sourceImage']['original_image'] = $this->getUncroppedImageData($imagePostObj->ID, 'original_image');
$result['sourceImage']['full'] = $this->getUncroppedImageData($imagePostObj->ID, 'full');
$result['sourceImage']['large'] = $this->getUncroppedImageData($imagePostObj->ID, 'large');
$result['sourceImage']['medium_large'] = $this->getUncroppedImageData($imagePostObj->ID, 'medium_large');
//image meta data
$meta_raw = wp_get_attachment_metadata($imagePostObj->ID);
if(!empty($meta_raw['image_meta'])) {
$result['sourceImageMeta'] = $meta_raw['image_meta'];
}
$result['hiddenOnPostType'] = self::shouldBeHiddenOnPostType($options, $result['postTypeFilter']);
if(!$result['hiddenOnPostType']) {
foreach($result['imageSizes'] as $key => $imageSize) {
if(empty($imageSize['crop']) || $imageSize['width']<0 || $imageSize['height']<0) {
//we do not need uncropped image sizes
unset($result['imageSizes'][$key]);
continue;//to the next entry
}
//DEFINE RATIO AND GCD
if($imageSize['width'] ===0 || $imageSize['height']===0) {
$ratioData = $this->calculateRatioData($result['sourceImage']['full']['width'],$result['sourceImage']['full']['height']);
} else {
//DEFAULT RATIO - defined by the defined image-size
$ratioData = $this->calculateRatioData($imageSize['width'],$imageSize['height']);
}
//DYNAMIC RATIO
//the dynamic ratio is defined by the original image size and fix width OR height
//@eee https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/
if($imageSize['width'] === 9999) {
//if you define width with 9999 - it crops for the exact defined height but the full width
$ratioData = $this->calculateRatioData($result['sourceImage']['full']['width'], $imageSize['height']);
} elseif($imageSize['height'] === 9999) {
//if you define height with 9999 - it crops for the exect defined width but the full height
$ratioData = $this->calculateRatioData($imageSize['width'], $result['sourceImage']['full']['height']);
}
$img_data = wp_get_attachment_image_src($imagePostObj->ID, $imageSize['id']);
$jsonDataValues = [
'name' => $imageSize['id'],
'nameLabel' => $imageSize['name'],//if you want to change the label of this image-size
'url' => $img_data[0],
'width' => $imageSize['width'],
'height' => $imageSize['height'],
'gcd' => $ratioData['gcd'],
'ratio' => $ratioData['ratio'],
'printRatio' => apply_filters('crop_thumbnails_editor_printratio', $ratioData['printRatio'], $imageSize['id']),
'hideByPostType' => self::shouldSizeBeHidden($options,$imageSize,$result['postTypeFilter']),
'crop' => true//legacy
];
$result['imageSizes'][$key] = apply_filters('crop_thumbnails_editor_jsonDataValues', $jsonDataValues);
}//END froeach
}
$result['imageSizes'] = apply_filters('crop_thumbnails_crop_data_image_sizes', $result['imageSizes']);
if(is_array($result['imageSizes'])) $result['imageSizes'] = array_values($result['imageSizes']);
return apply_filters('crop_thumbnails_crop_data', $result);
}
protected function getUncroppedImageData($ID, $imageSize = 'full') {
$orig_img = wp_get_attachment_image_src($ID, $imageSize);
if($imageSize === 'original_image') {
$tmp = wp_getimagesize(wp_get_original_image_path($ID));
$orig_img = [ wp_get_original_image_url($ID), $tmp[0], $tmp[1], false ];
}
$orig_ima_gcd = $this->gcd($orig_img[1], $orig_img[2]);
$result = [
'url' => $orig_img[0],
'width' => $orig_img[1],
'height' => $orig_img[2],
'gcd' => $orig_ima_gcd,
'ratio' => ($orig_img[1]/$orig_ima_gcd) / ($orig_img[2]/$orig_ima_gcd),
'printRatio' => ($orig_img[1]/$orig_ima_gcd).':'.($orig_img[2]/$orig_ima_gcd),
'image_size' => $imageSize
];
return $result;
}
protected function calculateRatioData($width,$height) {
$gcd = $this->gcd($width,$height);
$result = [
'gcd' => $gcd,
'ratio' => ($width/$gcd) / ($height/$gcd),
'printRatio' => $width/$gcd.':'.$height/$gcd
];
return $result;
}
protected static function shouldBeHiddenOnPostType($options,$post_type) {
if(empty($post_type)) {
return false;
}
if(empty($options['hide_post_type'][$post_type])) {
return false;
}
return true;
}
/**
* Check wether or not the image_size should be hidden for this post_type
* @param array options array
* @param array the image-size (i.e. post-thumbnail, ...)
* @param string name post-type (i.e. post, page, ...)
* @return boolean true if Image-size should be hidden
*/
protected static function shouldSizeBeHidden($options, $img_size, $post_type='') {
$_return = false;
if(!empty($post_type)) {
//we are NOT in the mediathek
//-if hide_size
if(!empty($options['hide_size'][$post_type][ $img_size['id'] ])) {
$_return = true;
}
//if not a crop-size and allow_non_cropped
if(empty($img_size['crop']) && empty($options['allow_non_cropped'])) {
$_return = true;
}
} else {
//we are in the mediathek
//-if not a crop-size and allow_non_cropped
if(empty($img_size['crop']) && empty($options['allow_non_cropped'])) {
$_return = true;
}
}
return $_return;
}
/**
* Greatest cummon divisor
*/
protected function gcd($a, $b) {
if(function_exists('gmp_gcd')) {
$gcd = gmp_strval(gmp_gcd($a,$b));
return ($gcd);
} else {
$gcd = self::my_gcd($a,$b);
return $gcd;
}
}
protected static function my_gcd($a, $b) {
$b = ( $a == 0 )? 0 : $b;
return ( $a % $b )? self::my_gcd($b, abs($a - $b)) : $b;
}
}