Force Regenerate Thumbnails - Version 2.1.0

Version Description

  • added: PHP 8.0 compatibility
  • added: support generating thumbnails from original (pre-scaled), on by default
  • added: support for PDF thumbnail generation
  • added: ability to skip an image by regenerate_thumbs_skip_image filter
  • changed: escape all output, sanitize all input
  • changed: ensure all strings are i18n
  • changed: remove HTML from i18n strings
  • changed: improve path lookup function
  • fixed: call to set_time_limit() when it is not allowed
Download this release

Release Info

Developer nosilver4u
Plugin Icon 128x128 Force Regenerate Thumbnails
Version 2.1.0
Comparing to
See all releases

Code changes from version 2.0.6 to 2.1.0

assets/jquery-ui-1.10.1.custom.css ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! jQuery UI - v1.10.1 - 2013-03-14
2
+ * Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
3
+ /* includes styling for progressbar and tooltip elements */
4
+ /* Layout helpers
5
+ ----------------------------------*/
6
+ .ui-helper-hidden {
7
+ display: none;
8
+ }
9
+ .ui-helper-hidden-accessible {
10
+ border: 0;
11
+ clip: rect(0 0 0 0);
12
+ height: 1px;
13
+ margin: -1px;
14
+ overflow: hidden;
15
+ padding: 0;
16
+ position: absolute;
17
+ width: 1px;
18
+ }
19
+ .ui-helper-reset {
20
+ margin: 0;
21
+ padding: 0;
22
+ border: 0;
23
+ outline: 0;
24
+ line-height: 1.3;
25
+ text-decoration: none;
26
+ font-size: 100%;
27
+ list-style: none;
28
+ }
29
+ .ui-helper-clearfix:before,
30
+ .ui-helper-clearfix:after {
31
+ content: "";
32
+ display: table;
33
+ border-collapse: collapse;
34
+ }
35
+ .ui-helper-clearfix:after {
36
+ clear: both;
37
+ }
38
+ .ui-helper-clearfix {
39
+ min-height: 0; /* support: IE7 */
40
+ }
41
+ .ui-helper-zfix {
42
+ width: 100%;
43
+ height: 100%;
44
+ top: 0;
45
+ left: 0;
46
+ position: absolute;
47
+ opacity: 0;
48
+ filter:Alpha(Opacity=0);
49
+ }
50
+ .ui-front {
51
+ z-index: 100;
52
+ }
53
+ /* Interaction Cues
54
+ ----------------------------------*/
55
+ .ui-state-disabled {
56
+ cursor: default !important;
57
+ }
58
+
59
+ /* Misc visuals
60
+ ----------------------------------*/
61
+ /* Corner radius */
62
+ .ui-corner-all,
63
+ .ui-corner-top,
64
+ .ui-corner-left,
65
+ .ui-corner-tl {
66
+ border-top-left-radius: 22px;
67
+ }
68
+ .ui-corner-all,
69
+ .ui-corner-top,
70
+ .ui-corner-right,
71
+ .ui-corner-tr {
72
+ border-top-right-radius: 22px;
73
+ }
74
+ .ui-corner-all,
75
+ .ui-corner-bottom,
76
+ .ui-corner-left,
77
+ .ui-corner-bl {
78
+ border-bottom-left-radius: 22px;
79
+ }
80
+ .ui-corner-all,
81
+ .ui-corner-bottom,
82
+ .ui-corner-right,
83
+ .ui-corner-br {
84
+ border-bottom-right-radius: 22px;
85
+ }
86
+ /* Overlays */
87
+ .ui-widget-overlay {
88
+ position: fixed;
89
+ top: 0;
90
+ left: 0;
91
+ width: 100%;
92
+ height: 100%;
93
+ }
94
+ .ui-progressbar {
95
+ height: 22px;
96
+ text-align: left;
97
+ overflow: hidden;
98
+ }
99
+ .ui-progressbar .ui-progressbar-value {
100
+ margin: 0px;
101
+ height: 100%;
102
+
103
+ }
104
+ .ui-accordion .ui-accordion-header {
105
+ display: block;
106
+ cursor: pointer;
107
+ position: relative;
108
+ margin-top: 2px;
109
+ padding: .5em .5em .5em .7em;
110
+ min-height: 0; /* support: IE7 */
111
+ }
112
+ .ui-accordion .ui-accordion-icons {
113
+ padding-left: 2.2em;
114
+ }
115
+ .ui-accordion .ui-accordion-noicons {
116
+ padding-left: .7em;
117
+ }
118
+ .ui-accordion .ui-accordion-icons .ui-accordion-icons {
119
+ padding-left: 2.2em;
120
+ }
121
+ .ui-accordion .ui-accordion-header .ui-accordion-header-icon {
122
+ position: absolute;
123
+ left: .5em;
124
+ top: 50%;
125
+ margin-top: -8px;
126
+ }
127
+ .ui-accordion .ui-accordion-content {
128
+ padding: 1em 2.2em;
129
+ border-top: 0;
130
+ overflow: auto;
131
+ border-top-left-radius: 0px;
132
+ border-top-right-radius: 0px;
133
+ }
134
+ .ui-slider {
135
+ position: relative;
136
+ text-align: left;
137
+ }
138
+ .ui-slider .ui-slider-handle {
139
+ position: absolute;
140
+ z-index: 2;
141
+ width: 1.2em;
142
+ height: 1.2em;
143
+ cursor: default;
144
+ }
145
+ .ui-slider .ui-slider-range {
146
+ position: absolute;
147
+ z-index: 1;
148
+ font-size: .7em;
149
+ display: block;
150
+ border: 0;
151
+ background-position: 0 0;
152
+ }
153
+
154
+ /* For IE8 - See #6727 */
155
+ .ui-slider.ui-state-disabled .ui-slider-handle,
156
+ .ui-slider.ui-state-disabled .ui-slider-range {
157
+ filter: inherit;
158
+ }
159
+
160
+ .ui-slider-horizontal {
161
+ height: .8em;
162
+ }
163
+ .ui-slider-horizontal .ui-slider-handle {
164
+ top: -.3em;
165
+ margin-left: -.6em;
166
+ }
167
+ .ui-slider-horizontal .ui-slider-range {
168
+ top: 0;
169
+ height: 100%;
170
+ }
171
+ .ui-slider-horizontal .ui-slider-range-min {
172
+ left: 0;
173
+ }
174
+ .ui-slider-horizontal .ui-slider-range-max {
175
+ right: 0;
176
+ }
177
+
178
+ .ui-slider-vertical {
179
+ width: .8em;
180
+ height: 100px;
181
+ }
182
+ .ui-slider-vertical .ui-slider-handle {
183
+ left: -.3em;
184
+ margin-left: 0;
185
+ margin-bottom: -.6em;
186
+ }
187
+ .ui-slider-vertical .ui-slider-range {
188
+ left: 0;
189
+ width: 100%;
190
+ }
191
+ .ui-slider-vertical .ui-slider-range-min {
192
+ bottom: 0;
193
+ }
194
+ .ui-slider-vertical .ui-slider-range-max {
195
+ top: 0;
196
+ }
197
+ /* Component containers
198
+ ----------------------------------*/
199
+ .ui-widget-content {
200
+ background: none repeat scroll 0% 0% #dddddd;
201
+ -webkit-border-radius: 22px;
202
+ border-radius: 22px;
203
+ -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
204
+ box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
205
+ }
206
+ .ui-widget-content a {
207
+ color: #222222;
208
+ }
209
+ .ui-widget-header {
210
+ z-index: 9;
211
+ /* background-color: #00a32a;
212
+ background-color: #04a4cc;
213
+ background-color: #67c93e; */
214
+ background-color: #0073aa;
215
+ -webkit-border-radius: 22px;
216
+ border-radius: 22px;
217
+ }
218
+ .ui-widget-header a {
219
+ color: #ffffff;
220
+ }
221
+ /* Interaction states
222
+ ----------------------------------*/
223
+ .ui-state-default,
224
+ .ui-widget-content .ui-state-default,
225
+ .ui-widget-header .ui-state-default {
226
+ border: 1px solid #d3d3d3;
227
+ background: #e6e6e6 50% 50% repeat-x;
228
+ font-weight: normal;
229
+ color: #555555;
230
+ }
231
+ .ui-state-default a,
232
+ .ui-state-default a:link,
233
+ .ui-state-default a:visited {
234
+ color: #555555;
235
+ text-decoration: none;
236
+ }
237
+ .ui-state-hover,
238
+ .ui-widget-content .ui-state-hover,
239
+ .ui-widget-header .ui-state-hover,
240
+ .ui-state-focus,
241
+ .ui-widget-content .ui-state-focus,
242
+ .ui-widget-header .ui-state-focus {
243
+ border: 1px solid #999999;
244
+ background: #dadada 50% 50% repeat-x;
245
+ font-weight: normal;
246
+ color: #212121;
247
+ }
248
+ .ui-state-hover a,
249
+ .ui-state-hover a:hover,
250
+ .ui-state-hover a:link,
251
+ .ui-state-hover a:visited {
252
+ color: #212121;
253
+ text-decoration: none;
254
+ }
255
+ .ui-state-active,
256
+ .ui-widget-content .ui-state-active,
257
+ .ui-widget-header .ui-state-active {
258
+ border: 1px solid #aaaaaa;
259
+ background: #ffffff 50% 50% repeat-x;
260
+ font-weight: normal;
261
+ color: #212121;
262
+ }
263
+ .ui-state-active a,
264
+ .ui-state-active a:link,
265
+ .ui-state-active a:visited {
266
+ color: #212121;
267
+ text-decoration: none;
268
+ }
269
+
270
+ /* Interaction Cues
271
+ ----------------------------------*/
272
+ .ui-state-highlight,
273
+ .ui-widget-content .ui-state-highlight,
274
+ .ui-widget-header .ui-state-highlight {
275
+ border: 1px solid #fcefa1;
276
+ color: #363636;
277
+ }
278
+ .ui-state-highlight a,
279
+ .ui-widget-content .ui-state-highlight a,
280
+ .ui-widget-header .ui-state-highlight a {
281
+ color: #363636;
282
+ }
283
+ .ui-state-error,
284
+ .ui-widget-content .ui-state-error,
285
+ .ui-widget-header .ui-state-error {
286
+ border: 1px solid #cd0a0a;
287
+ color: #cd0a0a;
288
+ }
289
+ .ui-state-error a,
290
+ .ui-widget-content .ui-state-error a,
291
+ .ui-widget-header .ui-state-error a {
292
+ color: #cd0a0a;
293
+ }
294
+ .ui-state-error-text,
295
+ .ui-widget-content .ui-state-error-text,
296
+ .ui-widget-header .ui-state-error-text {
297
+ color: #cd0a0a;
298
+ }
299
+ .ui-priority-primary,
300
+ .ui-widget-content .ui-priority-primary,
301
+ .ui-widget-header .ui-priority-primary {
302
+ font-weight: bold;
303
+ }
304
+ .ui-priority-secondary,
305
+ .ui-widget-content .ui-priority-secondary,
306
+ .ui-widget-header .ui-priority-secondary {
307
+ opacity: .7;
308
+ filter:Alpha(Opacity=70);
309
+ font-weight: normal;
310
+ }
311
+ .ui-state-disabled,
312
+ .ui-widget-content .ui-state-disabled,
313
+ .ui-widget-header .ui-state-disabled {
314
+ opacity: .35;
315
+ filter:Alpha(Opacity=35);
316
+ background-image: none;
317
+ }
318
+ .ui-state-disabled .ui-icon {
319
+ filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
320
+ }
321
+
322
+ #regenthumbs-debuglist {
323
+ margin-left: 0;
324
+ padding: 1em 1.2em;
325
+ list-style-position: inside;
326
+ background: #fff;
327
+ -webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
328
+ box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
329
+ }
assets/regen.js ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($){
2
+ var i;
3
+ var rt_images = regen_thumbs.image_ids;
4
+ var rt_total = rt_images.length;
5
+ var rt_count = 1;
6
+ var rt_successes = 0;
7
+ var rt_errors = 0;
8
+ var rt_failedlist = '';
9
+ var rt_resulttext = '';
10
+ var rt_timestart = new Date().getTime();
11
+ var rt_timeend = 0;
12
+ var rt_totaltime = 0;
13
+ var rt_continue = true;
14
+
15
+ // Create the progress bar
16
+ $("#regenthumbs-bar").progressbar();
17
+
18
+ // Stop button
19
+ $("#regenthumbs-stop").click(function() {
20
+ rt_continue = false;
21
+ $('#regenthumbs-stop').val(regen_thumbs.stopping);
22
+ });
23
+
24
+ // Clear out the empty list element that's there for HTML validation purposes
25
+ $("#regenthumbs-debuglist li").remove();
26
+ $("#regenthumbs-debuglist").hide();
27
+
28
+ // Called after each resize. Updates debug information and the progress bar.
29
+ function RegenThumbsUpdateStatus(id, success, response) {
30
+ $("#regenthumbs-bar").progressbar("value", (rt_count / rt_total) * 100);
31
+ rt_count = rt_count + 1;
32
+
33
+ if (success) {
34
+ rt_successes = rt_successes + 1;
35
+ $("#regenthumbs-debug-successcount").html(rt_successes);
36
+ $("#regenthumbs-debuglist").append("<li>" + response.success + "</li>");
37
+ }
38
+ else {
39
+ rt_errors = rt_errors + 1;
40
+ rt_failedlist = rt_failedlist + ',' + id;
41
+ $("#regenthumbs-debug-failurecount").html(rt_errors);
42
+ $("#regenthumbs-debuglist").append("<li>" + response.error + "</li>");
43
+ }
44
+ $("#regenthumbs-debuglist").show();
45
+ }
46
+
47
+ // Called when all images have been processed. Shows the results and cleans up.
48
+ function RegenThumbsFinishUp() {
49
+ rt_timeend = new Date().getTime();
50
+ rt_totaltime = Math.round((rt_timeend - rt_timestart) / 1000);
51
+
52
+ $('#regenthumbs-stop').hide();
53
+
54
+ if (rt_errors > 0 && rt_failedlist ) {
55
+ $("#frt-retry-images").prop('href', $("#frt-retry-images").prop('href') + '&ids=' + rt_failedlist );
56
+ $("#frt-retry-container").show();
57
+ }
58
+
59
+ $("#frt-message").show();
60
+ }
61
+
62
+ // Regenerate a specified image via AJAX
63
+ function RegenThumbs(id) {
64
+ $.ajax({
65
+ type: 'POST',
66
+ cache: false,
67
+ url: ajaxurl,
68
+ data: { action: "regeneratethumbnail", id: id, frt_wpnonce: regen_thumbs._wpnonce },
69
+ success: function(response) {
70
+
71
+ //Catch unknown error
72
+ if(response === null) {
73
+ response = {};
74
+ response.success = false;
75
+ response.error = regen_thumbs.unknown_error;
76
+ }
77
+
78
+ if (response.success) {
79
+ RegenThumbsUpdateStatus(id, true, response);
80
+ } else {
81
+ RegenThumbsUpdateStatus(id, false, response);
82
+ }
83
+
84
+ if (rt_images.length && rt_continue) {
85
+ RegenThumbs(rt_images.shift());
86
+ } else {
87
+ RegenThumbsFinishUp();
88
+ }
89
+ },
90
+ error: function(request,response,error) {
91
+ var error_response = { error: response + ': ' + request.status + ' ' + error };
92
+ RegenThumbsUpdateStatus(id, false, error_response);
93
+
94
+ if (rt_images.length && rt_continue) {
95
+ RegenThumbs(rt_images.shift());
96
+ } else {
97
+ RegenThumbsFinishUp();
98
+ }
99
+ }
100
+ });
101
+ }
102
+
103
+ RegenThumbs(rt_images.shift());
104
+ });
changelog.txt ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ = 2.1.0 =
2
+ * added: PHP 8.0 compatibility
3
+ * added: support generating thumbnails from original (pre-scaled), on by default
4
+ * added: support for PDF thumbnail generation
5
+ * added: ability to skip an image by regenerate_thumbs_skip_image filter
6
+ * changed: escape all output, sanitize all input
7
+ * changed: ensure all strings are i18n
8
+ * changed: remove HTML from i18n strings
9
+ * changed: improve path lookup function
10
+ * fixed: call to set_time_limit() when it is not allowed
11
+
12
+ = 2.0.6 =
13
+ * Add PHP7 compatibility
14
+
15
+ = 2.0.5 =
16
+ * No timeout limit
17
+
18
+ = 2.0.4 =
19
+ * Fix issue when "opendir()" return FALSE (thanks Krody Robert)
20
+
21
+ = 2.0.3 =
22
+ * Add debug information on regenerate
23
+ * Fix issue with update "_wp_attachment_metadata" and "_wp_attached_file" on windows
24
+
25
+ = 2.0.2 =
26
+ * New style for results (thanks @justonarnar)
27
+ * Automatic update "_wp_attachment_metadata" and "_wp_attached_file" (thanks @norecipes)
28
+
29
+ = 2.0.1 =
30
+ * Fix issue with get_option('upload_path') in Wordpress 3.5+ (thanks @DavidLingren)
31
+
32
+ = 2.0.0 =
33
+ * Fix error handle
34
+
35
+ = 1.8 =
36
+ * New function to display ajax results
37
+
38
+ = 1.7 =
39
+ * Fix issue with getters path in Linux/Windows/Unix servers
40
+
41
+ = 1.6 =
42
+ * New CORE to regenerate thumbnails
43
+
44
+ = 1.5 =
45
+ * Reviewed some messages
46
+
47
+ = 1.4 =
48
+ * Change default image editor to GD in Wordpress 3.5+ (thanks @nikcree)
49
+
50
+ = 1.3 =
51
+ * Fix message error when WP_DEBUG in wp_config.php
52
+
53
+ = 1.2 =
54
+ * Fix for JPEG images
55
+
56
+ = 1.1 =
57
+ * Delete all custom image sizes when regenerate thumbnails
58
+ * Notifies you when thumbnails was deleted
59
+
60
+ = 1.0 =
61
+ * First release.
class-forceregeneratethumbnails.php ADDED
@@ -0,0 +1,920 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Main class for Force Regenerate Thumbnails.
4
+ *
5
+ * @link https://wordpress.org/plugins/force-regenerate-thumbnails/
6
+ * @package ForceRegenerateThumbnails
7
+ */
8
+
9
+ /**
10
+ * Force Regenerate Thumbnails
11
+ *
12
+ * @since 1.0
13
+ */
14
+ class ForceRegenerateThumbnails {
15
+
16
+ /**
17
+ * Register ID of management page, or false if the user has no permissions.
18
+ *
19
+ * @access public
20
+ * @var string|bool $menu_id
21
+ * @since 1.0
22
+ */
23
+ public $menu_id;
24
+
25
+ /**
26
+ * User capability required to use this plugin.
27
+ *
28
+ * @access public
29
+ * @var string $capability
30
+ * @since 1.0
31
+ */
32
+ public $capability;
33
+
34
+ /**
35
+ * Version of the plugin.
36
+ *
37
+ * @access public
38
+ * @var float VERSION
39
+ * @since 2.1.0
40
+ */
41
+ const VERSION = 210;
42
+
43
+ /**
44
+ * Plugin initialization
45
+ *
46
+ * @access public
47
+ * @since 1.0
48
+ */
49
+ function __construct() {
50
+
51
+ add_action( 'admin_menu', array( &$this, 'add_admin_menu' ) );
52
+ add_action( 'admin_enqueue_scripts', array( &$this, 'admin_enqueues' ) );
53
+ add_action( 'wp_ajax_regeneratethumbnail', array( &$this, 'ajax_process_image' ) );
54
+ add_filter( 'media_row_actions', array( &$this, 'add_media_row_action' ), 10, 2 );
55
+ add_filter( 'bulk_actions-upload', array( &$this, 'add_bulk_actions' ) );
56
+ add_filter( 'handle_bulk_actions-upload', array( &$this, 'bulk_action_handler' ), 10, 3 );
57
+
58
+ // Allow people to change what capability is required to use this plugin.
59
+ $this->capability = apply_filters( 'regenerate_thumbs_cap', 'manage_options' );
60
+ }
61
+
62
+ /**
63
+ * Register the management page
64
+ *
65
+ * @access public
66
+ * @since 1.0
67
+ */
68
+ function add_admin_menu() {
69
+ $this->menu_id = add_management_page(
70
+ __( 'Force Regenerate Thumbnails', 'force-regenerate-thumbnails' ),
71
+ __( 'Force Regenerate Thumbnails', 'force-regenerate-thumbnails' ),
72
+ $this->capability,
73
+ 'force-regenerate-thumbnails',
74
+ array( &$this, 'force_regenerate_interface' )
75
+ );
76
+ }
77
+
78
+ /**
79
+ * Enqueue the needed Javascript and CSS
80
+ *
81
+ * @param string $hook_suffix The hook suffix for the current admin page.
82
+ * @access public
83
+ * @since 1.0
84
+ */
85
+ function admin_enqueues( $hook_suffix ) {
86
+
87
+ if ( $hook_suffix !== $this->menu_id ) {
88
+ return;
89
+ }
90
+
91
+ global $wpdb;
92
+
93
+ wp_enqueue_style( 'jquery-ui-force-regen', plugins_url( 'assets/jquery-ui-1.10.1.custom.css', __FILE__ ), array(), self::VERSION );
94
+ wp_enqueue_script( 'force-regen-script', plugins_url( 'assets/regen.js', __FILE__ ), array( 'jquery-ui-progressbar' ), self::VERSION );
95
+ // If the button was clicked.
96
+ if ( ! empty( $_POST['force-regenerate-thumbnails'] ) || ! empty( $_REQUEST['ids'] ) ) {
97
+
98
+ // Capability check.
99
+ if ( ! current_user_can( $this->capability ) ) {
100
+ wp_die( esc_html__( 'Access denied.', 'force-regenerate-thumbnails' ) );
101
+ }
102
+
103
+ // Form nonce check.
104
+ check_admin_referer( 'force-regenerate-thumbnails' );
105
+
106
+ // Create the list of image IDs.
107
+ $images = array();
108
+ if (
109
+ ! empty( $_REQUEST['ids'] ) &&
110
+ (
111
+ preg_match( '/^[\d,]+$/', trim( sanitize_text_field( wp_unslash( $_REQUEST['ids'] ) ), ',' ), $request_ids ) ||
112
+ is_numeric( trim( sanitize_text_field( wp_unslash( $_REQUEST['ids'] ) ), ',' ) )
113
+ )
114
+ ) {
115
+ if ( is_numeric( trim( sanitize_text_field( wp_unslash( $_REQUEST['ids'] ) ), ',' ) ) ) {
116
+ $images[] = (int) trim( sanitize_text_field( wp_unslash( $_REQUEST['ids'] ) ), ',' );
117
+ } else {
118
+ $images = explode( ',', $request_ids[0] );
119
+ array_walk( $images, 'intval' );
120
+ }
121
+ $ids = implode( ',', $images );
122
+ } else {
123
+
124
+ // Directly querying the database is normally frowned upon, but all
125
+ // of the API functions will return the full post objects which will
126
+ // suck up lots of memory. This is best, just not as future proof.
127
+ if ( extension_loaded( 'imagick' ) ) {
128
+ $images = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND (post_mime_type LIKE '%%image%%' OR post_mime_type LIKE '%%pdf%%') ORDER BY ID DESC" );
129
+ } else {
130
+ $images = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE '%%image%%' ORDER BY ID DESC" );
131
+ }
132
+ if ( empty( $images ) ) {
133
+ return;
134
+ }
135
+
136
+ $ids = implode( ',', $images );
137
+ }
138
+
139
+ $this->image_count = count( $images );
140
+
141
+ wp_localize_script(
142
+ 'force-regen-script',
143
+ 'regen_thumbs',
144
+ array(
145
+ '_wpnonce' => wp_create_nonce( 'force-regenerate-attachment' ),
146
+ 'image_ids' => $images,
147
+ 'image_count' => $this->image_count,
148
+ 'stopping' => esc_html__( 'Stopping...', 'force-regenerate-thumbnails' ),
149
+ 'unknown_error' => esc_html__( 'Unknown error occured.', 'force-regenerate-thumbnails' ),
150
+ )
151
+ );
152
+ $this->get_admin_colors();
153
+ wp_add_inline_style( 'jquery-ui-force-regen', '.ui-widget-header { background-color: ' . $this->admin_color . '; }' );
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Grabs the color scheme information from the current admin theme.
159
+ *
160
+ * @global array $_wp_admin_css_colors An array of available admin color/theme objects.
161
+ */
162
+ function get_admin_colors() {
163
+ if ( ! empty( $this->admin_color ) && preg_match( '/^\#([0-9a-fA-F]){3,6}$/', $this->admin_color ) ) {
164
+ return;
165
+ }
166
+ global $_wp_admin_css_colors;
167
+ if ( function_exists( 'wp_add_inline_style' ) ) {
168
+ $user_info = wp_get_current_user();
169
+ if (
170
+ is_array( $_wp_admin_css_colors ) &&
171
+ ! empty( $user_info->admin_color ) &&
172
+ isset( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
173
+ is_object( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
174
+ is_array( $_wp_admin_css_colors[ $user_info->admin_color ]->colors ) &&
175
+ ! empty( $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] ) &&
176
+ preg_match( '/^\#([0-9a-fA-F]){3,6}$/', $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] )
177
+ ) {
178
+ $this->admin_color = $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2];
179
+ return;
180
+ }
181
+ switch ( $user_info->admin_color ) {
182
+ case 'midnight':
183
+ $this->admin_color = '#e14d43';
184
+ break;
185
+ case 'blue':
186
+ $this->admin_color = '#096484';
187
+ break;
188
+ case 'light':
189
+ $this->admin_color = '#04a4cc';
190
+ break;
191
+ case 'ectoplasm':
192
+ $this->admin_color = '#a3b745';
193
+ break;
194
+ case 'coffee':
195
+ $this->admin_color = '#c7a589';
196
+ break;
197
+ case 'ocean':
198
+ $this->admin_color = '#9ebaa0';
199
+ break;
200
+ case 'sunrise':
201
+ $this->admin_color = '#dd823b';
202
+ break;
203
+ default:
204
+ $this->admin_color = '#0073aa';
205
+ }
206
+ }
207
+ if ( empty( $this->admin_color ) ) {
208
+ $this->admin_color = '#0073aa';
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Add a "Force Regenerate Thumbnails" link to the media row actions
214
+ *
215
+ * @param array $actions A list of existing Media row actions.
216
+ * @param WP_Post $post The current attachment/post object.
217
+ * @return array
218
+ * @access public
219
+ * @since 1.0
220
+ */
221
+ function add_media_row_action( $actions, $post ) {
222
+ if ( 'application/pdf' === $post->post_mime_type && ! extension_loaded( 'imagick' ) ) {
223
+ return $actions;
224
+ }
225
+ if ( 'image/svg+xml' === $post->post_mime_type ) {
226
+ return $actions;
227
+ }
228
+ if (
229
+ ( 'application/pdf' === $post->post_mime_type || 'image/' === substr( $post->post_mime_type, 0, 6 ) ) &&
230
+ current_user_can( $this->capability )
231
+ ) {
232
+ $url = wp_nonce_url(
233
+ add_query_arg(
234
+ array(
235
+ 'page' => 'force-regenerate-thumbnails',
236
+ 'goback' => add_query_arg( null, null ),
237
+ 'ids' => (int) $post->ID,
238
+ ),
239
+ admin_url( 'tools.php' ),
240
+ ),
241
+ 'force-regenerate-thumbnails'
242
+ );
243
+
244
+ $actions['regenerate_thumbnails'] = '<a href="' . esc_url( $url ) . '" title="' . esc_attr__( 'Regenerate the thumbnails for this single image', 'force-regenerate-thumbnails' ) . '">' . __( 'Force Regenerate Thumbnails', 'force-regenerate-thumbnails' ) . '</a>';
245
+ }
246
+
247
+ return $actions;
248
+ }
249
+
250
+ /**
251
+ * Add "Force Regenerate Thumbnails" to the Bulk Actions media dropdown
252
+ *
253
+ * @param array $actions Bulk actions list.
254
+ * @return array
255
+ * @access public
256
+ * @since 1.0
257
+ */
258
+ function add_bulk_actions( $actions ) {
259
+
260
+ $delete = false;
261
+ if ( ! empty( $actions['delete'] ) ) {
262
+ $delete = $actions['delete'];
263
+ unset( $actions['delete'] );
264
+ }
265
+
266
+ $actions['bulk_force_regenerate_thumbnails'] = __( 'Force Regenerate Thumbnails', 'force-regenerate-thumbnails' );
267
+
268
+ if ( $delete ) {
269
+ $actions['delete'] = $delete;
270
+ }
271
+
272
+ return $actions;
273
+ }
274
+
275
+ /**
276
+ * Handles the bulk actions POST
277
+ *
278
+ * @access public
279
+ * @since 1.0
280
+ *
281
+ * @param string $redirect_to The URL from whence we came.
282
+ * @param string $doaction The action requested.
283
+ * @param array $post_ids An array of attachment ID numbers.
284
+ * @return string The URL to go back to when we are done handling the action.
285
+ */
286
+ function bulk_action_handler( $redirect_to, $doaction, $post_ids ) {
287
+ if ( empty( $doaction ) || 'bulk_force_regenerate_thumbnails' !== $doaction ) {
288
+ return $redirect_to;
289
+ }
290
+
291
+ if ( empty( $post_ids ) || ! is_array( $post_ids ) ) {
292
+ return $redirect_to;
293
+ }
294
+
295
+ check_admin_referer( 'bulk-media' );
296
+ $ids = implode( ',', array_map( 'intval', $post_ids ) );
297
+
298
+ return add_query_arg(
299
+ array(
300
+ '_wpnonce' => wp_create_nonce( 'force-regenerate-thumbnails' ),
301
+ 'page' => 'force-regenerate-thumbnails',
302
+ 'ids' => $ids,
303
+ 'goback' => esc_url( wp_get_referer() ),
304
+ ),
305
+ admin_url( 'tools.php' )
306
+ );
307
+ }
308
+
309
+
310
+ /**
311
+ * The user interface plus thumbnail regenerator
312
+ *
313
+ * @access public
314
+ * @since 1.0
315
+ */
316
+ function force_regenerate_interface() {
317
+ $retry_url = wp_nonce_url(
318
+ admin_url( 'tools.php?page=force-regenerate-thumbnails' ),
319
+ 'force-regenerate-thumbnails'
320
+ );
321
+ ?>
322
+
323
+ <div id="frt-message" class="notice notice-success is-dismissible" style="display:none">
324
+ <p><strong><?php esc_html_e( 'All done!', 'force-regenerate-thumbnails' ); ?></strong>
325
+ <?php if ( ! empty( $_GET['goback'] ) ) : ?>
326
+ <a href=<?php echo '"' . esc_url( sanitize_url( wp_unslash( $_GET['goback'] ) ) ) . '"'; ?>><?php esc_html_e( 'Go back to the previous page.', 'force-regenerate-thumbnails' ); ?></a>
327
+ <?php endif; ?>
328
+ </p>
329
+ <p id="frt-retry-container" style="display:none">
330
+ <a id="frt-retry-images" href="<?php echo esc_url( $retry_url ); ?>" class="button-secondary"><?php esc_html_e( 'Retry Failed Images', 'force-regenerate-thumbnails' ); ?></a>
331
+ </p>
332
+ </div>
333
+
334
+ <div class="wrap regenthumbs">
335
+ <h2><?php esc_html_e( 'Force Regenerate Thumbnails', 'force-regenerate-thumbnails' ); ?></h2>
336
+
337
+ <?php
338
+ // If the button was clicked.
339
+ if ( ! empty( $_POST['force-regenerate-thumbnails'] ) || ! empty( $_REQUEST['ids'] ) ) {
340
+
341
+ // Capability check.
342
+ if ( ! current_user_can( $this->capability ) ) {
343
+ wp_die( esc_html__( 'Access denied.', 'force-regenerate-thumbnails' ) );
344
+ }
345
+
346
+ // Form nonce check.
347
+ check_admin_referer( 'force-regenerate-thumbnails' );
348
+ if ( empty( $this->image_count ) ) {
349
+ echo '<p>' . esc_html__( 'You do not appear to have uploaded any images or PDF files yet.', 'force-regenerate-thumbnails' ) . '</p></div>';
350
+ return;
351
+ }
352
+ ?>
353
+
354
+ <p><?php esc_html_e( 'Please be patient while the thumbnails are regenerated. Details will be displayed below as each image is completed.', 'force-regenerate-thumbnails' ); ?></p>
355
+
356
+ <noscript><p><em><?php esc_html_e( 'You must enable Javascript in order to proceed!', 'force-regenerate-thumbnails' ); ?></em></p></noscript>
357
+
358
+ <div id="regenthumbs-bar" style="position:relative;height:25px;">
359
+ </div>
360
+
361
+ <p><input type="button" class="button hide-if-no-js" name="regenthumbs-stop" id="regenthumbs-stop" value="<?php esc_html_e( 'Abort Process', 'force-regenerate-thumbnails' ); ?>" /></p>
362
+
363
+ <h3 class="title"><?php esc_html_e( 'Process Information', 'force-regenerate-thumbnails' ); ?></h3>
364
+
365
+ <p>
366
+ <?php
367
+ /* translators: %d: the total number of images */
368
+ printf( esc_html__( 'Total: %s', 'force-regenerate-thumbnails' ), '<span id="regenthumbs-debug-totalcount">' . (int) $this->image_count . '</span>' );
369
+ echo '<br>';
370
+ /* translators: %d: the number of successfully regenerated images */
371
+ printf( esc_html__( 'Success: %s', 'force-regenerate-thumbnails' ), '<span id="regenthumbs-debug-successcount">0</span>' );
372
+ echo '<br>';
373
+ /* translators: %d: the number of regeneration failures */
374
+ printf( esc_html__( 'Failure: %s', 'force-regenerate-thumbnails' ), '<span id="regenthumbs-debug-failurecount">0</span>' );
375
+ ?>
376
+ </p>
377
+
378
+ <ol id="regenthumbs-debuglist">
379
+ <li style="display:none"></li>
380
+ </ol>
381
+
382
+ <?php
383
+ } else {
384
+ // No button click? Display the form.
385
+ ?>
386
+ <form method="post" action="">
387
+ <?php wp_nonce_field( 'force-regenerate-thumbnails' ); ?>
388
+
389
+ <h3><?php esc_html_e( 'All Thumbnails', 'force-regenerate-thumbnails' ); ?></h3>
390
+
391
+ <p>
392
+ <?php esc_html_e( 'You may regenerate thumbnails for all images that you have uploaded to your blog.', 'force-regenerate-thumbnails' ); ?><br>
393
+ <?php esc_html_e( 'Be sure to backup your site before you begin.', 'force-regenerate-thumbnails' ); ?>
394
+ </p>
395
+
396
+ <p>
397
+ <noscript><p><em><?php esc_html_e( 'You must enable Javascript in order to proceed!', 'force-regenerate-thumbnails' ); ?></em></p></noscript>
398
+ <input type="submit" class="button-primary hide-if-no-js" name="force-regenerate-thumbnails" id="force-regenerate-thumbnails" value="<?php esc_attr_e( 'Regenerate All Thumbnails', 'force-regenerate-thumbnails' ); ?>" />
399
+ </p>
400
+
401
+ </br>
402
+ <h3><?php esc_html_e( 'Specific Thumbnails', 'force-regenerate-thumbnails' ); ?></h3>
403
+
404
+ <p>
405
+ <?php /* translators: %s: Media Library (link) */ ?>
406
+ <?php printf( esc_html__( 'You may regenerate thumbnails for specific images from the %s in List mode.', 'force-regenerate-thumbnails' ), '<a href="' . esc_url( admin_url( 'upload.php?mode=list' ) ) . '">' . esc_html__( 'Media Library', 'force-regenerate-thumbnails' ) . '</a>' ); ?>
407
+ <?php esc_html_e( 'Be sure to backup your site before you begin.', 'force-regenerate-thumbnails' ); ?>
408
+ </p>
409
+ </form>
410
+ <?php
411
+ } // End if button
412
+ ?>
413
+ <?php if ( ! function_exists( 'ewww_image_optimizer' ) ) : ?>
414
+ <p>
415
+ <?php
416
+ printf(
417
+ /* translators: %s: link to install EWWW Image Optimizer plugin */
418
+ esc_html__( 'Install the free %s for sharper thumbnails, better compression, and to control which thumbnails are created.', 'force-regenerate-thumbnails' ),
419
+ '<a href="' . esc_url( admin_url( 'plugin-install.php?s=ewww+image+optimizer&tab=search&type=term' ) ) . '">EWWW Image Optimizer</a>'
420
+ );
421
+ ?>
422
+ </p>
423
+ <?php endif; ?>
424
+ </div>
425
+
426
+ <?php
427
+ }
428
+
429
+
430
+ /**
431
+ * Process a single image ID (this is an AJAX handler)
432
+ *
433
+ * @access public
434
+ * @since 1.0
435
+ * @throws Exception Any time we find an image we can't handle: permissions, corruption, doesn't exist, etc.
436
+ */
437
+ function ajax_process_image() {
438
+ if ( empty( $_REQUEST['id'] ) ) {
439
+ $this->ob_clean();
440
+ wp_die( wp_json_encode( array( 'error' => esc_html__( 'No attachment ID submitted.', 'force-regenerate-thumbnails' ) ) ) );
441
+ }
442
+
443
+ // No timeout limit.
444
+ if ( $this->stl_check() ) {
445
+ set_time_limit( 0 );
446
+ }
447
+
448
+ // Don't break the JSON result.
449
+ error_reporting( 0 );
450
+ $id = (int) $_REQUEST['id'];
451
+
452
+ try {
453
+ header( 'Content-type: application/json' );
454
+ if ( ! current_user_can( $this->capability ) ) {
455
+ throw new Exception( esc_html__( 'Your user account does not have permission to regenerate thumbnails.', 'force-regenerate-thumbnails' ) );
456
+ }
457
+ if ( empty( $_REQUEST['frt_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['frt_wpnonce'] ), 'force-regenerate-attachment' ) ) {
458
+ throw new Exception( esc_html__( 'Access token has expired, please reload the page.', 'force-regenerate-thumbnails' ) );
459
+ }
460
+
461
+ if ( apply_filters( 'regenerate_thumbs_skip_image', false, $id ) ) {
462
+ die(
463
+ wp_json_encode(
464
+ array(
465
+ /* translators: %d: attachment ID number */
466
+ 'success' => '<div id="message" class="notice notice-info"><p>' . sprintf( esc_html__( 'Skipped: %d', 'force-regenerate-thumbnails' ), (int) $id ) . '</p></div>',
467
+ )
468
+ )
469
+ );
470
+ }
471
+
472
+ $image = get_post( $id );
473
+
474
+ if ( is_null( $image ) ) {
475
+ /* translators: %d: attachment ID number */
476
+ throw new Exception( sprintf( esc_html__( 'Failed: %d is an invalid media ID.', 'force-regenerate-thumbnails' ), (int) $id ) );
477
+ }
478
+
479
+ if ( 'attachment' !== $image->post_type || ( 'image/' !== substr( $image->post_mime_type, 0, 6 ) && 'application/pdf' !== $image->post_mime_type ) ) {
480
+ /* translators: %d: attachment ID number */
481
+ throw new Exception( sprintf( esc_html__( 'Failed: %d is an invalid media ID.', 'force-regenerate-thumbnails' ), (int) $id ) );
482
+ }
483
+
484
+ if ( 'application/pdf' === $image->post_mime_type && ! extension_loaded( 'imagick' ) ) {
485
+ throw new Exception( esc_html__( 'Failed: The imagick extension is required for PDF files.', 'force-regenerate-thumbnails' ) );
486
+ }
487
+
488
+ if ( 'image/svg+xml' === $image->post_mime_type ) {
489
+ die(
490
+ wp_json_encode(
491
+ array(
492
+ /* translators: %d: attachment ID number */
493
+ 'success' => '<div id="message" class="notice notice-info"><p>' . sprintf( esc_html__( 'Skipped: %d is a SVG', 'force-regenerate-thumbnails' ), (int) $id ) . '</p></div>',
494
+ )
495
+ )
496
+ );
497
+ }
498
+
499
+ $upload_dir = wp_get_upload_dir();
500
+ $meta = wp_get_attachment_metadata( $image->ID );
501
+
502
+ // Get full-size image.
503
+ $image_fullpath = $this->get_attachment_path( $image->ID, $meta );
504
+
505
+ $debug_1 = $image_fullpath;
506
+ $debug_2 = '';
507
+ $debug_3 = '';
508
+ $debug_4 = '';
509
+
510
+ // Didn't get a valid image path.
511
+ if ( empty( $image_fullpath ) || false === realpath( $image_fullpath ) ) {
512
+ throw new Exception( esc_html__( 'The originally uploaded image file cannot be found.', 'force-regenerate-thumbnails' ) );
513
+ }
514
+
515
+ $thumb_deleted = array();
516
+ $thumb_error = array();
517
+ $thumb_regenerate = array();
518
+
519
+ /**
520
+ * Try delete all thumbnails
521
+ */
522
+ if ( ! empty( $meta['sizes'] ) && is_iterable( $meta['sizes'] ) ) {
523
+ foreach ( $meta['sizes'] as $size_data ) {
524
+ if ( empty( $size_data['file'] ) ) {
525
+ continue;
526
+ }
527
+ $thumb_fullpath = trailingslashit( $file_info['dirname'] ) . wp_basename( $size_data['file'] );
528
+ if ( apply_filters( 'regenerate_thumbs_weak', false, $thumb_fullpath ) ) {
529
+ continue;
530
+ }
531
+ if ( $thumb_fullpath !== $image_fullpath && is_file( $thumb_fullpath ) ) {
532
+ do_action( 'regenerate_thumbs_pre_delete', $thumb_fullpath );
533
+ unlink( $thumb_fullpath );
534
+ if ( is_file( $thumb_fullpath . '.webp' ) ) {
535
+ unlink( $thumb_fullpath . '.webp' );
536
+ }
537
+ clearstatcache();
538
+ do_action( 'regenerate_thumbs_post_delete', $thumb_fullpath );
539
+ if ( ! is_file( $thumb_fullpath ) ) {
540
+ $thumb_deleted[] = sprintf( '%dx%d', $size_data['width'], $size_data['height'] );
541
+ } else {
542
+ $thumb_error[] = sprintf( '%dx%d', $size_data['width'], $size_data['height'] );
543
+ }
544
+ }
545
+ }
546
+ }
547
+
548
+ // Hack to find thumbnail.
549
+ $file_info = pathinfo( $image_fullpath );
550
+ $file_stem = $this->remove_from_end( $file_info['filename'], '-scaled' ) . '-';
551
+
552
+ $files = array();
553
+ $path = opendir( $file_info['dirname'] );
554
+
555
+ if ( false !== $path ) {
556
+ $thumb = readdir( $path );
557
+ while ( false !== $thumb ) {
558
+ if ( 0 === strpos( $thumb, $file_stem ) && str_ends_with( $thumb, $file_info['extension'] ) ) {
559
+ $files[] = $thumb;
560
+ }
561
+ $thumb = readdir( $path );
562
+ }
563
+ closedir( $path );
564
+ sort( $files );
565
+ }
566
+
567
+ foreach ( $files as $thumb ) {
568
+ $thumb_fullpath = trailingslashit( $file_info['dirname'] ) . $thumb;
569
+ if ( apply_filters( 'regenerate_thumbs_weak', false, $thumb_fullpath ) ) {
570
+ continue;
571
+ }
572
+
573
+ $thumb_info = pathinfo( $thumb_fullpath );
574
+ $valid_thumb = explode( $file_stem, $thumb_info['filename'] );
575
+ if ( '' === $valid_thumb[0] && ! empty( $valid_thumb[1] ) ) {
576
+ if ( 0 === strpos( $valid_thumb[1], 'scaled-' ) ) {
577
+ $valid_thumb[1] = str_replace( 'scaled-', '', $valid_thumb[1] );
578
+ }
579
+ $dimension_thumb = explode( 'x', $valid_thumb[1] );
580
+ if ( 2 === count( $dimension_thumb ) ) {
581
+ if ( is_numeric( $dimension_thumb[0] ) && is_numeric( $dimension_thumb[1] ) ) {
582
+ do_action( 'regenerate_thumbs_pre_delete', $thumb_fullpath );
583
+ unlink( $thumb_fullpath );
584
+ if ( is_file( $thumb_fullpath . '.webp' ) ) {
585
+ unlink( $thumb_fullpath . '.webp' );
586
+ }
587
+ clearstatcache();
588
+ do_action( 'regenerate_thumbs_post_delete', $thumb_fullpath );
589
+ if ( ! is_file( $thumb_fullpath ) ) {
590
+ $thumb_deleted[] = sprintf( '%dx%d', $dimension_thumb[0], $dimension_thumb[1] );
591
+ } else {
592
+ $thumb_error[] = sprintf( '%dx%d', $dimension_thumb[0], $dimension_thumb[1] );
593
+ }
594
+ }
595
+ }
596
+ }
597
+ }
598
+
599
+ /**
600
+ * Regenerate all thumbnails
601
+ */
602
+ if ( function_exists( 'wp_get_original_image_path' ) ) {
603
+ $original_path = apply_filters( 'regenerate_thumbs_original_image', wp_get_original_image_path( $image->ID, true ) );
604
+ }
605
+ if ( empty( $original_path ) || ! is_file( $original_path ) ) {
606
+ $original_path = $image_fullpath;
607
+ }
608
+
609
+ $metadata = wp_generate_attachment_metadata( $image->ID, $original_path );
610
+ if ( is_wp_error( $metadata ) ) {
611
+ throw new Exception( esc_html( $metadata->get_error_message() ) );
612
+ }
613
+ if ( empty( $metadata ) ) {
614
+ throw new Exception( esc_html__( 'Unknown failure.', 'force-regenerate-thumbnails' ) );
615
+ }
616
+ wp_update_attachment_metadata( $image->ID, $metadata );
617
+ do_action( 'regenerate_thumbs_post_update', $image->ID, $original_path );
618
+
619
+ /**
620
+ * Verify results (deleted, errors, success)
621
+ */
622
+ $files = array();
623
+ $path = opendir( $file_info['dirname'] );
624
+ if ( false !== $path ) {
625
+ $thumb = readdir( $path );
626
+ while ( false !== $thumb ) {
627
+ /* if ( ! ( strrpos( $thumb, $file_info['filename'] ) === false ) ) { */
628
+ if ( 0 === strpos( $thumb, $file_stem ) && str_ends_with( $thumb, $file_info['extension'] ) ) {
629
+ $files[] = $thumb;
630
+ }
631
+ $thumb = readdir( $path );
632
+ }
633
+ closedir( $path );
634
+ sort( $files );
635
+ }
636
+ if ( ! empty( $metadata['sizes'] ) && is_iterable( $metadata['sizes'] ) ) {
637
+ foreach ( $metadata['sizes'] as $size_data ) {
638
+ if ( empty( $size_data['file'] ) ) {
639
+ continue;
640
+ }
641
+ if ( in_array( $size_data['file'], $files, true ) ) {
642
+ continue;
643
+ }
644
+ $thumb_regenerate[] = sprintf( '%dx%d', $size_data['width'], $size_data['height'] );
645
+ }
646
+ }
647
+
648
+ foreach ( $files as $thumb ) {
649
+ $thumb_fullpath = trailingslashit( $file_info['dirname'] ) . $thumb;
650
+ $thumb_info = pathinfo( $thumb_fullpath );
651
+ $valid_thumb = explode( $file_stem, $thumb_info['filename'] );
652
+ if ( '' === $valid_thumb[0] ) {
653
+ $dimension_thumb = explode( 'x', $valid_thumb[1] );
654
+ if ( 2 === count( $dimension_thumb ) ) {
655
+ if ( is_numeric( $dimension_thumb[0] ) && is_numeric( $dimension_thumb[1] ) ) {
656
+ $thumb_regenerate[] = sprintf( '%dx%d', $dimension_thumb[0], $dimension_thumb[1] );
657
+ }
658
+ }
659
+ }
660
+ }
661
+
662
+ // Remove success if has in error list.
663
+ foreach ( $thumb_regenerate as $key => $regenerate ) {
664
+ if ( in_array( $regenerate, $thumb_error, true ) ) {
665
+ unset( $thumb_regenerate[ $key ] );
666
+ }
667
+ }
668
+
669
+ // Remove deleted if has in success list, so that we only show those that were no longer registered.
670
+ foreach ( $thumb_deleted as $key => $deleted ) {
671
+ if ( in_array( $deleted, $thumb_regenerate, true ) ) {
672
+ unset( $thumb_deleted[ $key ] );
673
+ }
674
+ }
675
+
676
+ /**
677
+ * Display results
678
+ */
679
+ ob_start(); // To suppress any error output.
680
+ $message = '<strong>' .
681
+ sprintf(
682
+ /* translators: 1: attachment title 2: attachment ID number */
683
+ esc_html__( '%1$s (ID %2$d)', 'force-regenerate-thumbnails' ),
684
+ esc_html( get_the_title( $id ) ),
685
+ (int) $image->ID
686
+ ) .
687
+ '</strong>';
688
+ $message .= '<br><br>';
689
+ /* translators: %s: the path to the uploads directory */
690
+ $message .= '<code>' . sprintf( esc_html__( 'Upload Directory: %s', 'force-regenerate-thumbnails' ), esc_html( $upload_dir['basedir'] ) ) . '</code><br>';
691
+ /* translators: %s: the base URL of the uploads directory */
692
+ $message .= '<code>' . sprintf( esc_html__( 'Upload URL: %s', 'force-regenerate-thumbnails' ), esc_html( $upload_dir['baseurl'] ) ) . '</code><br>';
693
+ /* translators: %s: the full path of the image */
694
+ $message .= '<code>' . sprintf( esc_html__( 'Image: %s', 'force-regenerate-thumbnails' ), esc_html( $debug_1 ) ) . '</code><br>';
695
+ if ( $debug_2 ) {
696
+ /* translators: %s: debug info, if populated */
697
+ $message .= '<code>' . sprintf( esc_html__( 'Image Debug 2: %s', 'force-regenerate-thumbnails' ), esc_html( $debug_2 ) ) . '</code><br>';
698
+ }
699
+ if ( $debug_3 ) {
700
+ /* translators: %s: debug info, if populated */
701
+ $message .= '<code>' . sprintf( esc_html__( 'Image Debug 3: %s', 'force-regenerate-thumbnails' ), esc_html( $debug_3 ) ) . '</code><br>';
702
+ }
703
+ if ( $debug_4 ) {
704
+ /* translators: %s: debug info, if populated */
705
+ $message .= '<code>' . sprintf( esc_html__( 'Image Debug 4: %s', 'force-regenerate-thumbnails' ), esc_html( $debug_4 ) ) . '</code><br>';
706
+ }
707
+
708
+ $message .= '<br>';
709
+
710
+ if ( count( $thumb_deleted ) > 0 ) {
711
+ /* translators: %s: list of deleted thumbs */
712
+ $message .= sprintf( esc_html__( 'Deleted: %s', 'force-regenerate-thumbnails' ), esc_html( implode( ', ', $thumb_deleted ) ) ) . '<br>';
713
+ }
714
+ if ( count( $thumb_error ) > 0 ) {
715
+ /* translators: %s: an error message (translated elsewhere) */
716
+ $message .= '<strong><span style="color: #dd3d36;">' . sprintf( esc_html__( 'Deleted error: %s', 'force-regenerate-thumbnails' ), esc_html( implode( ', ', $thumb_error ) ) ) . '</span></strong><br>';
717
+ /* translators: %s: the path to the uploads directory */
718
+ $message .= '<span style="color: #dd3d36;">' . sprintf( esc_html__( 'Please ensure the folder has write permissions (chmod 755): %s', 'force-regenerate-thumbnails' ), esc_html( $upload_dir['basedir'] ) ) . '</span><br>';
719
+ }
720
+ if ( count( $thumb_regenerate ) > 0 ) {
721
+ /* translators: %s: list of regenerated thumbs/sizes */
722
+ $message .= sprintf( esc_html__( 'Regenerate: %s', 'force-regenerate-thumbnails' ), esc_html( implode( ', ', $thumb_regenerate ) ) ) . '<br>';
723
+ if ( count( $thumb_error ) <= 0 ) {
724
+ /* translators: %s: time elapsed */
725
+ $message .= sprintf( esc_html__( 'Successfully regenerated in %s seconds', 'force-regenerate-thumbnails' ), esc_html( timer_stop() ) ) . '<br>';
726
+ }
727
+ }
728
+
729
+ $message = $this->remove_from_end( $message, '<br>' );
730
+
731
+ $this->ob_clean();
732
+ if ( count( $thumb_error ) > 0 ) {
733
+ die( wp_json_encode( array( 'error' => '<div id="message" class="notice notice-error"><p>' . $message . '</p></div>' ) ) );
734
+ } else {
735
+ die( wp_json_encode( array( 'success' => '<div id="message" class="notice notice-success"><p>' . $message . '</p></div>' ) ) );
736
+ }
737
+ } catch ( Exception $e ) {
738
+ $this->die_json_failure_msg( $id, '<b><span style="color: #DD3D36;">' . $e->getMessage() . '</span></b>' );
739
+ }
740
+ exit;
741
+ }
742
+
743
+ /**
744
+ * Retrieves the path of an attachment via the ID number.
745
+ *
746
+ * @param int $id The attachment ID number.
747
+ * @param array $meta The attachment metadata.
748
+ * @return string The full path to the image.
749
+ */
750
+ function get_attachment_path( $id, $meta ) {
751
+
752
+ // Retrieve the location of the WordPress upload folder.
753
+ $upload_dir = wp_upload_dir( null, false, true );
754
+ $upload_path = trailingslashit( $upload_dir['basedir'] );
755
+
756
+ // Get the file path from postmeta.
757
+ $file = get_post_meta( $id, '_wp_attached_file', true );
758
+ $file_path = ( 0 !== strpos( $file, '/' ) && ! preg_match( '|^.:\\\|', $file ) ? $upload_path . $file : $file );
759
+ $filtered_file_path = apply_filters( 'get_attached_file', $file_path, $id );
760
+ if (
761
+ (
762
+ ! $this->stream_wrapped( $filtered_file_path ) ||
763
+ $this->stream_wrapper_exists()
764
+ )
765
+ && is_file( $filtered_file_path )
766
+ ) {
767
+ return $filtered_file_path;
768
+ }
769
+ if (
770
+ (
771
+ ! $this->stream_wrapped( $file_path ) ||
772
+ $this->stream_wrapper_exists()
773
+ )
774
+ && is_file( $file_path )
775
+ ) {
776
+ return $file_path;
777
+ }
778
+ if ( is_array( $meta ) && ! empty( $meta['file'] ) ) {
779
+ $file_path = $meta['file'];
780
+ if ( $this->stream_wrapped( $file_path ) && ! $this->stream_wrapper_exists() ) {
781
+ return '';
782
+ }
783
+ if ( is_file( $file_path ) ) {
784
+ return $file_path;
785
+ }
786
+ $file_path = trailingslashit( $upload_path ) . $file_path;
787
+ if ( is_file( $file_path ) ) {
788
+ return $file_path;
789
+ }
790
+ $upload_path = trailingslashit( WP_CONTENT_DIR ) . 'uploads/';
791
+ $file_path = $upload_path . $meta['file'];
792
+ if ( is_file( $file_path ) ) {
793
+ return $file_path;
794
+ }
795
+ }
796
+ return '';
797
+ }
798
+
799
+ /**
800
+ * Checks the existence of a cloud storage stream wrapper.
801
+ *
802
+ * @return bool True if a supported stream wrapper is found, false otherwise.
803
+ */
804
+ function stream_wrapper_exists() {
805
+ $wrappers = stream_get_wrappers();
806
+ if ( ! is_iterable( $wrappers ) ) {
807
+ return false;
808
+ }
809
+ foreach ( $wrappers as $wrapper ) {
810
+ if ( strpos( $wrapper, 's3' ) === 0 ) {
811
+ return true;
812
+ }
813
+ if ( strpos( $wrapper, 'gs' ) === 0 ) {
814
+ return true;
815
+ }
816
+ }
817
+ return false;
818
+ }
819
+
820
+ /**
821
+ * Checks the filename for an S3 or GCS stream wrapper.
822
+ *
823
+ * @param string $filename The filename to be searched.
824
+ * @return bool True if a stream wrapper is found, false otherwise.
825
+ */
826
+ function stream_wrapped( $filename ) {
827
+ if ( false !== strpos( $filename, '://' ) ) {
828
+ if ( strpos( $filename, 's3' ) === 0 ) {
829
+ return true;
830
+ }
831
+ if ( strpos( $filename, 'gs' ) === 0 ) {
832
+ return true;
833
+ }
834
+ }
835
+ return false;
836
+ }
837
+
838
+ /**
839
+ * Trims the given 'needle' from the end of the 'haystack'.
840
+ *
841
+ * @param string $haystack The string to be modified if it contains needle.
842
+ * @param string $needle The string to remove if it is at the end of the haystack.
843
+ * @return string The haystack with needle removed from the end.
844
+ */
845
+ function remove_from_end( $haystack, $needle ) {
846
+ $needle_length = strlen( $needle );
847
+ if ( substr( $haystack, -$needle_length ) === $needle ) {
848
+ return substr( $haystack, 0, -$needle_length );
849
+ }
850
+ return $haystack;
851
+ }
852
+
853
+ /**
854
+ * Checks if a function is disabled or does not exist.
855
+ *
856
+ * @param string $function The name of a function to test.
857
+ * @param bool $debug Whether to output debugging.
858
+ * @return bool True if the function is available, False if not.
859
+ */
860
+ function function_exists( $function, $debug = false ) {
861
+ if ( extension_loaded( 'suhosin' ) && function_exists( 'ini_get' ) ) {
862
+ // phpcs:ignore WordPress.PHP.NoSilencedErrors
863
+ $suhosin_disabled = @ini_get( 'suhosin.executor.func.blacklist' );
864
+ if ( ! empty( $suhosin_disabled ) ) {
865
+ $suhosin_disabled = explode( ',', $suhosin_disabled );
866
+ $suhosin_disabled = array_map( 'trim', $suhosin_disabled );
867
+ $suhosin_disabled = array_map( 'strtolower', $suhosin_disabled );
868
+ if ( function_exists( $function ) && ! in_array( $function, $suhosin_disabled, true ) ) {
869
+ return true;
870
+ }
871
+ return false;
872
+ }
873
+ }
874
+ return \function_exists( $function );
875
+ }
876
+
877
+ /**
878
+ * Find out if set_time_limit() is allowed.
879
+ */
880
+ function stl_check() {
881
+ if ( defined( 'FTR_DISABLE_STL' ) && FTR_DISABLE_STL ) {
882
+ // set_time_limit() disabled by user.
883
+ return false;
884
+ }
885
+ if ( function_exists( 'wp_is_ini_value_changeable' ) && ! wp_is_ini_value_changeable( 'max_execution_time' ) ) {
886
+ // max_execution_time is not configurable.
887
+ return false;
888
+ }
889
+ return $this->function_exists( 'set_time_limit' );
890
+ }
891
+
892
+ /**
893
+ * Clear output buffers without throwing a fit.
894
+ */
895
+ function ob_clean() {
896
+ if ( ob_get_length() ) {
897
+ ob_end_clean();
898
+ }
899
+ }
900
+
901
+ /**
902
+ * Helper to make a JSON failure message
903
+ *
904
+ * @param integer $id An attachment ID.
905
+ * @param string $message An error message.
906
+ * @access public
907
+ * @since 1.8
908
+ */
909
+ function die_json_failure_msg( $id, $message ) {
910
+ $this->ob_clean();
911
+ die(
912
+ wp_json_encode(
913
+ array(
914
+ /* translators: %d: the attachment ID number */
915
+ 'error' => sprintf( esc_html__( '(ID %d)', 'force-regenerate-thumbnails' ), $id ) . '<br />' . $message,
916
+ )
917
+ )
918
+ );
919
+ }
920
+ }
force-regenerate-thumbnails.php CHANGED
@@ -1,713 +1,83 @@
1
- <?php
2
-
3
- /*
4
- Plugin Name: Force Regenerate Thumbnails
5
- Plugin URI: http://pedroelsner.com/2012/08/forcando-a-atualizacao-de-thumbnails-no-wordpress
6
- Description: Delete and REALLY force the regenerate thumbnail.
7
- Version: 2.0.6
8
- Author: Pedro Elsner
9
- Author URI: http://www.pedroelsner.com/
10
- */
11
-
12
-
13
- /*
14
- Bebug URL
15
- wp-admin/admin-ajax.php?action=regeneratethumbnail&id=
16
- */
17
-
18
- /**
19
- * Force GD for Image handle (WordPress 3.5 or better)
20
- * Thanks (@nikcree)
21
- *
22
- * @since 1.5
23
- */
24
- $version = get_bloginfo('version');
25
- if ($version >= 3.5) {
26
- function ms_image_editor_default_to_gd_fix( $editors ) {
27
- $gd_editor = 'WP_Image_Editor_GD';
28
-
29
- $editors = array_diff( $editors, array( $gd_editor ) );
30
- array_unshift( $editors, $gd_editor );
31
-
32
- return $editors;
33
- }
34
- add_filter('wp_image_editors', 'ms_image_editor_default_to_gd_fix');
35
- }
36
-
37
-
38
-
39
- /**
40
- * Force Regenerate Thumbnails
41
- *
42
- * @since 1.0
43
- */
44
- class ForceRegenerateThumbnails {
45
-
46
- /**
47
- * Register ID of management page
48
- *
49
- * @var
50
- * @since 1.0
51
- */
52
- var $menu_id;
53
-
54
- /**
55
- * User capability
56
- *
57
- * @access public
58
- * @since 1.0
59
- */
60
- public $capability;
61
-
62
- /**
63
- * Plugin initialization
64
- *
65
- * @access public
66
- * @since 1.0
67
- */
68
- function __construct() {
69
-
70
- load_plugin_textdomain('force-regenerate-thumbnails', false, '/force-regenerate-thumbnails/localization');
71
-
72
- add_action('admin_menu', array(&$this, 'add_admin_menu'));
73
- add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueues'));
74
- add_action('wp_ajax_regeneratethumbnail', array(&$this, 'ajax_process_image'));
75
- add_filter('media_row_actions', array(&$this, 'add_media_row_action'), 10, 2);
76
- add_action('admin_head-upload.php', array(&$this, 'add_bulk_actions_via_javascript'));
77
- add_action('admin_action_bulk_force_regenerate_thumbnails', array(&$this, 'bulk_action_handler'));
78
- add_action('admin_action_-1', array(&$this, 'bulk_action_handler'));
79
-
80
- // Allow people to change what capability is required to use this plugin
81
- $this->capability = apply_filters('regenerate_thumbs_cap', 'manage_options');
82
- }
83
-
84
- /**
85
- * Register the management page
86
- *
87
- * @access public
88
- * @since 1.0
89
- */
90
- function add_admin_menu() {
91
- $this->menu_id = add_management_page(__('Force Regenerate Thumbnails', 'force-regenerate-thumbnails' ), __( 'Force Regenerate Thumbnails', 'force-regenerate-thumbnails' ), $this->capability, 'force-regenerate-thumbnails', array(&$this, 'force_regenerate_interface') );
92
- }
93
-
94
- /**
95
- * Enqueue the needed Javascript and CSS
96
- *
97
- * @param string $hook_suffix
98
- * @access public
99
- * @since 1.0
100
- */
101
- function admin_enqueues($hook_suffix) {
102
-
103
- if ($hook_suffix != $this->menu_id) {
104
- return;
105
- }
106
-
107
- // WordPress 3.1 vs older version compatibility
108
- //if (wp_script_is('jquery-ui-widget', 'registered')) {
109
- // wp_enqueue_script('jquery-ui-progressbar', plugins_url('jquery-ui/jquery.ui.progressbar.min.js', __FILE__), array('jquery-ui-core', 'jquery-ui-widget'), '1.8.6');
110
- //} else {
111
- // wp_enqueue_script('jquery-ui-progressbar', plugins_url('jquery-ui/jquery.ui.progressbar.min.1.7.2.js', __FILE__), array('jquery-ui-core'), '1.7.2');
112
- //}
113
-
114
- wp_enqueue_script('jquery-ui-progressbar', plugins_url('jquery-ui/jquery.ui.progressbar.min.1.7.2.js', __FILE__), array('jquery-ui-core'), '1.7.2');
115
- wp_enqueue_style('jquery-ui-regenthumbs', plugins_url('jquery-ui/redmond/jquery-ui-1.7.2.custom.css', __FILE__), array(), '1.7.2');
116
- wp_enqueue_style('plugin-custom-style', plugins_url('style.css', __FILE__), array(), '2.0.1');
117
- }
118
-
119
- /**
120
- * Add a "Force Regenerate Thumbnails" link to the media row actions
121
- *
122
- * @param array $actions
123
- * @param string $post
124
- * @return array
125
- * @access public
126
- * @since 1.0
127
- */
128
- function add_media_row_action($actions, $post) {
129
-
130
- if ('image/' != substr($post->post_mime_type, 0, 6) || !current_user_can($this->capability))
131
- return $actions;
132
-
133
- $url = wp_nonce_url( admin_url( 'tools.php?page=force-regenerate-thumbnails&goback=1&ids=' . $post->ID ), 'force-regenerate-thumbnails' );
134
- $actions['regenerate_thumbnails'] = '<a href="' . esc_url( $url ) . '" title="' . esc_attr( __( "Regenerate the thumbnails for this single image", 'force-regenerate-thumbnails' ) ) . '">' . __( 'Force Regenerate Thumbnails', 'force-regenerate-thumbnails' ) . '</a>';
135
-
136
- return $actions;
137
- }
138
-
139
- /**
140
- * Add "Force Regenerate Thumbnails" to the Bulk Actions media dropdown
141
- *
142
- * @param array $actions Actions list
143
- * @return array
144
- * @access public
145
- * @since 1.0
146
- */
147
- function add_bulk_actions($actions) {
148
-
149
- $delete = false;
150
- if (!empty($actions['delete'])) {
151
- $delete = $actions['delete'];
152
- unset($actions['delete']);
153
- }
154
-
155
- $actions['bulk_force_regenerate_thumbnails'] = __('Force Regenerate Thumbnails', 'force-regenerate-thumbnails');
156
-
157
- if ($delete) {
158
- $actions['delete'] = $delete;
159
- }
160
-
161
- return $actions;
162
- }
163
-
164
- /**
165
- * Add new items to the Bulk Actions using Javascript
166
- *
167
- * @access public
168
- * @since 1.0
169
- */
170
- function add_bulk_actions_via_javascript() {
171
-
172
- if (!current_user_can( $this->capability)) {
173
- return;
174
- }
175
- ?>
176
- <script type="text/javascript">
177
- jQuery(document).ready(function($){
178
- $('select[name^="action"] option:last-child').before('<option value="bulk_force_regenerate_thumbnails"><?php echo esc_attr(__('Force Regenerate Thumbnails', 'force-regenerate-thumbnails')); ?></option>');
179
- });
180
- </script>
181
- <?php
182
- }
183
-
184
- /**
185
- * Handles the bulk actions POST
186
- *
187
- * @access public
188
- * @since 1.0
189
- */
190
- function bulk_action_handler() {
191
-
192
- if (empty($_REQUEST['action']) || ('bulk_force_regenerate_thumbnails' != $_REQUEST['action'] && 'bulk_force_regenerate_thumbnails' != $_REQUEST['action2'])) {
193
- return;
194
- }
195
-
196
- if (empty($_REQUEST['media']) || ! is_array($_REQUEST['media'])) {
197
- return;
198
- }
199
-
200
- check_admin_referer('bulk-media');
201
- $ids = implode(',', array_map('intval', $_REQUEST['media']));
202
-
203
- wp_redirect(add_query_arg('_wpnonce', wp_create_nonce('force-regenerate-thumbnails'), admin_url('tools.php?page=force-regenerate-thumbnails&goback=1&ids=' . $ids)));
204
- exit();
205
- }
206
-
207
-
208
- /**
209
- * The user interface plus thumbnail regenerator
210
- *
211
- * @access public
212
- * @since 1.0
213
- */
214
- function force_regenerate_interface() {
215
-
216
- global $wpdb;
217
- ?>
218
-
219
- <div id="message" class="updated fade" style="display:none"></div>
220
-
221
- <div class="wrap regenthumbs">
222
- <h2><?php _e('Force Regenerate Thumbnails', 'force-regenerate-thumbnails'); ?></h2>
223
-
224
- <?php
225
-
226
- // If the button was clicked
227
- if (!empty($_POST['force-regenerate-thumbnails'] ) || !empty($_REQUEST['ids'])) {
228
-
229
- // Capability check
230
- if (!current_user_can( $this->capability))
231
- wp_die(__('Cheatin&#8217; uh?'));
232
-
233
- // Form nonce check
234
- check_admin_referer('force-regenerate-thumbnails');
235
-
236
- // Create the list of image IDs
237
- if (!empty($_REQUEST['ids'])) {
238
- $images = array_map('intval', explode(',', trim($_REQUEST['ids'], ',')));
239
- $ids = implode(',', $images);
240
- } else {
241
-
242
- // Directly querying the database is normally frowned upon, but all
243
- // of the API functions will return the full post objects which will
244
- // suck up lots of memory. This is best, just not as future proof.
245
- if (!$images = $wpdb->get_results("SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'image/%' ORDER BY ID DESC")) {
246
- echo ' <p>' . sprintf(__("Unable to find any images. Are you sure <a href='%s'>some exist</a>?", 'force-regenerate-thumbnails'), admin_url('upload.php?post_mime_type=image')) . "</p></div>";
247
- return;
248
- }
249
-
250
- // Generate the list of IDs
251
- $ids = array();
252
- foreach ($images as $image) {
253
- $ids[] = $image->ID;
254
- }
255
- $ids = implode(',', $ids);
256
- }
257
-
258
- echo ' <p>' . __("Please be patient while the thumbnails are regenerated. You will be notified via this page when the regenerating is completed.", 'force-regenerate-thumbnails') . '</p>';
259
-
260
- $count = count($images);
261
- $text_goback = (!empty($_GET['goback']))
262
- ? sprintf(__('To go back to the previous page, <a href="%s">click here</a>.', 'force-regenerate-thumbnails'), 'javascript:history.go(-1)')
263
- : '';
264
-
265
- $text_failures = sprintf(__('All done! %1$s image(s) were successfully resized in %2$s seconds and there were %3$s failure(s). To try regenerating the failed images again, <a href="%4$s">click here</a>. %5$s', 'force-regenerate-thumbnails'), "' + rt_successes + '", "' + rt_totaltime + '", "' + rt_errors + '", esc_url(wp_nonce_url(admin_url('tools.php?page=force-regenerate-thumbnails&goback=1'), 'force-regenerate-thumbnails') . '&ids=') . "' + rt_failedlist + '", $text_goback);
266
- $text_nofailures = sprintf(__('All done! %1$s image(s) were successfully resized in %2$s seconds and there were 0 failures. %3$s', 'force-regenerate-thumbnails'), "' + rt_successes + '", "' + rt_totaltime + '", $text_goback);
267
- ?>
268
-
269
- <noscript><p><em><?php _e('You must enable Javascript in order to proceed!', 'force-regenerate-thumbnails') ?></em></p></noscript>
270
-
271
- <div id="regenthumbs-bar" style="position:relative;height:25px;">
272
- <div id="regenthumbs-bar-percent" style="position:absolute;left:50%;top:50%;width:300px;margin-left:-150px;height:25px;margin-top:-9px;font-weight:bold;text-align:center;"></div>
273
- </div>
274
-
275
- <p><input type="button" class="button hide-if-no-js" name="regenthumbs-stop" id="regenthumbs-stop" value="<?php _e('Abort Process', 'force-regenerate-thumbnails') ?>" /></p>
276
-
277
- <h3 class="title"><?php _e('Process Information', 'force-regenerate-thumbnails'); ?></h3>
278
-
279
- <p>
280
- <?php printf(__('Total: %s', 'force-regenerate-thumbnails'), $count); ?><br />
281
- <?php printf(__('Success: %s', 'force-regenerate-thumbnails'), '<span id="regenthumbs-debug-successcount">0</span>'); ?><br />
282
- <?php printf(__('Failure: %s', 'force-regenerate-thumbnails'), '<span id="regenthumbs-debug-failurecount">0</span>'); ?>
283
- </p>
284
-
285
- <ol id="regenthumbs-debuglist">
286
- <li style="display:none"></li>
287
- </ol>
288
-
289
- <script type="text/javascript">
290
- // <![CDATA[
291
- jQuery(document).ready(function($){
292
- var i;
293
- var rt_images = [<?php echo $ids; ?>];
294
- var rt_total = rt_images.length;
295
- var rt_count = 1;
296
- var rt_percent = 0;
297
- var rt_successes = 0;
298
- var rt_errors = 0;
299
- var rt_failedlist = '';
300
- var rt_resulttext = '';
301
- var rt_timestart = new Date().getTime();
302
- var rt_timeend = 0;
303
- var rt_totaltime = 0;
304
- var rt_continue = true;
305
-
306
- // Create the progress bar
307
- $("#regenthumbs-bar").progressbar();
308
- $("#regenthumbs-bar-percent").html("0%");
309
-
310
- // Stop button
311
- $("#regenthumbs-stop").click(function() {
312
- rt_continue = false;
313
- $('#regenthumbs-stop').val("<?php echo $this->esc_quotes(__('Stopping...', 'force-regenerate-thumbnails')); ?>");
314
- });
315
-
316
- // Clear out the empty list element that's there for HTML validation purposes
317
- $("#regenthumbs-debuglist li").remove();
318
-
319
- // Called after each resize. Updates debug information and the progress bar.
320
- function RegenThumbsUpdateStatus(id, success, response) {
321
- $("#regenthumbs-bar").progressbar("value", (rt_count / rt_total) * 100);
322
- $("#regenthumbs-bar-percent").html(Math.round((rt_count / rt_total) * 1000) / 10 + "%");
323
- rt_count = rt_count + 1;
324
-
325
- if (success) {
326
- rt_successes = rt_successes + 1;
327
- $("#regenthumbs-debug-successcount").html(rt_successes);
328
- $("#regenthumbs-debuglist").append("<li>" + response.success + "</li>");
329
- }
330
- else {
331
- rt_errors = rt_errors + 1;
332
- rt_failedlist = rt_failedlist + ',' + id;
333
- $("#regenthumbs-debug-failurecount").html(rt_errors);
334
- $("#regenthumbs-debuglist").append("<li>" + response.error + "</li>");
335
- }
336
- }
337
-
338
- // Called when all images have been processed. Shows the results and cleans up.
339
- function RegenThumbsFinishUp() {
340
- rt_timeend = new Date().getTime();
341
- rt_totaltime = Math.round((rt_timeend - rt_timestart) / 1000);
342
-
343
- $('#regenthumbs-stop').hide();
344
-
345
- if (rt_errors > 0) {
346
- rt_resulttext = '<?php echo $text_failures; ?>';
347
- } else {
348
- rt_resulttext = '<?php echo $text_nofailures; ?>';
349
- }
350
-
351
- $("#message").html("<p><strong>" + rt_resulttext + "</strong></p>");
352
- $("#message").show();
353
- }
354
-
355
- // Regenerate a specified image via AJAX
356
- function RegenThumbs(id) {
357
- $.ajax({
358
- type: 'POST',
359
- cache: false,
360
- url: ajaxurl,
361
- data: { action: "regeneratethumbnail", id: id },
362
- success: function(response) {
363
-
364
- //Catch unknown error
365
- if(response === null) {
366
- response = {};
367
- response.success = false;
368
- response.error = 'Unknown error occured.';
369
- }
370
-
371
- if (response.success) {
372
- RegenThumbsUpdateStatus(id, true, response);
373
- } else {
374
- RegenThumbsUpdateStatus(id, false, response);
375
- }
376
-
377
- if (rt_images.length && rt_continue) {
378
- RegenThumbs(rt_images.shift());
379
- } else {
380
- RegenThumbsFinishUp();
381
- }
382
- },
383
- error: function(response) {
384
- RegenThumbsUpdateStatus(id, false, response);
385
-
386
- if (rt_images.length && rt_continue) {
387
- RegenThumbs(rt_images.shift());
388
- } else {
389
- RegenThumbsFinishUp();
390
- }
391
- }
392
- });
393
- }
394
-
395
- RegenThumbs(rt_images.shift());
396
- });
397
- // ]]>
398
- </script>
399
- <?php
400
- }
401
-
402
- // No button click? Display the form.
403
- else {
404
- ?>
405
- <form method="post" action="">
406
- <?php wp_nonce_field('force-regenerate-thumbnails') ?>
407
-
408
- <h3>All Thumbnails</h3>
409
-
410
- <p><?php printf(__("Pressing the follow button, you can regenerate thumbnails for all images that you have uploaded to your blog.", 'force-regenerate-thumbnails'), admin_url('options-media.php')); ?></p>
411
-
412
- <p>
413
- <noscript><p><em><?php _e('You must enable Javascript in order to proceed!', 'force-regenerate-thumbnails') ?></em></p></noscript>
414
- <input type="submit" class="button-primary hide-if-no-js" name="force-regenerate-thumbnails" id="force-regenerate-thumbnails" value="<?php _e('Regenerate All Thumbnails', 'force-regenerate-thumbnails') ?>" />
415
- </p>
416
-
417
- </br>
418
- <h3>Specific Thumbnails</h3>
419
-
420
- <p><?php printf(__("You can regenerate all thumbnails for specific images from the <a href='%s'>Media</a> page. (WordPress 3.1+ only)", 'force-regenerate-thumbnails'), admin_url('upload.php')); ?></p>
421
- </form>
422
- <?php
423
- } // End if button
424
- ?>
425
- </div>
426
-
427
- <?php
428
- }
429
-
430
-
431
- /**
432
- * Process a single image ID (this is an AJAX handler)
433
- *
434
- * @access public
435
- * @since 1.0
436
- */
437
- function ajax_process_image() {
438
-
439
- // No timeout limit
440
- set_time_limit(0);
441
-
442
- // Don't break the JSON result
443
- error_reporting(0);
444
- $id = (int) $_REQUEST['id'];
445
-
446
- try {
447
-
448
- header('Content-type: application/json');
449
- $image = get_post($id);
450
-
451
- if (is_null($image)) {
452
- throw new Exception(sprintf(__('Failed: %d is an invalid image ID.', 'force-regenerate-thumbnails'), $id));
453
- }
454
-
455
- if ('attachment' != $image->post_type || 'image/' != substr($image->post_mime_type, 0, 6)) {
456
- throw new Exception(sprintf(__('Failed: %d is an invalid image ID.', 'force-regenerate-thumbnails'), $id));
457
- }
458
-
459
- if (!current_user_can($this->capability)) {
460
- throw new Exception(__('Your user account does not have permission to regenerate images.', 'force-regenerate-thumbnails'));
461
- }
462
-
463
-
464
- /**
465
- * Fix for get_option('upload_path')
466
- * Thanks (@DavidLingren)
467
- *
468
- * @since 2.0.1
469
- */
470
- $upload_dir = wp_upload_dir();
471
-
472
- // Get original image
473
- $image_fullpath = get_attached_file($image->ID);
474
- $debug_1 = $image_fullpath;
475
- $debug_2 = '';
476
- $debug_3 = '';
477
- $debug_4 = '';
478
-
479
-
480
- // Can't get image path
481
- if (false === $image_fullpath || strlen($image_fullpath) == 0) {
482
-
483
- // Try get image path from url
484
- if ((strrpos($image->guid, $upload_dir['baseurl']) !== false)) {
485
- $image_fullpath = realpath($upload_dir['basedir'] . DIRECTORY_SEPARATOR . substr($image->guid, strlen($upload_dir['baseurl']), strlen($image->guid)));
486
- $debug_2 = $image_fullpath;
487
- if (realpath($image_fullpath) === false) {
488
- throw new Exception(sprintf(__('The originally uploaded image file cannot be found at &quot;%s&quot;.', 'force-regenerate-thumbnails'), esc_html((string) $image_fullpath)));
489
- }
490
- } else {
491
- throw new Exception(__('The originally uploaded image file cannot be found.', 'force-regenerate-thumbnails'));
492
- }
493
-
494
- }
495
-
496
- // Image path incomplete
497
- if ((strrpos($image_fullpath, $upload_dir['basedir']) === false)) {
498
- $image_fullpath = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . $image_fullpath;
499
- $debug_3 = $image_fullpath;
500
- }
501
-
502
-
503
-
504
- // Image don't exists
505
- if (!file_exists($image_fullpath) || realpath($image_fullpath) === false) {
506
-
507
- // Try get image path from url
508
- if ((strrpos($image->guid, $upload_dir['baseurl']) !== false)) {
509
- $image_fullpath = realpath($upload_dir['basedir'] . DIRECTORY_SEPARATOR . substr($image->guid, strlen($upload_dir['baseurl']), strlen($image->guid)));
510
- $debug_4 = $image_fullpath;
511
- if (realpath($image_fullpath) === false) {
512
- throw new Exception(sprintf(__('The originally uploaded image file cannot be found at &quot;%s&quot;.', 'force-regenerate-thumbnails'), esc_html((string) $image_fullpath)));
513
- }
514
- } else {
515
- throw new Exception(sprintf(__('The originally uploaded image file cannot be found at &quot;%s&quot;.', 'force-regenerate-thumbnails'), esc_html((string) $image_fullpath)));
516
- }
517
-
518
- }
519
-
520
-
521
- /**
522
- * Update META POST
523
- * Thanks (@norecipes)
524
- *
525
- * @since 2.0.2
526
- */
527
- update_attached_file($image->ID, $image_fullpath);
528
-
529
-
530
- // Results
531
- $thumb_deleted = array();
532
- $thumb_error = array();
533
- $thumb_regenerate = array();
534
-
535
-
536
- // Hack to find thumbnail
537
- $file_info = pathinfo($image_fullpath);
538
- $file_info['filename'] .= '-';
539
-
540
-
541
- /**
542
- * Try delete all thumbnails
543
- */
544
- $files = array();
545
- $path = opendir($file_info['dirname']);
546
-
547
- if ( false !== $path ) {
548
- while (false !== ($thumb = readdir($path))) {
549
- if (!(strrpos($thumb, $file_info['filename']) === false)) {
550
- $files[] = $thumb;
551
- }
552
- }
553
- closedir($path);
554
- sort($files);
555
- }
556
- foreach ($files as $thumb) {
557
- $thumb_fullpath = $file_info['dirname'] . DIRECTORY_SEPARATOR . $thumb;
558
- $thumb_info = pathinfo($thumb_fullpath);
559
- $valid_thumb = explode($file_info['filename'], $thumb_info['filename']);
560
- if ($valid_thumb[0] == "") {
561
- $dimension_thumb = explode('x', $valid_thumb[1]);
562
- if (count($dimension_thumb) == 2) {
563
- if (is_numeric($dimension_thumb[0]) && is_numeric($dimension_thumb[1])) {
564
- unlink($thumb_fullpath);
565
- if (!file_exists($thumb_fullpath)) {
566
- $thumb_deleted[] = sprintf("%sx%s", $dimension_thumb[0], $dimension_thumb[1]);
567
- } else {
568
- $thumb_error[] = sprintf("%sx%s", $dimension_thumb[0], $dimension_thumb[1]);
569
- }
570
- }
571
- }
572
- }
573
- }
574
-
575
-
576
- /**
577
- * Regenerate all thumbnails
578
- */
579
- $metadata = wp_generate_attachment_metadata($image->ID, $image_fullpath);
580
- if (is_wp_error($metadata)) {
581
- throw new Exception($metadata->get_error_message());
582
- }
583
- if (empty($metadata)) {
584
- throw new Exception(__('Unknown failure reason.', 'force-regenerate-thumbnails'));
585
- }
586
- wp_update_attachment_metadata($image->ID, $metadata);
587
-
588
-
589
- /**
590
- * Verify results (deleted, errors, success)
591
- */
592
- $files = array();
593
- $path = opendir($file_info['dirname']);
594
- if ( false !== $path ) {
595
- while (false !== ($thumb = readdir($path))) {
596
- if (!(strrpos($thumb, $file_info['filename']) === false)) {
597
- $files[] = $thumb;
598
- }
599
- }
600
- closedir($path);
601
- sort($files);
602
- }
603
- foreach ($files as $thumb) {
604
- $thumb_fullpath = $file_info['dirname'] . DIRECTORY_SEPARATOR . $thumb;
605
- $thumb_info = pathinfo($thumb_fullpath);
606
- $valid_thumb = explode($file_info['filename'], $thumb_info['filename']);
607
- if ($valid_thumb[0] == "") {
608
- $dimension_thumb = explode('x', $valid_thumb[1]);
609
- if (count($dimension_thumb) == 2) {
610
- if (is_numeric($dimension_thumb[0]) && is_numeric($dimension_thumb[1])) {
611
- $thumb_regenerate[] = sprintf("%sx%s", $dimension_thumb[0], $dimension_thumb[1]);
612
- }
613
- }
614
- }
615
- }
616
-
617
-
618
- // Remove success if has in error list
619
- foreach ($thumb_regenerate as $key => $regenerate) {
620
- if (in_array($regenerate, $thumb_error))
621
- unset($thumb_regenerate[$key]);
622
- }
623
-
624
- // Remove deleted if has in success list
625
- foreach ($thumb_deleted as $key => $deleted) {
626
- if (in_array($deleted, $thumb_regenerate))
627
- unset($thumb_deleted[$key]);
628
- }
629
-
630
-
631
- /**
632
- * Display results
633
- */
634
- $message = sprintf(__('<b>&quot;%s&quot; (ID %s)</b>', 'force-regenerate-thumbnails'), esc_html(get_the_title($id)), $image->ID);
635
-
636
-
637
- $message .= "<br /><br />";
638
- $message .= sprintf(__("<code>BaseDir: %s</code><br />", 'force-regenerate-thumbnails'), $upload_dir['basedir']);
639
- $message .= sprintf(__("<code>BaseUrl: %s</code><br />", 'force-regenerate-thumbnails'), $upload_dir['baseurl']);
640
- $message .= sprintf(__("<code>Image: %s</code><br />", 'force-regenerate-thumbnails'), $debug_1);
641
- if ($debug_2 != '')
642
- $message .= sprintf(__("<code>Image Debug 2: %s</code><br />", 'force-regenerate-thumbnails'), $debug_2);
643
- if ($debug_3 != '')
644
- $message .= sprintf(__("<code>Image Debug 3: %s</code><br />", 'force-regenerate-thumbnails'), $debug_3);
645
- if ($debug_4 != '')
646
- $message .= sprintf(__("<code>Image Debug 4: %s</code><br />", 'force-regenerate-thumbnails'), $debug_4);
647
-
648
- if (count($thumb_deleted) > 0) {
649
- $message .= sprintf(__('<br />Deleted: %s', 'force-regenerate-thumbnails'), implode(', ', $thumb_deleted));
650
- }
651
- if (count($thumb_error) > 0) {
652
- $message .= sprintf(__('<br /><b><span style="color: #DD3D36;">Deleted error: %s</span></b>', 'force-regenerate-thumbnails'), implode(', ', $thumb_error));
653
- $message .= sprintf(__('<br /><span style="color: #DD3D36;">Please, check the folder permission (chmod 777): %s</span>', 'force-regenerate-thumbnails'), $upload_dir['basedir']);
654
- }
655
- if (count($thumb_regenerate) > 0) {
656
- $message .= sprintf(__('<br />Regenerate: %s</span>', 'force-regenerate-thumbnails'), implode(', ', $thumb_regenerate));
657
- if (count($thumb_error) <= 0) {
658
- $message .= sprintf(__('<br />Successfully regenerated in %s seconds', 'force-regenerate-thumbnails'), timer_stop());
659
- }
660
- }
661
-
662
- if (count($thumb_error) > 0) {
663
- die(json_encode(array('error' => '<div id="message" class="error fade"><p>' . $message . '</p></div>')));
664
- } else {
665
- die(json_encode(array('success' => '<div id="message" class="updated fade"><p>' . $message . '</p></div>')));
666
- }
667
-
668
-
669
- } catch (Exception $e) {
670
- $this->die_json_failure_msg($id, '<b><span style="color: #DD3D36;">' . $e->getMessage() . '</span></b>');
671
- }
672
-
673
- exit;
674
- }
675
-
676
-
677
- /**
678
- * Helper to make a JSON failure message
679
- *
680
- * @param integer $id
681
- * @param string #message
682
- * @access public
683
- * @since 1.8
684
- */
685
- function die_json_failure_msg($id, $message) {
686
- die(json_encode(array('error' => sprintf(__('(ID %s)<br />%s', 'force-regenerate-thumbnails'), $id, $message))));
687
- }
688
-
689
- /**
690
- * Helper function to escape quotes in strings for use in Javascript
691
- *
692
- * @param string #message
693
- * @return string
694
- * @access public
695
- * @since 1.0
696
- */
697
- function esc_quotes($string) {
698
- return str_replace('"', '\"', $string);
699
- }
700
- }
701
-
702
-
703
- /**
704
- * Start
705
- */
706
- function ForceRegenerateThumbnails() {
707
- global $ForceRegenerateThumbnails;
708
- $ForceRegenerateThumbnails = new ForceRegenerateThumbnails();
709
- }
710
- add_action('init', 'ForceRegenerateThumbnails');
711
-
712
-
713
- ?>
1
+ <?php
2
+ /**
3
+ * Main file/class for Force Regenerate Thumbnails.
4
+ *
5
+ * @link https://wordpress.org/plugins/force-regenerate-thumbnails/
6
+ * @package ForceRegenerateThumbnails
7
+ */
8
+
9
+ /*
10
+ Plugin Name: Force Regenerate Thumbnails
11
+ Plugin URI: https://wordpress.org/plugins/force-regenerate-thumbnails/
12
+ Description: Delete and REALLY force the regenerate thumbnail.
13
+ Version: 2.1.0
14
+ Requires at least: 4.9
15
+ Requires PHP: 7.2
16
+ Author: Exactly WWW
17
+ Author URI: http://ewww.io/about/
18
+ License: GPLv2
19
+ */
20
+
21
+ /*
22
+ Debug URL
23
+ wp-admin/admin-ajax.php?action=regeneratethumbnail&id=
24
+ */
25
+
26
+ /**
27
+ * Force GD for Image handle (WordPress 3.5 or better)
28
+ * Thanks (@nikcree)
29
+ *
30
+ * @since 1.5
31
+ * @param array $editors A list of image editors within WordPress.
32
+ */
33
+ function ms_image_editor_default_to_gd_fix( $editors ) {
34
+ $gd_editor = 'WP_Image_Editor_GD';
35
+
36
+ $editors = array_diff( $editors, array( $gd_editor ) );
37
+ array_unshift( $editors, $gd_editor );
38
+
39
+ return $editors;
40
+ }
41
+ if ( apply_filters( 'regenerate_thumbs_force_gd', false ) ) {
42
+ add_filter( 'wp_image_editors', 'ms_image_editor_default_to_gd_fix' );
43
+ }
44
+
45
+ if ( ! function_exists( 'str_ends_with' ) ) {
46
+ /**
47
+ * Polyfill for `str_ends_with()` function added in WP 5.9 or PHP 8.0.
48
+ *
49
+ * Performs a case-sensitive check indicating if
50
+ * the haystack ends with needle.
51
+ *
52
+ * @since 2.1.0
53
+ *
54
+ * @param string $haystack The string to search in.
55
+ * @param string $needle The substring to search for in the `$haystack`.
56
+ * @return bool True if `$haystack` ends with `$needle`, otherwise false.
57
+ */
58
+ function str_ends_with( $haystack, $needle ) {
59
+ if ( '' === $haystack && '' !== $needle ) {
60
+ return false;
61
+ }
62
+
63
+ $len = strlen( $needle );
64
+
65
+ return 0 === substr_compare( $haystack, $needle, -$len, $len );
66
+ }
67
+ }
68
+
69
+ require_once( trailingslashit( __DIR__ ) . 'class-forceregeneratethumbnails.php' );
70
+
71
+ /**
72
+ * Initialize plugin and return FRT object.
73
+ *
74
+ * @return object The one and only ForceRegenerateThumbnails instance.
75
+ */
76
+ function force_regenerate_thumbnails() {
77
+ global $force_regenerate_thumbnails;
78
+ if ( ! is_object( $force_regenerate_thumbnails ) || ! is_a( $force_regenerate_thumbnails, 'ForceRegenerateThumbnails' ) ) {
79
+ $force_regenerate_thumbnails = new ForceRegenerateThumbnails();
80
+ }
81
+ return $force_regenerate_thumbnails;
82
+ }
83
+ add_action( 'init', 'force_regenerate_thumbnails' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
jquery-ui/jquery.ui.progressbar.min.1.7.2.js DELETED
@@ -1,13 +0,0 @@
1
- /*
2
- * jQuery UI Progressbar 1.7.2
3
- *
4
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5
- * Dual licensed under the MIT (MIT-LICENSE.txt)
6
- * and GPL (GPL-LICENSE.txt) licenses.
7
- *
8
- * http://docs.jquery.com/UI/Progressbar
9
- *
10
- * Depends:
11
- * ui.core.js
12
- */
13
- (function(a){a.widget("ui.progressbar",{_init:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=a('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow").removeData("progressbar").unbind(".progressbar");this.valueDiv.remove();a.widget.prototype.destroy.apply(this,arguments)},value:function(b){if(b===undefined){return this._value()}this._setData("value",b);return this},_setData:function(b,c){switch(b){case"value":this.options.value=c;this._refreshValue();this._trigger("change",null,{});break}a.widget.prototype._setData.apply(this,arguments)},_value:function(){var b=this.options.value;if(b<this._valueMin()){b=this._valueMin()}if(b>this._valueMax()){b=this._valueMax()}return b},_valueMin:function(){var b=0;return b},_valueMax:function(){var b=100;return b},_refreshValue:function(){var b=this.value();this.valueDiv[b==this._valueMax()?"addClass":"removeClass"]("ui-corner-right");this.valueDiv.width(b+"%");this.element.attr("aria-valuenow",b)}});a.extend(a.ui.progressbar,{version:"1.7.2",defaults:{value:0}})})(jQuery);;
 
 
 
 
 
 
 
 
 
 
 
 
 
jquery-ui/jquery.ui.progressbar.min.js DELETED
@@ -1,16 +0,0 @@
1
- /*
2
- * jQuery UI Progressbar 1.8.6
3
- *
4
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5
- * Dual licensed under the MIT or GPL Version 2 licenses.
6
- * http://jquery.org/license
7
- *
8
- * http://docs.jquery.com/UI/Progressbar
9
- *
10
- * Depends:
11
- * jquery.ui.core.js
12
- * jquery.ui.widget.js
13
- */
14
- (function(b,c){b.widget("ui.progressbar",{options:{value:0},min:0,max:100,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.max,"aria-valuenow":this._value()});this.valueDiv=b("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow");
15
- this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===c)return this._value();this._setOption("value",a);return this},_setOption:function(a,d){if(a==="value"){this.options.value=d;this._refreshValue();this._trigger("change");this._value()===this.max&&this._trigger("complete")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;return Math.min(this.max,Math.max(this.min,a))},_refreshValue:function(){var a=
16
- this.value();this.valueDiv.toggleClass("ui-corner-right",a===this.max).width(a+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.6"})})(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
jquery-ui/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png DELETED
Binary file
jquery-ui/redmond/images/ui-bg_flat_55_fbec88_40x100.png DELETED
Binary file
jquery-ui/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png DELETED
Binary file
jquery-ui/redmond/images/ui-bg_glass_85_dfeffc_1x400.png DELETED
Binary file
jquery-ui/redmond/images/ui-bg_glass_95_fef1ec_1x400.png DELETED
Binary file
jquery-ui/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png DELETED
Binary file
jquery-ui/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png DELETED
Binary file
jquery-ui/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png DELETED
Binary file
jquery-ui/redmond/jquery-ui-1.7.2.custom.css DELETED
@@ -1,406 +0,0 @@
1
- /*
2
- * jQuery UI CSS Framework
3
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
4
- * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
5
- */
6
-
7
- /* Layout helpers
8
- ----------------------------------*/
9
- .ui-helper-hidden { display: none; }
10
- .ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
11
- .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
12
- .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
13
- .ui-helper-clearfix { display: inline-block; }
14
- /* required comment for clearfix to work in Opera \*/
15
- * html .ui-helper-clearfix { height:1%; }
16
- .ui-helper-clearfix { display:block; }
17
- /* end clearfix */
18
- .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
19
-
20
-
21
- /* Interaction Cues
22
- ----------------------------------*/
23
- .ui-state-disabled { cursor: default !important; }
24
-
25
-
26
- /* Icons
27
- ----------------------------------*/
28
-
29
- /* states and images */
30
- .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
31
-
32
-
33
- /* Misc visuals
34
- ----------------------------------*/
35
-
36
- /* Overlays */
37
- .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
38
-
39
-
40
-
41
- /*
42
- * jQuery UI CSS Framework
43
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
44
- * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
45
- * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
46
- */
47
-
48
-
49
- /* Component containers
50
- ----------------------------------*/
51
- .ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; }
52
- .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }
53
- .ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; }
54
- .ui-widget-content a { color: #222222; }
55
- .ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
56
- .ui-widget-header a { color: #ffffff; }
57
-
58
- /* Interaction states
59
- ----------------------------------*/
60
- .ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; outline: none; }
61
- .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; text-decoration: none; outline: none; }
62
- .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; outline: none; }
63
- .ui-state-hover a, .ui-state-hover a:hover { color: #1d5987; text-decoration: none; outline: none; }
64
- .ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; outline: none; }
65
- .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; outline: none; text-decoration: none; }
66
-
67
- /* Interaction Cues
68
- ----------------------------------*/
69
- .ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; }
70
- .ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
71
- .ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
72
- .ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; }
73
- .ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
74
- .ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
75
- .ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
76
- .ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
77
-
78
- /* Icons
79
- ----------------------------------*/
80
-
81
- /* states and images */
82
- .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); }
83
- .ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); }
84
- .ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); }
85
- .ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); }
86
- .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); }
87
- .ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); }
88
- .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
89
- .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
90
-
91
- /* positioning */
92
- .ui-icon-carat-1-n { background-position: 0 0; }
93
- .ui-icon-carat-1-ne { background-position: -16px 0; }
94
- .ui-icon-carat-1-e { background-position: -32px 0; }
95
- .ui-icon-carat-1-se { background-position: -48px 0; }
96
- .ui-icon-carat-1-s { background-position: -64px 0; }
97
- .ui-icon-carat-1-sw { background-position: -80px 0; }
98
- .ui-icon-carat-1-w { background-position: -96px 0; }
99
- .ui-icon-carat-1-nw { background-position: -112px 0; }
100
- .ui-icon-carat-2-n-s { background-position: -128px 0; }
101
- .ui-icon-carat-2-e-w { background-position: -144px 0; }
102
- .ui-icon-triangle-1-n { background-position: 0 -16px; }
103
- .ui-icon-triangle-1-ne { background-position: -16px -16px; }
104
- .ui-icon-triangle-1-e { background-position: -32px -16px; }
105
- .ui-icon-triangle-1-se { background-position: -48px -16px; }
106
- .ui-icon-triangle-1-s { background-position: -64px -16px; }
107
- .ui-icon-triangle-1-sw { background-position: -80px -16px; }
108
- .ui-icon-triangle-1-w { background-position: -96px -16px; }
109
- .ui-icon-triangle-1-nw { background-position: -112px -16px; }
110
- .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
111
- .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
112
- .ui-icon-arrow-1-n { background-position: 0 -32px; }
113
- .ui-icon-arrow-1-ne { background-position: -16px -32px; }
114
- .ui-icon-arrow-1-e { background-position: -32px -32px; }
115
- .ui-icon-arrow-1-se { background-position: -48px -32px; }
116
- .ui-icon-arrow-1-s { background-position: -64px -32px; }
117
- .ui-icon-arrow-1-sw { background-position: -80px -32px; }
118
- .ui-icon-arrow-1-w { background-position: -96px -32px; }
119
- .ui-icon-arrow-1-nw { background-position: -112px -32px; }
120
- .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
121
- .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
122
- .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
123
- .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
124
- .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
125
- .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
126
- .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
127
- .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
128
- .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
129
- .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
130
- .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
131
- .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
132
- .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
133
- .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
134
- .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
135
- .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
136
- .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
137
- .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
138
- .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
139
- .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
140
- .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
141
- .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
142
- .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
143
- .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
144
- .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
145
- .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
146
- .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
147
- .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
148
- .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
149
- .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
150
- .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
151
- .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
152
- .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
153
- .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
154
- .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
155
- .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
156
- .ui-icon-arrow-4 { background-position: 0 -80px; }
157
- .ui-icon-arrow-4-diag { background-position: -16px -80px; }
158
- .ui-icon-extlink { background-position: -32px -80px; }
159
- .ui-icon-newwin { background-position: -48px -80px; }
160
- .ui-icon-refresh { background-position: -64px -80px; }
161
- .ui-icon-shuffle { background-position: -80px -80px; }
162
- .ui-icon-transfer-e-w { background-position: -96px -80px; }
163
- .ui-icon-transferthick-e-w { background-position: -112px -80px; }
164
- .ui-icon-folder-collapsed { background-position: 0 -96px; }
165
- .ui-icon-folder-open { background-position: -16px -96px; }
166
- .ui-icon-document { background-position: -32px -96px; }
167
- .ui-icon-document-b { background-position: -48px -96px; }
168
- .ui-icon-note { background-position: -64px -96px; }
169
- .ui-icon-mail-closed { background-position: -80px -96px; }
170
- .ui-icon-mail-open { background-position: -96px -96px; }
171
- .ui-icon-suitcase { background-position: -112px -96px; }
172
- .ui-icon-comment { background-position: -128px -96px; }
173
- .ui-icon-person { background-position: -144px -96px; }
174
- .ui-icon-print { background-position: -160px -96px; }
175
- .ui-icon-trash { background-position: -176px -96px; }
176
- .ui-icon-locked { background-position: -192px -96px; }
177
- .ui-icon-unlocked { background-position: -208px -96px; }
178
- .ui-icon-bookmark { background-position: -224px -96px; }
179
- .ui-icon-tag { background-position: -240px -96px; }
180
- .ui-icon-home { background-position: 0 -112px; }
181
- .ui-icon-flag { background-position: -16px -112px; }
182
- .ui-icon-calendar { background-position: -32px -112px; }
183
- .ui-icon-cart { background-position: -48px -112px; }
184
- .ui-icon-pencil { background-position: -64px -112px; }
185
- .ui-icon-clock { background-position: -80px -112px; }
186
- .ui-icon-disk { background-position: -96px -112px; }
187
- .ui-icon-calculator { background-position: -112px -112px; }
188
- .ui-icon-zoomin { background-position: -128px -112px; }
189
- .ui-icon-zoomout { background-position: -144px -112px; }
190
- .ui-icon-search { background-position: -160px -112px; }
191
- .ui-icon-wrench { background-position: -176px -112px; }
192
- .ui-icon-gear { background-position: -192px -112px; }
193
- .ui-icon-heart { background-position: -208px -112px; }
194
- .ui-icon-star { background-position: -224px -112px; }
195
- .ui-icon-link { background-position: -240px -112px; }
196
- .ui-icon-cancel { background-position: 0 -128px; }
197
- .ui-icon-plus { background-position: -16px -128px; }
198
- .ui-icon-plusthick { background-position: -32px -128px; }
199
- .ui-icon-minus { background-position: -48px -128px; }
200
- .ui-icon-minusthick { background-position: -64px -128px; }
201
- .ui-icon-close { background-position: -80px -128px; }
202
- .ui-icon-closethick { background-position: -96px -128px; }
203
- .ui-icon-key { background-position: -112px -128px; }
204
- .ui-icon-lightbulb { background-position: -128px -128px; }
205
- .ui-icon-scissors { background-position: -144px -128px; }
206
- .ui-icon-clipboard { background-position: -160px -128px; }
207
- .ui-icon-copy { background-position: -176px -128px; }
208
- .ui-icon-contact { background-position: -192px -128px; }
209
- .ui-icon-image { background-position: -208px -128px; }
210
- .ui-icon-video { background-position: -224px -128px; }
211
- .ui-icon-script { background-position: -240px -128px; }
212
- .ui-icon-alert { background-position: 0 -144px; }
213
- .ui-icon-info { background-position: -16px -144px; }
214
- .ui-icon-notice { background-position: -32px -144px; }
215
- .ui-icon-help { background-position: -48px -144px; }
216
- .ui-icon-check { background-position: -64px -144px; }
217
- .ui-icon-bullet { background-position: -80px -144px; }
218
- .ui-icon-radio-off { background-position: -96px -144px; }
219
- .ui-icon-radio-on { background-position: -112px -144px; }
220
- .ui-icon-pin-w { background-position: -128px -144px; }
221
- .ui-icon-pin-s { background-position: -144px -144px; }
222
- .ui-icon-play { background-position: 0 -160px; }
223
- .ui-icon-pause { background-position: -16px -160px; }
224
- .ui-icon-seek-next { background-position: -32px -160px; }
225
- .ui-icon-seek-prev { background-position: -48px -160px; }
226
- .ui-icon-seek-end { background-position: -64px -160px; }
227
- .ui-icon-seek-first { background-position: -80px -160px; }
228
- .ui-icon-stop { background-position: -96px -160px; }
229
- .ui-icon-eject { background-position: -112px -160px; }
230
- .ui-icon-volume-off { background-position: -128px -160px; }
231
- .ui-icon-volume-on { background-position: -144px -160px; }
232
- .ui-icon-power { background-position: 0 -176px; }
233
- .ui-icon-signal-diag { background-position: -16px -176px; }
234
- .ui-icon-signal { background-position: -32px -176px; }
235
- .ui-icon-battery-0 { background-position: -48px -176px; }
236
- .ui-icon-battery-1 { background-position: -64px -176px; }
237
- .ui-icon-battery-2 { background-position: -80px -176px; }
238
- .ui-icon-battery-3 { background-position: -96px -176px; }
239
- .ui-icon-circle-plus { background-position: 0 -192px; }
240
- .ui-icon-circle-minus { background-position: -16px -192px; }
241
- .ui-icon-circle-close { background-position: -32px -192px; }
242
- .ui-icon-circle-triangle-e { background-position: -48px -192px; }
243
- .ui-icon-circle-triangle-s { background-position: -64px -192px; }
244
- .ui-icon-circle-triangle-w { background-position: -80px -192px; }
245
- .ui-icon-circle-triangle-n { background-position: -96px -192px; }
246
- .ui-icon-circle-arrow-e { background-position: -112px -192px; }
247
- .ui-icon-circle-arrow-s { background-position: -128px -192px; }
248
- .ui-icon-circle-arrow-w { background-position: -144px -192px; }
249
- .ui-icon-circle-arrow-n { background-position: -160px -192px; }
250
- .ui-icon-circle-zoomin { background-position: -176px -192px; }
251
- .ui-icon-circle-zoomout { background-position: -192px -192px; }
252
- .ui-icon-circle-check { background-position: -208px -192px; }
253
- .ui-icon-circlesmall-plus { background-position: 0 -208px; }
254
- .ui-icon-circlesmall-minus { background-position: -16px -208px; }
255
- .ui-icon-circlesmall-close { background-position: -32px -208px; }
256
- .ui-icon-squaresmall-plus { background-position: -48px -208px; }
257
- .ui-icon-squaresmall-minus { background-position: -64px -208px; }
258
- .ui-icon-squaresmall-close { background-position: -80px -208px; }
259
- .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
260
- .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
261
- .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
262
- .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
263
- .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
264
- .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
265
-
266
-
267
- /* Misc visuals
268
- ----------------------------------*/
269
-
270
- /* Corner radius */
271
- .ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; }
272
- .ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; }
273
- .ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; }
274
- .ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
275
- .ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; }
276
- .ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
277
- .ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
278
- .ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; }
279
- .ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; }
280
-
281
- /* Overlays */
282
- .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
283
- .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Accordion
284
- ----------------------------------*/
285
- .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
286
- .ui-accordion .ui-accordion-li-fix { display: inline; }
287
- .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
288
- .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
289
- .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
290
- .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
291
- .ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
292
- ----------------------------------*/
293
- .ui-datepicker { width: 17em; padding: .2em .2em 0; }
294
- .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
295
- .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
296
- .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
297
- .ui-datepicker .ui-datepicker-prev { left:2px; }
298
- .ui-datepicker .ui-datepicker-next { right:2px; }
299
- .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
300
- .ui-datepicker .ui-datepicker-next-hover { right:1px; }
301
- .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
302
- .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
303
- .ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
304
- .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
305
- .ui-datepicker select.ui-datepicker-month,
306
- .ui-datepicker select.ui-datepicker-year { width: 49%;}
307
- .ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
308
- .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
309
- .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
310
- .ui-datepicker td { border: 0; padding: 1px; }
311
- .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
312
- .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
313
- .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
314
- .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
315
-
316
- /* with multiple calendars */
317
- .ui-datepicker.ui-datepicker-multi { width:auto; }
318
- .ui-datepicker-multi .ui-datepicker-group { float:left; }
319
- .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
320
- .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
321
- .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
322
- .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
323
- .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
324
- .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
325
- .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
326
- .ui-datepicker-row-break { clear:both; width:100%; }
327
-
328
- /* RTL support */
329
- .ui-datepicker-rtl { direction: rtl; }
330
- .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
331
- .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
332
- .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
333
- .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
334
- .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
335
- .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
336
- .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
337
- .ui-datepicker-rtl .ui-datepicker-group { float:right; }
338
- .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
339
- .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
340
-
341
- /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
342
- .ui-datepicker-cover {
343
- display: none; /*sorry for IE5*/
344
- display/**/: block; /*sorry for IE5*/
345
- position: absolute; /*must have*/
346
- z-index: -1; /*must have*/
347
- filter: mask(); /*must have*/
348
- top: -4px; /*must have*/
349
- left: -4px; /*must have*/
350
- width: 200px; /*must have*/
351
- height: 200px; /*must have*/
352
- }/* Dialog
353
- ----------------------------------*/
354
- .ui-dialog { position: relative; padding: .2em; width: 300px; }
355
- .ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; }
356
- .ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; }
357
- .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
358
- .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
359
- .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
360
- .ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
361
- .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
362
- .ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
363
- .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
364
- .ui-draggable .ui-dialog-titlebar { cursor: move; }
365
- /* Progressbar
366
- ----------------------------------*/
367
- .ui-progressbar { height:2em; text-align: left; }
368
- .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable
369
- ----------------------------------*/
370
- .ui-resizable { position: relative;}
371
- .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
372
- .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
373
- .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
374
- .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
375
- .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
376
- .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
377
- .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
378
- .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
379
- .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
380
- .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider
381
- ----------------------------------*/
382
- .ui-slider { position: relative; text-align: left; }
383
- .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
384
- .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
385
-
386
- .ui-slider-horizontal { height: .8em; }
387
- .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
388
- .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
389
- .ui-slider-horizontal .ui-slider-range-min { left: 0; }
390
- .ui-slider-horizontal .ui-slider-range-max { right: 0; }
391
-
392
- .ui-slider-vertical { width: .8em; height: 100px; }
393
- .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
394
- .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
395
- .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
396
- .ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
397
- ----------------------------------*/
398
- .ui-tabs { padding: .2em; zoom: 1; }
399
- .ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
400
- .ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
401
- .ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
402
- .ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
403
- .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
404
- .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
405
- .ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
406
- .ui-tabs .ui-tabs-hide { display: none !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
phpcs.ruleset.xml ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <ruleset name="WordPress Coding Standards for Plugins">
3
+ <description>Generally-applicable sniffs for WordPress plugins</description>
4
+
5
+ <exclude-pattern>*/vendor/*</exclude-pattern>
6
+ <exclude-pattern>*/tests/*</exclude-pattern>
7
+
8
+ <rule ref="WordPress-Core" />
9
+ <rule ref="WordPress-Docs" />
10
+ <rule ref="WordPress.PHP.NoSilencedErrors">
11
+ <properties>
12
+ <property name="custom_whitelist" type="array" value="exif_read_data"/>
13
+ </properties>
14
+ </rule>
15
+
16
+ <rule ref="PHPCompatibilityWP">
17
+ <severity>10</severity>
18
+ </rule>
19
+
20
+ <rule ref="WordPress.Security">
21
+ <severity>10</severity>
22
+ </rule>
23
+
24
+ <rule ref="WordPress.DB.PreparedSQL">
25
+ <severity>10</severity>
26
+ </rule>
27
+ </ruleset>
readme.txt CHANGED
@@ -1,17 +1,21 @@
1
  === Force Regenerate Thumbnails ===
2
- Contributors: Pedro Elsner
3
- Requires at least: 2.8
4
- Tested up to: 4.0
5
- Stable tag: trunk
 
 
6
  Tags: force, regenerate thumbnails, thumbnail, thumbnails
7
 
8
- Delete and REALLY force the regenerate thumbnail.
9
 
10
  == Description ==
11
 
12
- Force Regenerate Thumbnails allows you to delete all old images size and REALLY regenerate the thumbnails for your image attachments.
13
 
14
- See the [screenshots tab](http://wordpress.org/extend/plugins/force-regenerate-thumbnails/screenshots/) for more details.
 
 
15
 
16
  == Installation ==
17
 
@@ -19,6 +23,7 @@ See the [screenshots tab](http://wordpress.org/extend/plugins/force-regenerate-t
19
  2. Search for "Force Regenerate Thumbnails".
20
  3. Click install.
21
  4. Click activate.
 
22
 
23
  == Screenshots ==
24
 
@@ -27,6 +32,17 @@ See the [screenshots tab](http://wordpress.org/extend/plugins/force-regenerate-t
27
 
28
  == ChangeLog ==
29
 
 
 
 
 
 
 
 
 
 
 
 
30
  = 2.0.6 =
31
  * Add PHP7 compatibility
32
 
@@ -47,35 +63,8 @@ See the [screenshots tab](http://wordpress.org/extend/plugins/force-regenerate-t
47
  = 2.0.1 =
48
  * Fix issue with get_option('upload_path') in Wordpress 3.5+ (thanks @DavidLingren)
49
 
50
- = 2.0.0 =
51
  * Fix error handle
52
 
53
- = 1.8 =
54
- * New function to display ajax results
55
-
56
- = 1.7 =
57
- * Fix issue with getters path in Linux/Windows/Unix servers
58
-
59
- = 1.6 =
60
- * New CORE to regenerate thumbnails
61
-
62
- = 1.5 =
63
- * Reviewed some messages
64
-
65
- = 1.4 =
66
- * Change default image editor to GB in Wordpress 3.5+ (thanks @nikcree)
67
-
68
- = 1.3 =
69
- * Fix message error when WP_DEBUG in wp_config.php
70
-
71
- = 1.2 =
72
- * Fix for JPEG images
73
-
74
- = 1.1 =
75
- * Delete all custom image sizes when regenerate thumbnails
76
- * Notifies you when thumbnails was deleted
77
-
78
- = 1.0 =
79
- * First release.
80
-
81
- == Upgrade Notice ==
1
  === Force Regenerate Thumbnails ===
2
+ Contributors: pedro-elsner, nosilver4u
3
+ Requires at least: 4.9
4
+ Tested up to: 6.1
5
+ Requires PHP: 7.2
6
+ Stable tag: 2.1.0
7
+ License: GPLv2
8
  Tags: force, regenerate thumbnails, thumbnail, thumbnails
9
 
10
+ Delete and REALLY force thumbnail regeneration.
11
 
12
  == Description ==
13
 
14
+ Force Regenerate Thumbnails allows you to delete all old images sizes and REALLY regenerate the thumbnails for your uploads.
15
 
16
+ Regenerate all thumbnails from the Tools admin menu. Regenerate batches of images via the Media Library list mode. Select the images to regenerate and then use the Bulk Actions drop-down menu to Force Regenerate Thumbnails. Use attachment actions to regenerate thumbnails for a single image.
17
+
18
+ Several filters exist for advanced usage. See more via [this gist](https://gist.github.com/nosilver4u/eb858df10521aece2044a3a15ccdd17b).
19
 
20
  == Installation ==
21
 
23
  2. Search for "Force Regenerate Thumbnails".
24
  3. Click install.
25
  4. Click activate.
26
+ 5. Go to Tools -> Force Regenerate Thumbnails OR select specific images from the Media Library list mode to regenerate.
27
 
28
  == Screenshots ==
29
 
32
 
33
  == ChangeLog ==
34
 
35
+ = 2.1.0 =
36
+ * added: PHP 8.0 compatibility
37
+ * added: support generating thumbnails from original (pre-scaled), on by default
38
+ * added: support for PDF thumbnail generation
39
+ * added: ability to skip an image by regenerate_thumbs_skip_image filter
40
+ * changed: escape all output, sanitize all input
41
+ * changed: ensure all strings are i18n
42
+ * changed: remove HTML from i18n strings
43
+ * changed: improve path lookup function
44
+ * fixed: call to set_time_limit() when it is not allowed
45
+
46
  = 2.0.6 =
47
  * Add PHP7 compatibility
48
 
63
  = 2.0.1 =
64
  * Fix issue with get_option('upload_path') in Wordpress 3.5+ (thanks @DavidLingren)
65
 
66
+ = 2.0.0 =
67
  * Fix error handle
68
 
69
+ = Earlier versions =
70
+ Please refer to the separate changelog.txt file.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
screenshot-1.png DELETED
Binary file
screenshot-2.png DELETED
Binary file
style.css DELETED
@@ -1,12 +0,0 @@
1
-
2
- #regenthumbs-debuglist {
3
- overflow: auto;
4
- height: 400px;
5
- margin-left: 0;
6
- padding: 1em 1.2em;
7
- list-style-position: inside;
8
- background: #fff;
9
- -webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
10
- box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
11
- }
12
-