Version Description
- the used cropping data are now stored in the image after the crop, making it possible to code a plugin for restoring the cropped region on new image-sizes
- fix for hiding crop sizes is not working when the image_size_names_choose-filter is used for that post-type
- change permission from 'upload_files' to 'edit_files' (Attention: authors will no longer able to crop the thumbnails)
- add a filter function to override the permission to crop thumbnails (crop_thumbnails_user_permission_check)
- add settings-section to set if users can crop thumbnails with capability "edit_files" or "upload_files"
- get featured image panel button working in wordpress v5
Download this release
Release Info
Developer | Volkmar Kantor |
Plugin | Crop-Thumbnails |
Version | 1.2.0 |
Comparing to | |
See all releases |
Code changes from version 1.1.3 to 1.2.0
- app/app.css +1 -1
- app/app.js +9 -1
- crop-thumbnails.php +2 -2
- functions/backendpreparer.php +52 -7
- functions/editor.php +71 -53
- functions/helper.php +2 -2
- functions/save.php +51 -8
- functions/settingsscreen.php +27 -3
- readme.txt +10 -2
app/app.css
CHANGED
@@ -82,7 +82,7 @@
|
|
82 |
padding-bottom: 0;
|
83 |
}
|
84 |
/**** button icon ****/
|
85 |
-
|
86 |
content: "\F165";
|
87 |
font: normal 12px/1 dashicons;
|
88 |
-webkit-font-smoothing: antialiased;
|
82 |
padding-bottom: 0;
|
83 |
}
|
84 |
/**** button icon ****/
|
85 |
+
.cropThumbnailsLink .wp-media-buttons-icon::before {
|
86 |
content: "\F165";
|
87 |
font: normal 12px/1 dashicons;
|
88 |
-webkit-font-smoothing: antialiased;
|
app/app.js
CHANGED
@@ -564,6 +564,14 @@ CROP_THUMBNAILS_VUE.components.cropeditor = {
|
|
564 |
that.lang = that.cropData.lang;
|
565 |
that.nonce = that.cropData.nonce;
|
566 |
delete that.cropData.nonce;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
567 |
}).always(function () {
|
568 |
that.loading = false;
|
569 |
});
|
@@ -789,7 +797,7 @@ CROP_THUMBNAILS_VUE.components.cropeditor = {
|
|
789 |
/* 16 */
|
790 |
/***/ (function(module, exports) {
|
791 |
|
792 |
-
module.exports = "<div class=\"cptEditorInner\" v-if=\"cropData && lang\" :class=\"{loading:loading,cropEditorActive:croppingApi}\">\n\t\n\t<div class=\"cptWaitingWindow\" v-if=\"loading\">\n\t\t<div class=\"msg\">\n\t\t\t{{ lang.waiting }}\n\t\t\t<div>\n\t\t\t\t<div class=\"cptLoadingSpinner\"></div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t\n\t<div class=\"cptWaitingWindow cptCropDisabledMsg\" v-if=\"cropData.hiddenOnPostType\">\n\t\t<div class=\"msg\">{{lang.cropDisabled}}</div>\n\t</div>\n\t\n\t\n\t<div class=\"mainWindow\" v-if=\"!cropData.hiddenOnPostType\">\n\t\t\n\t\t<div class=\"cptSelectionPane\" :class=\"{ cptImagesAreSelected : (activeImageSizes.length>0) }\">\n\t\t\t<div class=\"cptSelectionPaneInner\">\n\t\t\t\t<message v-if=\"sourceImageHasOrientation\">{{lang.message_image_orientation}}</message>\n\t\t\t\t<p>\n\t\t\t\t\t<label class=\"cptSameRatioLabel\">\n\t\t\t\t\t\t<input type=\"checkbox\" v-model=\"selectSameRatio\" />\n\t\t\t\t\t\t{{lang.label_same_ratio}}\n\t\t\t\t\t</label>\n\t\t\t\t\t<button type=\"button\" class=\"button\" @click=\"makeAllInactive()\">{{lang.label_deselect_all}}</button>\n\t\t\t\t</p>\n\t\t\t\t<ul class=\"cptImageSizelist\">\n\t\t\t\t\t<li v-for=\"i in filteredImageSizes\" :class=\"imageSizeClass(i)\" @click=\"toggleActive(i)\">\n\t\t\t\t\t\t<section class=\"cptImageSizeInner\">\n\t\t\t\t\t\t\t<header>{{i.nameLabel}}</header>\n\t\t\t\t\t\t\t<div class=\"lowResWarning\" v-if=\"isLowRes(i)\" :title=\"lang.lowResWarning\"><span>!</span></div>\n\t\t\t\t\t\t\t<div class=\"notYetCropped\" v-if=\"!isLowRes(i) && i.url === cropData.sourceImage.full.url\" :title=\"lang.notYetCropped\"><span class=\"dashicons dashicons-image-crop\"></span></div>\n\t\t\t\t\t\t\t<div class=\"dimensions\">{{ lang.dimensions }} {{i.width}} x {{i.height}} {{ lang.pixel }}</div>\n\t\t\t\t\t\t\t<div class=\"ratio\">{{ lang.ratio }} {{i.printRatio}}</div>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<loadingcontainer :image=\"i.url+'?cacheBreak='+i.cacheBreak\">\n\t\t\t\t\t\t\t\t<div class=\"cptImageBgContainer\" :style=\"{'background-image': 'url('+i.url+'?cacheBreak='+i.cacheBreak+')'}\"></div>\n\t\t\t\t\t\t\t</loadingcontainer>\n\t\t\t\t\t\t</section>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"cptCropPane\">\n\t\t\t<div class=\"info\">\n\t\t\t\t<h3>{{ lang.rawImage }}</h3>\n\t\t\t\t<div class=\"dimensions\">{{ lang.dimensions }} {{cropData.sourceImage.full.width}} x {{cropData.sourceImage.full.height}} {{ lang.pixel }}</div>\n\t\t\t\t<div class=\"ratio\">{{ lang.ratio }} {{cropData.sourceImage.full.printRatio}}</div>\n\t\t\t</div>\n\t\t\t<button type=\"button\" class=\"button cptGenerate\" :class=\"{'button-primary':croppingApi}\" @click=\"cropThumbnails()\" :disabled=\"!croppingApi\">{{ lang.label_crop }}</button>\n\t\t\t\n\t\t\t<div class=\"cropContainer\">\n\t\t\t\t<img class=\"cptCroppingImage\" :src=\"cropImage.url\" />\n\t\t\t</div>\n\t\n\t\t\t<h4>{{ lang.instructions_header }}</h4>\n\t\t\t<ul class=\"step-info\">\n\t\t\t\t<li>{{ lang.instructions_step_1 }}</li>\n\t\t\t\t<li>{{ lang.instructions_step_2 }}</li>\n\t\t\t\t<li>{{ lang.instructions_step_3 }}</li>\n\t\t\t</ul>\n\n\t\t\t<div>\n\t\t\t\t<button type=\"button\" class=\"button\" v-if=\"cropData.options.debug_js\" @click=\"showDebugClick('js')\">show JS-Debug</button>\n\t\t\t\t<button type=\"button\" class=\"button\" v-if=\"cropData.options.debug_data && dataDebug!==null\" @click=\"showDebugClick('data')\">show Data-Debug</button>\n\t\t\t\t<pre v-if=\"showDebugType==='data'\">{{ dataDebug }}</pre>\n\t\t\t\t<pre v-if=\"showDebugType==='js'\"><br />cropImage:{{cropImage}}<br />cropData:{{ cropData }}</pre>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
|
793 |
|
794 |
/***/ }),
|
795 |
/* 17 */
|
564 |
that.lang = that.cropData.lang;
|
565 |
that.nonce = that.cropData.nonce;
|
566 |
delete that.cropData.nonce;
|
567 |
+
}).fail(function (data) {
|
568 |
+
that.cropData = data.responseJSON;
|
569 |
+
that.lang = that.cropData.lang;
|
570 |
+
that.nonce = that.cropData.nonce;
|
571 |
+
delete that.cropData.nonce;
|
572 |
+
if (data.status === 403) {
|
573 |
+
that.cropData.noPermission = true;
|
574 |
+
}
|
575 |
}).always(function () {
|
576 |
that.loading = false;
|
577 |
});
|
797 |
/* 16 */
|
798 |
/***/ (function(module, exports) {
|
799 |
|
800 |
+
module.exports = "<div class=\"cptEditorInner\" v-if=\"cropData && lang\" :class=\"{loading:loading,cropEditorActive:croppingApi}\">\n\t\n\t<div class=\"cptWaitingWindow\" v-if=\"loading\">\n\t\t<div class=\"msg\">\n\t\t\t{{ lang.waiting }}\n\t\t\t<div>\n\t\t\t\t<div class=\"cptLoadingSpinner\"></div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t\n\t<div class=\"cptWaitingWindow cptCropDisabledMsg\" v-if=\"cropData.hiddenOnPostType\">\n\t\t<div class=\"msg\">{{lang.cropDisabled}}</div>\n\t</div>\n\t\n\t<div class=\"cptWaitingWindow cptNoPermissionMsg\" v-if=\"cropData.noPermission\">\n\t\t<div class=\"msg\">{{lang.noPermission}}</div>\n\t</div>\n\n\t<div class=\"mainWindow\" v-if=\"!cropData.hiddenOnPostType && !cropData.noPermission\">\n\t\t\n\t\t<div class=\"cptSelectionPane\" :class=\"{ cptImagesAreSelected : (activeImageSizes.length>0) }\">\n\t\t\t<div class=\"cptSelectionPaneInner\">\n\t\t\t\t<message v-if=\"sourceImageHasOrientation\">{{lang.message_image_orientation}}</message>\n\t\t\t\t<p>\n\t\t\t\t\t<label class=\"cptSameRatioLabel\">\n\t\t\t\t\t\t<input type=\"checkbox\" v-model=\"selectSameRatio\" />\n\t\t\t\t\t\t{{lang.label_same_ratio}}\n\t\t\t\t\t</label>\n\t\t\t\t\t<button type=\"button\" class=\"button\" @click=\"makeAllInactive()\">{{lang.label_deselect_all}}</button>\n\t\t\t\t</p>\n\t\t\t\t<ul class=\"cptImageSizelist\">\n\t\t\t\t\t<li v-for=\"i in filteredImageSizes\" :class=\"imageSizeClass(i)\" @click=\"toggleActive(i)\">\n\t\t\t\t\t\t<section class=\"cptImageSizeInner\">\n\t\t\t\t\t\t\t<header>{{i.nameLabel}}</header>\n\t\t\t\t\t\t\t<div class=\"lowResWarning\" v-if=\"isLowRes(i)\" :title=\"lang.lowResWarning\"><span>!</span></div>\n\t\t\t\t\t\t\t<div class=\"notYetCropped\" v-if=\"!isLowRes(i) && i.url === cropData.sourceImage.full.url\" :title=\"lang.notYetCropped\"><span class=\"dashicons dashicons-image-crop\"></span></div>\n\t\t\t\t\t\t\t<div class=\"dimensions\">{{ lang.dimensions }} {{i.width}} x {{i.height}} {{ lang.pixel }}</div>\n\t\t\t\t\t\t\t<div class=\"ratio\">{{ lang.ratio }} {{i.printRatio}}</div>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<loadingcontainer :image=\"i.url+'?cacheBreak='+i.cacheBreak\">\n\t\t\t\t\t\t\t\t<div class=\"cptImageBgContainer\" :style=\"{'background-image': 'url('+i.url+'?cacheBreak='+i.cacheBreak+')'}\"></div>\n\t\t\t\t\t\t\t</loadingcontainer>\n\t\t\t\t\t\t</section>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"cptCropPane\">\n\t\t\t<div class=\"info\">\n\t\t\t\t<h3>{{ lang.rawImage }}</h3>\n\t\t\t\t<div class=\"dimensions\">{{ lang.dimensions }} {{cropData.sourceImage.full.width}} x {{cropData.sourceImage.full.height}} {{ lang.pixel }}</div>\n\t\t\t\t<div class=\"ratio\">{{ lang.ratio }} {{cropData.sourceImage.full.printRatio}}</div>\n\t\t\t</div>\n\t\t\t<button type=\"button\" class=\"button cptGenerate\" :class=\"{'button-primary':croppingApi}\" @click=\"cropThumbnails()\" :disabled=\"!croppingApi\">{{ lang.label_crop }}</button>\n\t\t\t\n\t\t\t<div class=\"cropContainer\">\n\t\t\t\t<img class=\"cptCroppingImage\" :src=\"cropImage.url\" />\n\t\t\t</div>\n\t\n\t\t\t<h4>{{ lang.instructions_header }}</h4>\n\t\t\t<ul class=\"step-info\">\n\t\t\t\t<li>{{ lang.instructions_step_1 }}</li>\n\t\t\t\t<li>{{ lang.instructions_step_2 }}</li>\n\t\t\t\t<li>{{ lang.instructions_step_3 }}</li>\n\t\t\t</ul>\n\n\t\t\t<div>\n\t\t\t\t<button type=\"button\" class=\"button\" v-if=\"cropData.options.debug_js\" @click=\"showDebugClick('js')\">show JS-Debug</button>\n\t\t\t\t<button type=\"button\" class=\"button\" v-if=\"cropData.options.debug_data && dataDebug!==null\" @click=\"showDebugClick('data')\">show Data-Debug</button>\n\t\t\t\t<pre v-if=\"showDebugType==='data'\">{{ dataDebug }}</pre>\n\t\t\t\t<pre v-if=\"showDebugType==='js'\"><br />cropImage:{{cropImage}}<br />cropData:{{ cropData }}</pre>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
|
801 |
|
802 |
/***/ }),
|
803 |
/* 17 */
|
crop-thumbnails.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
* Plugin URI: https://wordpress.org/extend/plugins/crop-thumbnails/
|
5 |
* Author: Volkmar Kantor
|
6 |
* Author URI: https://www.totalmedial.de
|
7 |
-
* Version: 1.
|
8 |
* Description: The easy way to adjust your cropped image sizes.
|
9 |
*
|
10 |
*
|
@@ -26,7 +26,7 @@
|
|
26 |
*/
|
27 |
|
28 |
|
29 |
-
define('CROP_THUMBNAILS_VERSION','1.
|
30 |
|
31 |
|
32 |
function cptLoadLanguage() {
|
4 |
* Plugin URI: https://wordpress.org/extend/plugins/crop-thumbnails/
|
5 |
* Author: Volkmar Kantor
|
6 |
* Author URI: https://www.totalmedial.de
|
7 |
+
* Version: 1.2.0
|
8 |
* Description: The easy way to adjust your cropped image sizes.
|
9 |
*
|
10 |
*
|
26 |
*/
|
27 |
|
28 |
|
29 |
+
define('CROP_THUMBNAILS_VERSION','1.2.0');
|
30 |
|
31 |
|
32 |
function cptLoadLanguage() {
|
functions/backendpreparer.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
*/
|
6 |
class CropPostThumbnailsBackendPreparer {
|
7 |
|
8 |
-
|
9 |
|
10 |
public function __construct() {
|
11 |
if ( is_admin() ) {
|
@@ -29,7 +29,7 @@ class CropPostThumbnailsBackendPreparer {
|
|
29 |
* });
|
30 |
* </code>
|
31 |
*/
|
32 |
-
|
33 |
global $pagenow;
|
34 |
$result = ($pagenow == 'post.php'
|
35 |
|| $pagenow == 'post-new.php'
|
@@ -92,7 +92,7 @@ class CropPostThumbnailsBackendPreparer {
|
|
92 |
/**
|
93 |
* Check if on the current admin page (posttype) the crop-button should be visible in the featured image Box.
|
94 |
*/
|
95 |
-
|
96 |
$screenData = get_current_screen();
|
97 |
$settings = $GLOBALS['CROP_THUMBNAILS_HELPER']->getOptions();
|
98 |
$showFeaturedImageCropButton = false;
|
@@ -120,7 +120,7 @@ jQuery(document).ready(function($) {
|
|
120 |
CROP_THUMBNAILS_CURRENT_POST_ID = null;
|
121 |
|
122 |
/**
|
123 |
-
* Adds a button to the featured image metabox.
|
124 |
* The button will be visible only if a featured image is set.
|
125 |
*/
|
126 |
function handleFeaturedImageBox() {
|
@@ -128,9 +128,7 @@ jQuery(document).ready(function($) {
|
|
128 |
* add link to featured image box
|
129 |
*/
|
130 |
var baseElem = $('#postimagediv');
|
131 |
-
if(!baseElem.length) {
|
132 |
-
return;
|
133 |
-
}
|
134 |
|
135 |
var featuredImageLinkButton = '';
|
136 |
featuredImageLinkButton+= '<p class="cropFeaturedImageWrap hidden">';
|
@@ -165,6 +163,52 @@ jQuery(document).ready(function($) {
|
|
165 |
|
166 |
updateCropFeaturedImageButton( parseInt(wp.media.featuredImage.get()) );
|
167 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
|
169 |
<?php if(self::showCropButtonOnThisAdminPage()) : ?>
|
170 |
/** add link on posts and pages **/
|
@@ -176,6 +220,7 @@ jQuery(document).ready(function($) {
|
|
176 |
CROP_THUMBNAILS_CURRENT_POST_ID = post_id_hidden;
|
177 |
|
178 |
handleFeaturedImageBox();
|
|
|
179 |
|
180 |
$('body').on('cropThumbnailModalClosed',function() {
|
181 |
//lets cache-break the crop-thumbnail-preview-box
|
5 |
*/
|
6 |
class CropPostThumbnailsBackendPreparer {
|
7 |
|
8 |
+
protected $allowedMime = array('image/jpeg','image/png');
|
9 |
|
10 |
public function __construct() {
|
11 |
if ( is_admin() ) {
|
29 |
* });
|
30 |
* </code>
|
31 |
*/
|
32 |
+
protected function shouldCropThumbnailsBeActive() {
|
33 |
global $pagenow;
|
34 |
$result = ($pagenow == 'post.php'
|
35 |
|| $pagenow == 'post-new.php'
|
92 |
/**
|
93 |
* Check if on the current admin page (posttype) the crop-button should be visible in the featured image Box.
|
94 |
*/
|
95 |
+
protected static function showCropButtonOnThisAdminPage() {
|
96 |
$screenData = get_current_screen();
|
97 |
$settings = $GLOBALS['CROP_THUMBNAILS_HELPER']->getOptions();
|
98 |
$showFeaturedImageCropButton = false;
|
120 |
CROP_THUMBNAILS_CURRENT_POST_ID = null;
|
121 |
|
122 |
/**
|
123 |
+
* Adds a button to the featured image metabox (Wordpress < 5).
|
124 |
* The button will be visible only if a featured image is set.
|
125 |
*/
|
126 |
function handleFeaturedImageBox() {
|
128 |
* add link to featured image box
|
129 |
*/
|
130 |
var baseElem = $('#postimagediv');
|
131 |
+
if(!baseElem.length) { return; }//this is not wordpress < 5
|
|
|
|
|
132 |
|
133 |
var featuredImageLinkButton = '';
|
134 |
featuredImageLinkButton+= '<p class="cropFeaturedImageWrap hidden">';
|
163 |
|
164 |
updateCropFeaturedImageButton( parseInt(wp.media.featuredImage.get()) );
|
165 |
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Adds a button to the featured image panel (Wordpress >= 5)
|
169 |
+
*
|
170 |
+
* I know this way to add the button is quite dirty - will refactoring it when i learned the api-way to do it.
|
171 |
+
*/
|
172 |
+
function handleFeaturedImagePanel() {
|
173 |
+
// @see https://github.com/WordPress/gutenberg/tree/master/packages/editor/src/components/post-featured-image
|
174 |
+
|
175 |
+
if(typeof wp.element === 'undefined') { return };//this is not wordpress 5.x
|
176 |
+
|
177 |
+
var el = wp.element.createElement;
|
178 |
+
function wrapPostFeaturedImage( OriginalComponent ) {
|
179 |
+
return function( props ) {
|
180 |
+
setTimeout(function() {
|
181 |
+
var baseElem = $('.edit-post-sidebar');
|
182 |
+
var cropButton = $('<button class="button cropThumbnailsLink" style="margin-top:1em" data-cropthumbnail=\'{"image_id":'+ parseInt(props.featuredImageId) +',"viewmode":"single","posttype":"<?php echo get_post_type(); ?>"}\' title="<?php esc_attr_e('Crop Featured Image','crop-thumbnails') ?>"><span class="wp-media-buttons-icon"></span> <?php esc_html_e('Crop Featured Image','crop-thumbnails'); ?></button>');
|
183 |
+
if(typeof props.media !== 'undefined') {
|
184 |
+
var panel = baseElem.find('.editor-post-featured-image');
|
185 |
+
panel.find('.cropThumbnailsLink').remove();
|
186 |
+
if(panel.find('.components-responsive-wrapper').length>0) {
|
187 |
+
panel.append(cropButton);
|
188 |
+
}
|
189 |
+
}
|
190 |
+
}, 50);
|
191 |
+
|
192 |
+
return (
|
193 |
+
el(
|
194 |
+
wp.element.Fragment,
|
195 |
+
{},
|
196 |
+
el(
|
197 |
+
OriginalComponent,
|
198 |
+
props
|
199 |
+
),
|
200 |
+
//TODO add in a better way here
|
201 |
+
)
|
202 |
+
);
|
203 |
+
}
|
204 |
+
}
|
205 |
+
|
206 |
+
wp.hooks.addFilter(
|
207 |
+
'editor.PostFeaturedImage',
|
208 |
+
'crop-thumbnails/wrap-post-featured-image',
|
209 |
+
wrapPostFeaturedImage
|
210 |
+
);
|
211 |
+
}
|
212 |
|
213 |
<?php if(self::showCropButtonOnThisAdminPage()) : ?>
|
214 |
/** add link on posts and pages **/
|
220 |
CROP_THUMBNAILS_CURRENT_POST_ID = post_id_hidden;
|
221 |
|
222 |
handleFeaturedImageBox();
|
223 |
+
handleFeaturedImagePanel();
|
224 |
|
225 |
$('body').on('cropThumbnailModalClosed',function() {
|
226 |
//lets cache-break the crop-thumbnail-preview-box
|
functions/editor.php
CHANGED
@@ -8,39 +8,82 @@ class CPT_ForbiddenException extends Exception {}
|
|
8 |
|
9 |
class CropPostThumbnailsEditor {
|
10 |
|
11 |
-
|
12 |
|
13 |
function __construct() {
|
14 |
add_action('wp_ajax_cpt_cropdata', array($this, 'provideCropData') );
|
15 |
}
|
16 |
|
17 |
public function provideCropData() {
|
|
|
18 |
try {
|
19 |
-
|
20 |
-
$result = $this->getCropData();
|
21 |
-
echo json_encode($result);
|
22 |
} catch(InvalidArgumentException $e) {
|
23 |
-
|
24 |
-
echo 'FAILURE while processing request: '.$e->getMessage();
|
25 |
} catch(CPT_ForbiddenException $e) {
|
26 |
-
|
27 |
-
echo 'ERROR not allowed.';
|
28 |
} catch(Exception $e) {
|
29 |
-
|
30 |
-
echo 'FAILURE while processing request.';
|
31 |
}
|
32 |
die();//to prevent to send back a "0"
|
33 |
}
|
34 |
|
35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
return str_replace('"','"',esc_js($msg));
|
37 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
public function getCropData() {
|
40 |
-
if(!self::isUserPermitted()) {
|
41 |
-
throw new CPT_ForbiddenException();
|
42 |
-
}
|
43 |
-
|
44 |
global $content_width;//include nasty content_width
|
45 |
$content_width = 9999;//override the idioty
|
46 |
|
@@ -56,27 +99,7 @@ class CropPostThumbnailsEditor {
|
|
56 |
'sourceImageMeta' => null,
|
57 |
'postTypeFilter' => null,
|
58 |
'imageSizes' => array_values($GLOBALS['CROP_THUMBNAILS_HELPER']->getImageSizes()),
|
59 |
-
'lang' =>
|
60 |
-
'warningOriginalToSmall' => self::fixJsLangStrings(__('Warning: the original image is too small to be cropped in good quality with this thumbnail size.','crop-thumbnails')),
|
61 |
-
'cropDisabled' => self::fixJsLangStrings(__('Cropping is disabled for this post-type.','crop-thumbnails')),
|
62 |
-
'waiting' => self::fixJsLangStrings(__('Please wait until the images are cropped.','crop-thumbnails')),
|
63 |
-
'rawImage' => self::fixJsLangStrings(__('Raw','crop-thumbnails')),
|
64 |
-
'pixel' => self::fixJsLangStrings(__('pixel','crop-thumbnails')),
|
65 |
-
'instructions_header' => self::fixJsLangStrings(__('Quick Instructions','crop-thumbnails')),
|
66 |
-
'instructions_step_1' => self::fixJsLangStrings(__('Step 1: Choose an image-size from the list.','crop-thumbnails')),
|
67 |
-
'instructions_step_2' => self::fixJsLangStrings(__('Step 2: Change the selection of the image above.','crop-thumbnails')),
|
68 |
-
'instructions_step_3' => self::fixJsLangStrings(__('Step 3: Click on "Save Crop".','crop-thumbnails')),
|
69 |
-
'label_crop' => self::fixJsLangStrings(__('Save Crop','crop-thumbnails')),
|
70 |
-
'label_same_ratio' => self::fixJsLangStrings(__('Crop all images with same ratio at once','crop-thumbnails')),
|
71 |
-
'label_deselect_all' => self::fixJsLangStrings(__('deselect all','crop-thumbnails')),
|
72 |
-
'dimensions' => self::fixJsLangStrings(__('Dimensions:','crop-thumbnails')),
|
73 |
-
'ratio' => self::fixJsLangStrings(__('Ratio:','crop-thumbnails')),
|
74 |
-
'cropped' => self::fixJsLangStrings(__('cropped','crop-thumbnails')),
|
75 |
-
'lowResWarning' => self::fixJsLangStrings(__('Original image size too small for good crop quality!','crop-thumbnails')),
|
76 |
-
'notYetCropped' => self::fixJsLangStrings(__('Not yet cropped by wordpress.','crop-thumbnails')),
|
77 |
-
'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')),
|
78 |
-
'script_connection_error' => self::fixJsLangStrings(__('The plugin can not correctly connect to the server.','crop-thumbnails'))
|
79 |
-
),
|
80 |
'nonce' => wp_create_nonce($GLOBALS['CROP_THUMBNAILS_HELPER']->getNonceBase())
|
81 |
);
|
82 |
|
@@ -84,6 +107,7 @@ class CropPostThumbnailsEditor {
|
|
84 |
if(empty($_REQUEST['imageId'])) {
|
85 |
throw new InvalidArgumentException('Missing Parameter "imageId".');
|
86 |
}
|
|
|
87 |
|
88 |
$imagePostObj = get_post(intval($_REQUEST['imageId']));
|
89 |
if(empty($imagePostObj) || $imagePostObj->post_type!=='attachment') {
|
@@ -91,6 +115,10 @@ class CropPostThumbnailsEditor {
|
|
91 |
}
|
92 |
$result['sourceImageId'] = $imagePostObj->ID;
|
93 |
|
|
|
|
|
|
|
|
|
94 |
if(!empty($_REQUEST['posttype']) && post_type_exists($_REQUEST['posttype'])) {
|
95 |
$result['postTypeFilter'] = $_REQUEST['posttype'];
|
96 |
}
|
@@ -162,7 +190,7 @@ class CropPostThumbnailsEditor {
|
|
162 |
return $result;
|
163 |
}
|
164 |
|
165 |
-
|
166 |
$orig_img = wp_get_attachment_image_src($ID, $imageSize);
|
167 |
$orig_ima_gcd = $this->gcd($orig_img[1], $orig_img[2]);
|
168 |
$result = array(
|
@@ -177,7 +205,7 @@ class CropPostThumbnailsEditor {
|
|
177 |
return $result;
|
178 |
}
|
179 |
|
180 |
-
|
181 |
$gcd = $this->gcd($width,$height);
|
182 |
$result = array(
|
183 |
'gcd' => $gcd,
|
@@ -187,7 +215,7 @@ class CropPostThumbnailsEditor {
|
|
187 |
return $result;
|
188 |
}
|
189 |
|
190 |
-
|
191 |
if(empty($post_type)) {
|
192 |
return false;
|
193 |
}
|
@@ -204,13 +232,13 @@ class CropPostThumbnailsEditor {
|
|
204 |
* @param string name post-type (i.e. post, page, ...)
|
205 |
* @return boolean true if Image-size should be hidden
|
206 |
*/
|
207 |
-
|
208 |
$_return = false;
|
209 |
if(!empty($post_type)) {
|
210 |
//we are NOT in the mediathek
|
211 |
|
212 |
//-if hide_size
|
213 |
-
if(!empty($options['hide_size'][$post_type][ $img_size['
|
214 |
$_return = true;
|
215 |
}
|
216 |
|
@@ -230,20 +258,10 @@ class CropPostThumbnailsEditor {
|
|
230 |
}
|
231 |
|
232 |
|
233 |
-
private static function isUserPermitted() {
|
234 |
-
$return = false;
|
235 |
-
if(current_user_can('upload_files')) {
|
236 |
-
$return = true;
|
237 |
-
}
|
238 |
-
//TODO maybe add noence (is it needed? there are no file- or db-operations)
|
239 |
-
return $return;
|
240 |
-
}
|
241 |
-
|
242 |
-
|
243 |
/**
|
244 |
* Greatest cummon divisor
|
245 |
*/
|
246 |
-
|
247 |
if(function_exists('gmp_gcd')) {
|
248 |
$gcd = gmp_strval(gmp_gcd($a,$b));
|
249 |
return ($gcd);
|
@@ -253,7 +271,7 @@ class CropPostThumbnailsEditor {
|
|
253 |
}
|
254 |
}
|
255 |
|
256 |
-
|
257 |
$b = ( $a == 0 )? 0 : $b;
|
258 |
return ( $a % $b )? self::my_gcd($b, abs($a - $b)) : $b;
|
259 |
}
|
8 |
|
9 |
class CropPostThumbnailsEditor {
|
10 |
|
11 |
+
protected $debugOutput = '';
|
12 |
|
13 |
function __construct() {
|
14 |
add_action('wp_ajax_cpt_cropdata', array($this, 'provideCropData') );
|
15 |
}
|
16 |
|
17 |
public function provideCropData() {
|
18 |
+
header('Content-Type: application/json; charset=UTF-8');
|
19 |
try {
|
20 |
+
echo json_encode( $this->getCropData() );
|
|
|
|
|
21 |
} catch(InvalidArgumentException $e) {
|
22 |
+
self::doErrorResponse(400, 'FAILURE while processing request: '.$e->getMessage());
|
|
|
23 |
} catch(CPT_ForbiddenException $e) {
|
24 |
+
self::doErrorResponse(403, 'ERROR not allowed.');
|
|
|
25 |
} catch(Exception $e) {
|
26 |
+
self::doErrorResponse(400, 'FAILURE while processing request.');
|
|
|
27 |
}
|
28 |
die();//to prevent to send back a "0"
|
29 |
}
|
30 |
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Will directly print an error-output
|
34 |
+
* @param int $statusCode the statuscode of the response
|
35 |
+
* @param string $errorMsg the provided errormessage
|
36 |
+
*/
|
37 |
+
protected static function doErrorResponse($statusCode, $errorMsg) {
|
38 |
+
http_response_code($statusCode);
|
39 |
+
echo json_encode(array(
|
40 |
+
'lang' => self::getLangArray(),
|
41 |
+
'nonce' => wp_create_nonce($GLOBALS['CROP_THUMBNAILS_HELPER']->getNonceBase()),
|
42 |
+
'error' => $errorMsg,
|
43 |
+
'statusCode' => $statusCode
|
44 |
+
));
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Fix html-encoded language strings
|
49 |
+
* Note: abstraction to keep the code DRY
|
50 |
+
* @param string $msg the language string to fix
|
51 |
+
* @return string
|
52 |
+
*/
|
53 |
+
protected function fixJsLangStrings($msg) {
|
54 |
return str_replace('"','"',esc_js($msg));
|
55 |
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Returns the lang-array needed for the js-app to work
|
59 |
+
* @return Array
|
60 |
+
*/
|
61 |
+
protected static function getLangArray() {
|
62 |
+
return array(
|
63 |
+
'warningOriginalToSmall' => self::fixJsLangStrings(__('Warning: the original image is too small to be cropped in good quality with this thumbnail size.','crop-thumbnails')),
|
64 |
+
'cropDisabled' => self::fixJsLangStrings(__('Cropping is disabled for this post-type.','crop-thumbnails')),
|
65 |
+
'waiting' => self::fixJsLangStrings(__('Please wait until the images are cropped.','crop-thumbnails')),
|
66 |
+
'rawImage' => self::fixJsLangStrings(__('Raw','crop-thumbnails')),
|
67 |
+
'pixel' => self::fixJsLangStrings(__('pixel','crop-thumbnails')),
|
68 |
+
'instructions_header' => self::fixJsLangStrings(__('Quick Instructions','crop-thumbnails')),
|
69 |
+
'instructions_step_1' => self::fixJsLangStrings(__('Step 1: Choose an image-size from the list.','crop-thumbnails')),
|
70 |
+
'instructions_step_2' => self::fixJsLangStrings(__('Step 2: Change the selection of the image above.','crop-thumbnails')),
|
71 |
+
'instructions_step_3' => self::fixJsLangStrings(__('Step 3: Click on "Save Crop".','crop-thumbnails')),
|
72 |
+
'label_crop' => self::fixJsLangStrings(__('Save Crop','crop-thumbnails')),
|
73 |
+
'label_same_ratio' => self::fixJsLangStrings(__('Crop all images with same ratio at once','crop-thumbnails')),
|
74 |
+
'label_deselect_all' => self::fixJsLangStrings(__('deselect all','crop-thumbnails')),
|
75 |
+
'dimensions' => self::fixJsLangStrings(__('Dimensions:','crop-thumbnails')),
|
76 |
+
'ratio' => self::fixJsLangStrings(__('Ratio:','crop-thumbnails')),
|
77 |
+
'cropped' => self::fixJsLangStrings(__('cropped','crop-thumbnails')),
|
78 |
+
'lowResWarning' => self::fixJsLangStrings(__('Original image size too small for good crop quality!','crop-thumbnails')),
|
79 |
+
'notYetCropped' => self::fixJsLangStrings(__('Not yet cropped by wordpress.','crop-thumbnails')),
|
80 |
+
'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')),
|
81 |
+
'script_connection_error' => self::fixJsLangStrings(__('The plugin can not correctly connect to the server.','crop-thumbnails')),
|
82 |
+
'noPermission' => self::fixJsLangStrings(__('You are not permitted to crop the thumbnails.','crop-thumbnails'))
|
83 |
+
);
|
84 |
+
}
|
85 |
|
86 |
public function getCropData() {
|
|
|
|
|
|
|
|
|
87 |
global $content_width;//include nasty content_width
|
88 |
$content_width = 9999;//override the idioty
|
89 |
|
99 |
'sourceImageMeta' => null,
|
100 |
'postTypeFilter' => null,
|
101 |
'imageSizes' => array_values($GLOBALS['CROP_THUMBNAILS_HELPER']->getImageSizes()),
|
102 |
+
'lang' => self::getLangArray(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
'nonce' => wp_create_nonce($GLOBALS['CROP_THUMBNAILS_HELPER']->getNonceBase())
|
104 |
);
|
105 |
|
107 |
if(empty($_REQUEST['imageId'])) {
|
108 |
throw new InvalidArgumentException('Missing Parameter "imageId".');
|
109 |
}
|
110 |
+
|
111 |
|
112 |
$imagePostObj = get_post(intval($_REQUEST['imageId']));
|
113 |
if(empty($imagePostObj) || $imagePostObj->post_type!=='attachment') {
|
115 |
}
|
116 |
$result['sourceImageId'] = $imagePostObj->ID;
|
117 |
|
118 |
+
if(!CptSaveThumbnail::isUserPermitted( $imagePostObj->ID )) {
|
119 |
+
throw new CPT_ForbiddenException();
|
120 |
+
}
|
121 |
+
|
122 |
if(!empty($_REQUEST['posttype']) && post_type_exists($_REQUEST['posttype'])) {
|
123 |
$result['postTypeFilter'] = $_REQUEST['posttype'];
|
124 |
}
|
190 |
return $result;
|
191 |
}
|
192 |
|
193 |
+
protected function getUncroppedImageData($ID, $imageSize = 'full') {
|
194 |
$orig_img = wp_get_attachment_image_src($ID, $imageSize);
|
195 |
$orig_ima_gcd = $this->gcd($orig_img[1], $orig_img[2]);
|
196 |
$result = array(
|
205 |
return $result;
|
206 |
}
|
207 |
|
208 |
+
protected function calculateRatioData($width,$height) {
|
209 |
$gcd = $this->gcd($width,$height);
|
210 |
$result = array(
|
211 |
'gcd' => $gcd,
|
215 |
return $result;
|
216 |
}
|
217 |
|
218 |
+
protected static function shouldBeHiddenOnPostType($options,$post_type) {
|
219 |
if(empty($post_type)) {
|
220 |
return false;
|
221 |
}
|
232 |
* @param string name post-type (i.e. post, page, ...)
|
233 |
* @return boolean true if Image-size should be hidden
|
234 |
*/
|
235 |
+
protected static function shouldSizeBeHidden($options, $img_size, $post_type='') {
|
236 |
$_return = false;
|
237 |
if(!empty($post_type)) {
|
238 |
//we are NOT in the mediathek
|
239 |
|
240 |
//-if hide_size
|
241 |
+
if(!empty($options['hide_size'][$post_type][ $img_size['id'] ])) {
|
242 |
$_return = true;
|
243 |
}
|
244 |
|
258 |
}
|
259 |
|
260 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
261 |
/**
|
262 |
* Greatest cummon divisor
|
263 |
*/
|
264 |
+
protected function gcd($a, $b) {
|
265 |
if(function_exists('gmp_gcd')) {
|
266 |
$gcd = gmp_strval(gmp_gcd($a,$b));
|
267 |
return ($gcd);
|
271 |
}
|
272 |
}
|
273 |
|
274 |
+
protected static function my_gcd($a, $b) {
|
275 |
$b = ( $a == 0 )? 0 : $b;
|
276 |
return ( $a % $b )? self::my_gcd($b, abs($a - $b)) : $b;
|
277 |
}
|
functions/helper.php
CHANGED
@@ -12,8 +12,8 @@
|
|
12 |
* This class is for overriding settings in php-tests - therefore the functions cant be static :(
|
13 |
*/
|
14 |
class CropThumbnailsHelper {
|
15 |
-
|
16 |
-
|
17 |
|
18 |
public function getUploadDir() {
|
19 |
$upload_dir = wp_upload_dir();
|
12 |
* This class is for overriding settings in php-tests - therefore the functions cant be static :(
|
13 |
*/
|
14 |
class CropThumbnailsHelper {
|
15 |
+
protected static $defaultSizes = array('thumbnail','medium','medium_large','large');
|
16 |
+
protected static $optionsKey = 'crop-post-thumbs';
|
17 |
|
18 |
public function getUploadDir() {
|
19 |
$upload_dir = wp_upload_dir();
|
functions/save.php
CHANGED
@@ -4,7 +4,7 @@ add_action( 'wp_ajax_cptSaveThumbnail', array($cptSave, 'saveThumbnailAjaxWrap')
|
|
4 |
|
5 |
class CptSaveThumbnail {
|
6 |
|
7 |
-
|
8 |
|
9 |
/**
|
10 |
* Handle-function called via ajax request.
|
@@ -105,7 +105,7 @@ class CptSaveThumbnail {
|
|
105 |
|
106 |
if(!$_error) {
|
107 |
//update metadata --> otherwise new sizes will not be updated
|
108 |
-
$imageMetadata = self::updateMetadata($imageMetadata, $activeImageSize->name, $currentFilePathInfo, $croppedSize['width'], $croppedSize['height']);
|
109 |
} else {
|
110 |
self::addDebug('error on '.$currentFilePathInfo['basename']);
|
111 |
self::addDebug($_processing_error);
|
@@ -195,18 +195,29 @@ class CptSaveThumbnail {
|
|
195 |
die();
|
196 |
}
|
197 |
|
198 |
-
|
199 |
self::$debug[] = $text;
|
200 |
}
|
201 |
|
202 |
-
|
203 |
if(!empty(self::$debug)) {
|
204 |
return self::$debug;
|
205 |
}
|
206 |
return array();
|
207 |
}
|
208 |
|
209 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
$fullFilePath = trailingslashit($currentFilePathInfo['dirname']) . $currentFilePathInfo['basename'];
|
211 |
|
212 |
$fileTypeInformations = wp_check_filetype($fullFilePath);
|
@@ -216,6 +227,14 @@ class CptSaveThumbnail {
|
|
216 |
$newValues['width'] = intval($croppedWidth);
|
217 |
$newValues['height'] = intval($croppedHeight);
|
218 |
$newValues['mime-type'] = $fileTypeInformations['type'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
|
220 |
$oldValues = array();
|
221 |
if(empty($imageMetadata['sizes'])) {
|
@@ -235,7 +254,7 @@ class CptSaveThumbnail {
|
|
235 |
* @param array all available ImageSizes
|
236 |
* @return boolean true if the newImageSize is in the list of ImageSizes and dimensions are correct
|
237 |
*/
|
238 |
-
|
239 |
if(empty($submitted->name)) {
|
240 |
return false;
|
241 |
}
|
@@ -256,7 +275,8 @@ class CptSaveThumbnail {
|
|
256 |
* @return object JSON-Object with submitted data
|
257 |
* @throw Exception if the security validation fails
|
258 |
*/
|
259 |
-
|
|
|
260 |
if(!check_ajax_referer($GLOBALS['CROP_THUMBNAILS_HELPER']->getNonceBase(),'_ajax_nonce',false)) {
|
261 |
throw new Exception(__("ERROR: Security Check failed (maybe a timeout - please try again).",'crop-thumbnails'), 1);
|
262 |
}
|
@@ -272,6 +292,9 @@ class CptSaveThumbnail {
|
|
272 |
throw new Exception(__('ERROR: Submitted data is incomplete.','crop-thumbnails'), 1);
|
273 |
}
|
274 |
|
|
|
|
|
|
|
275 |
|
276 |
if(!isset($input->selection->x) || !isset($input->selection->y) || !isset($input->selection->x2) || !isset($input->selection->y2)) {
|
277 |
throw new Exception(__('ERROR: Submitted data is incomplete.','crop-thumbnails'), 1);
|
@@ -306,7 +329,7 @@ class CptSaveThumbnail {
|
|
306 |
* @param int height of the new image
|
307 |
* @return string path to the new image
|
308 |
*/
|
309 |
-
|
310 |
$info = pathinfo($file);
|
311 |
$dir = $info['dirname'];
|
312 |
$ext = $info['extension'];
|
@@ -315,4 +338,24 @@ class CptSaveThumbnail {
|
|
315 |
$destfilename = $dir.'/'.$name.'-'.$suffix.'.'.$ext;
|
316 |
return $destfilename;
|
317 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
}
|
4 |
|
5 |
class CptSaveThumbnail {
|
6 |
|
7 |
+
protected static $debug = array();
|
8 |
|
9 |
/**
|
10 |
* Handle-function called via ajax request.
|
105 |
|
106 |
if(!$_error) {
|
107 |
//update metadata --> otherwise new sizes will not be updated
|
108 |
+
$imageMetadata = self::updateMetadata($imageMetadata, $activeImageSize->name, $currentFilePathInfo, $croppedSize['width'], $croppedSize['height'], $input);
|
109 |
} else {
|
110 |
self::addDebug('error on '.$currentFilePathInfo['basename']);
|
111 |
self::addDebug($_processing_error);
|
195 |
die();
|
196 |
}
|
197 |
|
198 |
+
protected static function addDebug($text) {
|
199 |
self::$debug[] = $text;
|
200 |
}
|
201 |
|
202 |
+
protected static function getDebug() {
|
203 |
if(!empty(self::$debug)) {
|
204 |
return self::$debug;
|
205 |
}
|
206 |
return array();
|
207 |
}
|
208 |
|
209 |
+
/**
|
210 |
+
* Update the metadata for one image-size.
|
211 |
+
*
|
212 |
+
* @param array $imageMetadata the image-metadata base array to modify
|
213 |
+
* @param string $imageSizeName the name of the image-size
|
214 |
+
* @param array $currentFilePathInfo pathinfo of the new thumbnail/image-size
|
215 |
+
* @param int $croppedWidth the new width of the image
|
216 |
+
* @param int $croppedHeight the new height of the image
|
217 |
+
* @param array $croppingInput the input data for the cropping (to store the crop-informations)
|
218 |
+
* @return array the modified $imageMetadata
|
219 |
+
*/
|
220 |
+
protected static function updateMetadata($imageMetadata, $imageSizeName, $currentFilePathInfo, $croppedWidth, $croppedHeight, $croppingInput) {
|
221 |
$fullFilePath = trailingslashit($currentFilePathInfo['dirname']) . $currentFilePathInfo['basename'];
|
222 |
|
223 |
$fileTypeInformations = wp_check_filetype($fullFilePath);
|
227 |
$newValues['width'] = intval($croppedWidth);
|
228 |
$newValues['height'] = intval($croppedHeight);
|
229 |
$newValues['mime-type'] = $fileTypeInformations['type'];
|
230 |
+
$newValues['cpt_last_cropping_data'] = array(
|
231 |
+
'x' => $croppingInput->selection->x,
|
232 |
+
'y' => $croppingInput->selection->y,
|
233 |
+
'x2' => $croppingInput->selection->x2,
|
234 |
+
'y2' => $croppingInput->selection->y2,
|
235 |
+
'original_width' => $imageMetadata['width'],
|
236 |
+
'original_height' => $imageMetadata['height'],
|
237 |
+
);
|
238 |
|
239 |
$oldValues = array();
|
240 |
if(empty($imageMetadata['sizes'])) {
|
254 |
* @param array all available ImageSizes
|
255 |
* @return boolean true if the newImageSize is in the list of ImageSizes and dimensions are correct
|
256 |
*/
|
257 |
+
protected static function isImageSizeValid(&$submitted,$dbData) {
|
258 |
if(empty($submitted->name)) {
|
259 |
return false;
|
260 |
}
|
275 |
* @return object JSON-Object with submitted data
|
276 |
* @throw Exception if the security validation fails
|
277 |
*/
|
278 |
+
protected function getValidatedInput() {
|
279 |
+
|
280 |
if(!check_ajax_referer($GLOBALS['CROP_THUMBNAILS_HELPER']->getNonceBase(),'_ajax_nonce',false)) {
|
281 |
throw new Exception(__("ERROR: Security Check failed (maybe a timeout - please try again).",'crop-thumbnails'), 1);
|
282 |
}
|
292 |
throw new Exception(__('ERROR: Submitted data is incomplete.','crop-thumbnails'), 1);
|
293 |
}
|
294 |
|
295 |
+
if(!self::isUserPermitted($input->sourceImageId)) {
|
296 |
+
throw new Exception(__("You are not permitted to crop the thumbnails.",'crop-thumbnails'), 1);
|
297 |
+
}
|
298 |
|
299 |
if(!isset($input->selection->x) || !isset($input->selection->y) || !isset($input->selection->x2) || !isset($input->selection->y2)) {
|
300 |
throw new Exception(__('ERROR: Submitted data is incomplete.','crop-thumbnails'), 1);
|
329 |
* @param int height of the new image
|
330 |
* @return string path to the new image
|
331 |
*/
|
332 |
+
protected static function generateFilename( $file, $w, $h ){
|
333 |
$info = pathinfo($file);
|
334 |
$dir = $info['dirname'];
|
335 |
$ext = $info['extension'];
|
338 |
$destfilename = $dir.'/'.$name.'-'.$suffix.'.'.$ext;
|
339 |
return $destfilename;
|
340 |
}
|
341 |
+
|
342 |
+
/**
|
343 |
+
* Check if the user is permitted to crop the thumbnails.
|
344 |
+
*
|
345 |
+
* You may override the default result of this function by using the filter 'crop_thumbnails_user_permission_check'.
|
346 |
+
*
|
347 |
+
* @param int $imageId The ID of the image that should be cropped (not used in default test)
|
348 |
+
* @return boolean true if the user is permitted
|
349 |
+
*/
|
350 |
+
public static function isUserPermitted($imageId) {
|
351 |
+
$return = false;
|
352 |
+
$cropThumbnailSettings = $GLOBALS['CROP_THUMBNAILS_HELPER']->getOptions();
|
353 |
+
if(current_user_can('edit_files')) {
|
354 |
+
$return = true;
|
355 |
+
}
|
356 |
+
if(current_user_can('upload_files') && empty($cropThumbnailSettings['user_permission_only_on_edit_files'])) {
|
357 |
+
$return = true;
|
358 |
+
}
|
359 |
+
return apply_filters('crop_thumbnails_user_permission_check', $return, $imageId);
|
360 |
+
}
|
361 |
}
|
functions/settingsscreen.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
class CropThumbnailsSettingsScreen {
|
3 |
-
|
4 |
-
|
5 |
|
6 |
public function __construct() {
|
7 |
add_action('admin_menu', array($this,'addOptionsPage'));
|
@@ -75,6 +75,11 @@ class CropThumbnailsSettingsScreen {
|
|
75 |
$_sectionID = 'choose_sizes_section';
|
76 |
add_settings_section($_sectionID, esc_html__('Sizes and Post Types','crop-thumbnails'), array($this,'sectionDescriptionChooseSizes'), 'page1');
|
77 |
|
|
|
|
|
|
|
|
|
|
|
78 |
$_sectionID = 'quick_test';
|
79 |
add_settings_section($_sectionID, esc_html__('Plugin Test','crop-thumbnails'), array($this,'sectionDescriptionTest'), 'page1');
|
80 |
|
@@ -86,7 +91,7 @@ class CropThumbnailsSettingsScreen {
|
|
86 |
add_settings_field($_tmpID, esc_html__('Enable Data-Debug.','crop-thumbnails'), array($this,'callback_'.$_tmpID), 'page1', $_sectionID, array( 'label_for' => self::$cssPrefix.$_tmpID ));
|
87 |
}
|
88 |
|
89 |
-
|
90 |
$settings = array(
|
91 |
'options' => $GLOBALS['CROP_THUMBNAILS_HELPER']->getOptions(),
|
92 |
'post_types' => $GLOBALS['CROP_THUMBNAILS_HELPER']->getPostTypes(),
|
@@ -123,6 +128,20 @@ class CropThumbnailsSettingsScreen {
|
|
123 |
|
124 |
public function emptySectionDescription() {/*empty*/ }
|
125 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
public function callback_debug_js() {
|
127 |
$options = $GLOBALS['CROP_THUMBNAILS_HELPER']->getOptions();
|
128 |
$_id = 'debug_js';
|
@@ -166,6 +185,11 @@ class CropThumbnailsSettingsScreen {
|
|
166 |
}
|
167 |
}
|
168 |
|
|
|
|
|
|
|
|
|
|
|
169 |
/* Advanced Section */
|
170 |
$_tmpID = 'debug_js';
|
171 |
if(!empty($input[$_tmpID])) {
|
1 |
<?php
|
2 |
class CropThumbnailsSettingsScreen {
|
3 |
+
protected static $uniqeSettingsId = 'cpt-settings';
|
4 |
+
protected static $cssPrefix = 'cpt_settings_';
|
5 |
|
6 |
public function __construct() {
|
7 |
add_action('admin_menu', array($this,'addOptionsPage'));
|
75 |
$_sectionID = 'choose_sizes_section';
|
76 |
add_settings_section($_sectionID, esc_html__('Sizes and Post Types','crop-thumbnails'), array($this,'sectionDescriptionChooseSizes'), 'page1');
|
77 |
|
78 |
+
$_sectionID = 'userPermission';
|
79 |
+
add_settings_section($_sectionID, esc_html__('User Permission','crop-thumbnails'), array($this,'emptySectionDescription'), 'page1');
|
80 |
+
$_tmpID = 'user_permission_only_on_edit_files';
|
81 |
+
add_settings_field($_tmpID, esc_html__('When active, only users who are able to edit files can crop thumbnails. Otherwise (default), any user who can upload files can also crop thumbnails.','crop-thumbnails'), array($this,'callback_'.$_tmpID), 'page1', $_sectionID, array( 'label_for' => self::$cssPrefix.$_tmpID ));
|
82 |
+
|
83 |
$_sectionID = 'quick_test';
|
84 |
add_settings_section($_sectionID, esc_html__('Plugin Test','crop-thumbnails'), array($this,'sectionDescriptionTest'), 'page1');
|
85 |
|
91 |
add_settings_field($_tmpID, esc_html__('Enable Data-Debug.','crop-thumbnails'), array($this,'callback_'.$_tmpID), 'page1', $_sectionID, array( 'label_for' => self::$cssPrefix.$_tmpID ));
|
92 |
}
|
93 |
|
94 |
+
protected function vueSettingsScreen() {
|
95 |
$settings = array(
|
96 |
'options' => $GLOBALS['CROP_THUMBNAILS_HELPER']->getOptions(),
|
97 |
'post_types' => $GLOBALS['CROP_THUMBNAILS_HELPER']->getPostTypes(),
|
128 |
|
129 |
public function emptySectionDescription() {/*empty*/ }
|
130 |
|
131 |
+
|
132 |
+
|
133 |
+
public function callback_user_permission_only_on_edit_files() {
|
134 |
+
$options = $GLOBALS['CROP_THUMBNAILS_HELPER']->getOptions();
|
135 |
+
$_id = 'user_permission_only_on_edit_files';
|
136 |
+
if(empty($options[$_id])) { $options[$_id] = ''; }
|
137 |
+
echo '<input name="'.$GLOBALS['CROP_THUMBNAILS_HELPER']->getOptionsKey().'['.$_id.']" id="'.self::$cssPrefix.$_id.'" type="checkbox" value="1" ' . checked( 1, $options[$_id], false) . ' />';
|
138 |
+
?>
|
139 |
+
<div class="<?php echo self::$cssPrefix ?>submit">
|
140 |
+
<input name="Submit" type="submit" value="<?php esc_attr_e('Save Changes','crop-thumbnails'); ?>" class="button-primary" />
|
141 |
+
</div>
|
142 |
+
<?php
|
143 |
+
}
|
144 |
+
|
145 |
public function callback_debug_js() {
|
146 |
$options = $GLOBALS['CROP_THUMBNAILS_HELPER']->getOptions();
|
147 |
$_id = 'debug_js';
|
185 |
}
|
186 |
}
|
187 |
|
188 |
+
$_tmpID = 'user_permission_only_on_edit_files';
|
189 |
+
if(!empty($input[$_tmpID])) {
|
190 |
+
$storeInDb[$_tmpID] = 1;
|
191 |
+
}
|
192 |
+
|
193 |
/* Advanced Section */
|
194 |
$_tmpID = 'debug_js';
|
195 |
if(!empty($input[$_tmpID])) {
|
readme.txt
CHANGED
@@ -4,8 +4,8 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=volkm
|
|
4 |
Tags: post-thumbnails, images, media library
|
5 |
Requires at least: 4.6
|
6 |
Requires PHP: 5.3.0
|
7 |
-
Tested up to:
|
8 |
-
Stable tag: 1.
|
9 |
License: GPL v3
|
10 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
11 |
|
@@ -123,6 +123,14 @@ If you fork and planning to publish the forked plugin, please contact me.
|
|
123 |
5. Quicktest on settings-page, to check if your system is correct setup.
|
124 |
|
125 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
= 1.1.3 =
|
127 |
* add a filter (crop_thumbnails_activat_on_adminpages), for adding the plugins js/css on futher admin-pages like the taxonomy edit-page.
|
128 |
* update js and webpack dependencies
|
4 |
Tags: post-thumbnails, images, media library
|
5 |
Requires at least: 4.6
|
6 |
Requires PHP: 5.3.0
|
7 |
+
Tested up to: 5.0
|
8 |
+
Stable tag: 1.2.0
|
9 |
License: GPL v3
|
10 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
11 |
|
123 |
5. Quicktest on settings-page, to check if your system is correct setup.
|
124 |
|
125 |
== Changelog ==
|
126 |
+
= 1.2.0 =
|
127 |
+
* the used cropping data are now stored in the image after the crop, making it possible to code a plugin for restoring the cropped region on new image-sizes
|
128 |
+
* fix for hiding crop sizes is not working when the image_size_names_choose-filter is used for that post-type
|
129 |
+
* change permission from 'upload_files' to 'edit_files' (Attention: authors will no longer able to crop the thumbnails)
|
130 |
+
* add a filter function to override the permission to crop thumbnails (crop_thumbnails_user_permission_check)
|
131 |
+
* add settings-section to set if users can crop thumbnails with capability "edit_files" or "upload_files"
|
132 |
+
* get featured image panel button working in wordpress v5
|
133 |
+
|
134 |
= 1.1.3 =
|
135 |
* add a filter (crop_thumbnails_activat_on_adminpages), for adding the plugins js/css on futher admin-pages like the taxonomy edit-page.
|
136 |
* update js and webpack dependencies
|